xref: /csrg-svn/old/pcc/mip/optim.c (revision 24404)
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