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