1 #ifndef lint 2 static char *sccsid ="@(#)optim.c 4.6 (Berkeley) 08/22/85"; 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 if( i == 1 && optype(LO(p)) == LTYPE){ 140 /* multiplication by 2 */ 141 p->in.op = (asgop(o) ? ASG PLUS : PLUS); 142 o = p->in.op; 143 ncopy(p->in.right, p->in.left); 144 } 145 else { 146 p->in.op = (asgop(o) ? ASG LS : LS); 147 o = p->in.op; 148 p->in.right->in.type = p->in.right->fn.csiz = INT; 149 RV(p) = i; 150 } 151 } 152 153 /* change +'s of negative consts back to - */ 154 if( o==PLUS && nncon(p->in.right) && RV(p)<0 ){ 155 RV(p) = -RV(p); 156 o = p->in.op = MINUS; 157 } 158 /* FALL THROUGH */ 159 case ASG AND: 160 case ASG PLUS: 161 case ASG MINUS: 162 case RS: 163 case LS: 164 /* Operations with zero */ 165 if( nncon(p->in.right) && RV(p) == 0 ) { 166 if( o == MUL || o == ASG MUL || 167 o == AND || o == ASG AND ) { 168 if( asgop(o) ) 169 p->in.op = ASSIGN; 170 else if( optype(LO(p)) == LTYPE ) { 171 p->in.op = FREE; 172 LO(p) = FREE; 173 p = p->in.right; 174 } 175 else 176 p->in.op = COMOP; /* side effects */ 177 } 178 else if( o == PLUS || o == MINUS || 179 o == ASG PLUS || o == ASG MINUS || 180 o == OR || o == ER || 181 o == LS || o == RS ) 182 goto zapright; 183 } 184 break; 185 186 case ASG DIV: 187 case DIV: 188 if( nncon( p->in.right ) ){ 189 if( RV(p) == 0 ) uerror("division by zero"); 190 else if( RV(p) == 1 ) goto zapright; 191 /* Unsigned division by a power of two */ 192 else if( (i=ispow2(RV(p)))>=0 && 193 (ISUNSIGNED(p->in.left->in.type) || 194 ISUNSIGNED(p->in.right->in.type)) ){ 195 p->in.op = (asgop(o) ? ASG RS : RS); 196 p->in.right->in.type = p->in.right->fn.csiz = INT; 197 RV(p) = i; 198 } 199 } 200 break; 201 202 case ASG MOD: 203 case MOD: 204 if( nncon(p->in.right) ){ 205 if( RV(p) == 0 ) uerror("modulus of zero"); 206 else if( RV(p) == 1 ){ /* mod by one gives zero */ 207 RV(p) = 0; 208 if( asgop(o) ) 209 p->in.op = ASSIGN; 210 else if( optype(LO(p)) == LTYPE ) { 211 p->in.op = FREE; 212 LO(p) = FREE; 213 p = p->in.right; 214 } 215 else 216 p->in.op = COMOP; /* side effects */ 217 } 218 else if ((i=ispow2(RV(p)))>=0 && 219 (ISUNSIGNED(p->in.left->in.type) || 220 ISUNSIGNED(p->in.right->in.type)) ){ 221 /* Unsigned mod by a power of two */ 222 p->in.op = (asgop(o) ? ASG AND : AND); 223 RV(p)--; 224 } 225 } 226 break; 227 228 case EQ: 229 case NE: 230 case LT: 231 case LE: 232 case GT: 233 case GE: 234 case ULT: 235 case ULE: 236 case UGT: 237 case UGE: 238 if( !LCON(p) ) break; 239 240 /* exchange operands */ 241 242 sp = p->in.left; 243 p->in.left = p->in.right; 244 p->in.right = sp; 245 p->in.op = revrel[p->in.op - EQ ]; 246 break; 247 248 } 249 250 return(p); 251 } 252 253 ispow2( c ) CONSZ c; { 254 register i; 255 if( c <= 0 || (c&(c-1)) ) return(-1); 256 for( i=0; c>1; ++i) c >>= 1; 257 return(i); 258 } 259