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