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