|
|
1.1 root 1: /*
2: * C compiler part 2 -- expression optimizer
3: */
4:
5: #include "c1.h"
6:
7: union tree *
8: optim(tree)
9: register union tree *tree;
10: {
11: register op, dope;
12: int d1, d2;
13: union tree *t;
14: union { double dv; int iv[4];} fp11;
15:
16: if (tree==NULL)
17: return(NULL);
18: if ((op = tree->t.op)==0)
19: return(tree);
20: if (op==NAME && tree->n.class==AUTO) {
21: tree->n.class = OFFS;
22: tree->n.regno = 5;
23: tree->n.offset = tree->n.nloc;
24: }
25: dope = opdope[op];
26: if ((dope&LEAF) != 0) {
27: if (op==FCON) {
28: fp11.dv = tree->f.fvalue;
29: if (fp11.iv[1]==0
30: && fp11.iv[2]==0
31: && fp11.iv[3]==0) {
32: tree->t.op = SFCON;
33: tree->f.value = fp11.iv[0];
34: }
35: }
36: return(tree);
37: }
38: if ((dope&BINARY) == 0)
39: return(unoptim(tree));
40: /* is known to be binary */
41: if (tree->t.type==CHAR)
42: tree->t.type = INT;
43: switch(op) {
44: /*
45: * PDP-11 special:
46: * generate new &=~ operator out of &=
47: * by complementing the RHS.
48: */
49: case ASAND:
50: tree->t.op = ASANDN;
51: tree->t.tr2 = tnode(COMPL, tree->t.tr2->t.type, tree->t.tr2, TNULL);
52: break;
53:
54: /*
55: * On the PDP-11, int->ptr via multiplication
56: * Longs are just truncated.
57: */
58: case LTOP:
59: tree->t.op = ITOP;
60: tree->t.tr1 = unoptim(tnode(LTOI,INT,tree->t.tr1, TNULL));
61: case ITOP:
62: tree->t.op = TIMES;
63: break;
64:
65: case MINUS:
66: if ((t = isconstant(tree->t.tr2)) && (!uns(t) || tree->t.type!=LONG)
67: && (t->t.type!=INT || t->c.value!=0100000)) {
68: tree->t.op = PLUS;
69: if (t->t.type==DOUBLE)
70: /* PDP-11 FP representation */
71: t->c.value ^= 0100000;
72: else
73: t->c.value = -t->c.value;
74: }
75: break;
76: }
77: op = tree->t.op;
78: dope = opdope[op];
79: if (dope&LVALUE && tree->t.tr1->t.op==FSEL)
80: return(lvfield(tree));
81: if ((dope&COMMUTE)!=0) {
82: d1 = tree->t.type;
83: tree = acommute(tree);
84: if (tree->t.op == op)
85: tree->t.type = d1;
86: /*
87: * PDP-11 special:
88: * replace a&b by a ANDN ~ b.
89: * This will be undone when in
90: * truth-value context.
91: */
92: if (tree->t.op!=AND)
93: return(tree);
94: /*
95: * long & pos-int is simpler
96: */
97: if (tree->t.type==LONG && tree->t.tr2->t.op==ITOL
98: && (tree->t.tr2->t.tr1->t.op==CON && tree->t.tr2->t.tr1->c.value>=0
99: || uns(tree->t.tr2->t.tr1))) {
100: tree->t.type = UNSIGN;
101: t = tree->t.tr2;
102: tree->t.tr2 = tree->t.tr2->t.tr1;
103: t->t.tr1 = tree;
104: tree->t.tr1 = tnode(LTOI, UNSIGN, tree->t.tr1, TNULL);
105: return(optim(t));
106: }
107: /*
108: * Keep constants to the right
109: */
110: if ((tree->t.tr1->t.op==ITOL && tree->t.tr1->t.tr1->t.op==CON)
111: || tree->t.tr1->t.op==LCON) {
112: t = tree->t.tr1;
113: tree->t.tr1 = tree->t.tr2;
114: tree->t.tr2 = t;
115: }
116: tree->t.op = ANDN;
117: op = ANDN;
118: tree->t.tr2 = tnode(COMPL, tree->t.tr2->t.type, tree->t.tr2, TNULL);
119: }
120: again:
121: tree->t.tr1 = optim(tree->t.tr1);
122: tree->t.tr2 = optim(tree->t.tr2);
123: if (tree->t.type == LONG) {
124: t = lconst(tree->t.op, tree->t.tr1, tree->t.tr2);
125: if (t)
126: return(t);
127: }
128: if ((dope&RELAT) != 0) {
129: if ((d1=degree(tree->t.tr1)) < (d2=degree(tree->t.tr2))
130: || d1==d2 && tree->t.tr1->t.op==NAME && tree->t.tr2->t.op!=NAME) {
131: t = tree->t.tr1;
132: tree->t.tr1 = tree->t.tr2;
133: tree->t.tr2 = t;
134: tree->t.op = maprel[op-EQUAL];
135: }
136: if (tree->t.tr1->t.type==CHAR && tree->t.tr2->t.op==CON
137: && (dcalc(tree->t.tr1, 0) <= 12 || tree->t.tr1->t.op==STAR)
138: && tree->t.tr2->c.value <= 127 && tree->t.tr2->c.value >= 0)
139: tree->t.tr2->t.type = CHAR;
140: }
141: d1 = max(degree(tree->t.tr1), islong(tree->t.type));
142: d2 = max(degree(tree->t.tr2), 0);
143: switch (op) {
144:
145: /*
146: * In assignment to fields, treat all-zero and all-1 specially.
147: */
148: case FSELA:
149: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==0) {
150: tree->t.op = ASAND;
151: tree->t.tr2->c.value = ~tree->F.mask;
152: return(optim(tree));
153: }
154: if (tree->t.tr2->t.op==CON && tree->F.mask==tree->t.tr2->c.value) {
155: tree->t.op = ASOR;
156: return(optim(tree));
157: }
158:
159: case LTIMES:
160: case LDIV:
161: case LMOD:
162: case LASTIMES:
163: case LASDIV:
164: case LASMOD:
165: case UDIV:
166: case UMOD:
167: case ASUDIV:
168: case ASUMOD:
169: tree->t.degree = 10;
170: break;
171:
172: case ANDN:
173: if (isconstant(tree->t.tr2) && tree->t.tr2->c.value==0) {
174: return(tree->t.tr1);
175: }
176: goto def;
177:
178: case CALL:
179: tree->t.degree = 10;
180: break;
181:
182: case QUEST:
183: case COLON:
184: tree->t.degree = max(d1, d2);
185: break;
186:
187: case PTOI:
188: case DIVIDE:
189: case ASDIV:
190: case ASTIMES:
191: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==1) {
192: if (op==PTOI)
193: return(optim(tnode(LTOI,INT,paint(tree->t.tr1,LONG), TNULL)));
194: return(paint(tree->t.tr1, tree->t.type));
195: }
196: case MOD:
197: case ASMOD:
198: if ((uns(tree->t.tr1) || tree->t.op==PTOI) && ispow2(tree))
199: return(pow2(tree));
200: if ((op==MOD||op==ASMOD) && tree->t.type==DOUBLE) {
201: error("Floating %% not defined");
202: tree->t.type = INT;
203: }
204: case ULSH:
205: case ASULSH:
206: d1 += 2 + regpanic;
207: d2 += 2 + regpanic;
208: panicposs++;
209: if (tree->t.type==LONG)
210: return(hardlongs(tree));
211: if ((op==MOD || op==DIVIDE || op==ASMOD || op==ASDIV)
212: && (uns(tree->t.tr1) || uns(tree->t.tr2))
213: && (tree->t.tr2->t.op!=CON || tree->t.tr2->c.value<=1)) {
214: if (op>=ASDIV) {
215: tree->t.op += ASUDIV - ASDIV;
216: } else
217: tree->t.op += UDIV - DIVIDE;
218: d1 = d2 = 10;
219: }
220: goto constant;
221:
222: case ASPLUS:
223: case ASMINUS:
224: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==0)
225: return(tree->t.tr1);
226: goto def;
227:
228: case LSHIFT:
229: case RSHIFT:
230: case ASRSH:
231: case ASLSH:
232: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==0)
233: return(paint(tree->t.tr1, tree->t.type));
234: /*
235: * PDP-11 special: turn right shifts into negative
236: * left shifts
237: */
238: if (tree->t.type == LONG) {
239: d1++;
240: d2++;
241: }
242: if (op==LSHIFT||op==ASLSH)
243: goto constant;
244: if (tree->t.tr2->t.op==CON && tree->t.tr2->c.value==1
245: && !uns(tree->t.tr1) && !uns(tree->t.tr2))
246: goto constant;
247: op += (LSHIFT-RSHIFT);
248: tree->t.op = op;
249: tree->t.tr2 = tnode(NEG, tree->t.tr2->t.type, tree->t.tr2, TNULL);
250: if (uns(tree->t.tr1) || uns(tree->t.tr2)) {
251: if (tree->t.op==LSHIFT)
252: tree->t.op = ULSH;
253: else if (tree->t.op==ASLSH)
254: tree->t.op = ASULSH;
255: }
256: goto again;
257:
258: constant:
259: if (tree->t.tr1->t.op==CON && tree->t.tr2->t.op==CON) {
260: const(op, &tree->t.tr1->c.value, tree->t.tr2->c.value, tree->t.type);
261: return(tree->t.tr1);
262: }
263:
264:
265: def:
266: default:
267: if (dope&RELAT) {
268: if (tree->t.tr1->t.type==LONG) /* long relations are a mess */
269: d1 = 10;
270: if (opdope[tree->t.tr1->t.op]&RELAT && tree->t.tr2->t.op==CON
271: && tree->t.tr2->c.value==0) {
272: tree = tree->t.tr1;
273: switch(op) {
274: case GREATEQ:
275: return((union tree *)&cone);
276: case LESS:
277: return((union tree *)&czero);
278: case LESSEQ:
279: case EQUAL:
280: tree->t.op = notrel[tree->t.op-EQUAL];
281: }
282: return(tree);
283: }
284: }
285: tree->t.degree = d1==d2? d1+islong(tree->t.type): max(d1, d2);
286: break;
287: }
288: return(tree);
289: }
290:
291: union tree *
292: unoptim(tree)
293: register union tree *tree;
294: {
295: register union tree *subtre, *p;
296:
297: if (tree==NULL)
298: return(NULL);
299: again:
300: if (tree->t.op==AMPER && tree->t.tr1->t.op==STAR) {
301: subtre = tree->t.tr1->t.tr1;
302: subtre->t.type = tree->t.type;
303: return(optim(subtre));
304: }
305: subtre = tree->t.tr1 = optim(tree->t.tr1);
306: switch (tree->t.op) {
307:
308: case INCAFT:
309: case DECAFT:
310: if (tree->t.type!=subtre->t.type)
311: paint(subtre, tree->t.type);
312: break;
313:
314: case ITOL:
315: if (subtre->t.op==CON && subtre->t.type==INT && subtre->c.value<0) {
316: subtre = getblk(sizeof(struct lconst));
317: subtre->t.op = LCON;
318: subtre->t.type = LONG;
319: subtre->l.lvalue = tree->t.tr1->c.value;
320: return(subtre);
321: }
322: break;
323:
324: case FTOI:
325: if (uns(tree)) {
326: tree->t.op = FTOL;
327: tree->t.type = LONG;
328: tree = tnode(LTOI, UNSIGN, tree, TNULL);
329: }
330: break;
331:
332: case LTOF:
333: if (subtre->t.op==LCON) {
334: tree = getblk(sizeof(struct ftconst));
335: tree->t.op = FCON;
336: tree->t.type = DOUBLE;
337: tree->c.value = isn++;
338: tree->f.fvalue = subtre->l.lvalue;
339: return(optim(tree));
340: }
341: break;
342:
343: case ITOF:
344: if (subtre->t.op==CON) {
345: tree = getblk(sizeof(struct ftconst));
346: tree->t.op = FCON;
347: tree->t.type = DOUBLE;
348: tree->f.value = isn++;
349: if (uns(subtre))
350: tree->f.fvalue = (unsigned)subtre->c.value;
351: else
352: tree->f.fvalue = subtre->c.value;
353: return(optim(tree));
354: }
355: if (uns(subtre)) {
356: tree->t.tr1 = tnode(ITOL, LONG, subtre, TNULL);
357: tree->t.op = LTOF;
358: return(optim(tree));
359: }
360: break;
361:
362: case ITOC:
363: /*
364: * Sign-extend PDP-11 characters
365: */
366: if (subtre->t.op==CON) {
367: char c;
368: c = subtre->c.value;
369: subtre->c.value = c;
370: subtre->t.type = tree->t.type;
371: return(subtre);
372: } else if (subtre->t.op==NAME && tree->t.type==INT) {
373: subtre->t.type = CHAR;
374: return(subtre);
375: }
376: break;
377:
378: case LTOI:
379: switch (subtre->t.op) {
380:
381: case LCON:
382: subtre->t.op = CON;
383: subtre->t.type = tree->t.type;
384: subtre->c.value = subtre->l.lvalue;
385: return(subtre);
386:
387: case NAME:
388: subtre->n.offset += 2;
389: subtre->t.type = tree->t.type;
390: return(subtre);
391:
392: case STAR:
393: subtre->t.type = tree->t.type;
394: subtre->t.tr1->t.type = tree->t.type+PTR;
395: subtre->t.tr1 = tnode(PLUS, tree->t.type, subtre->t.tr1, tconst(2, INT));
396: return(optim(subtre));
397:
398: case ITOL:
399: return(paint(subtre->t.tr1, tree->t.type));
400:
401: case PLUS:
402: case MINUS:
403: case AND:
404: case ANDN:
405: case OR:
406: case EXOR:
407: subtre->t.tr2 = tnode(LTOI, tree->t.type, subtre->t.tr2, TNULL);
408: case NEG:
409: case COMPL:
410: subtre->t.tr1 = tnode(LTOI, tree->t.type, subtre->t.tr1, TNULL);
411: subtre->t.type = tree->t.type;
412: return(optim(subtre));
413: }
414: break;
415:
416: case FSEL:
417: tree->t.op = AND;
418: tree->t.tr1 = tree->t.tr2->t.tr1;
419: tree->t.tr2->t.tr1 = subtre;
420: tree->t.tr2->t.op = RSHIFT;
421: tree->t.tr1->c.value = (1 << tree->t.tr1->c.value) - 1;
422: return(optim(tree));
423:
424: case FSELR:
425: tree->t.op = LSHIFT;
426: tree->t.type = UNSIGN;
427: tree->t.tr1 = tree->t.tr2;
428: tree->t.tr1->t.op = AND;
429: tree->t.tr2 = tree->t.tr2->t.tr2;
430: tree->t.tr1->t.tr2 = subtre;
431: tree->t.tr1->t.tr1->c.value = (1 << tree->t.tr1->t.tr1->c.value) -1;
432: return(optim(tree));
433:
434: case AMPER:
435: if (subtre->t.op==STAR)
436: return(subtre->t.tr1);
437: if (subtre->t.op==NAME && subtre->n.class == OFFS) {
438: p = tnode(PLUS, tree->t.type, subtre, tree);
439: subtre->t.type = tree->t.type;
440: tree->t.op = CON;
441: tree->t.type = INT;
442: tree->t.degree = 0;
443: tree->c.value = subtre->n.offset;
444: subtre->n.class = REG;
445: subtre->n.nloc = subtre->n.regno;
446: subtre->n.offset = 0;
447: return(optim(p));
448: }
449: if (subtre->t.op==LOAD) {
450: tree->t.tr1 = subtre->t.tr1;
451: goto again;
452: }
453: break;
454:
455: case STAR:
456: if (subtre->t.op==AMPER) {
457: subtre->t.tr1->t.type = tree->t.type;
458: return(subtre->t.tr1);
459: }
460: if (tree->t.type==STRUCT)
461: break;
462: if (subtre->t.op==NAME && subtre->n.class==REG) {
463: subtre->t.type = tree->t.type;
464: subtre->n.class = OFFS;
465: subtre->n.regno = subtre->n.nloc;
466: return(subtre);
467: }
468: p = subtre->t.tr1;
469: if ((subtre->t.op==INCAFT||subtre->t.op==DECBEF)&&tree->t.type!=LONG
470: && p->t.op==NAME && p->n.class==REG && p->t.type==subtre->t.type) {
471: p->t.type = tree->t.type;
472: p->t.op = subtre->t.op==INCAFT? AUTOI: AUTOD;
473: return(p);
474: }
475: if (subtre->t.op==PLUS && p->t.op==NAME && p->n.class==REG) {
476: if (subtre->t.tr2->t.op==CON) {
477: p->n.offset += subtre->t.tr2->c.value;
478: p->n.class = OFFS;
479: p->t.type = tree->t.type;
480: p->n.regno = p->n.nloc;
481: return(p);
482: }
483: if (subtre->t.tr2->t.op==AMPER) {
484: subtre = subtre->t.tr2->t.tr1;
485: subtre->n.class += XOFFS-EXTERN;
486: subtre->n.regno = p->n.nloc;
487: subtre->t.type = tree->t.type;
488: return(subtre);
489: }
490: }
491: break;
492: case EXCLA:
493: if ((opdope[subtre->t.op]&RELAT)==0)
494: break;
495: tree = subtre;
496: tree->t.op = notrel[tree->t.op-EQUAL];
497: break;
498:
499: case COMPL:
500: if (tree->t.type==CHAR)
501: tree->t.type = INT;
502: if (tree->t.op == subtre->t.op)
503: return(paint(subtre->t.tr1, tree->t.type));
504: if (subtre->t.op==CON) {
505: subtre->c.value = ~subtre->c.value;
506: return(paint(subtre, tree->t.type));
507: }
508: if (subtre->t.op==LCON) {
509: subtre->l.lvalue = ~subtre->l.lvalue;
510: return(subtre);
511: }
512: if (subtre->t.op==ITOL) {
513: if (subtre->t.tr1->t.op==CON) {
514: tree = getblk(sizeof(struct lconst));
515: tree->t.op = LCON;
516: tree->t.type = LONG;
517: if (uns(subtre->t.tr1))
518: tree->l.lvalue = ~(long)(unsigned)subtre->t.tr1->c.value;
519: else
520: tree->l.lvalue = ~subtre->t.tr1->c.value;
521: return(tree);
522: }
523: if (uns(subtre->t.tr1))
524: break;
525: subtre->t.op = tree->t.op;
526: subtre->t.type = subtre->t.tr1->t.type;
527: tree->t.op = ITOL;
528: tree->t.type = LONG;
529: goto again;
530: }
531:
532: case NEG:
533: if (tree->t.type==CHAR)
534: tree->t.type = INT;
535: if (tree->t.op==subtre->t.op)
536: return(paint(subtre->t.tr1, tree->t.type));
537: if (subtre->t.op==CON) {
538: subtre->c.value = -subtre->c.value;
539: return(paint(subtre, tree->t.type));
540: }
541: if (subtre->t.op==LCON) {
542: subtre->l.lvalue = -subtre->l.lvalue;
543: return(subtre);
544: }
545: if (subtre->t.op==ITOL && subtre->t.tr1->t.op==CON) {
546: tree = getblk(sizeof(struct lconst));
547: tree->t.op = LCON;
548: tree->t.type = LONG;
549: if (uns(subtre->t.tr1))
550: tree->l.lvalue = -(long)(unsigned)subtre->t.tr1->c.value;
551: else
552: tree->l.lvalue = -subtre->t.tr1->c.value;
553: return(tree);
554: }
555: /*
556: * PDP-11 FP negation
557: */
558: if (subtre->t.op==SFCON) {
559: subtre->c.value ^= 0100000;
560: subtre->f.fvalue = -subtre->f.fvalue;
561: return(subtre);
562: }
563: if (subtre->t.op==FCON) {
564: subtre->f.fvalue = -subtre->f.fvalue;
565: return(subtre);
566: }
567: }
568: if ((opdope[tree->t.op]&LEAF)==0)
569: tree->t.degree = max(islong(tree->t.type), degree(subtre));
570: return(tree);
571: }
572:
573: /*
574: * Deal with assignments to partial-word fields.
575: * The game is that select(x) += y turns into
576: * select(x += select(y)) where the shifts and masks
577: * are chosen properly. The outer select
578: * is discarded where the value doesn't matter.
579: * Sadly, overflow is undetected on += and the like.
580: * Pure assignment is handled specially.
581: */
582:
583: union tree *
584: lvfield(t)
585: register union tree *t;
586: {
587: register union tree *t1, *t2;
588:
589: switch (t->t.op) {
590:
591: case ASSIGN:
592: t2 = getblk(sizeof(struct fasgn));
593: t2->t.op = FSELA;
594: t2->t.type = UNSIGN;
595: t1 = t->t.tr1->t.tr2;
596: t2->F.mask = ((1<<t1->t.tr1->c.value)-1)<<t1->t.tr2->c.value;
597: t2->t.tr1 = t->t.tr1;
598: t2->t.tr2 = t->t.tr2;
599: t = t2;
600:
601: case ASANDN:
602: case ASPLUS:
603: case ASMINUS:
604: case ASOR:
605: case ASXOR:
606: case INCBEF:
607: case INCAFT:
608: case DECBEF:
609: case DECAFT:
610: t1 = t->t.tr1;
611: t1->t.op = FSELR;
612: t->t.tr1 = t1->t.tr1;
613: t1->t.tr1 = t->t.tr2;
614: t->t.tr2 = t1;
615: t1 = t1->t.tr2;
616: t1 = tnode(COMMA, INT, tconst(t1->t.tr1->c.value, INT),
617: tconst(t1->t.tr2->c.value, INT));
618: return(optim(tnode(FSELT, UNSIGN, t, t1)));
619:
620: }
621: error("Unimplemented field operator");
622: return(t);
623: }
624:
625: #define LSTSIZ 20
626: struct acl {
627: int nextl;
628: int nextn;
629: union tree *nlist[LSTSIZ];
630: union tree *llist[LSTSIZ+1];
631: };
632:
633: union tree *
634: acommute(tree)
635: register union tree *tree;
636: {
637: struct acl acl;
638: int d, i, op, flt, d1, type;
639: register union tree *t1, **t2;
640: union tree *t;
641:
642: acl.nextl = 0;
643: acl.nextn = 0;
644: op = tree->t.op;
645: type = tree->t.type;
646: flt = isfloat(tree);
647: insert(op, tree, &acl);
648: acl.nextl--;
649: t2 = &acl.llist[acl.nextl];
650: if (!flt) {
651: /* put constants together */
652: for (i=acl.nextl; i>0; i--) {
653: d = t2[-1]->t.type==UNSIGN||t2[0]->t.type==UNSIGN?UNSIGN:INT;
654: if (t2[0]->t.op==CON && t2[-1]->t.op==CON) {
655: acl.nextl--;
656: t2--;
657: const(op, &t2[0]->c.value, t2[1]->c.value, d);
658: t2[0]->t.type = d;
659: } else if (t = lconst(op, t2[-1], t2[0])) {
660: acl.nextl--;
661: t2--;
662: t2[0] = t;
663: }
664: }
665: }
666: if (op==PLUS || op==OR) {
667: /* toss out "+0" */
668: if (acl.nextl>0 && ((t1 = isconstant(*t2)) && t1->c.value==0
669: || (*t2)->t.op==LCON && (*t2)->l.lvalue==0)) {
670: acl.nextl--;
671: t2--;
672: }
673: if (acl.nextl <= 0) {
674: if ((*t2)->t.type==CHAR || (*t2)->t.type==UNCHAR)
675: *t2 = tnode(LOAD, tree->t.type, *t2, TNULL);
676: (*t2)->t.type = tree->t.type;
677: return(*t2);
678: }
679: /* subsume constant in "&x+c" */
680: if (op==PLUS && t2[0]->t.op==CON && t2[-1]->t.op==AMPER) {
681: t2--;
682: t2[0]->t.tr1->n.offset += t2[1]->c.value;
683: acl.nextl--;
684: }
685: } else if (op==TIMES || op==AND) {
686: t1 = acl.llist[acl.nextl];
687: if (t1->t.op==CON) {
688: if (t1->c.value==0) {
689: for (i=0; i<acl.nextl; i++)
690: if (sideeffects(acl.llist[i]))
691: break;
692: if (i==acl.nextl)
693: return(t1);
694: }
695: if (op==TIMES && t1->c.value==1 && acl.nextl>0)
696: if (--acl.nextl <= 0) {
697: t1 = acl.llist[0];
698: if (uns(tree))
699: paint(t1, tree->t.type);
700: return(t1);
701: }
702: }
703: }
704: if (op==PLUS && !flt)
705: distrib(&acl);
706: tree = *(t2 = &acl.llist[0]);
707: d = max(degree(tree), islong(tree->t.type));
708: if (op==TIMES && !flt) {
709: d += regpanic+1;
710: panicposs++;
711: }
712: for (i=0; i<acl.nextl; i++) {
713: t1 = acl.nlist[i];
714: t1->t.tr2 = t = *++t2;
715: d1 = degree(t);
716: /*
717: * PDP-11 strangeness:
718: * rt. op of ^ must be in a register.
719: */
720: if (op==EXOR && dcalc(t, 0)<=12) {
721: t1->t.tr2 = t = optim(tnode(LOAD, t->t.type, t, TNULL));
722: d1 = t->t.degree;
723: }
724: t1->t.degree = d = d==d1? d+islong(t1->t.type): max(d, d1);
725: t1->t.tr1 = tree;
726: tree = t1;
727: if (tree->t.type==LONG) {
728: if (tree->t.op==TIMES)
729: tree = hardlongs(tree);
730: else if (tree->t.op==PLUS && (t = isconstant(tree->t.tr1))
731: && t->c.value < 0 && !uns(t)) {
732: tree->t.op = MINUS;
733: t->c.value = - t->c.value;
734: t = tree->t.tr1;
735: tree->t.tr1 = tree->t.tr2;
736: tree->t.tr2 = t;
737: }
738: }
739: }
740: if (tree->t.op==TIMES && ispow2(tree))
741: tree->t.degree = max(degree(tree->t.tr1), islong(tree->t.type));
742: paint(tree, type);
743: return(tree);
744: }
745:
746: sideeffects(tp)
747: register union tree *tp;
748: {
749: register dope;
750:
751: if (tp==NULL)
752: return(0);
753: dope = opdope[tp->t.op];
754: if (dope&LEAF) {
755: if (tp->t.op==AUTOI || tp->t.op==AUTOD)
756: return(1);
757: return(0);
758: }
759: if (dope&ASSGOP)
760: return(1);
761: switch(tp->t.op) {
762: case CALL:
763: case FSELA:
764: case STRASG:
765: return(1);
766: }
767: if (sideeffects(tp->t.tr1))
768: return(1);
769: if (dope&BINARY)
770: return(sideeffects(tp->t.tr2));
771: return(0);
772: }
773:
774: distrib(list)
775: struct acl *list;
776: {
777: /*
778: * Find a list member of the form c1c2*x such
779: * that c1c2 divides no other such constant, is divided by
780: * at least one other (say in the form c1*y), and which has
781: * fewest divisors. Reduce this pair to c1*(y+c2*x)
782: * and iterate until no reductions occur.
783: */
784: register union tree **p1, **p2;
785: union tree *t;
786: int ndmaj, ndmin;
787: union tree **dividend, **divisor;
788: union tree **maxnod, **mindiv;
789:
790: loop:
791: maxnod = &list->llist[list->nextl];
792: ndmaj = 1000;
793: dividend = 0;
794: for (p1 = list->llist; p1 <= maxnod; p1++) {
795: if ((*p1)->t.op!=TIMES || (*p1)->t.tr2->t.op!=CON)
796: continue;
797: ndmin = 0;
798: for (p2 = list->llist; p2 <= maxnod; p2++) {
799: if (p1==p2 || (*p2)->t.op!=TIMES || (*p2)->t.tr2->t.op!=CON)
800: continue;
801: if ((*p1)->t.tr2->c.value == (*p2)->t.tr2->c.value) {
802: (*p2)->t.tr2 = (*p1)->t.tr1;
803: (*p2)->t.op = PLUS;
804: (*p1)->t.tr1 = (*p2);
805: *p1 = optim(*p1);
806: squash(p2, maxnod);
807: list->nextl--;
808: goto loop;
809: }
810: if (((*p2)->t.tr2->c.value % (*p1)->t.tr2->c.value) == 0)
811: goto contmaj;
812: if (((*p1)->t.tr2->c.value % (*p2)->t.tr2->c.value) == 0) {
813: ndmin++;
814: mindiv = p2;
815: }
816: }
817: if (ndmin > 0 && ndmin < ndmaj) {
818: ndmaj = ndmin;
819: dividend = p1;
820: divisor = mindiv;
821: }
822: contmaj:;
823: }
824: if (dividend==0)
825: return;
826: t = list->nlist[--list->nextn];
827: p1 = dividend;
828: p2 = divisor;
829: t->t.op = PLUS;
830: t->t.type = (*p1)->t.type;
831: t->t.tr1 = (*p1);
832: t->t.tr2 = (*p2)->t.tr1;
833: (*p1)->t.tr2->c.value /= (*p2)->t.tr2->c.value;
834: (*p2)->t.tr1 = t;
835: t = optim(*p2);
836: if (p1 < p2) {
837: *p1 = t;
838: squash(p2, maxnod);
839: } else {
840: *p2 = t;
841: squash(p1, maxnod);
842: }
843: list->nextl--;
844: goto loop;
845: }
846:
847: squash(p, maxp)
848: union tree **p, **maxp;
849: {
850: register union tree **np;
851:
852: for (np = p; np < maxp; np++)
853: *np = *(np+1);
854: }
855:
856: const(op, vp, v, type)
857: register int *vp, v;
858: {
859: switch (op) {
860:
861: case PTOI:
862: (*vp) /= (unsigned)v;
863: return;
864:
865: case PLUS:
866: *vp += v;
867: return;
868:
869: case TIMES:
870: *vp *= v;
871: return;
872:
873: case AND:
874: *vp &= v;
875: return;
876:
877: case OR:
878: *vp |= v;
879: return;
880:
881: case EXOR:
882: *vp ^= v;
883: return;
884:
885: case UDIV:
886: case UMOD:
887: type = UNSIGN;
888: case DIVIDE:
889: case MOD:
890: if (type==UNSIGN && v!=0 && v<=1) {
891: if (op==UDIV || op==DIVIDE) {
892: if (v==1)
893: return;
894: *vp = *(unsigned *)vp >= (unsigned)v;
895: return;
896: } else {
897: if (v==1) {
898: *vp = 0;
899: return;
900: }
901: if (*(unsigned *)vp >= (unsigned)v)
902: *vp -= v;
903: return;
904: }
905: }
906: if (v==0) {
907: error("Warning: divide check");
908: nerror--;
909: } else
910: if (type==INT)
911: if (op==DIVIDE || op==UDIV)
912: *vp /= v;
913: else
914: *vp %= v;
915: else
916: if (op==DIVIDE || op==UDIV)
917: *(unsigned *)vp /= (unsigned)v;
918: else
919: *(unsigned *)vp %= (unsigned)v;
920: return;
921:
922: case RSHIFT:
923: rshift:
924: if (v<0) {
925: v = -v;
926: goto lshift;
927: }
928: if (type==INT)
929: *vp >>= v;
930: else
931: *(unsigned *)vp >>= (unsigned)v;
932: return;
933:
934: case ULSH:
935: type = UNSIGN;
936:
937: case LSHIFT:
938: lshift:
939: if (v<0) {
940: v = -v;
941: goto rshift;
942: }
943: if (type==INT)
944: *vp <<= v;
945: else
946: *(unsigned *)vp <<= (unsigned)v;
947: return;
948:
949: case ANDN:
950: *vp &= ~ v;
951: return;
952: }
953: error("C error: const");
954: }
955:
956: union tree *
957: lconst(op, lp, rp)
958: register union tree *lp, *rp;
959: {
960: long l, r;
961:
962: if (lp->t.op==LCON)
963: l = lp->l.lvalue;
964: else if (lp->t.op==ITOL && lp->t.tr1->t.op==CON) {
965: if (lp->t.tr1->t.type==INT)
966: l = lp->t.tr1->c.value;
967: else
968: l = (unsigned)lp->t.tr1->c.value;
969: } else
970: return(0);
971: if (rp->t.op==LCON)
972: r = rp->l.lvalue;
973: else if (rp->t.op==ITOL && rp->t.tr1->t.op==CON) {
974: if (rp->t.tr1->t.type==INT)
975: r = rp->t.tr1->c.value;
976: else
977: r = (unsigned)rp->t.tr1->c.value;
978: } else
979: return(0);
980: switch (op) {
981:
982: case PLUS:
983: l += r;
984: break;
985:
986: case MINUS:
987: l -= r;
988: break;
989:
990: case TIMES:
991: case LTIMES:
992: l *= r;
993: break;
994:
995: case DIVIDE:
996: case LDIV:
997: if (r==0)
998: error("Divide check");
999: else
1000: l /= r;
1001: break;
1002:
1003: case MOD:
1004: case LMOD:
1005: if (r==0)
1006: error("Divide check");
1007: else
1008: l %= r;
1009: break;
1010:
1011: case AND:
1012: l &= r;
1013: break;
1014:
1015: case ANDN:
1016: l &= ~r;
1017: break;
1018:
1019: case OR:
1020: l |= r;
1021: break;
1022:
1023: case EXOR:
1024: l ^= r;
1025: break;
1026:
1027: case LSHIFT:
1028: l <<= r;
1029: break;
1030:
1031: case RSHIFT:
1032: l >>= r;
1033: break;
1034:
1035: default:
1036: return(0);
1037: }
1038: if (lp->t.op==LCON) {
1039: lp->l.lvalue = l;
1040: return(lp);
1041: }
1042: lp = getblk(sizeof(struct lconst));
1043: lp->t.op = LCON;
1044: lp->t.type = LONG;
1045: lp->l.lvalue = l;
1046: return(lp);
1047: }
1048:
1049: insert(op, tree, list)
1050: register union tree *tree;
1051: register struct acl *list;
1052: {
1053: register d;
1054: int d1, i;
1055: union tree *t;
1056:
1057: ins:
1058: if (tree->t.op != op)
1059: tree = optim(tree);
1060: if (tree->t.op == op && list->nextn < LSTSIZ-2) {
1061: list->nlist[list->nextn++] = tree;
1062: insert(op, tree->t.tr1, list);
1063: insert(op, tree->t.tr2, list);
1064: return;
1065: }
1066: if (!isfloat(tree)) {
1067: /* c1*(x+c2) -> c1*x+c1*c2 */
1068: if ((tree->t.op==TIMES||tree->t.op==LSHIFT)
1069: && tree->t.tr2->t.op==CON && tree->t.tr2->c.value>0
1070: && tree->t.tr1->t.op==PLUS && tree->t.tr1->t.tr2->t.op==CON) {
1071: d = tree->t.tr2->c.value;
1072: if (tree->t.op==TIMES)
1073: tree->t.tr2->c.value *= tree->t.tr1->t.tr2->c.value;
1074: else
1075: tree->t.tr2->c.value = tree->t.tr1->t.tr2->c.value << d;
1076: tree->t.tr1->t.tr2->c.value = d;
1077: tree->t.tr1->t.op = tree->t.op;
1078: tree->t.op = PLUS;
1079: tree = optim(tree);
1080: if (op==PLUS)
1081: goto ins;
1082: }
1083: }
1084: d = degree(tree);
1085: for (i=0; i<list->nextl; i++) {
1086: if ((d1=degree(list->llist[i]))<d) {
1087: t = list->llist[i];
1088: list->llist[i] = tree;
1089: tree = t;
1090: d = d1;
1091: }
1092: }
1093: list->llist[list->nextl++] = tree;
1094: }
1095:
1096: union tree *
1097: tnode(op, type, tr1, tr2)
1098: union tree *tr1, *tr2;
1099: {
1100: register union tree *p;
1101:
1102: p = getblk(sizeof(struct tnode));
1103: p->t.op = op;
1104: p->t.type = type;
1105: p->t.degree = 0;
1106: p->t.tr1 = tr1;
1107: p->t.tr2 = tr2;
1108: return(p);
1109: }
1110:
1111: union tree *
1112: tconst(val, type)
1113: {
1114: register union tree *p;
1115:
1116: p = getblk(sizeof(struct tconst));
1117: p->t.op = CON;
1118: p->t.type = type;
1119: p->c.value = val;
1120: return(p);
1121: }
1122:
1123: union tree *
1124: getblk(size)
1125: {
1126: register union tree *p;
1127:
1128: if (size&01) {
1129: error("compiler botch: odd size");
1130: exit(1);
1131: }
1132: p = (union tree *)curbase;
1133: if ((curbase += size) >= coremax) {
1134: if (sbrk(1024) == (char *)-1) {
1135: error("Out of space-- c1");
1136: exit(1);
1137: }
1138: coremax += 1024;
1139: }
1140: return(p);
1141: }
1142:
1143: islong(t)
1144: {
1145: if (t==LONG)
1146: return(2);
1147: return(1);
1148: }
1149:
1150: union tree *
1151: isconstant(t)
1152: register union tree *t;
1153: {
1154: if (t->t.op==CON || t->t.op==SFCON)
1155: return(t);
1156: if (t->t.op==ITOL && t->t.tr1->t.op==CON)
1157: return(t->t.tr1);
1158: return(NULL);
1159: }
1160:
1161: union tree *
1162: hardlongs(t)
1163: register union tree *t;
1164: {
1165: switch(t->t.op) {
1166:
1167: case TIMES:
1168: case DIVIDE:
1169: case MOD:
1170: t->t.op += LTIMES-TIMES;
1171: break;
1172:
1173: case ASTIMES:
1174: case ASDIV:
1175: case ASMOD:
1176: t->t.op += LASTIMES-ASTIMES;
1177: t->t.tr1 = tnode(AMPER, LONG+PTR, t->t.tr1, TNULL);
1178: break;
1179:
1180: default:
1181: return(t);
1182: }
1183: return(optim(t));
1184: }
1185:
1186: /*
1187: * Is tree of unsigned type?
1188: */
1189: uns(tp)
1190: union tree *tp;
1191: {
1192: register t;
1193:
1194: t = tp->t.type;
1195: if (t==UNSIGN || t==UNCHAR || t&XTYPE)
1196: return(1);
1197: return(0);
1198: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.