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