|
|
1.1 root 1: #
2: static char sccsid[] = "@(#)c20.c 4.5 7/5/81";
3: /* char C20[] = {"@(#)c20.c 1.35 80/08/26 14:13:40"}; /* sccs ident */
4: /*
5: * C object code improver
6: */
7:
8: #include "c2.h"
9: #include <stdio.h>
10: #include <ctype.h>
11:
12: char _sibuf[BUFSIZ], _sobuf[BUFSIZ];
13: int ioflag;
14: long isn = 2000000;
15: struct optab *oplook();
16: struct optab *getline();
17: long lgensym[10] =
18: {100000L,200000L,300000L,400000L,500000L,600000L,700000L,800000L,900000L,1000000L};
19:
20: struct node *
21: alloc(an)
22: {
23: register int n;
24: register char *p;
25:
26: n = an;
27: n+=sizeof(char *)-1;
28: n &= ~(sizeof(char *)-1);
29: if (lasta+n >= lastr) {
30: if (sbrk(2000) == -1) {
31: fprintf(stderr, "Optimizer: out of space\n");
32: exit(1);
33: }
34: lastr += 2000;
35: }
36: p = lasta;
37: lasta += n;
38: return(p);
39: }
40:
41: main(argc, argv)
42: char **argv;
43: {
44: register int niter, maxiter, isend;
45: int nflag,infound;
46:
47: nflag = 0; infound=0; argc--; argv++;
48: while (argc>0) {/* get flags */
49: if (**argv=='+') debug++;
50: else if (**argv=='-') {
51: if ((*argv)[1]=='i') ioflag++; else nflag++;
52: } else if (infound==0) {
53: if (freopen(*argv, "r", stdin) ==NULL) {
54: fprintf(stderr,"C2: can't find %s\n", *argv);
55: exit(1);
56: }
57: setbuf(stdin,_sibuf); ++infound;
58: } else if (freopen(*argv, "w", stdout) ==NULL) {
59: fprintf(stderr,"C2: can't create %s\n", *argv);
60: exit(1);
61: }
62: setbuf(stdout,_sobuf);
63: argc--; argv++;
64: }
65: lasta = lastr = sbrk(2);
66: opsetup();
67: lasta = firstr = lastr = alloc(0);
68: maxiter = 0;
69: do {
70: isend = input();
71: niter = 0;
72: bmove();
73: do {
74: refcount();
75: do {
76: iterate();
77: clearreg();
78: niter++;
79: } while (nchange);
80: comjump();
81: rmove();
82: } while (nchange || jumpsw());
83: addsob();
84: output();
85: if (niter > maxiter)
86: maxiter = niter;
87: lasta = firstr;
88: } while (isend);
89: if (nflag) {
90: fprintf(stderr,"%d iterations\n", maxiter);
91: fprintf(stderr,"%d jumps to jumps\n", nbrbr);
92: fprintf(stderr,"%d inst. after jumps\n", iaftbr);
93: fprintf(stderr,"%d jumps to .+1\n", njp1);
94: fprintf(stderr,"%d redundant labels\n", nrlab);
95: fprintf(stderr,"%d cross-jumps\n", nxjump);
96: fprintf(stderr,"%d code motions\n", ncmot);
97: fprintf(stderr,"%d branches reversed\n", nrevbr);
98: fprintf(stderr,"%d redundant moves\n", redunm);
99: fprintf(stderr,"%d simplified addresses\n", nsaddr);
100: fprintf(stderr,"%d loops inverted\n", loopiv);
101: fprintf(stderr,"%d redundant jumps\n", nredunj);
102: fprintf(stderr,"%d common seqs before jmp's\n", ncomj);
103: fprintf(stderr,"%d skips over jumps\n", nskip);
104: fprintf(stderr,"%d sob's added\n", nsob);
105: fprintf(stderr,"%d redundant tst's\n", nrtst);
106: fprintf(stderr,"%d jump on bit\n", nbj);
107: fprintf(stderr,"%d field operations\n", nfield);
108: fprintf(stderr,"%dK core\n", ((unsigned)lastr+01777) >> 10);
109: }
110: putc('\n',stdout);
111: fflush(stdout); exit(0);
112: }
113:
114: input()
115: {
116: register struct node *p, *lastp;
117: struct optab *op; register char *cp1;
118: static struct optab F77JSW = {".long", T(JSW,1)};
119:
120: lastp = &first;
121: for (;;) {
122: top:
123: op = getline();
124: if (debug && op==0) fprintf(stderr,"? %s\n",line);
125: switch (op->opcode&0377) {
126:
127: case LABEL:
128: p = alloc(sizeof first);
129: if (isdigit(line[0]) && (p->labno=locdef(line)) ||
130: (line[0] == 'L') && (p->labno=getnum(line+1))) {
131: p->combop = LABEL;
132: if (p->labno<100000L && isn<=p->labno) isn=1+p->labno;
133: p->code = 0;
134: } else {
135: p->combop = DLABEL;
136: p->labno = 0;
137: p->code = copy(line);
138: }
139: break;
140:
141: case LGEN:
142: if (*curlp!='L' && !locuse(curlp)) goto std;
143: op= &F77JSW;
144: case JBR:
145: if (op->opcode==T(JBR,RET) || op->opcode==T(JBR,RSB)) goto std;
146: case CBR:
147: case JMP:
148: case JSW:
149: case SOBGEQ: case SOBGTR: case AOBLEQ: case AOBLSS: case ACB:
150: p = alloc(sizeof first);
151: p->combop = op->opcode; p->code=0; cp1=curlp;
152: if ((!isdigit(*cp1) || 0==(p->labno=locuse(cp1))) &&
153: (*cp1!='L' || 0==(p->labno = getnum(cp1+1)))) {/* jbs, etc.? */
154: while (*cp1++); while (*--cp1!=',' && cp1!=curlp);
155: if (cp1==curlp ||
156: (!isdigit(*++cp1) || 0==(p->labno=locuse(cp1))) &&
157: (*cp1!='L' || 0==(p->labno=getnum(cp1+1))))
158: p->labno = 0;
159: else *--cp1=0;
160: p->code = copy(curlp);
161: }
162: if (isn<=p->labno) isn=1+p->labno;
163: break;
164:
165: case MOVA:
166: p=alloc(sizeof first);
167: p->combop=op->opcode; p->code=0; cp1=curlp+1;
168: if (cp1[-1]=='L' || isdigit(cp1[-1])) {
169: while (*cp1++!=','); *--cp1=0;
170: if (0!=(p->labno=locuse(curlp)) ||
171: 0!=(p->labno=getnum(curlp+1))) p->code=copy(cp1+1);
172: else {*cp1=','; p->code=copy(curlp);}
173: } else {p->code=copy(--cp1); p->labno=0;}
174: break;
175:
176: case SET:
177: case COMM:
178: case LCOMM:
179: printf("%s\n",line); goto top;
180:
181: case BSS:
182: case DATA:
183: for (;;) {
184: printf("%s%c",line,(op->opcode==LABEL ? ':' : '\n'));
185: if (op->opcode==TEXT) goto top;
186: if (END==(op=getline())->opcode) {/* dangling .data is bad for you */
187: printf(".text\n");
188: break;
189: }
190: }
191:
192: std:
193: default:
194: p = alloc(sizeof first);
195: p->combop = op->opcode;
196: p->labno = 0;
197: p->code = copy(curlp);
198: break;
199:
200: }
201: p->forw = 0;
202: p->back = lastp;
203: p->pop = op;
204: lastp->forw = p;
205: lastp = p;
206: p->ref = 0;
207: if (p->op==CASE) {
208: char *lp; int ncase;
209: lp=curlp; while (*lp++); while (*--lp!='$'); ncase=getnum(lp+1);
210: if (LABEL!=(getline())->opcode) abort(-2);
211: do {
212: if (WGEN!=(getline())->opcode) abort(-3);
213: p = alloc(sizeof first); p->combop = JSW; p->code = 0;
214: lp=curlp; while(*lp++!='-'); *--lp=0; p->labno=getnum(curlp+1);
215: if (isn<=p->labno) isn=1+p->labno;
216: p->forw = 0; p->back = lastp; lastp->forw = p; lastp = p;
217: p->ref = 0; p->pop=0;
218: } while (--ncase>=0);
219: }
220: if (op->opcode==EROU)
221: return(1);
222: if (op->opcode==END)
223: return(0);
224: }
225: }
226:
227: struct optab *
228: getline()
229: {
230: register char *lp;
231: register c;
232: static struct optab OPLABEL={"",LABEL};
233: static struct optab OPEND={"",END};
234:
235: lp = line;
236: while (EOF!=(c=getchar()) && isspace(c));
237: while (EOF!=c) {
238: if (c==':') {
239: *lp++ = 0;
240: return(&OPLABEL);
241: }
242: if (c=='\n') {
243: *lp++ = 0;
244: return(oplook());
245: }
246: *lp++ = c;
247: c = getchar();
248: }
249: *lp++ = 0;
250: return(&OPEND);
251: }
252:
253: long
254: getnum(p)
255: register char *p;
256: {
257: register c; int neg; register long n;
258:
259: n = 0; neg=0; if (*p=='-') {++neg; ++p;}
260: while (isdigit(c = *p++)) {
261: c -= '0'; n *= 10; if (neg) n -= c; else n += c;
262: }
263: if (*--p != 0)
264: return(0);
265: return(n);
266: }
267:
268: locuse(p)
269: register char *p;
270: {
271: register c; int neg; register long n;
272:
273: if (!isdigit(p[0]) || p[1] != 'f' && p[1] != 'b' || p[2]) return(0);
274: return (lgensym[p[0] - '0'] - (p[1] == 'b'));
275: }
276:
277: locdef(p)
278: register char *p;
279: {
280:
281: if (!isdigit(p[0]) || p[1]) return(0);
282: return (lgensym[p[0] - '0']++);
283: }
284:
285: output()
286: {
287: register struct node *t;
288: int casebas;
289:
290: t = &first;
291: while (t = t->forw) switch (t->op) {
292:
293: case END:
294: fflush(stdout);
295: return;
296:
297: case LABEL:
298: printf("L%d:", t->labno);
299: continue;
300:
301: case DLABEL:
302: printf("%s:", t->code);
303: continue;
304:
305: case CASE:
306: casebas=0;
307:
308: default: std:
309: if (t->pop==0) {/* must find it */
310: register struct optab *p;
311: for (p=optab; p->opstring[0]; ++p)
312: if (p->opcode==t->combop) {t->pop=p; break;}
313: }
314: printf("%s", t->pop->opstring);
315: if (t->code) printf("\t%s", t->code);
316: if (t->labno!=0) printf("%cL%d\n",
317: (t->code ? ',' : '\t'),
318: t->labno);
319: else printf("\n");
320: continue;
321:
322: case MOVA:
323: if (t->labno==0) goto std;
324: printf("mova%c\tL%d,%s\n","bwlq"[t->subop-BYTE],t->labno,t->code);
325: continue;
326:
327: case JSW:
328: if (t->subop!=0) {/* F77JSW */
329: printf(".long\tL%d\n",t->labno); continue;
330: }
331: if (casebas==0) printf("L%d:\n",casebas=isn++);
332: printf(".word L%d-L%d\n", t->labno, casebas);
333: continue;
334:
335: case MOV:
336: if (t->forw) if(t->forw->op == CBR) goto std;
337: if (*t->code == '$') goto std;
338: if (t->subop == FLOAT)
339: {
340: printf("movl\t%s\n", t->code);
341: continue;
342: }
343: if (t->subop == DOUBLE)
344: {
345: printf("movq\t%s\n", t->code);
346: continue;
347: }
348: goto std;
349: }
350: }
351:
352: char *
353: copy(ap)
354: char *ap;
355: {
356: register char *p, *np;
357: char *onp;
358: register n;
359: int na;
360:
361: na = nargs();
362: p = ap;
363: n = 0;
364: if (*p==0)
365: return(0);
366: do
367: n++;
368: while (*p++);
369: if (na>1) {
370: p = (&ap)[1];
371: while (*p++)
372: n++;
373: }
374: onp = np = alloc(n);
375: p = ap;
376: while (*np++ = *p++);
377: if (na>1) {
378: p = (&ap)[1];
379: np--;
380: while (*np++ = *p++);
381: }
382: return(onp);
383: }
384:
385: #define OPHS 560
386: struct optab *ophash[OPHS];
387:
388: opsetup()
389: {
390: register struct optab *optp, **ophp;
391: register int i,t;
392:
393: for(i=NREG+5;--i>=0;) regs[i]=alloc(C2_ASIZE);
394: for (optp = optab; optp->opstring[0]; optp++) {
395: t=7; i=0; while (--t>=0) i+= i+optp->opstring[t];
396: ophp = &ophash[i % OPHS];
397: while (*ophp++) {
398: /* fprintf(stderr,"\ncollision: %d %s %s",
399: /* ophp-1-ophash,optp->opstring,(*(ophp-1))->opstring);
400: */
401: if (ophp > &ophash[OPHS])
402: ophp = ophash;
403: }
404: *--ophp = optp;
405: }
406: }
407:
408: struct optab *
409: oplook()
410: {
411: register struct optab *optp,**ophp;
412: register char *p,*p2;
413: register int t;
414: char tempop[20];
415: static struct optab OPNULL={"",0};
416:
417: for (p=line, p2=tempop; *p && !isspace(*p); *p2++= *p++); *p2=0; p2=p;
418: while (isspace(*p2)) ++p2; curlp=p2;
419: t=0; while(--p>=line) t += t+*p; ophp = &ophash[t % OPHS];
420: while (optp = *ophp) {
421: if (equstr(tempop,optp->opstring)) return(optp);
422: if ((++ophp) >= &ophash[OPHS]) ophp = ophash;
423: }
424: curlp = line;
425: return(&OPNULL);
426: }
427:
428: refcount()
429: {
430: register struct node *p, *lp;
431: struct node *labhash[LABHS];
432: register struct node **hp;
433:
434: for (hp = labhash; hp < &labhash[LABHS];)
435: *hp++ = 0;
436: for (p = first.forw; p!=0; p = p->forw)
437: if (p->op==LABEL) {
438: labhash[p->labno % LABHS] = p;
439: p->refc = 0;
440: }
441: for (p = first.forw; p!=0; p = p->forw) {
442: if (p->combop==JBR || p->op==CBR || p->op==JSW || p->op==JMP
443: || p->op==SOBGEQ || p->op==SOBGTR || p->op==AOBLEQ || p->op==AOBLSS
444: || p->op==ACB || (p->op==MOVA && p->labno!=0)) {
445: p->ref = 0;
446: lp = labhash[p->labno % LABHS];
447: if (lp==0 || p->labno!=lp->labno)
448: for (lp = first.forw; lp!=0; lp = lp->forw) {
449: if (lp->op==LABEL && p->labno==lp->labno)
450: break;
451: }
452: if (lp) {
453: hp = nonlab(lp)->back;
454: if (hp!=lp) {
455: p->labno = hp->labno;
456: lp = hp;
457: }
458: p->ref = lp;
459: lp->refc++;
460: }
461: }
462: }
463: for (p = first.forw; p!=0; p = p->forw)
464: if (p->op==LABEL && p->refc==0
465: && (lp = nonlab(p))->op && lp->op!=JSW)
466: decref(p);
467: }
468:
469: iterate()
470: {
471: register struct node *p, *rp, *p1;
472:
473: nchange = 0;
474: for (p = first.forw; p!=0; p = p->forw) {
475: if ((p->op==JBR||p->op==CBR||p->op==JSW) && p->ref) {
476: rp = nonlab(p->ref);
477: if (rp->op==JBR && rp->labno && p->labno!=rp->labno) {
478: nbrbr++;
479: p->labno = rp->labno;
480: decref(p->ref);
481: rp->ref->refc++;
482: p->ref = rp->ref;
483: nchange++;
484: }
485: }
486: #ifndef COPYCODE
487: if (p->op==CBR && (p1 = p->forw)->combop==JBR) {/* combop: RET problems */
488: #else
489: if (p->op==CBR && (p1 = p->forw)->combop==JBR &&
490: p->ref) {/* combop: RET problems */
491: #endif
492: rp = p->ref;
493: do
494: rp = rp->back;
495: while (rp->op==LABEL);
496: if (rp==p1) {
497: decref(p->ref);
498: p->ref = p1->ref;
499: p->labno = p1->labno;
500: #ifdef COPYCODE
501: if (p->labno == 0)
502: p->code = p1->code;
503: #endif
504: p1->forw->back = p;
505: p->forw = p1->forw;
506: p->subop = revbr[p->subop];
507: p->pop=0;
508: nchange++;
509: nskip++;
510: }
511: }
512: if (p->op==JBR || p->op==JMP) {
513: while (p->forw && p->forw->op!=LABEL && p->forw->op!=DLABEL
514: && p->forw->op!=EROU && p->forw->op!=END
515: && p->forw->op!=ALIGN
516: && p->forw->op!=0 && p->forw->op!=DATA) {
517: nchange++;
518: iaftbr++;
519: if (p->forw->ref)
520: decref(p->forw->ref);
521: p->forw = p->forw->forw;
522: p->forw->back = p;
523: }
524: rp = p->forw;
525: while (rp && rp->op==LABEL) {
526: if (p->ref == rp) {
527: p->back->forw = p->forw;
528: p->forw->back = p->back;
529: p = p->back;
530: decref(rp);
531: nchange++;
532: njp1++;
533: break;
534: }
535: rp = rp->forw;
536: }
537: xjump(p);
538: p = codemove(p);
539: }
540: }
541: }
542:
543: xjump(p1)
544: register struct node *p1;
545: {
546: register struct node *p2, *p3;
547: int nxj;
548:
549: nxj = 0;
550: if ((p2 = p1->ref)==0)
551: return(0);
552: for (;;) {
553: while ((p1 = p1->back) && p1->op==LABEL);
554: while ((p2 = p2->back) && p2->op==LABEL);
555: if (!equop(p1, p2) || p1==p2)
556: return(nxj);
557: p3 = insertl(p2);
558: p1->combop = JBR;
559: p1->pop=0;
560: p1->ref = p3;
561: p1->labno = p3->labno;
562: p1->code = 0;
563: nxj++;
564: nxjump++;
565: nchange++;
566: }
567: }
568:
569: struct node *
570: insertl(op)
571: register struct node *op;
572: {
573: register struct node *lp;
574:
575: if (op->op == LABEL) {
576: op->refc++;
577: return(op);
578: }
579: if (op->back->op == LABEL) {
580: op = op->back;
581: op->refc++;
582: return(op);
583: }
584: lp = alloc(sizeof first);
585: lp->combop = LABEL;
586: lp->labno = isn++;
587: lp->ref = 0;
588: lp->code = 0;
589: lp->refc = 1;
590: lp->back = op->back;
591: lp->forw = op;
592: op->back->forw = lp;
593: op->back = lp;
594: return(lp);
595: }
596:
597: struct node *
598: codemove(ap)
599: struct node *ap;
600: {
601: register struct node *p1, *p2, *p3;
602: struct node *t, *tl;
603: int n;
604:
605: p1 = ap;
606: /* last clause to avoid infinite loop on partial compiler droppings:
607: L183: jbr L179
608: L191: jbr L179
609: casel r0,$0,$1
610: L193: .word L183-L193
611: .word L191-L193
612: L179: ret
613: */
614: if (p1->op!=JBR || (p2 = p1->ref)==0 || p2==p1->forw)
615: return(p1);
616: while (p2->op == LABEL)
617: if ((p2 = p2->back) == 0)
618: return(p1);
619: if (p2->op!=JBR && p2->op!=JMP)
620: goto ivloop;
621: p2 = p2->forw;
622: p3 = p1->ref;
623: while (p3) {
624: if (p3->op==JBR || p3->op==JMP) {
625: if (p1==p3)
626: return(p1);
627: ncmot++;
628: nchange++;
629: p1->back->forw = p2;
630: p1->forw->back = p3;
631: p2->back->forw = p3->forw;
632: p3->forw->back = p2->back;
633: p2->back = p1->back;
634: p3->forw = p1->forw;
635: decref(p1->ref);
636: return(p2);
637: } else
638: p3 = p3->forw;
639: }
640: return(p1);
641: ivloop:
642: if (p1->forw->op!=LABEL)
643: return(p1);
644: p3 = p2 = p2->forw;
645: n = 16;
646: do {
647: if ((p3 = p3->forw) == 0 || p3==p1 || --n==0)
648: return(p1);
649: } while (p3->op!=CBR || p3->labno!=p1->forw->labno);
650: do
651: if ((p1 = p1->back) == 0)
652: return(ap);
653: while (p1!=p3);
654: p1 = ap;
655: tl = insertl(p1);
656: p3->subop = revbr[p3->subop];
657: p3->pop=0;
658: decref(p3->ref);
659: p2->back->forw = p1;
660: p3->forw->back = p1;
661: p1->back->forw = p2;
662: p1->forw->back = p3;
663: t = p1->back;
664: p1->back = p2->back;
665: p2->back = t;
666: t = p1->forw;
667: p1->forw = p3->forw;
668: p3->forw = t;
669: p2 = insertl(p1->forw);
670: p3->labno = p2->labno;
671: #ifdef COPYCODE
672: if (p3->labno == 0)
673: p3->code = p2->code;
674: #endif
675: p3->ref = p2;
676: decref(tl);
677: if (tl->refc<=0)
678: nrlab--;
679: loopiv++;
680: nchange++;
681: return(p3);
682: }
683:
684: comjump()
685: {
686: register struct node *p1, *p2, *p3;
687:
688: for (p1 = first.forw; p1!=0; p1 = p1->forw)
689: if (p1->op==JBR && ((p2 = p1->ref) && p2->refc > 1
690: || p1->subop==RET || p1->subop==RSB))
691: for (p3 = p1->forw; p3!=0; p3 = p3->forw)
692: if (p3->op==JBR && p3->ref == p2)
693: backjmp(p1, p3);
694: }
695:
696: backjmp(ap1, ap2)
697: struct node *ap1, *ap2;
698: {
699: register struct node *p1, *p2, *p3;
700:
701: p1 = ap1;
702: p2 = ap2;
703: for(;;) {
704: while ((p1 = p1->back) && p1->op==LABEL);
705: p2 = p2->back;
706: if (equop(p1, p2)) {
707: p3 = insertl(p1);
708: p2->back->forw = p2->forw;
709: p2->forw->back = p2->back;
710: p2 = p2->forw;
711: decref(p2->ref);
712: p2->combop = JBR; /* to handle RET */
713: p2->pop=0;
714: p2->labno = p3->labno;
715: #ifdef COPYCODE
716: p2->code = 0;
717: #endif
718: p2->ref = p3;
719: nchange++;
720: ncomj++;
721: } else
722: return;
723: }
724: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.