1 #include "cc.h"
2
3 static Node*
acast(Type * t,Node * n)4 acast(Type *t, Node *n)
5 {
6 if(n->type->etype != t->etype || n->op == OBIT) {
7 n = new1(OCAST, n, Z);
8 if(nocast(n->left->type, t))
9 *n = *n->left;
10 n->type = t;
11 }
12 return n;
13 }
14
15
16 void
evconst(Node * n)17 evconst(Node *n)
18 {
19 Node *l, *r;
20 int et, isf;
21 vlong v;
22 double d;
23
24 if(n == Z || n->type == T)
25 return;
26
27 et = n->type->etype;
28 isf = typefd[et];
29
30 l = n->left;
31 r = n->right;
32
33 d = 0;
34 v = 0;
35
36 switch(n->op) {
37 default:
38 return;
39
40 case ONEG:
41 if(isf)
42 d = -l->fconst;
43 else
44 v = -l->vconst;
45 break;
46
47 case OCOM:
48 v = ~l->vconst;
49 break;
50
51 case OCAST:
52 if(et == TVOID)
53 return;
54 et = l->type->etype;
55 if(isf) {
56 if(typefd[et])
57 d = l->fconst;
58 else
59 d = l->vconst;
60 } else {
61 if(typefd[et])
62 v = l->fconst;
63 else
64 v = convvtox(l->vconst, n->type->etype);
65 }
66 break;
67
68 case OCONST:
69 break;
70
71 case OADD:
72 if(isf)
73 d = l->fconst + r->fconst;
74 else {
75 v = l->vconst + r->vconst;
76 }
77 break;
78
79 case OSUB:
80 if(isf)
81 d = l->fconst - r->fconst;
82 else
83 v = l->vconst - r->vconst;
84 break;
85
86 case OMUL:
87 if(isf)
88 d = l->fconst * r->fconst;
89 else {
90 v = l->vconst * r->vconst;
91 }
92 break;
93
94 case OLMUL:
95 v = (uvlong)l->vconst * (uvlong)r->vconst;
96 break;
97
98
99 case ODIV:
100 if(vconst(r) == 0) {
101 warn(n, "divide by zero");
102 return;
103 }
104 if(isf)
105 d = l->fconst / r->fconst;
106 else
107 v = l->vconst / r->vconst;
108 break;
109
110 case OLDIV:
111 if(vconst(r) == 0) {
112 warn(n, "divide by zero");
113 return;
114 }
115 v = (uvlong)l->vconst / (uvlong)r->vconst;
116 break;
117
118 case OMOD:
119 if(vconst(r) == 0) {
120 warn(n, "modulo by zero");
121 return;
122 }
123 v = l->vconst % r->vconst;
124 break;
125
126 case OLMOD:
127 if(vconst(r) == 0) {
128 warn(n, "modulo by zero");
129 return;
130 }
131 v = (uvlong)l->vconst % (uvlong)r->vconst;
132 break;
133
134 case OAND:
135 v = l->vconst & r->vconst;
136 break;
137
138 case OOR:
139 v = l->vconst | r->vconst;
140 break;
141
142 case OXOR:
143 v = l->vconst ^ r->vconst;
144 break;
145
146 case OLSHR:
147 v = (uvlong)l->vconst >> r->vconst;
148 break;
149
150 case OASHR:
151 v = l->vconst >> r->vconst;
152 break;
153
154 case OASHL:
155 v = l->vconst << r->vconst;
156 break;
157
158 case OLO:
159 v = (uvlong)l->vconst < (uvlong)r->vconst;
160 break;
161
162 case OLT:
163 if(typefd[l->type->etype])
164 v = l->fconst < r->fconst;
165 else
166 v = l->vconst < r->vconst;
167 break;
168
169 case OHI:
170 v = (uvlong)l->vconst > (uvlong)r->vconst;
171 break;
172
173 case OGT:
174 if(typefd[l->type->etype])
175 v = l->fconst > r->fconst;
176 else
177 v = l->vconst > r->vconst;
178 break;
179
180 case OLS:
181 v = (uvlong)l->vconst <= (uvlong)r->vconst;
182 break;
183
184 case OLE:
185 if(typefd[l->type->etype])
186 v = l->fconst <= r->fconst;
187 else
188 v = l->vconst <= r->vconst;
189 break;
190
191 case OHS:
192 v = (uvlong)l->vconst >= (uvlong)r->vconst;
193 break;
194
195 case OGE:
196 if(typefd[l->type->etype])
197 v = l->fconst >= r->fconst;
198 else
199 v = l->vconst >= r->vconst;
200 break;
201
202 case OEQ:
203 if(typefd[l->type->etype])
204 v = l->fconst == r->fconst;
205 else
206 v = l->vconst == r->vconst;
207 break;
208
209 case ONE:
210 if(typefd[l->type->etype])
211 v = l->fconst != r->fconst;
212 else
213 v = l->vconst != r->vconst;
214 break;
215
216 case ONOT:
217 if(typefd[l->type->etype])
218 v = !l->fconst;
219 else
220 v = !l->vconst;
221 break;
222
223 case OANDAND:
224 if(typefd[l->type->etype])
225 v = l->fconst && r->fconst;
226 else
227 v = l->vconst && r->vconst;
228 break;
229
230 case OOROR:
231 if(typefd[l->type->etype])
232 v = l->fconst || r->fconst;
233 else
234 v = l->vconst || r->vconst;
235 break;
236 }
237 if(isf) {
238 n->fconst = d;
239 } else {
240 n->vconst = convvtox(v, n->type->etype);
241 }
242 n->oldop = n->op;
243 n->op = OCONST;
244 }
245
246 void
acom(Node * n)247 acom(Node *n)
248 {
249 Type *t;
250 Node *l, *r;
251 int i;
252
253 switch(n->op)
254 {
255
256 case ONAME:
257 case OCONST:
258 case OSTRING:
259 case OINDREG:
260 case OREGISTER:
261 return;
262
263 case ONEG:
264 l = n->left;
265 if(addo(n) && addo(l))
266 break;
267 acom(l);
268 return;
269
270 case OADD:
271 case OSUB:
272 case OMUL:
273 l = n->left;
274 r = n->right;
275 if(addo(n)) {
276 if(addo(r))
277 break;
278 if(addo(l))
279 break;
280 }
281 acom(l);
282 acom(r);
283 return;
284
285 default:
286 l = n->left;
287 r = n->right;
288 if(l != Z)
289 acom(l);
290 if(r != Z)
291 acom(r);
292 return;
293 }
294
295 /* bust terms out */
296 t = n->type;
297 term[0].mult = 0;
298 term[0].node = Z;
299 nterm = 1;
300 acom1(1, n);
301 if(debug['m'])
302 for(i=0; i<nterm; i++) {
303 print("%d %3lld ", i, term[i].mult);
304 prtree1(term[i].node, 1, 0);
305 }
306 if(nterm < NTERM)
307 acom2(n, t);
308 n->type = t;
309 }
310
311 int
acomcmp1(const void * a1,const void * a2)312 acomcmp1(const void *a1, const void *a2)
313 {
314 vlong c1, c2;
315 Term *t1, *t2;
316
317 t1 = (Term*)a1;
318 t2 = (Term*)a2;
319 c1 = t1->mult;
320 if(c1 < 0)
321 c1 = -c1;
322 c2 = t2->mult;
323 if(c2 < 0)
324 c2 = -c2;
325 if(c1 > c2)
326 return 1;
327 if(c1 < c2)
328 return -1;
329 c1 = 1;
330 if(t1->mult < 0)
331 c1 = 0;
332 c2 = 1;
333 if(t2->mult < 0)
334 c2 = 0;
335 if(c2 -= c1)
336 return c2;
337 if(t2 > t1)
338 return 1;
339 return -1;
340 }
341
342 int
acomcmp2(const void * a1,const void * a2)343 acomcmp2(const void *a1, const void *a2)
344 {
345 vlong c1, c2;
346 Term *t1, *t2;
347
348 t1 = (Term*)a1;
349 t2 = (Term*)a2;
350 c1 = t1->mult;
351 c2 = t2->mult;
352 if(c1 > c2)
353 return 1;
354 if(c1 < c2)
355 return -1;
356 if(t2 > t1)
357 return 1;
358 return -1;
359 }
360
361 void
acom2(Node * n,Type * t)362 acom2(Node *n, Type *t)
363 {
364 Node *l, *r;
365 Term trm[NTERM];
366 int et, nt, i, j;
367 vlong c1, c2;
368
369 /*
370 * copy into automatic
371 */
372 c2 = 0;
373 nt = nterm;
374 for(i=0; i<nt; i++)
375 trm[i] = term[i];
376 /*
377 * recur on subtrees
378 */
379 j = 0;
380 for(i=1; i<nt; i++) {
381 c1 = trm[i].mult;
382 if(c1 == 0)
383 continue;
384 l = trm[i].node;
385 if(l != Z) {
386 j = 1;
387 acom(l);
388 }
389 }
390 c1 = trm[0].mult;
391 if(j == 0) {
392 n->oldop = n->op;
393 n->op = OCONST;
394 n->vconst = c1;
395 return;
396 }
397 et = t->etype;
398
399 /*
400 * prepare constant term,
401 * combine it with an addressing term
402 */
403 if(c1 != 0) {
404 l = new1(OCONST, Z, Z);
405 l->type = t;
406 l->vconst = c1;
407 trm[0].mult = 1;
408 for(i=1; i<nt; i++) {
409 if(trm[i].mult != 1)
410 continue;
411 r = trm[i].node;
412 if(r->op != OADDR)
413 continue;
414 r->type = t;
415 l = new1(OADD, r, l);
416 l->type = t;
417 trm[i].mult = 0;
418 break;
419 }
420 trm[0].node = l;
421 }
422 /*
423 * look for factorable terms
424 * c1*i + c1*c2*j -> c1*(i + c2*j)
425 */
426 qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
427 for(i=nt-1; i>=0; i--) {
428 c1 = trm[i].mult;
429 if(c1 < 0)
430 c1 = -c1;
431 if(c1 <= 1)
432 continue;
433 for(j=i+1; j<nt; j++) {
434 c2 = trm[j].mult;
435 if(c2 < 0)
436 c2 = -c2;
437 if(c2 <= 1)
438 continue;
439 if(c2 % c1)
440 continue;
441 r = trm[j].node;
442 if(r->type->etype != et)
443 r = acast(t, r);
444 c2 = trm[j].mult/trm[i].mult;
445 if(c2 != 1 && c2 != -1) {
446 r = new1(OMUL, r, new(OCONST, Z, Z));
447 r->type = t;
448 r->right->type = t;
449 r->right->vconst = c2;
450 }
451 l = trm[i].node;
452 if(l->type->etype != et)
453 l = acast(t, l);
454 r = new1(OADD, l, r);
455 r->type = t;
456 if(c2 == -1)
457 r->op = OSUB;
458 trm[i].node = r;
459 trm[j].mult = 0;
460 }
461 }
462 if(debug['m']) {
463 print("\n");
464 for(i=0; i<nt; i++) {
465 print("%d %3lld ", i, trm[i].mult);
466 prtree1(trm[i].node, 1, 0);
467 }
468 }
469
470 /*
471 * put it all back together
472 */
473 qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
474 l = Z;
475 for(i=nt-1; i>=0; i--) {
476 c1 = trm[i].mult;
477 if(c1 == 0)
478 continue;
479 r = trm[i].node;
480 if(r->type->etype != et || r->op == OBIT)
481 r = acast(t, r);
482 if(c1 != 1 && c1 != -1) {
483 r = new1(OMUL, r, new(OCONST, Z, Z));
484 r->type = t;
485 r->right->type = t;
486 if(c1 < 0) {
487 r->right->vconst = -c1;
488 c1 = -1;
489 } else {
490 r->right->vconst = c1;
491 c1 = 1;
492 }
493 }
494 if(l == Z) {
495 l = r;
496 c2 = c1;
497 continue;
498 }
499 if(c1 < 0)
500 if(c2 < 0)
501 l = new1(OADD, l, r);
502 else
503 l = new1(OSUB, l, r);
504 else
505 if(c2 < 0) {
506 l = new1(OSUB, r, l);
507 c2 = 1;
508 } else
509 l = new1(OADD, l, r);
510 l->type = t;
511 }
512 if(c2 < 0) {
513 r = new1(OCONST, 0, 0);
514 r->vconst = 0;
515 r->type = t;
516 l = new1(OSUB, r, l);
517 l->type = t;
518 }
519 *n = *l;
520 }
521
522 void
acom1(vlong v,Node * n)523 acom1(vlong v, Node *n)
524 {
525 Node *l, *r;
526
527 if(v == 0 || nterm >= NTERM)
528 return;
529 if(!addo(n)) {
530 if(n->op == OCONST)
531 if(!typefd[n->type->etype]) {
532 term[0].mult += v*n->vconst;
533 return;
534 }
535 term[nterm].mult = v;
536 term[nterm].node = n;
537 nterm++;
538 return;
539 }
540 switch(n->op) {
541
542 case OCAST:
543 acom1(v, n->left);
544 break;
545
546 case ONEG:
547 acom1(-v, n->left);
548 break;
549
550 case OADD:
551 acom1(v, n->left);
552 acom1(v, n->right);
553 break;
554
555 case OSUB:
556 acom1(v, n->left);
557 acom1(-v, n->right);
558 break;
559
560 case OMUL:
561 l = n->left;
562 r = n->right;
563 if(l->op == OCONST)
564 if(!typefd[n->type->etype]) {
565 acom1(v*l->vconst, r);
566 break;
567 }
568 if(r->op == OCONST)
569 if(!typefd[n->type->etype]) {
570 acom1(v*r->vconst, l);
571 break;
572 }
573 break;
574
575 default:
576 diag(n, "not addo");
577 }
578 }
579
580 int
addo(Node * n)581 addo(Node *n)
582 {
583
584 if(n != Z)
585 if(!typefd[n->type->etype])
586 if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
587 switch(n->op) {
588
589 case OCAST:
590 if(nilcast(n->left->type, n->type))
591 return 1;
592 break;
593
594 case ONEG:
595 case OADD:
596 case OSUB:
597 return 1;
598
599 case OMUL:
600 if(n->left->op == OCONST)
601 return 1;
602 if(n->right->op == OCONST)
603 return 1;
604 }
605 return 0;
606 }
607