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