xref: /plan9/sys/src/cmd/cc/scon.c (revision 2cca75a1b2b8c6083390679d69d5c50cf66d9a01)
1375daca8SDavid du Colombier #include "cc.h"
2375daca8SDavid du Colombier 
3*2cca75a1SDavid du Colombier static Node*
acast(Type * t,Node * n)4*2cca75a1SDavid du Colombier acast(Type *t, Node *n)
5*2cca75a1SDavid du Colombier {
6*2cca75a1SDavid du Colombier 	if(n->type->etype != t->etype || n->op == OBIT) {
7*2cca75a1SDavid du Colombier 		n = new1(OCAST, n, Z);
8*2cca75a1SDavid du Colombier 		if(nocast(n->left->type, t))
9*2cca75a1SDavid du Colombier 			*n = *n->left;
10*2cca75a1SDavid du Colombier 		n->type = t;
11*2cca75a1SDavid du Colombier 	}
12*2cca75a1SDavid du Colombier 	return n;
13*2cca75a1SDavid du Colombier }
14*2cca75a1SDavid du Colombier 
15*2cca75a1SDavid du Colombier 
16375daca8SDavid du Colombier void
evconst(Node * n)17375daca8SDavid du Colombier evconst(Node *n)
18375daca8SDavid du Colombier {
19375daca8SDavid du Colombier 	Node *l, *r;
20375daca8SDavid du Colombier 	int et, isf;
21375daca8SDavid du Colombier 	vlong v;
22375daca8SDavid du Colombier 	double d;
23375daca8SDavid du Colombier 
24375daca8SDavid du Colombier 	if(n == Z || n->type == T)
25375daca8SDavid du Colombier 		return;
26375daca8SDavid du Colombier 
27375daca8SDavid du Colombier 	et = n->type->etype;
28375daca8SDavid du Colombier 	isf = typefd[et];
29375daca8SDavid du Colombier 
30375daca8SDavid du Colombier 	l = n->left;
31375daca8SDavid du Colombier 	r = n->right;
32375daca8SDavid du Colombier 
33375daca8SDavid du Colombier 	d = 0;
34375daca8SDavid du Colombier 	v = 0;
35375daca8SDavid du Colombier 
36375daca8SDavid du Colombier 	switch(n->op) {
37375daca8SDavid du Colombier 	default:
38375daca8SDavid du Colombier 		return;
39375daca8SDavid du Colombier 
40375daca8SDavid du Colombier 	case ONEG:
41375daca8SDavid du Colombier 		if(isf)
42375daca8SDavid du Colombier 			d = -l->fconst;
43375daca8SDavid du Colombier 		else
44375daca8SDavid du Colombier 			v = -l->vconst;
45375daca8SDavid du Colombier 		break;
46375daca8SDavid du Colombier 
47375daca8SDavid du Colombier 	case OCOM:
48375daca8SDavid du Colombier 		v = ~l->vconst;
49375daca8SDavid du Colombier 		break;
50375daca8SDavid du Colombier 
51375daca8SDavid du Colombier 	case OCAST:
52375daca8SDavid du Colombier 		if(et == TVOID)
53375daca8SDavid du Colombier 			return;
54375daca8SDavid du Colombier 		et = l->type->etype;
55375daca8SDavid du Colombier 		if(isf) {
56375daca8SDavid du Colombier 			if(typefd[et])
57375daca8SDavid du Colombier 				d = l->fconst;
58375daca8SDavid du Colombier 			else
59375daca8SDavid du Colombier 				d = l->vconst;
60375daca8SDavid du Colombier 		} else {
61375daca8SDavid du Colombier 			if(typefd[et])
62375daca8SDavid du Colombier 				v = l->fconst;
63375daca8SDavid du Colombier 			else
64375daca8SDavid du Colombier 				v = convvtox(l->vconst, n->type->etype);
65375daca8SDavid du Colombier 		}
66375daca8SDavid du Colombier 		break;
67375daca8SDavid du Colombier 
68375daca8SDavid du Colombier 	case OCONST:
69375daca8SDavid du Colombier 		break;
70375daca8SDavid du Colombier 
71375daca8SDavid du Colombier 	case OADD:
72375daca8SDavid du Colombier 		if(isf)
73375daca8SDavid du Colombier 			d = l->fconst + r->fconst;
74375daca8SDavid du Colombier 		else {
75375daca8SDavid du Colombier 			v = l->vconst + r->vconst;
76375daca8SDavid du Colombier 		}
77375daca8SDavid du Colombier 		break;
78375daca8SDavid du Colombier 
79375daca8SDavid du Colombier 	case OSUB:
80375daca8SDavid du Colombier 		if(isf)
81375daca8SDavid du Colombier 			d = l->fconst - r->fconst;
82375daca8SDavid du Colombier 		else
83375daca8SDavid du Colombier 			v = l->vconst - r->vconst;
84375daca8SDavid du Colombier 		break;
85375daca8SDavid du Colombier 
86375daca8SDavid du Colombier 	case OMUL:
87375daca8SDavid du Colombier 		if(isf)
88375daca8SDavid du Colombier 			d = l->fconst * r->fconst;
89375daca8SDavid du Colombier 		else {
90375daca8SDavid du Colombier 			v = l->vconst * r->vconst;
91375daca8SDavid du Colombier 		}
92375daca8SDavid du Colombier 		break;
93375daca8SDavid du Colombier 
94375daca8SDavid du Colombier 	case OLMUL:
95375daca8SDavid du Colombier 		v = (uvlong)l->vconst * (uvlong)r->vconst;
96375daca8SDavid du Colombier 		break;
97375daca8SDavid du Colombier 
98375daca8SDavid du Colombier 
99375daca8SDavid du Colombier 	case ODIV:
100375daca8SDavid du Colombier 		if(vconst(r) == 0) {
101375daca8SDavid du Colombier 			warn(n, "divide by zero");
102375daca8SDavid du Colombier 			return;
103375daca8SDavid du Colombier 		}
104375daca8SDavid du Colombier 		if(isf)
105375daca8SDavid du Colombier 			d = l->fconst / r->fconst;
106375daca8SDavid du Colombier 		else
107375daca8SDavid du Colombier 			v = l->vconst / r->vconst;
108375daca8SDavid du Colombier 		break;
109375daca8SDavid du Colombier 
110375daca8SDavid du Colombier 	case OLDIV:
111375daca8SDavid du Colombier 		if(vconst(r) == 0) {
112375daca8SDavid du Colombier 			warn(n, "divide by zero");
113375daca8SDavid du Colombier 			return;
114375daca8SDavid du Colombier 		}
115375daca8SDavid du Colombier 		v = (uvlong)l->vconst / (uvlong)r->vconst;
116375daca8SDavid du Colombier 		break;
117375daca8SDavid du Colombier 
118375daca8SDavid du Colombier 	case OMOD:
119375daca8SDavid du Colombier 		if(vconst(r) == 0) {
120375daca8SDavid du Colombier 			warn(n, "modulo by zero");
121375daca8SDavid du Colombier 			return;
122375daca8SDavid du Colombier 		}
123375daca8SDavid du Colombier 		v = l->vconst % r->vconst;
124375daca8SDavid du Colombier 		break;
125375daca8SDavid du Colombier 
126375daca8SDavid du Colombier 	case OLMOD:
127375daca8SDavid du Colombier 		if(vconst(r) == 0) {
128375daca8SDavid du Colombier 			warn(n, "modulo by zero");
129375daca8SDavid du Colombier 			return;
130375daca8SDavid du Colombier 		}
131375daca8SDavid du Colombier 		v = (uvlong)l->vconst % (uvlong)r->vconst;
132375daca8SDavid du Colombier 		break;
133375daca8SDavid du Colombier 
134375daca8SDavid du Colombier 	case OAND:
135375daca8SDavid du Colombier 		v = l->vconst & r->vconst;
136375daca8SDavid du Colombier 		break;
137375daca8SDavid du Colombier 
138375daca8SDavid du Colombier 	case OOR:
139375daca8SDavid du Colombier 		v = l->vconst | r->vconst;
140375daca8SDavid du Colombier 		break;
141375daca8SDavid du Colombier 
142375daca8SDavid du Colombier 	case OXOR:
143375daca8SDavid du Colombier 		v = l->vconst ^ r->vconst;
144375daca8SDavid du Colombier 		break;
145375daca8SDavid du Colombier 
146375daca8SDavid du Colombier 	case OLSHR:
147375daca8SDavid du Colombier 		v = (uvlong)l->vconst >> r->vconst;
148375daca8SDavid du Colombier 		break;
149375daca8SDavid du Colombier 
150375daca8SDavid du Colombier 	case OASHR:
151375daca8SDavid du Colombier 		v = l->vconst >> r->vconst;
152375daca8SDavid du Colombier 		break;
153375daca8SDavid du Colombier 
154375daca8SDavid du Colombier 	case OASHL:
155375daca8SDavid du Colombier 		v = l->vconst << r->vconst;
156375daca8SDavid du Colombier 		break;
157375daca8SDavid du Colombier 
158375daca8SDavid du Colombier 	case OLO:
159375daca8SDavid du Colombier 		v = (uvlong)l->vconst < (uvlong)r->vconst;
160375daca8SDavid du Colombier 		break;
161375daca8SDavid du Colombier 
162375daca8SDavid du Colombier 	case OLT:
163375daca8SDavid du Colombier 		if(typefd[l->type->etype])
164375daca8SDavid du Colombier 			v = l->fconst < r->fconst;
165375daca8SDavid du Colombier 		else
166375daca8SDavid du Colombier 			v = l->vconst < r->vconst;
167375daca8SDavid du Colombier 		break;
168375daca8SDavid du Colombier 
169375daca8SDavid du Colombier 	case OHI:
170375daca8SDavid du Colombier 		v = (uvlong)l->vconst > (uvlong)r->vconst;
171375daca8SDavid du Colombier 		break;
172375daca8SDavid du Colombier 
173375daca8SDavid du Colombier 	case OGT:
174375daca8SDavid du Colombier 		if(typefd[l->type->etype])
175375daca8SDavid du Colombier 			v = l->fconst > r->fconst;
176375daca8SDavid du Colombier 		else
177375daca8SDavid du Colombier 			v = l->vconst > r->vconst;
178375daca8SDavid du Colombier 		break;
179375daca8SDavid du Colombier 
180375daca8SDavid du Colombier 	case OLS:
181375daca8SDavid du Colombier 		v = (uvlong)l->vconst <= (uvlong)r->vconst;
182375daca8SDavid du Colombier 		break;
183375daca8SDavid du Colombier 
184375daca8SDavid du Colombier 	case OLE:
185375daca8SDavid du Colombier 		if(typefd[l->type->etype])
186375daca8SDavid du Colombier 			v = l->fconst <= r->fconst;
187375daca8SDavid du Colombier 		else
188375daca8SDavid du Colombier 			v = l->vconst <= r->vconst;
189375daca8SDavid du Colombier 		break;
190375daca8SDavid du Colombier 
191375daca8SDavid du Colombier 	case OHS:
192375daca8SDavid du Colombier 		v = (uvlong)l->vconst >= (uvlong)r->vconst;
193375daca8SDavid du Colombier 		break;
194375daca8SDavid du Colombier 
195375daca8SDavid du Colombier 	case OGE:
196375daca8SDavid du Colombier 		if(typefd[l->type->etype])
197375daca8SDavid du Colombier 			v = l->fconst >= r->fconst;
198375daca8SDavid du Colombier 		else
199375daca8SDavid du Colombier 			v = l->vconst >= r->vconst;
200375daca8SDavid du Colombier 		break;
201375daca8SDavid du Colombier 
202375daca8SDavid du Colombier 	case OEQ:
203375daca8SDavid du Colombier 		if(typefd[l->type->etype])
204375daca8SDavid du Colombier 			v = l->fconst == r->fconst;
205375daca8SDavid du Colombier 		else
206375daca8SDavid du Colombier 			v = l->vconst == r->vconst;
207375daca8SDavid du Colombier 		break;
208375daca8SDavid du Colombier 
209375daca8SDavid du Colombier 	case ONE:
210375daca8SDavid du Colombier 		if(typefd[l->type->etype])
211375daca8SDavid du Colombier 			v = l->fconst != r->fconst;
212375daca8SDavid du Colombier 		else
213375daca8SDavid du Colombier 			v = l->vconst != r->vconst;
214375daca8SDavid du Colombier 		break;
215375daca8SDavid du Colombier 
216375daca8SDavid du Colombier 	case ONOT:
217375daca8SDavid du Colombier 		if(typefd[l->type->etype])
218375daca8SDavid du Colombier 			v = !l->fconst;
219375daca8SDavid du Colombier 		else
220375daca8SDavid du Colombier 			v = !l->vconst;
221375daca8SDavid du Colombier 		break;
222375daca8SDavid du Colombier 
223375daca8SDavid du Colombier 	case OANDAND:
224375daca8SDavid du Colombier 		if(typefd[l->type->etype])
225375daca8SDavid du Colombier 			v = l->fconst && r->fconst;
226375daca8SDavid du Colombier 		else
227375daca8SDavid du Colombier 			v = l->vconst && r->vconst;
228375daca8SDavid du Colombier 		break;
229375daca8SDavid du Colombier 
230375daca8SDavid du Colombier 	case OOROR:
231375daca8SDavid du Colombier 		if(typefd[l->type->etype])
232375daca8SDavid du Colombier 			v = l->fconst || r->fconst;
233375daca8SDavid du Colombier 		else
234375daca8SDavid du Colombier 			v = l->vconst || r->vconst;
235375daca8SDavid du Colombier 		break;
236375daca8SDavid du Colombier 	}
237375daca8SDavid du Colombier 	if(isf) {
238375daca8SDavid du Colombier 		n->fconst = d;
239375daca8SDavid du Colombier 	} else {
240375daca8SDavid du Colombier 		n->vconst = convvtox(v, n->type->etype);
241375daca8SDavid du Colombier 	}
24222a127bbSDavid du Colombier 	n->oldop = n->op;
243375daca8SDavid du Colombier 	n->op = OCONST;
244375daca8SDavid du Colombier }
245375daca8SDavid du Colombier 
246375daca8SDavid du Colombier void
acom(Node * n)247375daca8SDavid du Colombier acom(Node *n)
248375daca8SDavid du Colombier {
249375daca8SDavid du Colombier 	Type *t;
250375daca8SDavid du Colombier 	Node *l, *r;
251375daca8SDavid du Colombier 	int i;
252375daca8SDavid du Colombier 
253375daca8SDavid du Colombier 	switch(n->op)
254375daca8SDavid du Colombier 	{
255375daca8SDavid du Colombier 
256375daca8SDavid du Colombier 	case ONAME:
257375daca8SDavid du Colombier 	case OCONST:
258375daca8SDavid du Colombier 	case OSTRING:
259375daca8SDavid du Colombier 	case OINDREG:
260375daca8SDavid du Colombier 	case OREGISTER:
261375daca8SDavid du Colombier 		return;
262375daca8SDavid du Colombier 
263375daca8SDavid du Colombier 	case ONEG:
264375daca8SDavid du Colombier 		l = n->left;
265375daca8SDavid du Colombier 		if(addo(n) && addo(l))
266375daca8SDavid du Colombier 			break;
267375daca8SDavid du Colombier 		acom(l);
268375daca8SDavid du Colombier 		return;
269375daca8SDavid du Colombier 
270375daca8SDavid du Colombier 	case OADD:
271375daca8SDavid du Colombier 	case OSUB:
272375daca8SDavid du Colombier 	case OMUL:
273375daca8SDavid du Colombier 		l = n->left;
274375daca8SDavid du Colombier 		r = n->right;
275375daca8SDavid du Colombier 		if(addo(n)) {
276375daca8SDavid du Colombier 			if(addo(r))
277375daca8SDavid du Colombier 				break;
278375daca8SDavid du Colombier 			if(addo(l))
279375daca8SDavid du Colombier 				break;
280375daca8SDavid du Colombier 		}
281375daca8SDavid du Colombier 		acom(l);
282375daca8SDavid du Colombier 		acom(r);
283375daca8SDavid du Colombier 		return;
284375daca8SDavid du Colombier 
285375daca8SDavid du Colombier 	default:
286375daca8SDavid du Colombier 		l = n->left;
287375daca8SDavid du Colombier 		r = n->right;
288375daca8SDavid du Colombier 		if(l != Z)
289375daca8SDavid du Colombier 			acom(l);
290375daca8SDavid du Colombier 		if(r != Z)
291375daca8SDavid du Colombier 			acom(r);
292375daca8SDavid du Colombier 		return;
293375daca8SDavid du Colombier 	}
294375daca8SDavid du Colombier 
295375daca8SDavid du Colombier 	/* bust terms out */
296375daca8SDavid du Colombier 	t = n->type;
297375daca8SDavid du Colombier 	term[0].mult = 0;
298375daca8SDavid du Colombier 	term[0].node = Z;
299375daca8SDavid du Colombier 	nterm = 1;
300375daca8SDavid du Colombier 	acom1(1, n);
301375daca8SDavid du Colombier 	if(debug['m'])
302375daca8SDavid du Colombier 	for(i=0; i<nterm; i++) {
303375daca8SDavid du Colombier 		print("%d %3lld ", i, term[i].mult);
304375daca8SDavid du Colombier 		prtree1(term[i].node, 1, 0);
305375daca8SDavid du Colombier 	}
306375daca8SDavid du Colombier 	if(nterm < NTERM)
307375daca8SDavid du Colombier 		acom2(n, t);
308375daca8SDavid du Colombier 	n->type = t;
309375daca8SDavid du Colombier }
310375daca8SDavid du Colombier 
311375daca8SDavid du Colombier int
acomcmp1(const void * a1,const void * a2)312375daca8SDavid du Colombier acomcmp1(const void *a1, const void *a2)
313375daca8SDavid du Colombier {
314375daca8SDavid du Colombier 	vlong c1, c2;
315375daca8SDavid du Colombier 	Term *t1, *t2;
316375daca8SDavid du Colombier 
317375daca8SDavid du Colombier 	t1 = (Term*)a1;
318375daca8SDavid du Colombier 	t2 = (Term*)a2;
319375daca8SDavid du Colombier 	c1 = t1->mult;
320375daca8SDavid du Colombier 	if(c1 < 0)
321375daca8SDavid du Colombier 		c1 = -c1;
322375daca8SDavid du Colombier 	c2 = t2->mult;
323375daca8SDavid du Colombier 	if(c2 < 0)
324375daca8SDavid du Colombier 		c2 = -c2;
325375daca8SDavid du Colombier 	if(c1 > c2)
326375daca8SDavid du Colombier 		return 1;
327375daca8SDavid du Colombier 	if(c1 < c2)
328375daca8SDavid du Colombier 		return -1;
329375daca8SDavid du Colombier 	c1 = 1;
330375daca8SDavid du Colombier 	if(t1->mult < 0)
331375daca8SDavid du Colombier 		c1 = 0;
332375daca8SDavid du Colombier 	c2 = 1;
333375daca8SDavid du Colombier 	if(t2->mult < 0)
334375daca8SDavid du Colombier 		c2 = 0;
335375daca8SDavid du Colombier 	if(c2 -= c1)
336375daca8SDavid du Colombier 		return c2;
337375daca8SDavid du Colombier 	if(t2 > t1)
338375daca8SDavid du Colombier 		return 1;
339375daca8SDavid du Colombier 	return -1;
340375daca8SDavid du Colombier }
341375daca8SDavid du Colombier 
342375daca8SDavid du Colombier int
acomcmp2(const void * a1,const void * a2)343375daca8SDavid du Colombier acomcmp2(const void *a1, const void *a2)
344375daca8SDavid du Colombier {
345375daca8SDavid du Colombier 	vlong c1, c2;
346375daca8SDavid du Colombier 	Term *t1, *t2;
347375daca8SDavid du Colombier 
348375daca8SDavid du Colombier 	t1 = (Term*)a1;
349375daca8SDavid du Colombier 	t2 = (Term*)a2;
350375daca8SDavid du Colombier 	c1 = t1->mult;
351375daca8SDavid du Colombier 	c2 = t2->mult;
352375daca8SDavid du Colombier 	if(c1 > c2)
353375daca8SDavid du Colombier 		return 1;
354375daca8SDavid du Colombier 	if(c1 < c2)
355375daca8SDavid du Colombier 		return -1;
356375daca8SDavid du Colombier 	if(t2 > t1)
357375daca8SDavid du Colombier 		return 1;
358375daca8SDavid du Colombier 	return -1;
359375daca8SDavid du Colombier }
360375daca8SDavid du Colombier 
361375daca8SDavid du Colombier void
acom2(Node * n,Type * t)362375daca8SDavid du Colombier acom2(Node *n, Type *t)
363375daca8SDavid du Colombier {
364375daca8SDavid du Colombier 	Node *l, *r;
365375daca8SDavid du Colombier 	Term trm[NTERM];
366375daca8SDavid du Colombier 	int et, nt, i, j;
367375daca8SDavid du Colombier 	vlong c1, c2;
368375daca8SDavid du Colombier 
369375daca8SDavid du Colombier 	/*
370375daca8SDavid du Colombier 	 * copy into automatic
371375daca8SDavid du Colombier 	 */
372375daca8SDavid du Colombier 	c2 = 0;
373375daca8SDavid du Colombier 	nt = nterm;
374375daca8SDavid du Colombier 	for(i=0; i<nt; i++)
375375daca8SDavid du Colombier 		trm[i] = term[i];
376375daca8SDavid du Colombier 	/*
377375daca8SDavid du Colombier 	 * recur on subtrees
378375daca8SDavid du Colombier 	 */
379375daca8SDavid du Colombier 	j = 0;
380375daca8SDavid du Colombier 	for(i=1; i<nt; i++) {
381375daca8SDavid du Colombier 		c1 = trm[i].mult;
382375daca8SDavid du Colombier 		if(c1 == 0)
383375daca8SDavid du Colombier 			continue;
384375daca8SDavid du Colombier 		l = trm[i].node;
385375daca8SDavid du Colombier 		if(l != Z) {
386375daca8SDavid du Colombier 			j = 1;
387375daca8SDavid du Colombier 			acom(l);
388375daca8SDavid du Colombier 		}
389375daca8SDavid du Colombier 	}
390375daca8SDavid du Colombier 	c1 = trm[0].mult;
391375daca8SDavid du Colombier 	if(j == 0) {
39222a127bbSDavid du Colombier 		n->oldop = n->op;
393375daca8SDavid du Colombier 		n->op = OCONST;
394375daca8SDavid du Colombier 		n->vconst = c1;
395375daca8SDavid du Colombier 		return;
396375daca8SDavid du Colombier 	}
397375daca8SDavid du Colombier 	et = t->etype;
398375daca8SDavid du Colombier 
399375daca8SDavid du Colombier 	/*
400375daca8SDavid du Colombier 	 * prepare constant term,
401375daca8SDavid du Colombier 	 * combine it with an addressing term
402375daca8SDavid du Colombier 	 */
403375daca8SDavid du Colombier 	if(c1 != 0) {
404375daca8SDavid du Colombier 		l = new1(OCONST, Z, Z);
405375daca8SDavid du Colombier 		l->type = t;
406375daca8SDavid du Colombier 		l->vconst = c1;
407375daca8SDavid du Colombier 		trm[0].mult = 1;
408375daca8SDavid du Colombier 		for(i=1; i<nt; i++) {
409375daca8SDavid du Colombier 			if(trm[i].mult != 1)
410375daca8SDavid du Colombier 				continue;
411375daca8SDavid du Colombier 			r = trm[i].node;
412375daca8SDavid du Colombier 			if(r->op != OADDR)
413375daca8SDavid du Colombier 				continue;
414375daca8SDavid du Colombier 			r->type = t;
415375daca8SDavid du Colombier 			l = new1(OADD, r, l);
416375daca8SDavid du Colombier 			l->type = t;
417375daca8SDavid du Colombier 			trm[i].mult = 0;
418375daca8SDavid du Colombier 			break;
419375daca8SDavid du Colombier 		}
420375daca8SDavid du Colombier 		trm[0].node = l;
421375daca8SDavid du Colombier 	}
422375daca8SDavid du Colombier 	/*
423375daca8SDavid du Colombier 	 * look for factorable terms
424375daca8SDavid du Colombier 	 * c1*i + c1*c2*j -> c1*(i + c2*j)
425375daca8SDavid du Colombier 	 */
426375daca8SDavid du Colombier 	qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
427375daca8SDavid du Colombier 	for(i=nt-1; i>=0; i--) {
428375daca8SDavid du Colombier 		c1 = trm[i].mult;
429375daca8SDavid du Colombier 		if(c1 < 0)
430375daca8SDavid du Colombier 			c1 = -c1;
431375daca8SDavid du Colombier 		if(c1 <= 1)
432375daca8SDavid du Colombier 			continue;
433375daca8SDavid du Colombier 		for(j=i+1; j<nt; j++) {
434375daca8SDavid du Colombier 			c2 = trm[j].mult;
435375daca8SDavid du Colombier 			if(c2 < 0)
436375daca8SDavid du Colombier 				c2 = -c2;
437375daca8SDavid du Colombier 			if(c2 <= 1)
438375daca8SDavid du Colombier 				continue;
439375daca8SDavid du Colombier 			if(c2 % c1)
440375daca8SDavid du Colombier 				continue;
441375daca8SDavid du Colombier 			r = trm[j].node;
442*2cca75a1SDavid du Colombier 			if(r->type->etype != et)
443*2cca75a1SDavid du Colombier 				r = acast(t, r);
444375daca8SDavid du Colombier 			c2 = trm[j].mult/trm[i].mult;
445375daca8SDavid du Colombier 			if(c2 != 1 && c2 != -1) {
446375daca8SDavid du Colombier 				r = new1(OMUL, r, new(OCONST, Z, Z));
447375daca8SDavid du Colombier 				r->type = t;
448375daca8SDavid du Colombier 				r->right->type = t;
449375daca8SDavid du Colombier 				r->right->vconst = c2;
450375daca8SDavid du Colombier 			}
451375daca8SDavid du Colombier 			l = trm[i].node;
452*2cca75a1SDavid du Colombier 			if(l->type->etype != et)
453*2cca75a1SDavid du Colombier 				l = acast(t, l);
454375daca8SDavid du Colombier 			r = new1(OADD, l, r);
455375daca8SDavid du Colombier 			r->type = t;
456375daca8SDavid du Colombier 			if(c2 == -1)
457375daca8SDavid du Colombier 				r->op = OSUB;
458375daca8SDavid du Colombier 			trm[i].node = r;
459375daca8SDavid du Colombier 			trm[j].mult = 0;
460375daca8SDavid du Colombier 		}
461375daca8SDavid du Colombier 	}
462375daca8SDavid du Colombier 	if(debug['m']) {
463375daca8SDavid du Colombier 		print("\n");
464375daca8SDavid du Colombier 		for(i=0; i<nt; i++) {
465375daca8SDavid du Colombier 			print("%d %3lld ", i, trm[i].mult);
466375daca8SDavid du Colombier 			prtree1(trm[i].node, 1, 0);
467375daca8SDavid du Colombier 		}
468375daca8SDavid du Colombier 	}
469375daca8SDavid du Colombier 
470375daca8SDavid du Colombier 	/*
471375daca8SDavid du Colombier 	 * put it all back together
472375daca8SDavid du Colombier 	 */
473375daca8SDavid du Colombier 	qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
474375daca8SDavid du Colombier 	l = Z;
475375daca8SDavid du Colombier 	for(i=nt-1; i>=0; i--) {
476375daca8SDavid du Colombier 		c1 = trm[i].mult;
477375daca8SDavid du Colombier 		if(c1 == 0)
478375daca8SDavid du Colombier 			continue;
479375daca8SDavid du Colombier 		r = trm[i].node;
480*2cca75a1SDavid du Colombier 		if(r->type->etype != et || r->op == OBIT)
481*2cca75a1SDavid du Colombier 			r = acast(t, r);
482375daca8SDavid du Colombier 		if(c1 != 1 && c1 != -1) {
483375daca8SDavid du Colombier 			r = new1(OMUL, r, new(OCONST, Z, Z));
484375daca8SDavid du Colombier 			r->type = t;
485375daca8SDavid du Colombier 			r->right->type = t;
486375daca8SDavid du Colombier 			if(c1 < 0) {
487375daca8SDavid du Colombier 				r->right->vconst = -c1;
488375daca8SDavid du Colombier 				c1 = -1;
489375daca8SDavid du Colombier 			} else {
490375daca8SDavid du Colombier 				r->right->vconst = c1;
491375daca8SDavid du Colombier 				c1 = 1;
492375daca8SDavid du Colombier 			}
493375daca8SDavid du Colombier 		}
494375daca8SDavid du Colombier 		if(l == Z) {
495375daca8SDavid du Colombier 			l = r;
496375daca8SDavid du Colombier 			c2 = c1;
497375daca8SDavid du Colombier 			continue;
498375daca8SDavid du Colombier 		}
499375daca8SDavid du Colombier 		if(c1 < 0)
500375daca8SDavid du Colombier 			if(c2 < 0)
501375daca8SDavid du Colombier 				l = new1(OADD, l, r);
502375daca8SDavid du Colombier 			else
503375daca8SDavid du Colombier 				l = new1(OSUB, l, r);
504375daca8SDavid du Colombier 		else
505375daca8SDavid du Colombier 			if(c2 < 0) {
506375daca8SDavid du Colombier 				l = new1(OSUB, r, l);
507375daca8SDavid du Colombier 				c2 = 1;
508375daca8SDavid du Colombier 			} else
509375daca8SDavid du Colombier 				l = new1(OADD, l, r);
510375daca8SDavid du Colombier 		l->type = t;
511375daca8SDavid du Colombier 	}
512375daca8SDavid du Colombier 	if(c2 < 0) {
513375daca8SDavid du Colombier 		r = new1(OCONST, 0, 0);
514375daca8SDavid du Colombier 		r->vconst = 0;
515375daca8SDavid du Colombier 		r->type = t;
516375daca8SDavid du Colombier 		l = new1(OSUB, r, l);
517375daca8SDavid du Colombier 		l->type = t;
518375daca8SDavid du Colombier 	}
519375daca8SDavid du Colombier 	*n = *l;
520375daca8SDavid du Colombier }
521375daca8SDavid du Colombier 
522375daca8SDavid du Colombier void
acom1(vlong v,Node * n)523375daca8SDavid du Colombier acom1(vlong v, Node *n)
524375daca8SDavid du Colombier {
525375daca8SDavid du Colombier 	Node *l, *r;
526375daca8SDavid du Colombier 
527375daca8SDavid du Colombier 	if(v == 0 || nterm >= NTERM)
528375daca8SDavid du Colombier 		return;
529375daca8SDavid du Colombier 	if(!addo(n)) {
530375daca8SDavid du Colombier 		if(n->op == OCONST)
531375daca8SDavid du Colombier 		if(!typefd[n->type->etype]) {
532375daca8SDavid du Colombier 			term[0].mult += v*n->vconst;
533375daca8SDavid du Colombier 			return;
534375daca8SDavid du Colombier 		}
535375daca8SDavid du Colombier 		term[nterm].mult = v;
536375daca8SDavid du Colombier 		term[nterm].node = n;
537375daca8SDavid du Colombier 		nterm++;
538375daca8SDavid du Colombier 		return;
539375daca8SDavid du Colombier 	}
540375daca8SDavid du Colombier 	switch(n->op) {
541375daca8SDavid du Colombier 
542375daca8SDavid du Colombier 	case OCAST:
543375daca8SDavid du Colombier 		acom1(v, n->left);
544375daca8SDavid du Colombier 		break;
545375daca8SDavid du Colombier 
546375daca8SDavid du Colombier 	case ONEG:
547375daca8SDavid du Colombier 		acom1(-v, n->left);
548375daca8SDavid du Colombier 		break;
549375daca8SDavid du Colombier 
550375daca8SDavid du Colombier 	case OADD:
551375daca8SDavid du Colombier 		acom1(v, n->left);
552375daca8SDavid du Colombier 		acom1(v, n->right);
553375daca8SDavid du Colombier 		break;
554375daca8SDavid du Colombier 
555375daca8SDavid du Colombier 	case OSUB:
556375daca8SDavid du Colombier 		acom1(v, n->left);
557375daca8SDavid du Colombier 		acom1(-v, n->right);
558375daca8SDavid du Colombier 		break;
559375daca8SDavid du Colombier 
560375daca8SDavid du Colombier 	case OMUL:
561375daca8SDavid du Colombier 		l = n->left;
562375daca8SDavid du Colombier 		r = n->right;
563375daca8SDavid du Colombier 		if(l->op == OCONST)
564375daca8SDavid du Colombier 		if(!typefd[n->type->etype]) {
565375daca8SDavid du Colombier 			acom1(v*l->vconst, r);
566375daca8SDavid du Colombier 			break;
567375daca8SDavid du Colombier 		}
568375daca8SDavid du Colombier 		if(r->op == OCONST)
569375daca8SDavid du Colombier 		if(!typefd[n->type->etype]) {
570375daca8SDavid du Colombier 			acom1(v*r->vconst, l);
571375daca8SDavid du Colombier 			break;
572375daca8SDavid du Colombier 		}
573375daca8SDavid du Colombier 		break;
574375daca8SDavid du Colombier 
575375daca8SDavid du Colombier 	default:
576375daca8SDavid du Colombier 		diag(n, "not addo");
577375daca8SDavid du Colombier 	}
578375daca8SDavid du Colombier }
579375daca8SDavid du Colombier 
580375daca8SDavid du Colombier int
addo(Node * n)581375daca8SDavid du Colombier addo(Node *n)
582375daca8SDavid du Colombier {
583375daca8SDavid du Colombier 
584375daca8SDavid du Colombier 	if(n != Z)
585375daca8SDavid du Colombier 	if(!typefd[n->type->etype])
586*2cca75a1SDavid du Colombier 	if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
587375daca8SDavid du Colombier 	switch(n->op) {
588375daca8SDavid du Colombier 
589375daca8SDavid du Colombier 	case OCAST:
590375daca8SDavid du Colombier 		if(nilcast(n->left->type, n->type))
591375daca8SDavid du Colombier 			return 1;
592375daca8SDavid du Colombier 		break;
593375daca8SDavid du Colombier 
594375daca8SDavid du Colombier 	case ONEG:
595375daca8SDavid du Colombier 	case OADD:
596375daca8SDavid du Colombier 	case OSUB:
597375daca8SDavid du Colombier 		return 1;
598375daca8SDavid du Colombier 
599375daca8SDavid du Colombier 	case OMUL:
600375daca8SDavid du Colombier 		if(n->left->op == OCONST)
601375daca8SDavid du Colombier 			return 1;
602375daca8SDavid du Colombier 		if(n->right->op == OCONST)
603375daca8SDavid du Colombier 			return 1;
604375daca8SDavid du Colombier 	}
605375daca8SDavid du Colombier 	return 0;
606375daca8SDavid du Colombier }
607