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