117746Sralph #ifndef lint 2*24404Smckusick static char *sccsid ="@(#)optim.c 4.6 (Berkeley) 08/22/85"; 317746Sralph #endif lint 417746Sralph 518393Sralph # include "pass1.h" 616935Sralph 716935Sralph # define SWAP(p,q) {sp=p; p=q; q=sp;} 816935Sralph # define RCON(p) (p->in.right->in.op==ICON) 916935Sralph # define RO(p) p->in.right->in.op 1016935Sralph # define RV(p) p->in.right->tn.lval 1116935Sralph # define LCON(p) (p->in.left->in.op==ICON) 1216935Sralph # define LO(p) p->in.left->in.op 1316935Sralph # define LV(p) p->in.left->tn.lval 1416935Sralph 15*24404Smckusick /* is p a constant without a name */ 16*24404Smckusick # define nncon(p) ((p)->in.op == ICON && (p)->tn.rval == NONAME) 17*24404Smckusick 1816935Sralph int oflag = 0; 1916935Sralph 2016935Sralph NODE * 2116935Sralph fortarg( p ) NODE *p; { 2216935Sralph /* fortran function arguments */ 2316935Sralph 2416935Sralph if( p->in.op == CM ){ 2516935Sralph p->in.left = fortarg( p->in.left ); 2616935Sralph p->in.right = fortarg( p->in.right ); 2716935Sralph return(p); 2816935Sralph } 2916935Sralph 3016935Sralph while( ISPTR(p->in.type) ){ 3116935Sralph p = buildtree( UNARY MUL, p, NIL ); 3216935Sralph } 3316935Sralph return( optim(p) ); 3416935Sralph } 3516935Sralph 3616935Sralph /* mapping relationals when the sides are reversed */ 3716935Sralph short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT }; 3816935Sralph NODE * 3916935Sralph optim(p) register NODE *p; { 4016935Sralph /* local optimizations, most of which are probably machine independent */ 4116935Sralph 4216935Sralph register o, ty; 4316935Sralph NODE *sp; 4416935Sralph int i; 4516935Sralph TWORD t; 4616935Sralph 4716935Sralph if( (t=BTYPE(p->in.type))==ENUMTY || t==MOETY ) econvert(p); 4816935Sralph if( oflag ) return(p); 4916935Sralph ty = optype( o=p->in.op); 5016935Sralph if( ty == LTYPE ) return(p); 5116935Sralph 5216935Sralph if( ty == BITYPE ) p->in.right = optim(p->in.right); 5316935Sralph p->in.left = optim(p->in.left); 5416935Sralph 5516935Sralph /* collect constants */ 5616935Sralph 5716935Sralph switch(o){ 5816935Sralph 5916935Sralph case SCONV: 6016935Sralph case PCONV: 6116935Sralph return( clocal(p) ); 6216935Sralph 6316935Sralph case FORTCALL: 6416935Sralph p->in.right = fortarg( p->in.right ); 6516935Sralph break; 6616935Sralph 6716935Sralph case UNARY AND: 6816936Sralph if( LO(p) != NAME || !andable(p->in.left) ) return(p); 6916935Sralph 7016935Sralph LO(p) = ICON; 7116935Sralph 7216935Sralph setuleft: 7316935Sralph /* paint over the type of the left hand side with the type of the top */ 7416935Sralph p->in.left->in.type = p->in.type; 7516935Sralph p->in.left->fn.cdim = p->fn.cdim; 7616935Sralph p->in.left->fn.csiz = p->fn.csiz; 7716935Sralph p->in.op = FREE; 7816935Sralph return( p->in.left ); 7916935Sralph 8016935Sralph case UNARY MUL: 8116935Sralph if( LO(p) != ICON ) break; 8216935Sralph LO(p) = NAME; 8316935Sralph goto setuleft; 8416935Sralph 8516935Sralph case MINUS: 8616935Sralph if( !nncon(p->in.right) ) break; 8716935Sralph RV(p) = -RV(p); 8816935Sralph o = p->in.op = PLUS; 8916935Sralph 9016935Sralph case MUL: 9116935Sralph case PLUS: 9216935Sralph case AND: 9316935Sralph case OR: 9416935Sralph case ER: 9516935Sralph /* commutative ops; for now, just collect constants */ 9616935Sralph /* someday, do it right */ 9716935Sralph if( nncon(p->in.left) || ( LCON(p) && !RCON(p) ) ) SWAP( p->in.left, p->in.right ); 9816935Sralph /* make ops tower to the left, not the right */ 9916935Sralph if( RO(p) == o ){ 10016935Sralph NODE *t1, *t2, *t3; 10116935Sralph t1 = p->in.left; 10216935Sralph sp = p->in.right; 10316935Sralph t2 = sp->in.left; 10416935Sralph t3 = sp->in.right; 10516935Sralph /* now, put together again */ 10616935Sralph p->in.left = sp; 10716935Sralph sp->in.left = t1; 10816935Sralph sp->in.right = t2; 10916935Sralph p->in.right = t3; 11016935Sralph } 11116935Sralph if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->in.left) && 112*24404Smckusick conval(p->in.right, MINUS, p->in.left->in.right)){ 11316935Sralph zapleft: 11416935Sralph RO(p->in.left) = FREE; 11516935Sralph LO(p) = FREE; 11616935Sralph p->in.left = p->in.left->in.left; 11716935Sralph } 118*24404Smckusick if( RCON(p) && LO(p)==o && RCON(p->in.left) && 119*24404Smckusick conval( p->in.right, o, p->in.left->in.right ) ){ 12016935Sralph goto zapleft; 12116935Sralph } 122*24404Smckusick else if( LCON(p) && RCON(p) && 123*24404Smckusick conval( p->in.left, o, p->in.right ) ){ 12416935Sralph zapright: 12516935Sralph RO(p) = FREE; 12616935Sralph p->in.left = makety( p->in.left, p->in.type, p->fn.cdim, p->fn.csiz ); 12716935Sralph p->in.op = FREE; 12816935Sralph return( clocal( p->in.left ) ); 12916935Sralph } 130*24404Smckusick /* FALL THROUGH */ 13116935Sralph 132*24404Smckusick case ASG MUL: 133*24404Smckusick /* change muls to adds or shifts */ 13416935Sralph 135*24404Smckusick if( (o == MUL || o == ASG MUL) && 136*24404Smckusick nncon(p->in.right) && (i=ispow2(RV(p)))>=0){ 137*24404Smckusick if( i == 0 ) /* multiplication by 1 */ 13816935Sralph goto zapright; 139*24404Smckusick if( i == 1 && optype(LO(p)) == LTYPE){ 140*24404Smckusick /* multiplication by 2 */ 141*24404Smckusick p->in.op = (asgop(o) ? ASG PLUS : PLUS); 142*24404Smckusick o = p->in.op; 143*24404Smckusick ncopy(p->in.right, p->in.left); 14416935Sralph } 145*24404Smckusick else { 146*24404Smckusick p->in.op = (asgop(o) ? ASG LS : LS); 147*24404Smckusick o = p->in.op; 148*24404Smckusick p->in.right->in.type = p->in.right->fn.csiz = INT; 149*24404Smckusick RV(p) = i; 150*24404Smckusick } 15116935Sralph } 15216935Sralph 15316935Sralph /* change +'s of negative consts back to - */ 15416935Sralph if( o==PLUS && nncon(p->in.right) && RV(p)<0 ){ 15516935Sralph RV(p) = -RV(p); 15616935Sralph o = p->in.op = MINUS; 15716935Sralph } 158*24404Smckusick /* FALL THROUGH */ 159*24404Smckusick case ASG AND: 160*24404Smckusick case ASG PLUS: 161*24404Smckusick case ASG MINUS: 16218019Sralph case RS: 16318019Sralph case LS: 164*24404Smckusick /* Operations with zero */ 165*24404Smckusick if( nncon(p->in.right) && RV(p) == 0 ) { 166*24404Smckusick if( o == MUL || o == ASG MUL || 167*24404Smckusick o == AND || o == ASG AND ) { 168*24404Smckusick if( asgop(o) ) 169*24404Smckusick p->in.op = ASSIGN; 170*24404Smckusick else if( optype(LO(p)) == LTYPE ) { 171*24404Smckusick p->in.op = FREE; 172*24404Smckusick LO(p) = FREE; 173*24404Smckusick p = p->in.right; 174*24404Smckusick } 175*24404Smckusick else 176*24404Smckusick p->in.op = COMOP; /* side effects */ 177*24404Smckusick } 178*24404Smckusick else if( o == PLUS || o == MINUS || 179*24404Smckusick o == ASG PLUS || o == ASG MINUS || 180*24404Smckusick o == OR || o == ER || 181*24404Smckusick o == LS || o == RS ) 182*24404Smckusick goto zapright; 183*24404Smckusick } 184*24404Smckusick break; 18516935Sralph 186*24404Smckusick case ASG DIV: 18716935Sralph case DIV: 188*24404Smckusick if( nncon( p->in.right ) ){ 189*24404Smckusick if( RV(p) == 0 ) uerror("division by zero"); 190*24404Smckusick else if( RV(p) == 1 ) goto zapright; 191*24404Smckusick /* Unsigned division by a power of two */ 192*24404Smckusick else if( (i=ispow2(RV(p)))>=0 && 193*24404Smckusick (ISUNSIGNED(p->in.left->in.type) || 194*24404Smckusick ISUNSIGNED(p->in.right->in.type)) ){ 195*24404Smckusick p->in.op = (asgop(o) ? ASG RS : RS); 196*24404Smckusick p->in.right->in.type = p->in.right->fn.csiz = INT; 197*24404Smckusick RV(p) = i; 198*24404Smckusick } 19918019Sralph } 20016935Sralph break; 20116935Sralph 202*24404Smckusick case ASG MOD: 20318019Sralph case MOD: 204*24404Smckusick if( nncon(p->in.right) ){ 205*24404Smckusick if( RV(p) == 0 ) uerror("modulus of zero"); 206*24404Smckusick else if( RV(p) == 1 ){ /* mod by one gives zero */ 207*24404Smckusick RV(p) = 0; 208*24404Smckusick if( asgop(o) ) 209*24404Smckusick p->in.op = ASSIGN; 210*24404Smckusick else if( optype(LO(p)) == LTYPE ) { 211*24404Smckusick p->in.op = FREE; 212*24404Smckusick LO(p) = FREE; 213*24404Smckusick p = p->in.right; 214*24404Smckusick } 215*24404Smckusick else 216*24404Smckusick p->in.op = COMOP; /* side effects */ 217*24404Smckusick } 218*24404Smckusick else if ((i=ispow2(RV(p)))>=0 && 219*24404Smckusick (ISUNSIGNED(p->in.left->in.type) || 220*24404Smckusick ISUNSIGNED(p->in.right->in.type)) ){ 221*24404Smckusick /* Unsigned mod by a power of two */ 222*24404Smckusick p->in.op = (asgop(o) ? ASG AND : AND); 223*24404Smckusick RV(p)--; 224*24404Smckusick } 22518019Sralph } 22618019Sralph break; 22718019Sralph 22816935Sralph case EQ: 22916935Sralph case NE: 23016935Sralph case LT: 23116935Sralph case LE: 23216935Sralph case GT: 23316935Sralph case GE: 23416935Sralph case ULT: 23516935Sralph case ULE: 23616935Sralph case UGT: 23716935Sralph case UGE: 23816935Sralph if( !LCON(p) ) break; 23916935Sralph 24016935Sralph /* exchange operands */ 24116935Sralph 24216935Sralph sp = p->in.left; 24316935Sralph p->in.left = p->in.right; 24416935Sralph p->in.right = sp; 24516935Sralph p->in.op = revrel[p->in.op - EQ ]; 24616935Sralph break; 24716935Sralph 24816935Sralph } 24916935Sralph 25016935Sralph return(p); 25116935Sralph } 25216935Sralph 25316935Sralph ispow2( c ) CONSZ c; { 25416935Sralph register i; 25516935Sralph if( c <= 0 || (c&(c-1)) ) return(-1); 25616935Sralph for( i=0; c>1; ++i) c >>= 1; 25716935Sralph return(i); 25816935Sralph } 259