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