|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)branch.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: #include "as.h"
10: #include "c2.h"
11:
12: char *unbranch[] = {
13: "jne", "jeq", "jgt", "jlt", "jge", "jle",
14: "jhi", "jls", "jpl", "jmi", "jf",
15: "jcc", "jcs", "jvc", "jvs", "jra",
16: "jfneq", "jfeq", "jfnlt", "jflt",
17: "jfnle", "jfle", "jfngt", "jfgt",
18: "jfnge", "jfge",
19: "fjneq", "fjeq", "fjngt", "fjgt", "fjnge", "fjge",
20: "fjnlt", "fjlt", "fjnle", "fjle", "fjngl", "fjgl",
21: "fjngle", "fjgle", "fjule", "fjogt", "fjult", "fjoge",
22: "fjuge", "fjolt", "fjugt", "fjole", "fjueq", "fjogl",
23: "fjun", "fjor", "fjst", "fjsf", "fjsneq", "fjseq"
24: };
25: extern NODE *deletenode();
26:
27: NODE *
28: insert_label( p )
29: register NODE *p;
30: {
31: static int newlabno = 0;
32: register NODE *l;
33: register struct sym_bkt *s;
34: char labname[20];
35:
36: l = new();
37: l->op = OP_LABEL;
38: l->nref = 0;
39: sprintf( labname, "LY%05d", newlabno++ );
40: l->name = s = lookup(labname);
41: s->attr_s |= S_DEF|S_DEC;
42: s->csect_s = C_TEXT;
43: s->where_s = l;
44: l->forw = p;
45: l->back = p->back;
46: l->back->forw = l;
47: p->back = l;
48: l->ruse = l->rset = regmask0;
49: l->rlive = l->forw->rlive;
50: return l;
51: }
52:
53: NODE *
54: merge_labels( to, from )
55: register NODE * to, *from ;
56: {
57: /*
58: * there are two kinds of labels:
59: * those all of whose references we can find, and
60: * the others.
61: * In the latter case, we will want to move the label,
62: * and let someone smarter than us drop the equate.
63: */
64: register refs = 0;
65: register NODE *luse;
66: if (from->luse!=NULL){
67: for ( luse=from->luse; ; luse=luse->lnext ){
68: luse->luse = to;
69: refs++;
70: if (luse->lnext==NULL) break;
71: }
72: luse->lnext=to->luse;
73: to->luse =from->luse;
74: }
75: if (refs == from->nref){
76: from = deletenode( from )->forw;
77: meter.nrlab++;
78: } else {
79: /*
80: * at this point there are not references on our list, but
81: * still references to this label somewhere out there
82: * move the damn thing
83: * and null out the use list
84: */
85: NODE *temp;
86: from->nref -= refs;
87: from->luse = NULL;
88: temp = from->forw;
89: from->back->forw = from->forw;
90: from->forw->back = from->back;
91: from->forw = to->forw;
92: from->forw->back = from;
93: from->back = to;
94: to->forw = from;
95: from = temp;
96: }
97: to->nref += refs;
98: return from;
99: }
100:
101: int
102: fallthrough( t )
103: register NODE *t;
104: {
105: /*
106: * return 0 if t is a node that cannot "fall through" to the
107: * next instruction, such as an unconditional jump or code-
108: * emitting pseudo-instruction
109: * return 1 if this is not the case.
110: */
111: if (ISDIRECTIVE(t->op) ) return 1;
112: else if (ISPSEUDO(t->op) ) return 0;
113: else switch (t->op){
114: case OP_CSWITCH:
115: case OP_FIRST:
116: case OP_EXIT:
117: return 0;
118: case OP_BRANCH:
119: case OP_JUMP:
120: return t->subop!=JALL;
121: default:
122: return 1;
123: }
124: /* NOTREACHED */
125: }
126:
127:
128: # define nexti( t ) while( t->op==OP_LABEL ) t=t->forw
129: tangle()
130: {
131: /*
132: * remove:
133: * trivial jumps
134: * jumps to jumps
135: * jumps around jumps
136: */
137:
138: int changed = 1;
139: int niter=0;
140: register NODE *p, *t, *u;
141: NODE *j, *jdest, *savelabel;
142:
143: while (changed){
144: changed=0;
145: for (p=first.forw; p!=&first; p=p->forw){
146: if ((p->op==OP_JUMP&&p->subop!=JIND)||p->op==OP_CSWITCH){
147: t = p->luse;
148: nexti( t );
149: if (t==p){
150: /* selfloop */
151: if (p->luse->nref==1 && !fallthrough(p->back)){
152: /* unreachable */
153: unreference( p->luse, p);
154: p = deletenode( p );
155: meter.nbrbr++;
156: changed++;
157: }
158: continue;
159: }
160: if (t->op==p->op && (t->subop==JALL || t->subop==p->subop)){
161: /* jump-to-jump -- remove the middle reference */
162: if (p->luse==t->luse){
163: /* jump into selfloop */
164: continue;
165: }
166: unreference( p->luse, p);
167: newreference( t->luse, p);
168: t = p->luse;
169: nexti( t );
170: meter.nbrbr++;
171: changed++;
172: }
173: if (p->op==OP_CSWITCH ) continue;
174: if (p->luse==p->forw){
175: /* trivial jump */
176: unreference( p->luse, p);
177: p = deletenode( p );
178: changed++;
179: meter.njp1++;
180: continue;
181: }
182: if (p->subop == JALL){
183: u = (t=p->luse)->back;
184: /* find the non-pseudo-op before the destination */
185: while (ISDIRECTIVE(u->op))
186: u = u->back;
187: if ( t->nref==1 && ( u->op==OP_FIRST ||
188: ((u->op==OP_JUMP&&u->subop==JALL)|| u->op==OP_EXIT))){
189: /*
190: * this piece of code is reachable from p but not by
191: * fall through. move it to after p and delete
192: * the jump. stop moving after a cswitch
193: * or unconditional goto or return.
194: */
195: jdest = u->luse;
196: savelabel = 0;
197: u = t;
198: while ((u=u->forw)->op!= OP_FIRST){
199: if (u->op==OP_LABEL ){
200: if ( u->back->op==OP_CSWITCH )
201: break;
202: else if (savelabel != jdest
203: && !(u->forw->op==OP_CSWITCH ) )
204: savelabel = u;
205: }else if ((u->op==OP_JUMP && u->subop==JALL)
206: || u->op==OP_EXIT ){
207: u = u->forw;
208: break;
209: }
210: }
211: /* t points to the first node to move, and */
212: /* u points to the first node not to move. */
213: j = u->back;
214: if (j==p){
215: /*
216: * oh, my... a loop. It may be without any
217: * way in, but I'm too 'fraid to try deleteing
218: * it. Lets try pivoting around an appropriate
219: * label in the loop.
220: */
221: if (savelabel){
222: u = savelabel;
223: j = u->back;
224: } else
225: continue;
226: }
227: if (j->op != OP_CSWITCH
228: && !(j->op==OP_JUMP && j->subop==JALL)
229: && j->op != OP_EXIT
230: && u->op==OP_LABEL){
231: /* add unconditional branch here */
232: j->forw = new();
233: j->forw->back = j;
234: j = j->forw;
235: cannibalize( j, "jra" );
236: j->op = OP_JUMP; /* rather than OP_BRANCH */
237: newreference( u, j);
238: }
239: u->back = t->back;
240: t->back->forw = u;
241: t->back = p;
242: j->forw = p->forw;
243: p->forw->back = j;
244: p->forw = t;
245: /* the details will take care of themselves */
246: p = p->back;
247: changed++;
248: meter.ncmot++;
249: continue;
250: }
251: /* delete dead code after unconditional branch */
252: /* should do after exits, too */
253: u = p->forw;
254: while ((t=u)->op!=OP_LABEL && t->op!=OP_FIRST
255: && t->op != OP_EXIT){
256: u = t->forw;
257: if (ISPSEUDO( t->op ))
258: continue; /* don't delete pseudoops */
259: if (ISBRANCH(t->op))
260: unreference( t->luse, t);
261: (void)deletenode( t );
262: meter.iaftbr++;
263: changed++;
264: }
265: } else {
266: /* here for conditional branches */
267: u = p->forw;
268: /* may be no intervening branches here */
269: if (u->op==p->op && (u->subop==JALL || u->subop==p->subop)){
270: j = u;
271: u = u->forw;
272: nexti( u );
273: if (u==t){
274: /* jump-around-jump -- reverse condition, go directly */
275: cannibalize( j, unbranch[(int)(p->subop)-(int)JEQ] );
276: j->op = OP_JUMP; /* cannibalize makes an OP_BRANCH*/
277: unreference( p->luse, p );
278: p = deletenode( p );
279: meter.nrevbr++;
280: changed++;
281: }
282: } else if ( (int)p->subop <= (int)JNONE && u->op==OP_DJMP && u->subop==JNONE){
283: /*
284: * jXX Y
285: * dbra dZ,W
286: * should be changed to:
287: * dbXX dZ,W
288: * jXX Y
289: * because its faster. If label Y directly follows
290: * the dbra, the jump can be deleted entirely!
291: */
292: static char dbname[5] = {'d', 'b', '\0', '\0', '\0'};
293: /*
294: * since we cannot search for the correct instruction
295: * indexed by op and subop, we need to synthesize the
296: * new name and call cannibalize.
297: * jump instruction is of form [jb]CC[ls].
298: */
299: dbname[2] = p->instr->text_i[1];
300: dbname[3] = p->instr->text_i[2];
301: cannibalize( u, dbname );
302: u->op = OP_DJMP;
303:
304: /*
305: * unhook p from the list, reinsert it later
306: */
307: u = u->forw;
308: nexti( u );
309: if (u==t){
310: unreference( p->luse, p );
311: deletenode(p);
312: meter.nskip++;
313: } else {
314: p->back->forw = p->forw;
315: p->forw->back = p->back;
316: p->forw = p->back = 0;
317: insert( p, u->back );
318: meter.ndbrarev++;
319: }
320: p = u->back;
321: changed++;
322: }
323: }
324: }
325: }
326: if (++niter > 1000) sys_error("Tangled control-flow logic");
327: }
328: return niter-1;
329: }
330:
331: zipper()
332: {
333: /*
334: * For each label: look at all the jumps to that label:
335: * for those that are unconditional:
336: * compare the instructions preceeding to the
337: * instructions preceeding the label. The unconditional
338: * jump could jump to an earlier point in the "fall through"
339: * flow.
340: */
341:
342: register NODE *l, *u, *prec, *uprec, *luse;
343: NODE *pr, *upr;
344: int refs;
345: int nchange=0, didchange;
346:
347: for (l=first.forw; l!= &first; l=l->forw){
348: if (l->op!=OP_LABEL) continue;
349: prec = l->back;
350: /* skip over stabs */
351: while (ISDIRECTIVE(prec->op) )
352: prec=prec->back;
353: if (!ISINSTRUC(prec->op))
354: continue;
355: if (prec->op==OP_CSWITCH ) continue;
356: if ((prec->op==OP_BRANCH || prec->op==OP_JUMP) && prec->subop==JALL)
357: continue;
358: pr = prec;
359: for (u = l->luse; u!=NULL; u=upr, prec=pr){
360: upr = u->lnext;
361: uprec = u->back;
362: didchange=0;
363: if (u->op!=OP_JUMP || u->subop!=JALL) continue;
364: while (ISDIRECTIVE(uprec->op) )
365: uprec=uprec->back;
366: if (uprec->op==OP_FIRST) continue;
367: while(1){
368: if (uprec->op != prec->op ){
369: if (prec->op==OP_LABEL){
370: /* skip it */
371: prec=prec->back;
372: continue;
373: }else
374: break;
375: }
376: if (prec==uprec || prec==u || uprec==upr) break;
377: if (prec->op == OP_LABEL ){
378: uprec = merge_labels( prec, uprec );
379: didchange++;
380: } else{
381: if (ISPSEUDO( prec->op )) goto endzip;
382: if (!sameins( prec, uprec) ) goto endzip;
383: if (ISBRANCH(prec->op))
384: if (prec->luse != uprec->luse)
385: goto endzip;
386: else
387: unreference( uprec->luse, uprec);
388: uprec = deletenode( uprec )->forw;
389: didchange++;
390: }
391: prec=prec->back;
392: uprec=uprec->back;
393: }
394: endzip:
395: if (didchange){
396: /*
397: * we may have done something here.
398: * uprec addresses the first NON-common node we found.
399: * put the jump after it.
400: */
401: if ( uprec->forw != u ){
402: uprec->forw->back = u;
403: u->back->forw = u->forw;
404: u->forw->back = u->back;
405: u->forw = uprec->forw;
406: uprec->forw = u;
407: u->back = uprec;
408: }
409: if (prec->op!=OP_LABEL)
410: prec = insert_label( prec->forw );
411: unreference( u->luse, u);
412: newreference( prec, u);
413: u->rlive = u->luse->rlive;
414: nchange++;
415: }
416: }
417: }
418: meter.ncomj += nchange;
419: return nchange;
420: }
421:
422: int
423: tmerge()
424: {
425: /*
426: * For each label, z, in the program, try to find commonality
427: * amoung the pieces of code that end up at that label.
428: * We are very cautious.
429: * We are looking for the forms:
430: * jra elsewhere
431: * L: X
432: * X
433: * jra z
434: * and
435: * jYY L
436: * X
437: * X
438: * jra z
439: * L:
440: * which we can combine for smaller and no-slower code.
441: */
442:
443: NODE *z;
444: register NODE *a, *b;
445: NODE *ajmp;
446: NODE *bnext, *anext, *t;
447: NODE *bforw, *aforw;
448: int nchanged = 0;
449:
450: for (z=first.forw; z!=&first; z=z->forw){
451: if (z->op != OP_LABEL) continue;
452: for (ajmp=z->luse; ajmp!=NULL; ajmp=anext){
453: anext=ajmp->lnext;
454: if (ajmp->op != OP_JUMP || ajmp->subop != JALL) continue;
455: for (b=ajmp->lnext; b!=NULL; b=bnext){
456: bnext=b->lnext;
457: if (b->op != OP_JUMP || b->subop != JALL) continue;
458: bforw = b->forw;
459: a = ajmp;
460: aforw = a->forw;
461: /*
462: * compare backwards until:
463: * -- we hit a non-equality, or
464: * -- we hit a label, or
465: * -- we hit a jump
466: */
467: for ( a=a->back, b=b->back;
468: a->op!=OP_FIRST && b->op!=OP_FIRST;
469: a=a->back, b=b->back){
470:
471: while (ISDIRECTIVE( a->op ))
472: a=a->back;
473: while (ISDIRECTIVE( b->op ))
474: b=b->back;
475: switch (a->op){
476: default: /* | */
477: if ( ISPSEUDO(a->op) || !sameins( a, b ) ) break;
478: continue;
479: case OP_JUMP:
480: case OP_LABEL:
481: case OP_CSWITCH:
482: break; /* to outer break */
483: }/* +--------------------+ */
484: /* v */
485: break; /* out of for loop */
486: }/* +---------------------+ */
487: /* v
488: * we have now compared just a little too far:
489: * either *a != *b , or they are both pseudo-ops,
490: * jumps, labels, or something else unspeakable.
491: */
492: a = a->forw;
493: b = b->forw;
494: if (a == ajmp)
495: /* no equal sequences */
496: continue;
497: /* look for preceeding label, preceeded by unconditional jump */
498: if (b->back->op == OP_LABEL && (fallthrough(b->back->back)
499: || (a->back->op == OP_JUMP && a->back->luse == aforw)) ){
500: /* want to merge into "b" -- exchange */
501: t = b; b = a; a = t;
502: t = bforw; bforw = aforw; aforw = t;
503: /* and fall through into "a" test, which will succeed */
504: }
505: if (a->back->op == OP_LABEL){
506: if ( (t=b->back)->op == OP_LABEL && !fallthrough(t->back)){
507: /* merge into "a" */
508: (void)merge_labels( a->back, t);
509: /* cream junk trailing merged-out code */
510: if (anext == bforw->back)
511: anext = NULL;
512: while ( b!=bforw ){
513: if (ISBRANCH(b->op))
514: unreference( b->luse, b );
515: b = deletenode( b )->forw;
516: }
517: nchanged++;
518: break;
519: } else if (t->op == OP_JUMP && t->luse == bforw ){
520: a = a->back; /* "a" now addresses label */
521: cond_jumparound:
522: /*
523: * delete "b" code, complement branch condition,
524: * change branch target to "a"
525: */
526: if (anext == bforw->back)
527: anext = NULL;
528: while ( b!=bforw ){
529: if (ISBRANCH(b->op))
530: unreference( b->luse, b );
531: b = deletenode( b )->forw;
532: }
533: unreference( t->luse, t);
534: newreference( a, t);
535: cannibalize( t, unbranch[(int)(t->subop)-(int)JEQ] );
536: t->op = OP_JUMP; /* not BRANCH */
537: nchanged++;
538: break;
539: } else if (!fallthrough( a->back->back) ){
540: /*
541: * we can just move label "a" to before "b"
542: * and delete the rest of the "a" code
543: */
544: while (a != aforw ){
545: if (ISBRANCH(a->op))
546: unreference( a->luse, a );
547: a = deletenode( a )->forw;
548: }
549: a->back->back->forw = a;
550: a->back->forw = b;
551: t->forw = a->back;
552: a->back = a->back->back;
553: t->forw->back = t;
554: b->back = t->forw;
555: nchanged++;
556: break;
557: }
558: /* else out of luck */
559: } else if (a->back->op == OP_JUMP && a->back->luse == aforw
560: && b->back->op == OP_JUMP && b->back->luse == bforw ){
561: /*
562: * must insert new label, then treat like one of
563: * the labelled cases above.
564: */
565: a = insert_label( a );
566: t = b->back;
567: goto cond_jumparound;
568: }
569: }
570: }
571: }
572: meter.ncomj += nchanged;
573: return nchanged;
574: }
575:
576: /*
577: * assign a sequential node number to each node.
578: * Sequence is used to detect backwards edges.
579: */
580: order_nodes()
581: {
582: register NODE *n;
583: register nodenumber;
584:
585: nodenumber = 0;
586: for (n = first.forw; n != &first; n = n->forw) {
587: n->lineno = nodenumber++;
588: }
589: }
590:
591: /*
592: * change test-at-the-top loops to test-at-the-bottom
593: * with a jump to the test at the front.
594: * In order that we not get confused and loop forever moving the test
595: * back and forth, we will recompute the node ordering every time a
596: * loop is inverted.
597: */
598: int
599: invloop()
600: {
601: int nchanged;
602: register NODE *n;
603: register nodenumber;
604: register NODE *headlabel, *taillabel;
605: NODE *jump, *newlabel;
606:
607: nchanged = 0;
608: order_nodes();
609: for (n = first.forw; n != &first; n = n->forw){
610: /*
611: * look for this configuaration:
612: * headlabel -> Lx:
613: * <some instructions ( the test )>
614: * n -> conditional jump to Ly
615: * <some more instructions ( the loop body )>
616: * jump -> jra Lx
617: * taillabel -> Ly:
618: * If there are many conditional jumps (as in the case of
619: * while( xx && yy)) then we can key off of any of the jumps,
620: * but the first one makes the most sense, since it will be
621: * executed the most frequently.
622: */
623: if (n->op == OP_JUMP && n->subop != JALL &&
624: (taillabel = n->luse)->lineno > n->lineno){
625: jump = taillabel->back;
626: if (jump->op == OP_JUMP && jump->subop == JALL &&
627: (headlabel = jump->luse)->lineno < n->lineno){
628: /*
629: * Got it: now reorganize as:
630: * Lx:
631: * jmp Lnew2
632: * Lnew1:
633: * < some instructions ( the loop body ) >
634: * Lnew2:
635: * < some more instructions ( the test ) >
636: * conditional jump to Lnew1 ( reversed conditions )
637: * Ly:
638: * in the simple cases, Lx and Ly will become unused at this
639: * point.
640: */
641: /* move test & jmp code to after the jump */
642: unreference( headlabel, jump );
643: jump->forw = headlabel->forw;
644: headlabel->forw = n->forw;
645: n->forw->back = headlabel;
646: n->forw = taillabel;
647: taillabel->back = n;
648: jump->forw->back = jump;
649: /* delete the jump, replace by a label */
650: newlabel = insert_label( deletenode( jump )->forw );
651: /* insert new jump to new label at head of loop */
652: jump = new();
653: jump->forw = headlabel->forw;
654: headlabel->forw = jump;
655: jump->back = headlabel;
656: jump->forw->back = jump;
657: cannibalize( jump, "jra" );
658: jump->op = OP_JUMP; /* rather than OP_BRANCH */
659: newreference( newlabel, jump );
660: /* add another new label after the new jump */
661: newlabel = insert_label( jump->forw );
662: /* flip condition on conditional, point it at the new label */
663: cannibalize( n, unbranch[(int)(n->subop)-(int)JEQ] );
664: n->op = OP_JUMP; /* rather than OP_BRANCH */
665: unreference( taillabel, n );
666: newreference( newlabel, n );
667: order_nodes();
668: n = taillabel->back;
669: /* if either of the old labels is superfluous, delete it */
670: if (headlabel->nref == 0 ) (void)deletenode(headlabel);
671: if (taillabel->nref == 0 ) (void)deletenode(taillabel);
672: nchanged++;
673: meter.loopiv++;
674: }
675: }
676: }
677: return nchanged;
678: }
679:
680: chase(n,tail)
681: register NODE *n, *tail;
682: {
683: register NODE *p;
684: if (n == tail)
685: return;
686: for (p = n->forw; p != n; p = p->forw) {
687: if (p == tail)
688: return;
689: }
690: printf("lost track of node %s\n", tail);
691: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.