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