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