Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
}