1: /* @(#)c21.c 2.3 SCCS id keyword */ 2: # 3: /* 4: * C object code improver-- second part 5: */ 6: 7: #include "c2.h" 8: 9: rmove() 10: { 11: register struct node *p; 12: register int r; 13: register r1, flt; 14: 15: for (p=first.forw; p!=0; p = p->forw) { 16: flt = 0; 17: switch (p->op) { 18: 19: case MOVF: 20: case MOVFO: 21: case MOVOF: 22: flt = NREG; 23: 24: case MOV: 25: if (p->subop==BYTE) 26: goto dble; 27: dualop(p); 28: if ((r = findrand(regs[RT1], flt)) >= 0) { 29: if (r == flt+isreg(regs[RT2]) && p->forw->op!=CBR 30: && p->forw->op!=SXT 31: && p->forw->op!=CFCC) { 32: p->forw->back = p->back; 33: p->back->forw = p->forw; 34: redunm++; 35: continue; 36: } 37: } 38: if (equstr(regs[RT1], "$0")) { 39: p->op = CLR; 40: strcpy(regs[RT1], regs[RT2]); 41: regs[RT2][0] = 0; 42: p->code = copy(1, regs[RT1]); 43: goto sngl; 44: } 45: repladdr(p, 0, flt); 46: r = isreg(regs[RT1]); 47: r1 = isreg(regs[RT2]); 48: dest(regs[RT2], flt); 49: if (r >= 0) 50: if (r1 >= 0) 51: savereg(r1+flt, regs[r+flt]); 52: else 53: savereg(r+flt, regs[RT2]); 54: else 55: if (r1 >= 0) 56: savereg(r1+flt, regs[RT1]); 57: else 58: setcon(regs[RT1], regs[RT2]); 59: source(regs[RT1]); 60: setcc(regs[RT2]); 61: continue; 62: 63: case ADDF: 64: case SUBF: 65: case DIVF: 66: case MULF: 67: flt = NREG; 68: goto dble; 69: 70: case ADD: 71: case SUB: 72: case BIC: 73: case BIS: 74: case MUL: 75: case DIV: 76: case ASH: 77: dble: 78: dualop(p); 79: if (p->op==BIC && (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777"))) { 80: p->op = CLR; 81: strcpy(regs[RT1], regs[RT2]); 82: regs[RT2][0] = 0; 83: p->code = copy(1, regs[RT1]); 84: goto sngl; 85: } 86: if ((p->op==BIC || p->op==BIS) && equstr(regs[RT1], "$0")) { 87: if (p->forw->op!=CBR) { 88: p->back->forw = p->forw; 89: p->forw->back = p->back; 90: continue; 91: } 92: } 93: repladdr(p, 0, flt); 94: source(regs[RT1]); 95: dest(regs[RT2], flt); 96: if (p->op==DIV && (r = isreg(regs[RT2])>=0)) 97: regs[r+1][0] = 0; 98: ccloc[0] = 0; 99: continue; 100: 101: case CLRF: 102: case NEGF: 103: flt = NREG; 104: 105: case CLR: 106: case COM: 107: case INC: 108: case DEC: 109: case NEG: 110: case ASR: 111: case ASL: 112: case SXT: 113: singop(p); 114: sngl: 115: dest(regs[RT1], flt); 116: if (p->op==CLR && flt==0) 117: if ((r = isreg(regs[RT1])) >= 0) 118: savereg(r, "$0"); 119: else 120: setcon("$0", regs[RT1]); 121: ccloc[0] = 0; 122: continue; 123: 124: case TSTF: 125: flt = NREG; 126: 127: case TST: 128: singop(p); 129: repladdr(p, 0, flt); 130: source(regs[RT1]); 131: if (equstr(regs[RT1], ccloc)) { 132: p->back->forw = p->forw; 133: p->forw->back = p->back; 134: p = p->back; 135: nrtst++; 136: nchange++; 137: } 138: continue; 139: 140: case CMPF: 141: flt = NREG; 142: 143: case CMP: 144: case BIT: 145: dualop(p); 146: source(regs[RT1]); 147: source(regs[RT2]); 148: if(p->op==BIT) { 149: if (equstr(regs[RT1], "$-1") || equstr(regs[RT1], "$177777")) { 150: p->op = TST; 151: strcpy(regs[RT1], regs[RT2]); 152: regs[RT2][0] = 0; 153: p->code = copy(1, regs[RT1]); 154: nchange++; 155: nsaddr++; 156: } else if (equstr(regs[RT2], "$-1") || equstr(regs[RT2], "$177777")) { 157: p->op = TST; 158: regs[RT2][0] = 0; 159: p->code = copy(1, regs[RT1]); 160: nchange++; 161: nsaddr++; 162: } 163: if (equstr(regs[RT1], "$0")) { 164: p->op = TST; 165: regs[RT2][0] = 0; 166: p->code = copy(1, regs[RT1]); 167: nchange++; 168: nsaddr++; 169: } else if (equstr(regs[RT2], "$0")) { 170: p->op = TST; 171: strcpy(regs[RT1], regs[RT2]); 172: regs[RT2][0] = 0; 173: p->code = copy(1, regs[RT1]); 174: nchange++; 175: nsaddr++; 176: } 177: } 178: repladdr(p, 1, flt); 179: ccloc[0] = 0; 180: continue; 181: 182: case CBR: 183: if (p->back->op==TST || p->back->op==CMP) { 184: if (p->back->op==TST) { 185: singop(p->back); 186: savereg(RT2, "$0"); 187: } else 188: dualop(p->back); 189: r = compare(p->subop, findcon(RT1), findcon(RT2)); 190: if (r==0) { 191: /* 192: * The following is a correction suggested in: 193: * Addenda to Unix 7th ed, July 30, 1979 194: * note: dmr should be a little less careless. 195: */ 196: #ifdef BUGGYC 197: p->back->back->forw = p->forw; 198: p->forw->back = p->back->back; 199: #else 200: if (p->forw->op==CBR 201: || p->forw->op==SXT 202: || p->forw->op==CFCC) { 203: p->back->forw = p->forw; 204: p->forw->back = p->back; 205: } else { 206: p->back->back->forw = p->forw; 207: p->forw->back = p->back->back; 208: } 209: #endif 210: 211: /* 212: The old code deleted a test or compare with constant operands 213: and a following conditional branch that would always fail. 214: The new code only deletes the branch (leaves the test) 215: if the combination is followed by another instruction that 216: needs the condition codes. The test and second branch are liable 217: to be deleted later. 218: */ 219: decref(p->ref); 220: p = p->back->back; 221: nchange++; 222: } else if (r>0) { 223: p->op = JBR; 224: p->subop = 0; 225: p->back->back->forw = p; 226: p->back = p->back->back; 227: p = p->back; 228: nchange++; 229: } 230: } 231: case CFCC: 232: ccloc[0] = 0; 233: continue; 234: 235: case JBR: 236: redunbr(p); 237: 238: default: 239: clearreg(); 240: } 241: } 242: } 243: 244: jumpsw() 245: { 246: register struct node *p, *p1; 247: register t; 248: register struct node *tp; 249: int nj; 250: 251: t = 0; 252: nj = 0; 253: for (p=first.forw; p!=0; p = p->forw) 254: p->refc = ++t; 255: for (p=first.forw; p!=0; p = p1) { 256: p1 = p->forw; 257: if (p->op == CBR && p1->op==JBR && p->ref && p1->ref 258: && abs(p->refc - p->ref->refc) > abs(p1->refc - p1->ref->refc)) { 259: if (p->ref==p1->ref) 260: continue; 261: p->subop = revbr[p->subop]; 262: tp = p1->ref; 263: p1->ref = p->ref; 264: p->ref = tp; 265: t = p1->labno; 266: p1->labno = p->labno; 267: p->labno = t; 268: nrevbr++; 269: nj++; 270: } 271: } 272: return(nj); 273: } 274: 275: addsob() 276: { 277: register struct node *p, *p1; 278: 279: for (p = &first; (p1 = p->forw)!=0; p = p1) { 280: if (p->op==DEC && isreg(p->code)>=0 281: && p1->op==CBR && p1->subop==JNE) { 282: if (p->refc < p1->ref->refc) 283: continue; 284: if (toofar(p1)) 285: continue; 286: p->labno = p1->labno; 287: p->op = SOB; 288: p->subop = 0; 289: p1->forw->back = p; 290: p->forw = p1->forw; 291: nsob++; 292: } 293: } 294: } 295: 296: toofar(p) 297: struct node *p; 298: { 299: register struct node *p1; 300: int len; 301: 302: len = 0; 303: for (p1 = p->ref; p1 && p1!=p; p1 = p1->forw) 304: len += ilen(p1); 305: if (len < 128) 306: return(0); 307: return(1); 308: } 309: 310: ilen(p) 311: register struct node *p; 312: { 313: register l; 314: 315: switch (p->op) { 316: case LABEL: 317: case DLABEL: 318: case TEXT: 319: case EROU: 320: case EVEN: 321: return(0); 322: 323: case CBR: 324: return(6); 325: 326: default: 327: dualop(p); 328: return(2 + adrlen(regs[RT1]) + adrlen(regs[RT2])); 329: } 330: } 331: 332: adrlen(s) 333: register char *s; 334: { 335: if (*s == 0) 336: return(0); 337: if (*s=='r') 338: return(0); 339: if (*s=='(' && *(s+1)=='r') 340: return(0); 341: if (*s=='-' && *(s+1)=='(') 342: return(0); 343: return(2); 344: } 345: 346: abs(x) 347: { 348: return(x<0? -x: x); 349: } 350: 351: equop(ap1, p2) 352: struct node *ap1, *p2; 353: { 354: register char *cp1, *cp2; 355: register struct node *p1; 356: 357: p1 = ap1; 358: if (p1->op!=p2->op || p1->subop!=p2->subop) 359: return(0); 360: if (p1->op>0 && p1->op<MOV) 361: return(0); 362: cp1 = p1->code; 363: cp2 = p2->code; 364: if (cp1==0 && cp2==0) 365: return(1); 366: if (cp1==0 || cp2==0) 367: return(0); 368: while (*cp1 == *cp2++) 369: if (*cp1++ == 0) 370: return(1); 371: return(0); 372: } 373: 374: decref(p) 375: register struct node *p; 376: { 377: if (--p->refc <= 0) { 378: nrlab++; 379: p->back->forw = p->forw; 380: p->forw->back = p->back; 381: } 382: } 383: 384: struct node * 385: nonlab(p) 386: struct node *p; 387: { 388: while (p && p->op==LABEL) 389: p = p->forw; 390: return(p); 391: } 392: 393: char * 394: alloc(n) 395: register n; 396: { 397: register char *p; 398: 399: n++; 400: n &= ~01; 401: if (lasta+n >= lastr) { 402: if (sbrk(2000) == (char *)-1) { 403: fprintf(stderr, "C Optimizer: out of space\n"); 404: exit(1); 405: } 406: lastr += 2000; 407: } 408: p = lasta; 409: lasta += n; 410: return(p); 411: } 412: 413: clearreg() 414: { 415: register int i; 416: 417: for (i=0; i<2*NREG; i++) 418: regs[i][0] = '\0'; 419: conloc[0] = 0; 420: ccloc[0] = 0; 421: } 422: 423: savereg(ai, as) 424: char *as; 425: { 426: register char *p, *s, *sp; 427: 428: sp = p = regs[ai]; 429: s = as; 430: if (source(s)) 431: return; 432: while (*p++ = *s) { 433: if (s[0]=='(' && s[1]=='r' && s[2]<'5') { 434: *sp = 0; 435: return; 436: } 437: if (*s++ == ',') 438: break; 439: } 440: *--p = '\0'; 441: } 442: 443: dest(as, flt) 444: char *as; 445: { 446: register char *s; 447: register int i; 448: 449: s = as; 450: source(s); 451: if ((i = isreg(s)) >= 0) 452: regs[i+flt][0] = 0; 453: for (i=0; i<NREG+NREG; i++) 454: if (*regs[i]=='*' && equstr(s, regs[i]+1)) 455: regs[i][0] = 0; 456: while ((i = findrand(s, flt)) >= 0) 457: regs[i][0] = 0; 458: while (*s) { 459: if ((*s=='(' && (*(s+1)!='r' || *(s+2)!='5')) || *s++=='*') { 460: for (i=0; i<NREG+NREG; i++) { 461: if (regs[i][0] != '$') 462: regs[i][0] = 0; 463: conloc[0] = 0; 464: } 465: return; 466: } 467: } 468: } 469: 470: singop(ap) 471: struct node *ap; 472: { 473: register char *p1, *p2; 474: 475: p1 = ap->code; 476: p2 = regs[RT1]; 477: while (*p2++ = *p1++); 478: regs[RT2][0] = 0; 479: } 480: 481: 482: dualop(ap) 483: struct node *ap; 484: { 485: register char *p1, *p2; 486: register struct node *p; 487: 488: p = ap; 489: p1 = p->code; 490: p2 = regs[RT1]; 491: while (*p1 && *p1!=',') 492: *p2++ = *p1++; 493: *p2++ = 0; 494: p2 = regs[RT2]; 495: *p2 = 0; 496: if (*p1++ !=',') 497: return; 498: while (*p2++ = *p1++); 499: } 500: 501: findrand(as, flt) 502: char *as; 503: { 504: register int i; 505: for (i = flt; i<NREG+flt; i++) { 506: if (equstr(regs[i], as)) 507: return(i); 508: } 509: return(-1); 510: } 511: 512: isreg(as) 513: char *as; 514: { 515: register char *s; 516: 517: s = as; 518: if (s[0]=='r' && s[1]>='0' && s[1]<='4' && s[2]==0) 519: return(s[1]-'0'); 520: return(-1); 521: } 522: 523: check() 524: { 525: register struct node *p, *lp; 526: 527: lp = &first; 528: for (p=first.forw; p!=0; p = p->forw) { 529: if (p->back != lp) 530: abort(); 531: lp = p; 532: } 533: } 534: 535: source(ap) 536: char *ap; 537: { 538: register char *p1, *p2; 539: 540: p1 = ap; 541: p2 = p1; 542: if (*p1==0) 543: return(0); 544: while (*p2++); 545: if (*p1=='-' && *(p1+1)=='(' 546: || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='(' 547: || *(p2-2)=='+') { 548: while (*p1 && *p1++!='r'); 549: if (*p1>='0' && *p1<='4') 550: regs[*p1 - '0'][0] = 0; 551: return(1); 552: } 553: return(0); 554: } 555: 556: repladdr(p, f, flt) 557: struct node *p; 558: { 559: register r; 560: int r1; 561: register char *p1, *p2; 562: static char rt1[50], rt2[50]; 563: 564: if (f) 565: r1 = findrand(regs[RT2], flt); 566: else 567: r1 = -1; 568: r = findrand(regs[RT1], flt); 569: if (r1 >= NREG) 570: r1 -= NREG; 571: if (r >= NREG) 572: r -= NREG; 573: if (r>=0 || r1>=0) { 574: p2 = regs[RT1]; 575: for (p1 = rt1; *p1++ = *p2++;); 576: if (regs[RT2][0]) { 577: p1 = rt2; 578: *p1++ = ','; 579: for (p2 = regs[RT2]; *p1++ = *p2++;); 580: } else 581: rt2[0] = 0; 582: if (r>=0) { 583: rt1[0] = 'r'; 584: rt1[1] = r + '0'; 585: rt1[2] = 0; 586: nsaddr++; 587: } 588: if (r1>=0) { 589: rt2[1] = 'r'; 590: rt2[2] = r1 + '0'; 591: rt2[3] = 0; 592: nsaddr++; 593: } 594: p->code = copy(2, rt1, rt2); 595: } 596: } 597: 598: movedat() 599: { 600: register struct node *p1, *p2; 601: struct node *p3; 602: register seg; 603: struct node data; 604: struct node *datp; 605: 606: if (first.forw == 0) 607: return; 608: if (lastseg != TEXT && lastseg != -1) { 609: p1 = (struct node *)alloc(sizeof(first)); 610: p1->op = lastseg; 611: p1->subop = 0; 612: p1->code = NULL; 613: p1->forw = first.forw; 614: p1->back = &first; 615: first.forw->back = p1; 616: first.forw = p1; 617: } 618: datp = &data; 619: for (p1 = first.forw; p1!=0; p1 = p1->forw) { 620: if (p1->op == DATA) { 621: p2 = p1->forw; 622: while (p2 && p2->op!=TEXT) 623: p2 = p2->forw; 624: if (p2==0) 625: break; 626: p3 = p1->back; 627: p1->back->forw = p2->forw; 628: p2->forw->back = p3; 629: p2->forw = 0; 630: datp->forw = p1; 631: p1->back = datp; 632: p1 = p3; 633: datp = p2; 634: } 635: } 636: if (data.forw) { 637: datp->forw = first.forw; 638: first.forw->back = datp; 639: data.forw->back = &first; 640: first.forw = data.forw; 641: } 642: seg = lastseg; 643: for (p1 = first.forw; p1!=0; p1 = p1->forw) { 644: if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) { 645: if (p2 = p1->forw) { 646: if (p2->op==TEXT||p2->op==DATA||p2->op==BSS) 647: p1->op = p2->op; 648: } 649: if (p1->op == seg || p1->forw&&p1->forw->op==seg) { 650: p1->back->forw = p1->forw; 651: p1->forw->back = p1->back; 652: p1 = p1->back; 653: continue; 654: } 655: seg = p1->op; 656: } 657: } 658: } 659: 660: redunbr(p) 661: register struct node *p; 662: { 663: register struct node *p1; 664: register char *ap1; 665: char *ap2; 666: 667: if ((p1 = p->ref) == 0) 668: return; 669: p1 = nonlab(p1); 670: if (p1->op==TST) { 671: singop(p1); 672: savereg(RT2, "$0"); 673: } else if (p1->op==CMP) 674: dualop(p1); 675: else 676: return; 677: if (p1->forw->op!=CBR) 678: return; 679: ap1 = findcon(RT1); 680: ap2 = findcon(RT2); 681: p1 = p1->forw; 682: if (compare(p1->subop, ap1, ap2)>0) { 683: nredunj++; 684: nchange++; 685: decref(p->ref); 686: p->ref = p1->ref; 687: p->labno = p1->labno; 688: p->ref->refc++; 689: } 690: } 691: 692: char * 693: findcon(i) 694: { 695: register char *p; 696: register r; 697: 698: p = regs[i]; 699: if (*p=='$') 700: return(p); 701: if ((r = isreg(p)) >= 0) 702: return(regs[r]); 703: if (equstr(p, conloc)) 704: return(conval); 705: return(p); 706: } 707: 708: compare(oper, cp1, cp2) 709: register char *cp1, *cp2; 710: { 711: register unsigned n1, n2; 712: 713: if (*cp1++ != '$' || *cp2++ != '$') 714: return(-1); 715: n1 = 0; 716: while (*cp2 >= '0' && *cp2 <= '7') { 717: n1 <<= 3; 718: n1 += *cp2++ - '0'; 719: } 720: n2 = n1; 721: n1 = 0; 722: while (*cp1 >= '0' && *cp1 <= '7') { 723: n1 <<= 3; 724: n1 += *cp1++ - '0'; 725: } 726: if (*cp1=='+') 727: cp1++; 728: if (*cp2=='+') 729: cp2++; 730: do { 731: if (*cp1++ != *cp2) 732: return(-1); 733: } while (*cp2++); 734: switch(oper) { 735: 736: case JEQ: 737: return(n1 == n2); 738: case JNE: 739: return(n1 != n2); 740: case JLE: 741: return((int)n1 <= (int)n2); 742: case JGE: 743: return((int)n1 >= (int)n2); 744: case JLT: 745: return((int)n1 < (int)n2); 746: case JGT: 747: return((int)n1 > (int)n2); 748: case JLO: 749: return(n1 < n2); 750: case JHI: 751: return(n1 > n2); 752: case JLOS: 753: return(n1 <= n2); 754: case JHIS: 755: return(n1 >= n2); 756: } 757: return(-1); 758: } 759: 760: setcon(ar1, ar2) 761: char *ar1, *ar2; 762: { 763: register char *cl, *cv, *p; 764: 765: cl = ar2; 766: cv = ar1; 767: if (*cv != '$') 768: return; 769: if (!natural(cl)) 770: return; 771: p = conloc; 772: while (*p++ = *cl++); 773: p = conval; 774: while (*p++ = *cv++); 775: } 776: 777: equstr(ap1, ap2) 778: char *ap1, *ap2; 779: { 780: char *p1, *p2; 781: 782: p1 = ap1; 783: p2 = ap2; 784: do { 785: if (*p1++ != *p2) 786: return(0); 787: } while (*p2++); 788: return(1); 789: } 790: 791: setcc(ap) 792: char *ap; 793: { 794: register char *p, *p1; 795: 796: p = ap; 797: if (!natural(p)) { 798: ccloc[0] = 0; 799: return; 800: } 801: p1 = ccloc; 802: while (*p1++ = *p++); 803: } 804: 805: natural(ap) 806: char *ap; 807: { 808: register char *p; 809: 810: p = ap; 811: if (*p=='*' || *p=='(' || *p=='-'&&*(p+1)=='(') 812: return(0); 813: while (*p++); 814: p--; 815: if (*--p == '+' || *p ==')' && *--p != '5') 816: return(0); 817: return(1); 818: }