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