xref: /inferno-os/utils/8c/sgen.c (revision 2b69dba5038ffd0b59cf30a4c44bce549e5097f8)
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 OREGISTER:
92 		n->addable = 12;
93 		break;
94 
95 	case OINDREG:
96 		n->addable = 12;
97 		break;
98 
99 	case OADDR:
100 		xcom(l);
101 		if(l->addable == 10)
102 			n->addable = 13;
103 		else
104 		if(l->addable == 11)
105 			n->addable = 1;
106 		break;
107 
108 	case OADD:
109 		xcom(l);
110 		xcom(r);
111 		if(n->type->etype != TIND)
112 			break;
113 
114 		switch(r->addable) {
115 		case 20:
116 			switch(l->addable) {
117 			case 1:
118 			case 13:
119 			commadd:
120 				l->type = n->type;
121 				*n = *l;
122 				l = new(0, Z, Z);
123 				*l = *(n->left);
124 				l->xoffset += r->vconst;
125 				n->left = l;
126 				r = n->right;
127 				goto brk;
128 			}
129 			break;
130 
131 		case 1:
132 		case 13:
133 		case 10:
134 		case 11:
135 			/* l is the base, r is the index */
136 			if(l->addable != 20)
137 				n->addable = 8;
138 			break;
139 		}
140 		switch(l->addable) {
141 		case 20:
142 			switch(r->addable) {
143 			case 13:
144 			case 1:
145 				r = n->left;
146 				l = n->right;
147 				n->left = l;
148 				n->right = r;
149 				goto commadd;
150 			}
151 			break;
152 
153 		case 13:
154 		case 1:
155 		case 10:
156 		case 11:
157 			/* r is the base, l is the index */
158 			if(r->addable != 20)
159 				n->addable = 8;
160 			break;
161 		}
162 		if(n->addable == 8 && !side(n)) {
163 			indx(n);
164 			l = new1(OINDEX, idx.basetree, idx.regtree);
165 			l->scale = idx.scale;
166 			l->addable = 9;
167 			l->complex = l->right->complex;
168 			l->type = l->left->type;
169 			n->op = OADDR;
170 			n->left = l;
171 			n->right = Z;
172 			n->addable = 8;
173 			break;
174 		}
175 		break;
176 
177 	case OINDEX:
178 		xcom(l);
179 		xcom(r);
180 		n->addable = 9;
181 		break;
182 
183 	case OIND:
184 		xcom(l);
185 		if(l->op == OADDR) {
186 			l = l->left;
187 			l->type = n->type;
188 			*n = *l;
189 			return;
190 		}
191 		switch(l->addable) {
192 		case 20:
193 			n->addable = 21;
194 			break;
195 		case 1:
196 			n->addable = 11;
197 			break;
198 		case 13:
199 			n->addable = 10;
200 			break;
201 		}
202 		break;
203 
204 	case OASHL:
205 		xcom(l);
206 		xcom(r);
207 		indexshift(n);
208 		break;
209 
210 	case OMUL:
211 	case OLMUL:
212 		xcom(l);
213 		xcom(r);
214 		g = vlog(l);
215 		if(g >= 0) {
216 			n->left = r;
217 			n->right = l;
218 			l = r;
219 			r = n->right;
220 		}
221 		g = vlog(r);
222 		if(g >= 0) {
223 			n->op = OASHL;
224 			r->vconst = g;
225 			r->type = types[TINT];
226 			indexshift(n);
227 			break;
228 		}
229 commute(n);
230 		break;
231 
232 	case OASLDIV:
233 		xcom(l);
234 		xcom(r);
235 		g = vlog(r);
236 		if(g >= 0) {
237 			n->op = OASLSHR;
238 			r->vconst = g;
239 			r->type = types[TINT];
240 		}
241 		break;
242 
243 	case OLDIV:
244 		xcom(l);
245 		xcom(r);
246 		g = vlog(r);
247 		if(g >= 0) {
248 			n->op = OLSHR;
249 			r->vconst = g;
250 			r->type = types[TINT];
251 			indexshift(n);
252 			break;
253 		}
254 		break;
255 
256 	case OASLMOD:
257 		xcom(l);
258 		xcom(r);
259 		g = vlog(r);
260 		if(g >= 0) {
261 			n->op = OASAND;
262 			r->vconst--;
263 		}
264 		break;
265 
266 	case OLMOD:
267 		xcom(l);
268 		xcom(r);
269 		g = vlog(r);
270 		if(g >= 0) {
271 			n->op = OAND;
272 			r->vconst--;
273 		}
274 		break;
275 
276 	case OASMUL:
277 	case OASLMUL:
278 		xcom(l);
279 		xcom(r);
280 		g = vlog(r);
281 		if(g >= 0) {
282 			n->op = OASASHL;
283 			r->vconst = g;
284 		}
285 		break;
286 
287 	case OLSHR:
288 	case OASHR:
289 		xcom(l);
290 		xcom(r);
291 		indexshift(n);
292 		break;
293 
294 	default:
295 		if(l != Z)
296 			xcom(l);
297 		if(r != Z)
298 			xcom(r);
299 		break;
300 	}
301 brk:
302 	if(n->addable >= 10)
303 		return;
304 	if(l != Z)
305 		n->complex = l->complex;
306 	if(r != Z) {
307 		if(r->complex == n->complex)
308 			n->complex = r->complex+1;
309 		else
310 		if(r->complex > n->complex)
311 			n->complex = r->complex;
312 	}
313 	if(n->complex == 0)
314 		n->complex++;
315 
316 	if(com64(n))
317 		return;
318 
319 	switch(n->op) {
320 
321 	case OFUNC:
322 		n->complex = FNX;
323 		break;
324 
325 	case OLMOD:
326 	case OMOD:
327 	case OLMUL:
328 	case OLDIV:
329 	case OMUL:
330 	case ODIV:
331 	case OASLMUL:
332 	case OASLDIV:
333 	case OASLMOD:
334 	case OASMUL:
335 	case OASDIV:
336 	case OASMOD:
337 		if(r->complex >= l->complex) {
338 			n->complex = l->complex + 3;
339 			if(r->complex > n->complex)
340 				n->complex = r->complex;
341 		} else {
342 			n->complex = r->complex + 3;
343 			if(l->complex > n->complex)
344 				n->complex = l->complex;
345 		}
346 		break;
347 
348 	case OLSHR:
349 	case OASHL:
350 	case OASHR:
351 	case OASLSHR:
352 	case OASASHL:
353 	case OASASHR:
354 		if(r->complex >= l->complex) {
355 			n->complex = l->complex + 2;
356 			if(r->complex > n->complex)
357 				n->complex = r->complex;
358 		} else {
359 			n->complex = r->complex + 2;
360 			if(l->complex > n->complex)
361 				n->complex = l->complex;
362 		}
363 		break;
364 
365 	case OADD:
366 	case OXOR:
367 	case OAND:
368 	case OOR:
369 		/*
370 		 * immediate operators, make const on right
371 		 */
372 		if(l->op == OCONST) {
373 			n->left = r;
374 			n->right = l;
375 		}
376 		break;
377 
378 	case OEQ:
379 	case ONE:
380 	case OLE:
381 	case OLT:
382 	case OGE:
383 	case OGT:
384 	case OHI:
385 	case OHS:
386 	case OLO:
387 	case OLS:
388 		/*
389 		 * compare operators, make const on left
390 		 */
391 		if(r->op == OCONST) {
392 			n->left = r;
393 			n->right = l;
394 			n->op = invrel[relindex(n->op)];
395 		}
396 		break;
397 	}
398 }
399 
400 void
401 indx(Node *n)
402 {
403 	Node *l, *r;
404 
405 	if(debug['x'])
406 		prtree(n, "indx");
407 
408 	l = n->left;
409 	r = n->right;
410 	if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
411 		n->right = l;
412 		n->left = r;
413 		l = r;
414 		r = n->right;
415 	}
416 	if(l->addable != 7) {
417 		idx.regtree = l;
418 		idx.scale = 1;
419 	} else
420 	if(l->right->addable == 20) {
421 		idx.regtree = l->left;
422 		idx.scale = 1 << l->right->vconst;
423 	} else
424 	if(l->left->addable == 20) {
425 		idx.regtree = l->right;
426 		idx.scale = 1 << l->left->vconst;
427 	} else
428 		diag(n, "bad index");
429 
430 	idx.basetree = r;
431 	if(debug['x']) {
432 		print("scale = %d\n", idx.scale);
433 		prtree(idx.regtree, "index");
434 		prtree(idx.basetree, "base");
435 	}
436 }
437