|
|
1.1 root 1: #include "defs.h"
2: #include "optim.h"
3:
4:
5: #define SCFREE 0
6: #define SCSAFE 1
7:
8:
9:
10: typedef
11: struct varblock
12: {
13: struct varblock *next;
14: field vstg;
15: int memno; /* holds memalloc for TTEMP */
16: short sets;
17: short uses;
18: field setfirst;
19: } VARBLOCK;
20:
21: typedef VARBLOCK *Varp;
22:
23: #define TABLESIZE 59
24:
25: LOCAL Varp table[TABLESIZE];
26:
27:
28:
29: LOCAL Varp mkbucket(vstg,memno)
30: field vstg;
31: int memno;
32:
33: {
34: Varp q;
35:
36: q = ALLOC(varblock);
37: q->vstg = vstg;
38: q->memno = memno;
39: return q;
40: }
41:
42:
43:
44: LOCAL Varp lookup(p)
45: tagptr p;
46:
47: {
48: int vstg, memno;
49: int key;
50: Varp q, r;
51:
52: switch (p->tag)
53: {
54: case TTEMP:
55: vstg = 0;
56: memno = (int) p->tempblock.memalloc;
57: break;
58:
59: case TADDR:
60: vstg = p->addrblock.vstg;
61: memno = p->addrblock.memno;
62: break;
63:
64: default:
65: badtag ("lookup",p->tag);
66: }
67: key = memno % TABLESIZE;
68: q = table[key];
69:
70: if (q)
71: {
72: for (; q; r = q, q = q->next)
73: if ((q->vstg == vstg) && (q->memno == memno))
74: return q;
75: return r->next = mkbucket(vstg,memno);
76: }
77: else
78: return table[key] = mkbucket(vstg,memno);
79: }
80:
81:
82:
83: LOCAL freetable()
84:
85: {
86: int i;
87: Varp p, q;
88:
89: for (i = 0; i < TABLESIZE; i++)
90: if (table[i])
91: {
92: p = table[i];
93: table[i] = NULL;
94:
95: while (p)
96: {
97: q = p->next;
98: free((char *) p);
99: p = q;
100: }
101: }
102: }
103:
104:
105:
106: Slotp newcode;
107: Slotp dohead, doend;
108: LOCAL Slotp first, last;
109: LOCAL commonset;
110: LOCAL int comocount; /* count of number of code motions done */
111:
112:
113: optloops()
114:
115: {
116: int match;
117: Slotp nextslot;
118: Slotp sl1,sl2;
119: Slotp lastlabslot;
120: int lab;
121:
122: if (! optimflag) return;
123: if (debugflag[6]) return;
124:
125: lastlabslot = NULL;
126: comocount = 0;
127: for (sl1 = firstslot; sl1; sl1 = nextslot)
128: {
129: nextslot = sl1->next;
130: switch (sl1->type)
131: {
132: case SKLABEL:
133: lastlabslot = sl1;
134: break;
135:
136: case SKGOTO:
137: if (lastlabslot && sl1->label == lastlabslot->label)
138: {
139: lab = newlabel ();
140: first = optinsert (SKLABEL,0,lab,0,lastlabslot->next);
141: last = sl1;
142: last->label = lab;
143: optloop ();
144: }
145: break;
146:
147: case SKDOHEAD:
148: match = 0;
149: for (sl2 = sl1; sl2; sl2 = sl2->next)
150: {
151: if (sl2->type == SKDOHEAD) match++;
152: else if (sl2->type == SKENDDO) match--;
153: if (match == 0) break;
154: }
155: if (sl2)
156: last = sl2;
157: else
158: fatal ("unmatched do in code buffer");
159: if (sl2->type != SKENDDO)
160: fatal ("internal error in optloops");
161:
162: /* last now points to the SKENDDO slot; the SKNULL slot
163: * is reached through last->nullslot
164: */
165: last = (Slotp) last->nullslot;
166:
167: first = sl1;
168:
169: optloop ();
170: break;
171:
172: default:
173: break;
174: }
175: }
176:
177: if (debugflag[0])
178: fprintf (diagfile,"%d code motion%s performed\n",comocount,
179: (comocount==1 ? "" : "s") );
180: return;
181: }
182:
183:
184:
185: optloop()
186:
187: {
188: newcode = NULL;
189:
190: modify();
191:
192: return;
193: }
194:
195:
196: LOCAL modify()
197:
198: {
199: Slotp sp;
200: int s;
201:
202: scanvars();
203:
204: for (sp = first; sp != last->next; sp = sp->next)
205: switch (sp->type)
206: {
207: case SKEQ:
208: s = anex(sp->expr);
209: if (s == SCSAFE)
210: removesafe (&sp->expr);
211: break;
212:
213: case SKARIF:
214: case SKASGOTO:
215: case SKCALL:
216: case SKCMGOTO:
217: case SKIFN:
218: case SKSTOP:
219: case SKRETURN:
220: case SKPAUSE:
221: case SKIOIFN:
222: s = anex(sp->expr);
223: if (s == SCSAFE)
224: removesafe(&sp->expr);
225: break;
226:
227: default:
228: break;
229: }
230:
231: freetable();
232: return;
233: }
234:
235:
236: LOCAL scanvars()
237:
238: {
239: Slotp sp;
240: Varp varinfo;
241: int i;
242: Varp p;
243:
244: commonset = NO;
245:
246: for (sp = first; sp != last->next; sp = sp->next)
247: {
248: switch (sp->type)
249: {
250: case SKARIF:
251: case SKASGOTO:
252: case SKCALL:
253: case SKCMGOTO:
254: case SKIFN:
255: case SKSTOP:
256: case SKRETURN:
257: case SKPAUSE:
258: case SKIOIFN:
259: case SKEQ:
260: setsuses(sp->expr);
261: break;
262:
263: default:
264: break;
265: }
266: }
267:
268: if (commonset)
269: for (i = 0; i < TABLESIZE; i++)
270: for (p = table[i]; p; p = p->next)
271: if (p->vstg == STGCOMMON)
272: {
273: p->sets++;
274: p->setfirst = NO;
275: }
276: }
277:
278:
279: LOCAL setsuses(p)
280: expptr p;
281:
282: {
283: Addrp lhs;
284: Varp varinfo;
285: chainp args;
286:
287: if (!p) return;
288:
289: switch (p->tag)
290: {
291: case TEXPR:
292: switch (p->exprblock.opcode)
293: {
294: default:
295: setsuses(p->exprblock.leftp);
296: setsuses(p->exprblock.rightp);
297: setsuses(p->exprblock.vleng);
298: break;
299:
300: case OPASSIGN:
301: switch (p->exprblock.leftp->tag)
302: {
303: case TTEMP:
304: lhs = (Addrp) p->exprblock.leftp;
305: goto taddr;
306:
307: case TADDR:
308: lhs = (Addrp) p->exprblock.leftp;
309: setsuses(lhs->memoffset);
310: setsuses(lhs->vleng);
311: taddr:
312: setsuses(p->exprblock.rightp);
313: setsuses(p->exprblock.vleng);
314: varinfo = lookup(lhs);
315: varinfo->sets++;
316: if (varinfo->uses == 0)
317: varinfo->setfirst = YES;
318: break;
319:
320: default:
321: fatal("O6: l-value expected");
322: }
323: break;
324:
325: case OPSTAREQ:
326: case OPPLUSEQ:
327: switch (p->exprblock.leftp->tag)
328: {
329: case TADDR:
330: lhs = (Addrp) p->exprblock.leftp;
331: break;
332: case TTEMP:
333: lhs = (Addrp) p->exprblock.leftp;
334: break;
335: default:
336: fatal("O7: l-value expected");
337: }
338: setsuses(p->exprblock.leftp);
339: setsuses(p->exprblock.rightp);
340: setsuses(p->exprblock.vleng);
341: varinfo = lookup(lhs);
342: varinfo->sets++;
343: break;
344:
345: case OPCALL:
346: if (p->exprblock.leftp->tag != TADDR)
347: fatal("O8: subprogram expected");
348: setsuses(p->exprblock.rightp);
349: setsuses(p->exprblock.vleng);
350: if (p->exprblock.leftp->addrblock.vstg != STGEXT) break;
351: commonset = YES;
352: if (p->exprblock.rightp == NULL) break;
353: args = p->exprblock.rightp->listblock.listp;
354: for (; args; args = args->nextp)
355: if (args->datap->tag == TADDR)
356: {
357: lhs = (Addrp) args->datap;
358: switch (lhs->vstg)
359: {
360: case STGARG:
361: case STGAUTO:
362: case STGBSS:
363: case STGINIT:
364: case STGCOMMON:
365: case STGEQUIV:
366: case STGREG:
367: case STGPREG:
368: varinfo = lookup(lhs);
369: varinfo->sets++;
370: }
371: }
372: else if (args->datap->tag == TTEMP)
373: {
374: lhs = (Addrp) args->datap;
375: varinfo = lookup (lhs);
376: varinfo->sets++;
377: }
378: break;
379: }
380:
381: return;
382:
383: case TTEMP:
384: varinfo = lookup((Addrp) p);
385: varinfo->uses++;
386: return;
387:
388: case TADDR:
389: setsuses(p->addrblock.memoffset);
390: setsuses(p->addrblock.vleng);
391: varinfo = lookup((Addrp) p);
392: varinfo->uses++;
393: return;
394:
395: case TLIST:
396: for (args = p->listblock.listp; args; args = args->nextp)
397: setsuses(args->datap);
398:
399: case TCONST:
400: case TERROR:
401: return;
402:
403: default:
404: fatal("O9: bad tag value");
405: }
406: }
407:
408:
409: LOCAL int anex(p)
410: expptr p;
411:
412: {
413: int s1, s2, s3;
414: expptr q;
415: Varp varinfo;
416: chainp ch;
417: int setfirst;
418: expptr expr;
419:
420:
421: if (p == ENULL)
422: return SCSAFE;
423:
424: switch (p->tag)
425: {
426: case TCONST:
427: return SCSAFE;
428:
429: case TLIST:
430: for (ch = p->listblock.listp; ch; ch = ch->nextp)
431: {
432: s1 = anex (ch->datap);
433: if (s1 == SCSAFE)
434: removesafe (&ch->datap);
435: }
436: return SCFREE;
437:
438: case TEXPR:
439: s1 = anex(p->exprblock.leftp);
440: s2 = anex(p->exprblock.rightp);
441: s3 = anex(p->exprblock.vleng);
442:
443: switch (p->exprblock.opcode)
444: {
445: case OPASSIGN:
446: expr = p->exprblock.leftp;
447: varinfo = lookup(expr);
448: setfirst = varinfo->setfirst && (varinfo->sets == 1);
449: if (expr->tag == TTEMP && setfirst &&
450: s2 == SCSAFE && s3 == SCSAFE)
451: {
452: movefrtemp (expr);
453: return SCSAFE;
454: }
455: else
456: {
457: if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
458: if (s3 == SCSAFE) removesafe (&p->exprblock.vleng);
459: return SCFREE;
460: }
461:
462: case OPNEG:
463: case OPNOT:
464: case OPABS:
465: case OPADDR:
466: case OPBITNOT:
467: if ((s2 == SCSAFE) && (s3 == SCSAFE))
468: return s1;
469: else
470: return SCFREE;
471:
472: case OPCONV:
473: if ((s2 != SCSAFE) || (s3 != SCSAFE))
474: return SCFREE;
475:
476: if (ISINT(p->exprblock.vtype))
477: return s1;
478: if (ISINT(p->exprblock.leftp->headblock.vtype))
479: return s1;
480:
481: return SCFREE;
482:
483:
484: case OPSTAR:
485: if (ISINT(p->exprblock.vtype))
486: goto safeop;
487:
488: if (safefactor(p->exprblock.leftp) ||
489: safefactor(p->exprblock.rightp))
490: goto safeop;
491:
492: goto floatop;
493:
494:
495: case OPPLUS:
496: case OPMINUS:
497: if (ISINT(p->exprblock.vtype))
498: goto safeop;
499:
500: floatop:
501: if (!(ISREAL(p->exprblock.vtype) || ISCOMPLEX(p->exprblock.vtype)))
502: return SCFREE;
503:
504: switch (s1)
505: {
506: case SCSAFE:
507: removesafe(&p->exprblock.leftp);
508: if (s2 == SCSAFE)
509: removesafe(&p->exprblock.leftp);
510: return SCFREE;
511:
512: case SCFREE:
513: if (s2 == SCSAFE)
514: removesafe(&p->exprblock.rightp);
515: return SCFREE;
516: }
517:
518: case OPOR:
519: case OPAND:
520: case OPEQV:
521: case OPNEQV:
522: case OPLT:
523: case OPEQ:
524: case OPGT:
525: case OPLE:
526: case OPNE:
527: case OPGE:
528: case OPLSHIFT:
529: case OPMIN:
530: case OPMAX:
531: case OPBITOR:
532: case OPBITAND:
533: case OPBITXOR:
534: case OPRSHIFT:
535: safeop:
536: if ((p->exprblock.vleng != ENULL) && ( ! ISCONST(p->exprblock.vleng)))
537: return SCFREE;
538:
539: switch (s1)
540: {
541: case SCSAFE:
542: if (s2 == SCFREE) removesafe (&p->exprblock.leftp);
543: return s2;
544:
545: case SCFREE:
546: if (s2 == SCSAFE) removesafe (&p->exprblock.rightp);
547: return SCFREE;
548: }
549:
550: default:
551: if (s1 == SCSAFE) removesafe(&p->exprblock.leftp);
552: if (s2 == SCSAFE) removesafe(&p->exprblock.rightp);
553: if (s3 == SCSAFE) removesafe(&p->exprblock.vleng);
554: return SCFREE;
555: }
556:
557:
558: case TTEMP:
559: varinfo = lookup(p);
560: if (varinfo->sets == 0)
561: return SCSAFE;
562: else
563: return SCFREE;
564:
565: case TADDR:
566: s1 = anex(p->addrblock.memoffset);
567: s2 = anex(p->addrblock.vleng);
568:
569: varinfo = lookup(p);
570:
571: if (varinfo->sets == 0)
572: switch (s1)
573: {
574: case SCSAFE:
575: if (s2 == SCFREE) removesafe(&p->addrblock.memoffset);
576: return s2;
577:
578: case SCFREE:
579: if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
580: return SCFREE;
581: }
582:
583: if (s1 == SCSAFE) removesafe(&p->addrblock.memoffset);
584: if (s2 == SCSAFE) removesafe(&p->addrblock.vleng);
585: return SCFREE;
586:
587:
588: default:
589: return SCFREE;
590: }
591: }
592:
593:
594: LOCAL safefactor(p)
595: expptr p;
596:
597: {
598: if ( ! ISCONST(p))
599: return NO;
600:
601: if (ISINT(p->constblock.vtype))
602: if (abs(p->constblock.const.ci) <= 1)
603: return YES;
604:
605: if (ISREAL(p->constblock.vtype))
606: if (abs(p->constblock.const.cd[0]) <= 1.0)
607: return YES;
608:
609: return NO;
610: }
611:
612:
613: LOCAL int worthcost(p)
614: expptr p;
615:
616: {
617: int cost;
618: chainp q;
619: expptr memoffset,vleng;
620:
621: if (p == ENULL)
622: return NO;
623:
624: switch (p->tag)
625: {
626: case TCONST:
627: return NO;
628:
629: case TTEMP:
630: return NO;
631:
632: case TADDR:
633: if ((memoffset = p->addrblock.memoffset) && ! ISCONST(memoffset))
634: return YES;
635: else if ((vleng = p->addrblock.vleng) && ! ISCONST(vleng))
636: return YES;
637: else
638: return NO;
639:
640: case TEXPR:
641: return YES;
642:
643: case TLIST:
644: cost = 0;
645: for (q = p->listblock.listp; q; q = q->nextp)
646: {
647: if (worthcost ((expptr) q->datap))
648: return YES;
649: cost++;
650: }
651: return (cost>2 ? YES : NO);
652:
653: default:
654: return NO;
655: }
656: }
657:
658:
659: LOCAL removesafe(refexpr)
660: expptr *refexpr;
661:
662: {
663: expptr ep;
664: Tempp ap;
665: Slotp newslot;
666:
667: extern Addrp gettemp();
668:
669: ep = *refexpr;
670: if (! worthcost(ep))
671: return;
672:
673: if (ep->tag == TEXPR && ep->exprblock.opcode == OPASSIGN)
674: {
675: if (ep->exprblock.leftp->tag != TTEMP)
676: fatal ("non-TEMP in assignment to be moved in optloop");
677:
678: newslot = optinsert (SKEQ, ep, 0, 0, first);
679: *refexpr = ep->exprblock.leftp;
680: }
681: else
682: {
683: ap = (Tempp) gettemp(ep);
684: newslot = optinsert (SKEQ, mkexpr(OPASSIGN,cpexpr(ap),ep), 0, 0, first);
685: *refexpr = (expptr) ap;
686: optinsert (SKFRTEMP,ap->memalloc,0,0,last->next);
687: }
688:
689: comocount++;
690: if (!newcode)
691: newcode = newslot;
692:
693: return;
694: }
695:
696:
697: LOCAL Addrp gettemp(p)
698: expptr p;
699:
700: {
701: return mktemp(p->headblock.vtype, p->headblock.vleng);
702: }
703:
704:
705:
706: LOCAL movefrtemp (expr)
707: Tempp expr;
708:
709: {
710: Slotp s;
711:
712: if (expr->tag != TTEMP)
713: badtag ("movefrtemp",expr->tag);
714:
715: for (s = first; s; s = s->next)
716: if (s->type == SKFRTEMP && s->expr == (expptr) expr->memalloc)
717: {
718: removeslot (s);
719: insertslot (s,last->next);
720: return;
721: }
722: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.