xref: /inferno-os/utils/8c/sgen.c (revision e45fa0eb0763b57d6fb0649c064bc3b95ccdea6c)
1 #include "gc.h"
2 
3 void
4 noretval(int n)
5 {
6 
7 	if(n & 1) {
8 		gins(ANOP, Z, Z);
9 		p->to.type = REGRET;
10 	}
11 	if(n & 2) {
12 		gins(ANOP, Z, Z);
13 		p->to.type = FREGRET;
14 	}
15 	if((n&3) == 3)
16 	if(thisfn && thisfn->link && typefd[thisfn->link->etype])
17 		gins(AFLDZ, Z, Z);
18 }
19 
20 /* welcome to commute */
21 static void
22 commute(Node *n)
23 {
24 	Node *l, *r;
25 
26 	l = n->left;
27 	r = n->right;
28 	if(r->complex > l->complex) {
29 		n->left = r;
30 		n->right = l;
31 	}
32 }
33 
34 void
35 indexshift(Node *n)
36 {
37 	int g;
38 
39 	if(!typechlp[n->type->etype])
40 		return;
41 	simplifyshift(n);
42 	if(n->op == OASHL && n->right->op == OCONST){
43 		g = vconst(n->right);
44 		if(g >= 0 && g < 4)
45 			n->addable = 7;
46 	}
47 }
48 
49 /*
50  *	calculate addressability as follows
51  *		NAME ==> 10/11		name+value(SB/SP)
52  *		REGISTER ==> 12		register
53  *		CONST ==> 20		$value
54  *		*(20) ==> 21		value
55  *		&(10) ==> 13		$name+value(SB)
56  *		&(11) ==> 1		$name+value(SP)
57  *		(13) + (20) ==> 13	fold constants
58  *		(1) + (20) ==> 1	fold constants
59  *		*(13) ==> 10		back to name
60  *		*(1) ==> 11		back to name
61  *
62  *		(20) * (X) ==> 7	multiplier in indexing
63  *		(X,7) + (13,1) ==> 8	adder in indexing (addresses)
64  *		(8) ==> &9(OINDEX)	index, almost addressable
65  *
66  *	calculate complexity (number of registers)
67  */
68 void
69 xcom(Node *n)
70 {
71 	Node *l, *r;
72 	int g;
73 
74 	if(n == Z)
75 		return;
76 	l = n->left;
77 	r = n->right;
78 	n->complex = 0;
79 	n->addable = 0;
80 	switch(n->op) {
81 	case OCONST:
82 		n->addable = 20;
83 		break;
84 
85 	case ONAME:
86 		n->addable = 10;
87 		if(n->class == CPARAM || n->class == CAUTO)
88 			n->addable = 11;
89 		break;
90 
91 	case OEXREG:
92 		n->addable = 12;
93 		break;
94 
95 	case OREGISTER:
96 		n->addable = 12;
97 		break;
98 
99 	case OINDREG:
100 		n->addable = 12;
101 		break;
102 
103 	case OADDR:
104 		xcom(l);
105 		if(l->addable == 10)
106 			n->addable = 13;
107 		else
108 		if(l->addable == 11)
109 			n->addable = 1;
110 		break;
111 
112 	case OADD:
113 		xcom(l);
114 		xcom(r);
115 		if(n->type->etype != TIND)
116 			break;
117 
118 		switch(r->addable) {
119 		case 20:
120 			switch(l->addable) {
121 			case 1:
122 			case 13:
123 			commadd:
124 				l->type = n->type;
125 				*n = *l;
126 				l = new(0, Z, Z);
127 				*l = *(n->left);
128 				l->xoffset += r->vconst;
129 				n->left = l;
130 				r = n->right;
131 				goto brk;
132 			}
133 			break;
134 
135 		case 1:
136 		case 13:
137 		case 10:
138 		case 11:
139 			/* l is the base, r is the index */
140 			if(l->addable != 20)
141 				n->addable = 8;
142 			break;
143 		}
144 		switch(l->addable) {
145 		case 20:
146 			switch(r->addable) {
147 			case 13:
148 			case 1:
149 				r = n->left;
150 				l = n->right;
151 				n->left = l;
152 				n->right = r;
153 				goto commadd;
154 			}
155 			break;
156 
157 		case 13:
158 		case 1:
159 		case 10:
160 		case 11:
161 			/* r is the base, l is the index */
162 			if(r->addable != 20)
163 				n->addable = 8;
164 			break;
165 		}
166 		if(n->addable == 8 && !side(n)) {
167 			indx(n);
168 			l = new1(OINDEX, idx.basetree, idx.regtree);
169 			l->scale = idx.scale;
170 			l->addable = 9;
171 			l->complex = l->right->complex;
172 			l->type = l->left->type;
173 			n->op = OADDR;
174 			n->left = l;
175 			n->right = Z;
176 			n->addable = 8;
177 			break;
178 		}
179 		break;
180 
181 	case OINDEX:
182 		xcom(l);
183 		xcom(r);
184 		n->addable = 9;
185 		break;
186 
187 	case OIND:
188 		xcom(l);
189 		if(l->op == OADDR) {
190 			l = l->left;
191 			l->type = n->type;
192 			*n = *l;
193 			return;
194 		}
195 		switch(l->addable) {
196 		case 20:
197 			n->addable = 21;
198 			break;
199 		case 1:
200 			n->addable = 11;
201 			break;
202 		case 13:
203 			n->addable = 10;
204 			break;
205 		}
206 		break;
207 
208 	case OASHL:
209 		xcom(l);
210 		xcom(r);
211 		indexshift(n);
212 		break;
213 
214 	case OMUL:
215 	case OLMUL:
216 		xcom(l);
217 		xcom(r);
218 		g = vlog(l);
219 		if(g >= 0) {
220 			n->left = r;
221 			n->right = l;
222 			l = r;
223 			r = n->right;
224 		}
225 		g = vlog(r);
226 		if(g >= 0) {
227 			n->op = OASHL;
228 			r->vconst = g;
229 			r->type = types[TINT];
230 			indexshift(n);
231 			break;
232 		}
233 commute(n);
234 		break;
235 
236 	case OASLDIV:
237 		xcom(l);
238 		xcom(r);
239 		g = vlog(r);
240 		if(g >= 0) {
241 			n->op = OASLSHR;
242 			r->vconst = g;
243 			r->type = types[TINT];
244 		}
245 		break;
246 
247 	case OLDIV:
248 		xcom(l);
249 		xcom(r);
250 		g = vlog(r);
251 		if(g >= 0) {
252 			n->op = OLSHR;
253 			r->vconst = g;
254 			r->type = types[TINT];
255 			indexshift(n);
256 			break;
257 		}
258 		break;
259 
260 	case OASLMOD:
261 		xcom(l);
262 		xcom(r);
263 		g = vlog(r);
264 		if(g >= 0) {
265 			n->op = OASAND;
266 			r->vconst--;
267 		}
268 		break;
269 
270 	case OLMOD:
271 		xcom(l);
272 		xcom(r);
273 		g = vlog(r);
274 		if(g >= 0) {
275 			n->op = OAND;
276 			r->vconst--;
277 		}
278 		break;
279 
280 	case OASMUL:
281 	case OASLMUL:
282 		xcom(l);
283 		xcom(r);
284 		g = vlog(r);
285 		if(g >= 0) {
286 			n->op = OASASHL;
287 			r->vconst = g;
288 		}
289 		break;
290 
291 	case OLSHR:
292 	case OASHR:
293 		xcom(l);
294 		xcom(r);
295 		indexshift(n);
296 		break;
297 
298 	default:
299 		if(l != Z)
300 			xcom(l);
301 		if(r != Z)
302 			xcom(r);
303 		break;
304 	}
305 brk:
306 	if(n->addable >= 10)
307 		return;
308 	if(l != Z)
309 		n->complex = l->complex;
310 	if(r != Z) {
311 		if(r->complex == n->complex)
312 			n->complex = r->complex+1;
313 		else
314 		if(r->complex > n->complex)
315 			n->complex = r->complex;
316 	}
317 	if(n->complex == 0)
318 		n->complex++;
319 
320 	if(com64(n))
321 		return;
322 
323 	switch(n->op) {
324 
325 	case OFUNC:
326 		n->complex = FNX;
327 		break;
328 
329 	case OLMOD:
330 	case OMOD:
331 	case OLMUL:
332 	case OLDIV:
333 	case OMUL:
334 	case ODIV:
335 	case OASLMUL:
336 	case OASLDIV:
337 	case OASLMOD:
338 	case OASMUL:
339 	case OASDIV:
340 	case OASMOD:
341 		if(r->complex >= l->complex) {
342 			n->complex = l->complex + 3;
343 			if(r->complex > n->complex)
344 				n->complex = r->complex;
345 		} else {
346 			n->complex = r->complex + 3;
347 			if(l->complex > n->complex)
348 				n->complex = l->complex;
349 		}
350 		break;
351 
352 	case OLSHR:
353 	case OASHL:
354 	case OASHR:
355 	case OASLSHR:
356 	case OASASHL:
357 	case OASASHR:
358 		if(r->complex >= l->complex) {
359 			n->complex = l->complex + 2;
360 			if(r->complex > n->complex)
361 				n->complex = r->complex;
362 		} else {
363 			n->complex = r->complex + 2;
364 			if(l->complex > n->complex)
365 				n->complex = l->complex;
366 		}
367 		break;
368 
369 	case OADD:
370 	case OXOR:
371 	case OAND:
372 	case OOR:
373 		/*
374 		 * immediate operators, make const on right
375 		 */
376 		if(l->op == OCONST) {
377 			n->left = r;
378 			n->right = l;
379 		}
380 		break;
381 
382 	case OEQ:
383 	case ONE:
384 	case OLE:
385 	case OLT:
386 	case OGE:
387 	case OGT:
388 	case OHI:
389 	case OHS:
390 	case OLO:
391 	case OLS:
392 		/*
393 		 * compare operators, make const on left
394 		 */
395 		if(r->op == OCONST) {
396 			n->left = r;
397 			n->right = l;
398 			n->op = invrel[relindex(n->op)];
399 		}
400 		break;
401 	}
402 }
403 
404 void
405 indx(Node *n)
406 {
407 	Node *l, *r;
408 
409 	if(debug['x'])
410 		prtree(n, "indx");
411 
412 	l = n->left;
413 	r = n->right;
414 	if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
415 		n->right = l;
416 		n->left = r;
417 		l = r;
418 		r = n->right;
419 	}
420 	if(l->addable != 7) {
421 		idx.regtree = l;
422 		idx.scale = 1;
423 	} else
424 	if(l->right->addable == 20) {
425 		idx.regtree = l->left;
426 		idx.scale = 1 << l->right->vconst;
427 	} else
428 	if(l->left->addable == 20) {
429 		idx.regtree = l->right;
430 		idx.scale = 1 << l->left->vconst;
431 	} else
432 		diag(n, "bad index");
433 
434 	idx.basetree = r;
435 	if(debug['x']) {
436 		print("scale = %d\n", idx.scale);
437 		prtree(idx.regtree, "index");
438 		prtree(idx.basetree, "base");
439 	}
440 }
441