1 #ifndef lint 2 static char sccsid[] = "@(#)c22.c 1.2 (Berkeley) 03/03/86"; 3 #endif 4 5 /* 6 * C object code improver-- third part 7 */ 8 9 #include "c2.h" 10 #include <stdio.h> 11 #include <ctype.h> 12 13 rmove() 14 { 15 register struct node *p; 16 register int r, r1; 17 18 clearreg(); 19 for (p=first.forw; p!=0; p = p->forw) { 20 if (debug) { 21 printf("Regs: "); 22 for (r=0; r<=NREG; r++) 23 if (regs[r][0]) { 24 r1=regs[r][0]; 25 printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1); 26 } 27 printf("-\n"); 28 } 29 switch (p->op) { 30 31 case CVT: 32 case MOVZ: 33 splitrand(p); 34 repladdr(p); 35 r = isreg(regs[RT1]); 36 r1 = isreg(regs[RT2]); 37 dest(regs[RT2],p->subop, 1); 38 if (r>=0 && r1>=0) { 39 p->op = MOV; p->subop = LONG; 40 p->pop = 0; 41 nchange++; 42 goto case_mov; 43 } 44 if(p->op == CVT) { 45 if (r1>=0) savereg(r1, regs[RT1], p->subop); 46 } else 47 ccloc[0] = 0; 48 break; 49 50 case MOV: 51 case_mov: 52 splitrand(p); 53 if ((r = findrand(regs[RT1],p->subop)) >= 0) { 54 if (r == isreg(regs[RT2])) 55 if(p->forw->op!=CBR) { 56 delnode(p); redunm++; nchange++; break; 57 } else { 58 p->op=TST; p->pop=0; 59 while(*p->code++ != ','); 60 redunm++; nchange++; 61 goto case_tst; 62 } 63 } 64 repladdr(p); 65 r = isreg(regs[RT1]); 66 r1 = isreg(regs[RT2]); 67 dest(regs[RT2],p->subop, 1); 68 if ((regs[ACC][0]) && equstr(regs[RT2],regs[ACC]+1)) { 69 *(short *)(regs[ACC]) = 0;} 70 71 if (r>=0) { 72 if (r1>=0) { 73 if (r == r1 && p->forw->op!=CBR) { 74 delnode(p); redunm++; nchange++; break; 75 } 76 if(regs[r][0]) 77 savereg(r1, regs[r]+1, p->subop); 78 } else savereg(r, regs[RT2], p->subop); 79 } else if (r1>=0) savereg(r1, regs[RT1], p->subop); 80 else setcon(regs[RT1], regs[RT2], p->subop); 81 break; 82 83 /* .rx,.wx or .rx,.rx,.wx */ 84 case ADD: 85 case SUB: 86 case AND: 87 case OR: 88 case XOR: 89 case MUL: 90 case DIV: 91 #ifdef EMOD 92 case EDIV: 93 case EMOD: 94 #endif EMOD 95 case SHAL: 96 case SHAR: 97 case SHL: 98 case SHR: 99 case ADDA: 100 case SUBA: 101 /* .rx,.wx */ 102 case MFPR: 103 case COM: 104 case NEG: 105 splitrand(p); 106 repladdr(p); 107 dest(lastrand,p->subop, p->op!=ADDA && p->op!=SUBA); 108 break; 109 110 /* .mx or .wx */ 111 case STF: 112 if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) { 113 delnode(p); 114 nst++; nchange++; break; 115 } 116 savereg(ACC, p->code, p->subop); 117 case CLR: 118 case INC: 119 case DEC: 120 case CVFL: 121 dest(p->code,p->subop, 1); 122 if (p->op==CLR) 123 if ((r = isreg(p->code)) >= 0) 124 savereg(r, "$0", p->subop); 125 else 126 setcon("$0", p->code, p->subop); 127 break; 128 129 /* .rx */ 130 case LDF: 131 if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) { 132 delnode(p); 133 nld++; nchange++; break; 134 } 135 savereg(ACC, p->code, p->subop); 136 goto case_tst; 137 case LNF: 138 if(equstr(p->code, regs[ACC]+1) && p->subop==regs[ACC][0]) { 139 p->op = NEGF; p->pop = 0; p->code = 0; 140 regs[ACC][0] = 0; 141 break; 142 } 143 case CVLF: 144 case LDFD: 145 case ADDF: 146 case SUBF: 147 case MULF: 148 case DIVF: 149 regs[ACC][0] = 0; 150 case TST: 151 case_tst: 152 case PUSH: 153 splitrand(p); 154 lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */ 155 repladdr(p); 156 lastrand=regs[RT1]; 157 if (p->op==TST && equstr(lastrand, ccloc+1) 158 && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop))) { 159 delnode(p); nrtst++; nchange++; break; 160 } 161 if (p->op==PUSH && p->subop!=LONG && 162 (isreg(lastrand)>=0 || *lastrand=='$')) { 163 p->subop = LONG; 164 p->pop = 0; 165 nchange++; 166 } 167 if (p->op==TST || p->op==PUSH) 168 setcc(lastrand,p->subop); 169 break; 170 171 /* .rx,.rx,.rx */ 172 case PROBE: 173 case CASE: 174 /* .rx,.rx */ 175 case MTPR: 176 case CALLS: 177 case CALLF: 178 case CMP: 179 case BIT: 180 case CMPF: 181 case CMPF2: 182 splitrand(p); 183 /* fool repladdr into doing right number of operands */ 184 lastrand=byondrd(p); 185 if (p->op==CALLF || p->op==CALLS) clearreg(); 186 else repladdr(p); 187 case TSTF: 188 ccloc[0]=0; 189 case PUSHD: 190 break; 191 192 /* acc only */ 193 case CVDF: 194 case NEGF: 195 case SINF: 196 case COSF: 197 case ATANF: 198 case LOGF: 199 case SQRTF: 200 case EXPF: 201 regs[ACC][0] = 0; 202 break; 203 204 #ifndef EMOD 205 /* .rx,.rx,.wx,.wx */ 206 case EDIV: 207 splitrand(p); 208 lastrand = regs[RT3]; 209 repladdr(p); 210 dest(regs[RT3], p->subop, 1); 211 dest(regs[RT4], p->subop, 0); 212 break; 213 #endif EMOD 214 215 /* .rx,.rx,.rx,wx */ 216 case EMUL: 217 splitrand(p); 218 lastrand = regs[RT4]; 219 repladdr(p); 220 dest(regs[RT4],QUAD, 1); /* fourth operand is a quad */ 221 break; 222 case CBR: 223 if (p->subop>=JBC) { 224 splitrand(p); 225 lastrand=regs[RT3]; /* 2 operands can be optimized */ 226 repladdr(p); 227 ccloc[0] = 0; 228 } else 229 reduncbr(p); 230 break; 231 232 case JBR: 233 redunbr(p); 234 235 default: 236 clearreg(); 237 } 238 } 239 } 240 241 jumpsw() 242 { 243 register struct node *p, *p1, *pt; 244 register int t, nj; 245 246 t = 0; 247 nj = 0; 248 for (p=first.forw; p!=0; p = p->forw) 249 p->seq = ++t; 250 for (p=first.forw; p!=0; p = p1) { 251 p1 = p->forw; 252 if (p->op == CBR && p1->op==JBR && p->ref && p1->ref 253 && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) { 254 if (p->ref==p1->ref) 255 continue; 256 p->subop = revbr[p->subop]; 257 p->pop=0; 258 pt = p1->ref; 259 p1->ref = p->ref; 260 p->ref = pt; 261 t = p1->labno; 262 p1->labno = p->labno; 263 p->labno = t; 264 #ifdef COPYCODE 265 if (p->labno == 0) { 266 pt = (struct node *)p1->code; p1->code = p->code; p->code = (char *)pt; 267 } 268 #endif 269 nrevbr++; 270 nj++; 271 } 272 } 273 return(nj); 274 } 275 276 addaob() 277 { 278 register struct node *p, *p1, *p2, *p3; 279 280 for (p = &first; (p1 = p->forw)!=0; p = p1) { 281 if (p->op==INC && p->subop==LONG) { 282 if (p1->op==LABEL && p1->refc==1 && p1->forw->op==CMP && p1->forw->subop==LONG 283 && (p2=p1->forw->forw)->op==CBR && p2->subop==JLE 284 && (p3=p2->ref->back)->op==JBR && p3->subop==0 && p3->ref==p1 285 && p3->forw->op==LABEL && p3->forw==p2->ref) { 286 /* change INC LAB: CMP to LAB: INC CMP */ 287 p->back->forw=p1; p1->back=p->back; 288 p->forw=p1->forw; p1->forw->back=p; 289 p->back=p1; p1->forw=p; 290 p1=p->forw; 291 /* adjust beginning value by 1 */ 292 p2=alloc(sizeof first); p2->op = DEC; p2->subop = LONG; 293 p2->pop=0; 294 p2->forw=p3; p2->back=p3->back; p3->back->forw=p2; 295 p3->back=p2; p2->code=p->code; p2->labno=0; 296 } 297 if (p1->op==CMP && p1->subop==LONG && 298 (p2=p1->forw)->op==CBR && p2->forw->op!=CBR) { 299 register char *cp1,*cp2; 300 splitrand(p1); if (!equstr(p->code,regs[RT1])) continue; 301 if (p2->subop==JLE || p2->subop==JLT) { 302 if (p2->subop==JLE) p->op = AOBLEQ; else p->op = AOBLSS; p->subop = 0; 303 cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */ 304 cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */ 305 p->pop=0; newcode(p); 306 p->labno = p2->labno; delnode(p2); delnode(p1); naob++; 307 } 308 } 309 } 310 } 311 } 312 313 ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */ 314 register int log; 315 if (n==0 || n&(n-1)) return(-1); log=0; 316 for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);} 317 } 318 319 equop(p1, p2) 320 register struct node *p1, *p2; 321 { 322 register char *cp1, *cp2; 323 324 if (p1->op != p2->op || p1->subop != p2->subop) 325 return(0); 326 if (p1->op>0 && p1->op<MOV) 327 return(0); 328 if (p1->op==MOVA && p1->labno!=p2->labno) return(0); 329 cp1 = p1->code; 330 cp2 = p2->code; 331 if (cp1==0 && cp2==0) 332 return(1); 333 if (cp1==0 || cp2==0) 334 return(0); 335 while (*cp1 == *cp2++) 336 if (*cp1++ == 0) 337 return(1); 338 return(0); 339 } 340 341 delnode(p) register struct node *p; { 342 p->back->forw = p->forw; 343 p->forw->back = p->back; 344 } 345 346 decref(p) 347 register struct node *p; 348 { 349 if (p && --p->refc <= 0) { 350 nrlab++; nchange++; 351 delnode(p); 352 } 353 } 354 355 struct node * 356 nonlab(ap) 357 struct node *ap; 358 { 359 register struct node *p; 360 361 p = ap; 362 while (p && p->op==LABEL) 363 p = p->forw; 364 return(p); 365 } 366 367 clearuse() { 368 register struct node **i; 369 for (i=uses+NUSE; i>uses;) *--i=0; 370 useacc = 0; 371 } 372 373 clearreg() { 374 register char **i; 375 for (i=regs+NREG+1; i>regs;){ **--i=0; **i=0; } 376 conloc[0] = 0; ccloc[0] = 0; 377 } 378 379 savereg(ai, s, type) 380 register char *s; 381 { 382 register char *p, *sp; 383 384 sp = p = regs[ai]; 385 /* if any indexing, must be parameter or local */ 386 /* indirection (as in "*-4(fp)") is ok, however */ 387 *p++ = type; 388 if (*s=='*' || *s=='$') 389 *p++ = *s++; 390 if (natural(s)) 391 strcpy(p, s); 392 else {*sp = 0; return;} 393 } 394 395 dest(s,type, ccflg) 396 register char *s; 397 { 398 register int i; 399 400 if ((i = isreg(s)) >= 0) { 401 *(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */ 402 if (DOUBLE==(type&0xF) || DOUBLE==((type>>4)&0xF) || type==QUAD) 403 *(short *)(regs[i+1]) = 0; 404 } 405 for (i=NREG; --i>=0;) 406 if (regs[i][1]=='*' && equstr(s, regs[i]+2)) 407 *(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */ 408 while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */ 409 *(short *)(regs[i]) = 0; 410 411 if (!natural(s)) {/* wild store, everything except constants vanishes */ 412 for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0; 413 conloc[0] = 0; ccloc[0] = 0; 414 } else { 415 if(ccflg)setcc(s,type); /* natural destinations set condition codes */ 416 if (equstr(s, conloc)) 417 conloc[0] = 0; 418 } 419 } 420 421 splitrand(p) struct node *p; { 422 /* separate operands at commas, set up 'regs' and 'lastrand' */ 423 register char *p1, *p2; register char **preg; 424 425 preg=regs+RT1; 426 if (p1=p->code) while (*p1) { 427 lastrand=p2= *preg++; 428 while (*p1) if (','==(*p2++= *p1++)) {--p2; break;} 429 *p2=0; 430 } 431 while (preg<(regs+RT1+5)) *(*preg++)=0; 432 } 433 434 compat(have, want) 435 register int have, want; 436 { 437 register int hsrc, hdst; 438 extern int bitsize[]; 439 440 if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */ 441 hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc; 442 if (want>=QUAD) 443 return(bitsize[hdst]==bitsize[want] && bitsize[hsrc]==bitsize[want]); 444 return(hsrc==want && hdst>=want && hdst<QUAD); 445 } 446 447 equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));} 448 449 findrand(as, type) 450 char *as; 451 { 452 register char **i; 453 for (i = regs+NREG; --i>=regs;) { 454 if (**i && equstr(*i+1, as) && compat(**i,type)) 455 return(i-regs); 456 } 457 return(-1); 458 } 459 460 isreg(s) 461 register char *s; 462 { 463 if (*s++!='r' || !isdigit(*s++)) return(-1); 464 if (*s==0) return(*--s-'0'); 465 if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0'); 466 return(-1); 467 } 468 469 /* 470 check() 471 { 472 register struct node *p, *lp; 473 474 lp = &first; 475 for (p=first.forw; p!=0; p = p->forw) { 476 if (p->back != lp) 477 abort(-1); 478 lp = p; 479 } 480 } 481 */ 482 483 newcode(p) struct node *p; { 484 register char *p1,*p2,**preg; 485 486 preg=regs+RT1; p2=line; 487 while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';} 488 *--p2=0; 489 p->code=copy(line); 490 } 491 492 repladdr(p) 493 struct node *p; 494 { 495 register int r; 496 register char *p1; 497 register char **preg; 498 register int nrepl; 499 500 preg=regs+RT1; nrepl=0; 501 while (lastrand!=(p1= *preg++)) 502 if (0<=(r=findrand(p1,p->subop))) { 503 *p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0; 504 nchange++; nrepl++; nsaddr++; 505 } 506 if (nrepl) newcode(p); 507 } 508 509 /* conditional branches which are never/always taken */ 510 reduncbr(p) 511 register struct node *p; 512 { 513 register struct node *p1; 514 register char *ap1, *ap2; 515 516 p1 = p->back; 517 if (p1->op==CMP) { 518 splitrand(p1); 519 ap1 = findcon(regs[RT1], p1->subop); 520 ap2 = findcon(regs[RT2], p1->subop); 521 } else { 522 if(!ccloc[0]) 523 return; 524 ap1 = findcon(ccloc+1, ccloc[0]); 525 ap2 = "$0"; 526 } 527 switch (compare(p->subop, ap1, ap2)) { 528 case 0: /* branch never taken */ 529 delnode(p); 530 nredunj++; 531 nchange++; 532 decref(p->ref); 533 if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) { 534 delnode(p1); 535 nrtst++; 536 } 537 break; 538 case 1: /* branch always taken */ 539 p->op = JBR; 540 p->subop = 0; 541 p->pop = 0; 542 nchange++; 543 if(nonlab(p->ref)->op!=CBR && (p1->op==TST || p1->op==CMP)) { 544 delnode(p1); 545 nrtst++; 546 } 547 } 548 } 549 550 /* a jump to a redundant compare (start of a 'for') */ 551 redunbr(p) 552 register struct node *p; 553 { 554 register struct node *p1; 555 register char *ap1, *ap2; 556 557 if ((p1 = p->ref) == 0) 558 return; 559 p1 = nonlab(p1); 560 if (p1->op==TST || p1->op==CMP) 561 splitrand(p1); 562 else 563 return; 564 if (p1->forw->op==CBR) { 565 ap1 = findcon(regs[RT1], p1->subop); 566 if (p1->op==TST) 567 ap2 = "$0"; 568 else 569 ap2 = findcon(regs[RT2], p1->subop); 570 p1 = p1->forw; 571 if (compare(p1->subop, ap1, ap2) > 0) { 572 nredunj++; 573 nchange++; 574 decref(p->ref); 575 p->ref = p1->ref; 576 p->labno = p1->labno; 577 #ifdef COPYCODE 578 if (p->labno == 0) 579 p->code = p1->code; 580 if (p->ref) 581 #endif 582 p->ref->refc++; 583 } 584 } else if (p1->op==TST && equstr(regs[RT1],ccloc+1) && 585 equtype(ccloc[0],p1->subop)) { 586 p1=insertl(p1->forw); decref(p->ref); p->ref=p1; 587 nrtst++; nchange++; 588 } 589 } 590 591 char * 592 findcon(p, type) 593 register char *p; 594 { 595 register int r; 596 597 if (*p=='$') 598 return(p); 599 if ((r = isreg(p)) >= 0 && compat(regs[r][0],type)) 600 return(regs[r]+1); 601 if (equstr(p, conloc) && conval[0] == type) 602 return(conval+1); 603 return(p); 604 } 605 606 /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */ 607 compare(op, acp1, acp2) 608 char *acp1, *acp2; 609 { 610 register char *cp1, *cp2; 611 register int n1, n2, sign; 612 613 cp1 = acp1; 614 cp2 = acp2; 615 if (*cp1++ != '$' || *cp2++ != '$') 616 return(-1); 617 n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;} 618 while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';} 619 n1 *= sign; 620 n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;} 621 while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';} 622 n2 *= sign; 623 if (*cp1=='+') 624 cp1++; 625 if (*cp2=='+') 626 cp2++; 627 do { 628 if (*cp1++ != *cp2) 629 return(-1); 630 } while (*cp2++); 631 switch(op) { 632 633 case JEQ: 634 return(n1 == n2); 635 case JNE: 636 return(n1 != n2); 637 case JLE: 638 return(n1 <= n2); 639 case JGE: 640 return(n1 >= n2); 641 case JLT: 642 return(n1 < n2); 643 case JGT: 644 return(n1 > n2); 645 case JLO: 646 return((unsigned)n1 < (unsigned)n2); 647 case JHI: 648 return((unsigned)n1 > (unsigned)n2); 649 case JLOS: 650 return((unsigned)n1 <= (unsigned)n2); 651 case JHIS: 652 return((unsigned)n1 >= (unsigned)n2); 653 } 654 return(-1); 655 } 656 657 setcon(cv, cl, type) 658 register char *cv, *cl; 659 { 660 register char *p; 661 662 if (*cv != '$') 663 return; 664 if (!natural(cl)) 665 return; 666 p = conloc; 667 while (*p++ = *cl++); 668 p = conval; 669 *p++ = type; 670 while (*p++ = *cv++); 671 } 672 673 setcc(ap,type) 674 char *ap; 675 { 676 register char *p, *p1; 677 678 p = ap; 679 if (!natural(p)) { 680 ccloc[0] = 0; 681 return; 682 } 683 p1 = ccloc; 684 *p1++ = type; 685 while (*p1++ = *p++); 686 } 687 688 indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */ 689 while (*p) if (*p++=='[') return(1); 690 return(0); 691 } 692 693 natural(p) 694 register char *p; 695 {/* 1->simple local, parameter, global, or register; 0->otherwise */ 696 697 if (*p=='*' || *p=='(' || *p=='$') 698 return(0); 699 while (*p++); 700 p--; 701 if (*--p==']' || *p==')' && 702 !(*(p-2)=='f' || fortflg && (*--p=='1' || *p=='2') && *--p=='1')) 703 return(0); 704 return(1); 705 } 706 707 /* 708 ** Tell if an argument is most likely static. 709 */ 710 711 isstatic(cp) 712 register char *cp; 713 { 714 if (*cp == '_' || *cp == 'L') 715 return (1); 716 return (0); 717 } 718