|
|
1.1 ! root 1: /* ! 2: * C object code improver-- third part ! 3: */ ! 4: ! 5: #include "c2.h" ! 6: #include <stdio.h> ! 7: #include <ctype.h> ! 8: ! 9: #define NUSE 6 ! 10: struct node *uses[NUSE]; /* for backwards flow analysis */ ! 11: char *lastrand; /* last operand of instruction */ ! 12: char *findcon(); ! 13: ! 14: ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */ ! 15: register int log; ! 16: if (n==0 || n&(n-1)) return(-1); log=0; ! 17: for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);} ! 18: } ! 19: ! 20: equop(p1, p2) ! 21: register struct node *p1, *p2; ! 22: { ! 23: register char *cp1, *cp2; ! 24: ! 25: if (p1->op != p2->op || p1->subop != p2->subop) ! 26: return(0); ! 27: if (p1->op>0 && p1->op<MOV) ! 28: return(0); ! 29: if (p1->op==MOVA && p1->labno!=p2->labno) return(0); ! 30: cp1 = p1->code; ! 31: cp2 = p2->code; ! 32: if (cp1==0 && cp2==0) ! 33: return(1); ! 34: if (cp1==0 || cp2==0) ! 35: return(0); ! 36: while (*cp1 == *cp2++) ! 37: if (*cp1++ == 0) ! 38: return(1); ! 39: return(0); ! 40: } ! 41: ! 42: delnode(p) register struct node *p; { ! 43: p->back->forw = p->forw; ! 44: p->forw->back = p->back; ! 45: } ! 46: ! 47: decref(p) ! 48: register struct node *p; ! 49: { ! 50: if (p && --p->refc <= 0) { ! 51: nrlab++; nchange++; ! 52: delnode(p); ! 53: } ! 54: } ! 55: ! 56: struct node * ! 57: nonlab(ap) ! 58: struct node *ap; ! 59: { ! 60: register struct node *p; ! 61: ! 62: p = ap; ! 63: while (p && p->op==LABEL) ! 64: p = p->forw; ! 65: return(p); ! 66: } ! 67: ! 68: clearuse() { ! 69: register struct node **i; ! 70: for (i=uses+NUSE; i>uses;) *--i=0; ! 71: } ! 72: ! 73: clearreg() { ! 74: register char **i; ! 75: for (i=regs+NREG; i>regs;){ **--i=0; **i=0; } ! 76: conloc[0] = 0; ccloc[0] = 0; ! 77: } ! 78: ! 79: savereg(ai, s, type) ! 80: register char *s; ! 81: { ! 82: register char *p, *sp; ! 83: ! 84: sp = p = regs[ai]; ! 85: /* if any indexing, must be parameter or local */ ! 86: /* indirection (as in "*-4(fp)") is ok, however */ ! 87: *p++ = type; ! 88: while (*p++ = *s) ! 89: if (*s=='[' || *s++=='(' && *s!='f') {*sp = 0; return;} ! 90: } ! 91: ! 92: dest(s,type, ccflg) ! 93: register char *s; ! 94: { ! 95: register int i; ! 96: ! 97: if ((i = isreg(s)) >= 0) { ! 98: *(short *)(regs[i]) = 0; /* if register destination, that reg is a goner */ ! 99: } ! 100: for (i=NREG; --i>=0;) ! 101: if (regs[i][1]=='*' && equstr(s, regs[i]+2)) ! 102: *(short *)(regs[i]) = 0; /* previous indirection through destination is invalid */ ! 103: while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */ ! 104: *(short *)(regs[i]) = 0; ! 105: if (!natural(s)) {/* wild store, everything except constants vanishes */ ! 106: for (i=NREG; --i>=0;) if (regs[i][1] != '$') *(short *)(regs[i]) = 0; ! 107: conloc[0] = 0; ccloc[0] = 0; ! 108: } else if(ccflg)setcc(s,type); /* natural destinations set condition codes */ ! 109: } ! 110: ! 111: splitrand(p) struct node *p; { ! 112: /* separate operands at commas, set up 'regs' and 'lastrand' */ ! 113: register char *p1, *p2; register char **preg; ! 114: ! 115: preg=regs+RT1; ! 116: if (p1=p->code) while (*p1) { ! 117: lastrand=p2= *preg++; ! 118: while (*p1) if (','==(*p2++= *p1++)) {--p2; break;} ! 119: *p2=0; ! 120: } ! 121: while (preg<(regs+RT1+5)) *(*preg++)=0; ! 122: } ! 123: ! 124: compat(have, want) { ! 125: register int hsrc, hdst; ! 126: ! 127: if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */ ! 128: hsrc=have&0xF; if (0==(hdst=((have>>4)&0xF)) || hdst>=OP2) hdst=hsrc; ! 129: if (want>=QUAD) return(hdst==want && hsrc==want); ! 130: return(hsrc==want && hdst>=want && hdst<QUAD); ! 131: } ! 132: ! 133: equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));} ! 134: ! 135: findrand(as, type) ! 136: char *as; ! 137: { ! 138: register char **i; ! 139: for (i = regs+NREG; --i>=regs;) { ! 140: if (**i && equstr(*i+1, as) && compat(**i,type)) ! 141: return(i-regs); ! 142: } ! 143: return(-1); ! 144: } ! 145: ! 146: isreg(s) ! 147: register char *s; ! 148: { ! 149: if (*s++!='r' || !isdigit(*s++)) return(-1); ! 150: if (*s==0) return(*--s-'0'); ! 151: if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0'); ! 152: return(-1); ! 153: } ! 154: ! 155: /* ! 156: check() ! 157: { ! 158: register struct node *p, *lp; ! 159: ! 160: lp = &first; ! 161: for (p=first.forw; p!=0; p = p->forw) { ! 162: if (p->back != lp) ! 163: abort(-1); ! 164: lp = p; ! 165: } ! 166: } ! 167: */ ! 168: ! 169: newcode(p) struct node *p; { ! 170: register char *p1,*p2,**preg; ! 171: ! 172: preg=regs+RT1; p2=line; ! 173: while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';} ! 174: *--p2=0; ! 175: p->code=copy(line); ! 176: } ! 177: ! 178: repladdr(p) ! 179: struct node *p; ! 180: { ! 181: register r; ! 182: register char *p1; ! 183: register char **preg; ! 184: register int nrepl; ! 185: ! 186: preg=regs+RT1; nrepl=0; ! 187: while (lastrand!=(p1= *preg++)) ! 188: if (0<=(r=findrand(p1,p->subop))) { ! 189: *p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0; ! 190: nchange++; nrepl++; nsaddr++; ! 191: } ! 192: if (nrepl) newcode(p); ! 193: } ! 194: ! 195: /* conditional branches which are never/always taken */ ! 196: reduncbr(p) ! 197: register struct node *p; ! 198: { ! 199: register struct node *p1; ! 200: register char *ap1, *ap2; ! 201: ! 202: p1 = p->back; ! 203: if (p1->op==CMP) { ! 204: splitrand(p1); ! 205: ap1 = findcon(regs[RT1], p1->subop); ! 206: ap2 = findcon(regs[RT2], p1->subop); ! 207: } else { ! 208: if(!ccloc[0]) ! 209: return; ! 210: ap1 = findcon(ccloc+1, ccloc[0]); ! 211: ap2 = "$0"; ! 212: } ! 213: switch (compare(p->subop, ap1, ap2)) { ! 214: case 0: /* branch never taken */ ! 215: delnode(p); ! 216: nredunj++; ! 217: nchange++; ! 218: decref(p->ref); ! 219: if(p->forw->op!=CBR && (p1->op==TST || p1->op==CMP)) { ! 220: delnode(p1); ! 221: nrtst++; ! 222: } ! 223: break; ! 224: case 1: /* branch always taken */ ! 225: p->op = JBR; ! 226: p->subop = 0; ! 227: p->pop = 0; ! 228: nchange++; ! 229: } ! 230: } ! 231: ! 232: /* a jump to a redundant compare (start of a 'for') */ ! 233: redunbr(p) ! 234: register struct node *p; ! 235: { ! 236: register struct node *p1; ! 237: register char *ap1, *ap2; ! 238: ! 239: if ((p1 = p->ref) == 0) ! 240: return; ! 241: p1 = nonlab(p1); ! 242: if (p1->op==TST || p1->op==CMP) ! 243: splitrand(p1); ! 244: else ! 245: return; ! 246: if (p1->forw->op==CBR) { ! 247: ap1 = findcon(regs[RT1], p1->subop); ! 248: if (p1->op==TST) ! 249: ap2 = "$0"; ! 250: else ! 251: ap2 = findcon(regs[RT2], p1->subop); ! 252: p1 = p1->forw; ! 253: if (compare(p1->subop, ap1, ap2) > 0) { ! 254: nredunj++; ! 255: nchange++; ! 256: decref(p->ref); ! 257: p->ref = p1->ref; ! 258: p->labno = p1->labno; ! 259: #ifdef COPYCODE ! 260: if (p->labno == 0) ! 261: p->code = p1->code; ! 262: if (p->ref) ! 263: #endif ! 264: p->ref->refc++; ! 265: } ! 266: } else if (p1->op==TST && equstr(regs[RT1],ccloc+1) && ! 267: equtype(ccloc[0],p1->subop)) { ! 268: p1=insertl(p1->forw); decref(p->ref); p->ref=p1; ! 269: nrtst++; nchange++; ! 270: } ! 271: } ! 272: ! 273: char * ! 274: findcon(p, type) ! 275: register char *p; ! 276: { ! 277: register r; ! 278: ! 279: if (*p=='$') ! 280: return(p); ! 281: if ((r = isreg(p)) >= 0 && compat(regs[r][0],type)) ! 282: return(regs[r]+1); ! 283: if (equstr(p, conloc)) ! 284: return(conval+1); ! 285: return(p); ! 286: } ! 287: ! 288: /* compare constants: 0 - branch taken; 1 - not taken; -1 - don't know */ ! 289: compare(op, acp1, acp2) ! 290: char *acp1, *acp2; ! 291: { ! 292: register char *cp1, *cp2; ! 293: register n1, n2, sign; ! 294: ! 295: cp1 = acp1; ! 296: cp2 = acp2; ! 297: if (*cp1++ != '$' || *cp2++ != '$') ! 298: return(-1); ! 299: n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;} ! 300: while (isdigit(*cp1)) {n1 *= 10; n1 += *cp1++ - '0';} ! 301: n1 *= sign; ! 302: n2 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;} ! 303: while (isdigit(*cp2)) {n2 *= 10; n2 += *cp2++ - '0';} ! 304: n2 *= sign; ! 305: if (*cp1=='+') ! 306: cp1++; ! 307: if (*cp2=='+') ! 308: cp2++; ! 309: do { ! 310: if (*cp1++ != *cp2) ! 311: return(-1); ! 312: } while (*cp2++); ! 313: switch(op) { ! 314: ! 315: case JEQ: ! 316: return(n1 == n2); ! 317: case JNE: ! 318: return(n1 != n2); ! 319: case JLE: ! 320: return(n1 <= n2); ! 321: case JGE: ! 322: return(n1 >= n2); ! 323: case JLT: ! 324: return(n1 < n2); ! 325: case JGT: ! 326: return(n1 > n2); ! 327: case JLO: ! 328: return((unsigned)n1 < (unsigned)n2); ! 329: case JHI: ! 330: return((unsigned)n1 > (unsigned)n2); ! 331: case JLOS: ! 332: return((unsigned)n1 <= (unsigned)n2); ! 333: case JHIS: ! 334: return((unsigned)n1 >= (unsigned)n2); ! 335: } ! 336: return(-1); ! 337: } ! 338: ! 339: setcon(cv, cl, type) ! 340: register char *cv, *cl; ! 341: { ! 342: register char *p; ! 343: ! 344: if (*cv != '$') ! 345: return; ! 346: if (!natural(cl)) ! 347: return; ! 348: p = conloc; ! 349: while (*p++ = *cl++); ! 350: p = conval; ! 351: *p++ = type; ! 352: while (*p++ = *cv++); ! 353: } ! 354: ! 355: equstr(p1, p2) ! 356: register char *p1, *p2; ! 357: { ! 358: do { ! 359: if (*p1++ != *p2) ! 360: return(0); ! 361: } while (*p2++); ! 362: return(1); ! 363: } ! 364: ! 365: setcc(ap,type) ! 366: char *ap; ! 367: { ! 368: register char *p, *p1; ! 369: ! 370: p = ap; ! 371: if (!natural(p)) { ! 372: ccloc[0] = 0; ! 373: return; ! 374: } ! 375: p1 = ccloc; ! 376: *p1++ = type; ! 377: while (*p1++ = *p++); ! 378: } ! 379: ! 380: indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */ ! 381: while (*p) if (*p++=='[') return(1); ! 382: return(0); ! 383: } ! 384: ! 385: natural(p) ! 386: register char *p; ! 387: {/* 1->simple local, parameter, global, or register; 0->otherwise */ ! 388: ! 389: if (*p=='*' || *p=='(' || *p=='$') ! 390: return(0); ! 391: while (*p++); ! 392: p--; ! 393: if (*--p==']' || *p==')' && *(p-2)!='f') ! 394: return(0); ! 395: return(1); ! 396: } ! 397: ! 398: /* ! 399: ** Tell if an argument is most likely static. ! 400: */ ! 401: ! 402: isstatic(cp) ! 403: register char *cp; ! 404: { ! 405: if (*cp == '_' || *cp == 'L' || (*cp++ == 'v' && *cp == '.')) ! 406: return (1); ! 407: return (0); ! 408: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.