BSD 4_3 release
[unix-history] / usr / src / lib / mip / optim.c
CommitLineData
262eaf56 1#ifndef lint
95f51977 2static char *sccsid ="@(#)optim.c 4.7 (Berkeley) 1/8/86";
262eaf56
RC
3#endif lint
4
69023ebb 5# include "pass1.h"
ea305ab4
RC
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
3464f46e
KM
15 /* is p a constant without a name */
16# define nncon(p) ((p)->in.op == ICON && (p)->tn.rval == NONAME)
17
ea305ab4
RC
18int oflag = 0;
19
20NODE *
21fortarg( 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 */
37short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
38NODE *
39optim(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:
69d46158 68 if( LO(p) != NAME || !andable(p->in.left) ) return(p);
ea305ab4
RC
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) &&
3464f46e 112 conval(p->in.right, MINUS, p->in.left->in.right)){
ea305ab4
RC
113 zapleft:
114 RO(p->in.left) = FREE;
115 LO(p) = FREE;
116 p->in.left = p->in.left->in.left;
117 }
3464f46e
KM
118 if( RCON(p) && LO(p)==o && RCON(p->in.left) &&
119 conval( p->in.right, o, p->in.left->in.right ) ){
ea305ab4
RC
120 goto zapleft;
121 }
3464f46e
KM
122 else if( LCON(p) && RCON(p) &&
123 conval( p->in.left, o, p->in.right ) ){
ea305ab4
RC
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 }
3464f46e 130 /* FALL THROUGH */
ea305ab4 131
3464f46e
KM
132 case ASG MUL:
133 /* change muls to adds or shifts */
ea305ab4 134
3464f46e
KM
135 if( (o == MUL || o == ASG MUL) &&
136 nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
137 if( i == 0 ) /* multiplication by 1 */
ea305ab4 138 goto zapright;
c09c8c00 139 /* c2 will turn 'i << 1' into 'i + i' for us */
3464f46e
KM
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;
ea305ab4 145 }
ea305ab4
RC
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 }
3464f46e
KM
153 /* FALL THROUGH */
154 case ASG AND:
155 case ASG PLUS:
156 case ASG MINUS:
2cc78946
RC
157 case RS:
158 case LS:
3464f46e
KM
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 }
c09c8c00
DS
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 }
3464f46e 202 break;
ea305ab4 203
3464f46e 204 case ASG DIV:
ea305ab4 205 case DIV:
3464f46e
KM
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 }
2cc78946
RC
217 }
218 break;
219
3464f46e 220 case ASG MOD:
2cc78946 221 case MOD:
3464f46e
KM
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 }
2cc78946 243 }
ea305ab4
RC
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
271ispow2( 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 }