xref: /original-bsd/old/pcc/mip/optim.c (revision 2301fdfb)
1 #ifndef lint
2 static char *sccsid ="@(#)optim.c	4.7 (Berkeley) 01/08/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 	}
277