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