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