|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid ="@(#)optim.c 4.7 (Berkeley) 1/8/86"; ! 3: #endif lint ! 4: ! 5: # include "pass1.h" ! 6: ! 7: # define SWAP(p,q) {sp=p; p=q; q=sp;} ! 8: # define RCON(p) (p->in.right->in.op==ICON) ! 9: # define RO(p) p->in.right->in.op ! 10: # define RV(p) p->in.right->tn.lval ! 11: # define LCON(p) (p->in.left->in.op==ICON) ! 12: # define LO(p) p->in.left->in.op ! 13: # define LV(p) p->in.left->tn.lval ! 14: ! 15: /* is p a constant without a name */ ! 16: # define nncon(p) ((p)->in.op == ICON && (p)->tn.rval == NONAME) ! 17: ! 18: int oflag = 0; ! 19: ! 20: NODE * ! 21: fortarg( p ) NODE *p; { ! 22: /* fortran function arguments */ ! 23: ! 24: if( p->in.op == CM ){ ! 25: p->in.left = fortarg( p->in.left ); ! 26: p->in.right = fortarg( p->in.right ); ! 27: return(p); ! 28: } ! 29: ! 30: while( ISPTR(p->in.type) ){ ! 31: p = buildtree( UNARY MUL, p, NIL ); ! 32: } ! 33: return( optim(p) ); ! 34: } ! 35: ! 36: /* mapping relationals when the sides are reversed */ ! 37: short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT }; ! 38: NODE * ! 39: optim(p) register NODE *p; { ! 40: /* local optimizations, most of which are probably machine independent */ ! 41: ! 42: register o, ty; ! 43: NODE *sp; ! 44: int i; ! 45: TWORD t; ! 46: ! 47: if( (t=BTYPE(p->in.type))==ENUMTY || t==MOETY ) econvert(p); ! 48: if( oflag ) return(p); ! 49: ty = optype( o=p->in.op); ! 50: if( ty == LTYPE ) return(p); ! 51: ! 52: if( ty == BITYPE ) p->in.right = optim(p->in.right); ! 53: p->in.left = optim(p->in.left); ! 54: ! 55: /* collect constants */ ! 56: ! 57: switch(o){ ! 58: ! 59: case SCONV: ! 60: case PCONV: ! 61: return( clocal(p) ); ! 62: ! 63: case FORTCALL: ! 64: p->in.right = fortarg( p->in.right ); ! 65: break; ! 66: ! 67: case UNARY AND: ! 68: if( LO(p) != NAME || !andable(p->in.left) ) return(p); ! 69: ! 70: LO(p) = ICON; ! 71: ! 72: setuleft: ! 73: /* paint over the type of the left hand side with the type of the top */ ! 74: p->in.left->in.type = p->in.type; ! 75: p->in.left->fn.cdim = p->fn.cdim; ! 76: p->in.left->fn.csiz = p->fn.csiz; ! 77: p->in.op = FREE; ! 78: return( p->in.left ); ! 79: ! 80: case UNARY MUL: ! 81: if( LO(p) != ICON ) break; ! 82: LO(p) = NAME; ! 83: goto setuleft; ! 84: ! 85: case MINUS: ! 86: if( !nncon(p->in.right) ) break; ! 87: RV(p) = -RV(p); ! 88: o = p->in.op = PLUS; ! 89: ! 90: case MUL: ! 91: case PLUS: ! 92: case AND: ! 93: case OR: ! 94: case ER: ! 95: /* commutative ops; for now, just collect constants */ ! 96: /* someday, do it right */ ! 97: if( nncon(p->in.left) || ( LCON(p) && !RCON(p) ) ) SWAP( p->in.left, p->in.right ); ! 98: /* make ops tower to the left, not the right */ ! 99: if( RO(p) == o ){ ! 100: NODE *t1, *t2, *t3; ! 101: t1 = p->in.left; ! 102: sp = p->in.right; ! 103: t2 = sp->in.left; ! 104: t3 = sp->in.right; ! 105: /* now, put together again */ ! 106: p->in.left = sp; ! 107: sp->in.left = t1; ! 108: sp->in.right = t2; ! 109: p->in.right = t3; ! 110: } ! 111: if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->in.left) && ! 112: conval(p->in.right, MINUS, p->in.left->in.right)){ ! 113: zapleft: ! 114: RO(p->in.left) = FREE; ! 115: LO(p) = FREE; ! 116: p->in.left = p->in.left->in.left; ! 117: } ! 118: if( RCON(p) && LO(p)==o && RCON(p->in.left) && ! 119: conval( p->in.right, o, p->in.left->in.right ) ){ ! 120: goto zapleft; ! 121: } ! 122: else if( LCON(p) && RCON(p) && ! 123: conval( p->in.left, o, p->in.right ) ){ ! 124: zapright: ! 125: RO(p) = FREE; ! 126: p->in.left = makety( p->in.left, p->in.type, p->fn.cdim, p->fn.csiz ); ! 127: p->in.op = FREE; ! 128: return( clocal( p->in.left ) ); ! 129: } ! 130: /* FALL THROUGH */ ! 131: ! 132: case ASG MUL: ! 133: /* change muls to adds or shifts */ ! 134: ! 135: if( (o == MUL || o == ASG MUL) && ! 136: nncon(p->in.right) && (i=ispow2(RV(p)))>=0){ ! 137: if( i == 0 ) /* multiplication by 1 */ ! 138: goto zapright; ! 139: /* c2 will turn 'i << 1' into 'i + i' for us */ ! 140: else { ! 141: p->in.op = (asgop(o) ? ASG LS : LS); ! 142: o = p->in.op; ! 143: p->in.right->in.type = p->in.right->fn.csiz = INT; ! 144: RV(p) = i; ! 145: } ! 146: } ! 147: ! 148: /* change +'s of negative consts back to - */ ! 149: if( o==PLUS && nncon(p->in.right) && RV(p)<0 ){ ! 150: RV(p) = -RV(p); ! 151: o = p->in.op = MINUS; ! 152: } ! 153: /* FALL THROUGH */ ! 154: case ASG AND: ! 155: case ASG PLUS: ! 156: case ASG MINUS: ! 157: case RS: ! 158: case LS: ! 159: /* Operations with zero */ ! 160: if( nncon(p->in.right) && RV(p) == 0 ) { ! 161: if( o == MUL || o == ASG MUL || ! 162: o == AND || o == ASG AND ) { ! 163: if( asgop(o) ) ! 164: p->in.op = ASSIGN; ! 165: else if( optype(LO(p)) == LTYPE ) { ! 166: p->in.op = FREE; ! 167: LO(p) = FREE; ! 168: p = p->in.right; ! 169: } ! 170: else ! 171: p->in.op = COMOP; /* side effects */ ! 172: } ! 173: else if( o == PLUS || o == MINUS || ! 174: o == ASG PLUS || o == ASG MINUS || ! 175: o == OR || o == ER || ! 176: o == LS || o == RS ) ! 177: goto zapright; ! 178: } ! 179: if( o != LS && o != RS ) ! 180: break; ! 181: /* FALL THROUGH */ ! 182: ! 183: case ASG RS: ! 184: case ASG LS: ! 185: if( !ISUNSIGNED(p->in.left->in.type) ) ! 186: break; ! 187: if( p->in.right->in.op == ICON && ! 188: p->in.right->tn.lval < 0 ) { ! 189: /* ! 190: * Technically negative shifts are illegal ! 191: * but we can support them, at least with ! 192: * constants; you take potluck with variables. ! 193: */ ! 194: p->in.right->tn.lval = -p->in.right->tn.lval; ! 195: switch( o ){ ! 196: case LS: p->in.op = RS; break; ! 197: case ASG LS: p->in.op = ASG RS; break; ! 198: case RS: p->in.op = LS; break; ! 199: case ASG RS: p->in.op = ASG LS; break; ! 200: } ! 201: } ! 202: break; ! 203: ! 204: case ASG DIV: ! 205: case DIV: ! 206: if( nncon( p->in.right ) ){ ! 207: if( RV(p) == 0 ) uerror("division by zero"); ! 208: else if( RV(p) == 1 ) goto zapright; ! 209: /* Unsigned division by a power of two */ ! 210: else if( (i=ispow2(RV(p)))>=0 && ! 211: (ISUNSIGNED(p->in.left->in.type) || ! 212: ISUNSIGNED(p->in.right->in.type)) ){ ! 213: p->in.op = (asgop(o) ? ASG RS : RS); ! 214: p->in.right->in.type = p->in.right->fn.csiz = INT; ! 215: RV(p) = i; ! 216: } ! 217: } ! 218: break; ! 219: ! 220: case ASG MOD: ! 221: case MOD: ! 222: if( nncon(p->in.right) ){ ! 223: if( RV(p) == 0 ) uerror("modulus of zero"); ! 224: else if( RV(p) == 1 ){ /* mod by one gives zero */ ! 225: RV(p) = 0; ! 226: if( asgop(o) ) ! 227: p->in.op = ASSIGN; ! 228: else if( optype(LO(p)) == LTYPE ) { ! 229: p->in.op = FREE; ! 230: LO(p) = FREE; ! 231: p = p->in.right; ! 232: } ! 233: else ! 234: p->in.op = COMOP; /* side effects */ ! 235: } ! 236: else if ((i=ispow2(RV(p)))>=0 && ! 237: (ISUNSIGNED(p->in.left->in.type) || ! 238: ISUNSIGNED(p->in.right->in.type)) ){ ! 239: /* Unsigned mod by a power of two */ ! 240: p->in.op = (asgop(o) ? ASG AND : AND); ! 241: RV(p)--; ! 242: } ! 243: } ! 244: break; ! 245: ! 246: case EQ: ! 247: case NE: ! 248: case LT: ! 249: case LE: ! 250: case GT: ! 251: case GE: ! 252: case ULT: ! 253: case ULE: ! 254: case UGT: ! 255: case UGE: ! 256: if( !LCON(p) ) break; ! 257: ! 258: /* exchange operands */ ! 259: ! 260: sp = p->in.left; ! 261: p->in.left = p->in.right; ! 262: p->in.right = sp; ! 263: p->in.op = revrel[p->in.op - EQ ]; ! 264: break; ! 265: ! 266: } ! 267: ! 268: return(p); ! 269: } ! 270: ! 271: ispow2( c ) CONSZ c; { ! 272: register i; ! 273: if( c <= 0 || (c&(c-1)) ) return(-1); ! 274: for( i=0; c>1; ++i) c >>= 1; ! 275: return(i); ! 276: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.