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