|
|
1.1 root 1: /* %W% (Berkeley) %G% */
2: #include "defs.h"
3: #include "optim.h"
4:
5: /*
6: * This file contains code for determination of basic blocks,
7: * as well as some other optimization supporting routines
8: * [including the main routine 'optimize()'].
9: *
10: * The compiler's general debugging flag ['debugflag'] has been
11: * extended to provide the capability of having multiple flags
12: * which are contained in an array. If the option -d is used,
13: * then the flag debugflag[0] is set. If a sequence of one or more
14: * numbers are given (e.g, -d3,7,12), then the flags debugflag[3],
15: * debugflag[7], and debugflag[12] are set. The maximum number of
16: * flags available is specified in the defines.h file.
17: */
18:
19:
20: Bblockp firstblock = NULL; /* first block in buffer */
21: Bblockp lastblock = NULL; /* last block in buffer */
22:
23: expptr tempalloc();
24:
25:
26: optimize ()
27:
28: {
29: Bblockp bb;
30: Slotp sl,nextsl;
31:
32: if (debugflag[2]) showbuffer ();
33:
34: optloops ();
35:
36: if (debugflag[3]) showbuffer ();
37:
38: formbblock ();
39: optcse ();
40:
41: if (debugflag[4]) showbuffer ();
42:
43: if (! debugflag[7])
44: copyprop ();
45:
46: if (debugflag[9]) showbuffer ();
47:
48: for (sl = firstslot; sl; sl = nextsl)
49: {
50: nextsl = sl->next;
51: if (sl->type == SKFRTEMP)
52: {
53: templist = mkchain (sl->expr,templist);
54: sl->expr = NULL;
55: delslot (sl);
56: }
57: else
58: sl->expr = tempalloc (sl->expr);
59: }
60:
61: if (! debugflag[10])
62: regalloc ();
63:
64: flushopt ();
65: }
66:
67:
68:
69: /*
70: * creates a new basic block record
71: */
72:
73: LOCAL Bblockp newblock (sl)
74: Slotp sl;
75:
76: {
77: register Bblockp bb;
78:
79: bb = ALLOC( bblock );
80: bb->next = NULL ;
81: if (lastblock)
82: {
83: bb->prev = lastblock;
84: lastblock->next = bb;
85: lastblock = bb;
86: }
87: else
88: {
89: firstblock = lastblock = bb;
90: bb->prev = NULL;
91: }
92:
93: bb->first = sl;
94: return (bb);
95: }
96:
97:
98:
99: /*
100: * scans slot buffer, creating basic block records
101: */
102:
103: formbblock ()
104:
105: {
106: Slotp sl;
107: field type;
108: Bblockp newbb;
109:
110: newbb = NULL;
111: for (sl = firstslot; sl; sl = sl->next)
112: {
113: type = sl->type;
114: switch (type)
115: {
116: case SKEQ:
117: if (!newbb)
118: newbb = newblock(sl);
119: if (containscall(sl->expr))
120: {
121: newbb->last = sl;
122: newbb = NULL;
123: }
124: break;
125: case SKNULL:
126: case SKASSIGN:
127: case SKFRTEMP:
128: if (!newbb)
129: newbb = newblock(sl);
130: break;
131: case SKPAUSE:
132: case SKSTOP:
133: case SKIFN:
134: case SKGOTO:
135: case SKCMGOTO:
136: case SKARIF:
137: case SKASGOTO:
138: case SKIOIFN:
139: case SKCALL:
140: case SKRETURN:
141: if (!newbb)
142: newbb = newblock(sl);
143: newbb->last = sl;
144: newbb = NULL;
145: break;
146: case SKLABEL:
147: if (newbb)
148: newbb->last = sl->prev;
149: newbb = newblock(sl);
150: break;
151: case SKDOHEAD:
152: case SKENDDO:
153: if (!newbb)
154: newbb = newblock(sl);
155: break;
156: default:
157: badthing("SKtype", "formbblock", type);
158: break;
159: }
160: }
161: if (newbb)
162: newbb->last = lastslot;
163: }
164:
165:
166:
167: /*
168: * frees all basic block records
169: * as well as the id and value node chains hanging off the bb and their
170: * respective cross link chains (IDlist, DUPlist and NODElist structs)
171: */
172:
173: clearbb ()
174: {
175: Bblockp bb,next;
176:
177: for (bb = firstblock; bb; bb = next)
178: {
179: next = bb->next;
180: {
181: idptr idp,next;
182: for(idp = bb->headid; idp; idp = next)
183: {
184: next = idp->next;
185: {
186: nodelptr nodelp, next;
187: for(nodelp = idp->headnodelist; nodelp; nodelp = next)
188: {
189: next = nodelp->next;
190: free( (charptr) nodelp);
191: }
192: }
193: free( (charptr) idp);
194: }
195: }
196: {
197: valuen vp,next;
198: for(vp = bb->headnode; vp; vp = next)
199: {
200: next = vp->next;
201: {
202: idlptr idlp, next;
203: for(idlp = vp->headdeplist; idlp; idlp = next)
204: {
205: next = idlp->next;
206: free( (charptr) idlp);
207: }
208: }
209: {
210: duplptr duplp, next;
211: for(duplp = vp->headduplist; duplp; duplp = next)
212: {
213: next = duplp->next;
214: free( (charptr) duplp);
215: }
216: }
217: free( (charptr) vp);
218: }
219: }
220: free ( (charptr) bb);
221: }
222: firstblock = lastblock = NULL;
223: }
224:
225:
226: /* structure for maintaining records on copy statements */
227:
228: typedef struct Subrec {
229: Addrp lmem;
230: Addrp rmem;
231: int sets;
232: } *Subrecp;
233:
234:
235: LOCAL chainp sublist; /* list of copy statements */
236: LOCAL int prop1count; /* count of number of temporaries eliminated */
237: LOCAL int prop2count; /* count of number of uses of temporaries replaced */
238:
239: expptr rmcommaop();
240: Addrp subfor();
241:
242:
243:
244: /*
245: * eliminates copy statements of the form T1 = T2 from the intermediate
246: * code, where T1 and T2 are temporary variables which are each
247: * set only once; eliminates the copy statement and replaces each
248: * use of T1 by T2 (T1 is therefore totally eliminated).
249: */
250:
251: LOCAL copyprop ()
252:
253: {
254: Slotp sl,nextsl;
255: expptr expr;
256: Tempp lp,rp;
257:
258: for (sl = firstslot; sl; sl = sl->next)
259: sl->expr = rmcommaop (sl->expr,sl);
260:
261: prop1count = prop2count = 0;
262: findcopies ();
263:
264: for (sl = firstslot; sl; sl = nextsl)
265: {
266: nextsl = sl->next;
267: expr = sl->expr;
268:
269: if ((sl->type == SKFRTEMP) && subfor (expr))
270: {
271: delslot (sl);
272: expr = ENULL;
273: }
274: else if (expr && expr->tag == TEXPR &&
275: expr->exprblock.opcode == OPASSIGN)
276: {
277: lp = (Tempp) expr->exprblock.leftp;
278: rp = (Tempp) expr->exprblock.rightp;
279: if (lp->tag == TTEMP && rp->tag == TTEMP)
280: if (subfor(lp->memalloc) == rp->memalloc
281: && !subfor (rp->memalloc))
282: {
283: frexpr (expr);
284: expr = sl->expr = ENULL;
285: prop1count++;
286: }
287: }
288:
289: propagate (expr);
290: }
291:
292: if (debugflag[0])
293: fprintf (diagfile,
294: "%d temporarie%s replaced by copy propagation (%d use%s)\n",
295: prop1count,(prop1count==1 ? "" : "s"),
296: prop2count,(prop2count==1 ? "" : "s") );
297: }
298:
299:
300:
301: /*
302: * finds copy statements and enters information in table
303: */
304:
305: LOCAL findcopies ()
306:
307: {
308: Slotp sl;
309: expptr expr;
310: chainp cp;
311:
312: for (sl = firstslot; sl; sl = sl->next)
313: {
314: expr = sl->expr;
315: if (expr) switch (expr->tag)
316: {
317: case TEXPR:
318: ckexpr (expr);
319: break;
320:
321: case TLIST:
322: for (cp = expr->listblock.listp; cp; cp = cp->nextp)
323: {
324: expr = (expptr) cp->datap;
325: ckexpr (expr);
326: }
327: break;
328:
329: default:
330: break;
331: }
332: }
333: }
334:
335:
336:
337: /*
338: * checks an individual expression
339: */
340:
341: ckexpr (expr)
342: expptr expr;
343:
344: {
345: Tempp lp,rp;
346:
347: if (expr->exprblock.opcode == OPASSIGN)
348: {
349: lp = (Tempp) expr->exprblock.leftp;
350: rp = (Tempp) expr->exprblock.rightp;
351: if (lp->tag == TTEMP)
352: if (rp->tag == TTEMP)
353: enter (lp->memalloc, rp->memalloc);
354: else
355: enter (lp->memalloc, ENULL);
356: }
357: }
358:
359:
360:
361: /*
362: * Enters the given memalloc values in the table (or update if they
363: * are already there), for the assignment statement m1 = m2.
364: * If m2 is NULL, this indicates that the assignment is not a copy
365: * statement.
366: */
367:
368: LOCAL enter (m1,m2)
369: Addrp m1,m2;
370:
371: {
372: chainp cp;
373: Subrecp old,new;
374:
375: for (cp = sublist; cp; cp = cp->nextp)
376: {
377: old = (Subrecp) cp->datap;
378: if (old->lmem == m1)
379: {
380: old->sets++;
381: return;
382: }
383: }
384:
385: new = ALLOC (Subrec);
386: new->lmem = m1;
387: new->rmem = m2;
388: new->sets = 1;
389: sublist = mkchain (new, sublist);
390: }
391:
392:
393:
394: /*
395: * looks for record for the given memalloc value
396: */
397:
398: LOCAL Subrecp lookup (mem)
399: Addrp mem;
400:
401: {
402: chainp cp;
403: Subrecp rec;
404:
405: for (cp = sublist; cp; cp = cp->nextp)
406: {
407: rec = (Subrecp) cp->datap;
408: if (rec->lmem == mem)
409: return rec;
410: }
411:
412: return NULL;
413: }
414:
415:
416:
417: /*
418: * checks to see if there is a substitute for given memalloc value
419: */
420:
421: LOCAL Addrp subfor (mem)
422: Addrp mem;
423:
424: {
425: Subrecp rec,rec2;
426: Addrp sub;
427:
428: rec = lookup (mem);
429: if (rec && rec->sets == 1)
430: {
431: sub = rec->rmem;
432: rec2 = lookup(sub);
433: if (rec2 && rec2->sets == 1)
434: return sub;
435: }
436:
437: return NULL;
438: }
439:
440:
441:
442: /*
443: * actually propagates the information
444: */
445:
446: LOCAL propagate (expr)
447: expptr expr;
448:
449: {
450: chainp t;
451: Addrp new;
452:
453: if (! expr) return;
454:
455: switch (expr->tag)
456: {
457: case TEXPR:
458: propagate (expr->exprblock.leftp);
459: propagate (expr->exprblock.rightp);
460: break;
461:
462: case TADDR:
463: propagate (expr->addrblock.vleng);
464: propagate (expr->addrblock.memoffset);
465: break;
466:
467: case TLIST:
468: for (t = expr->listblock.listp; t; t = t->nextp)
469: propagate (t->datap);
470: break;
471:
472: case TTEMP:
473: new = subfor (expr->tempblock.memalloc);
474: if (new)
475: {
476: expr->tempblock.memalloc = new;
477: prop2count++;
478: }
479: break;
480:
481: default:
482: break;
483: }
484: }
485:
486:
487:
488: /*
489: * allocates ADDR blocks for each TEMP in the expression
490: */
491:
492: LOCAL expptr tempalloc (expr)
493: expptr expr;
494:
495: {
496: chainp t;
497:
498: if (! expr)
499: return NULL;
500:
501: switch (expr->tag)
502: {
503: case TEXPR:
504: expr->exprblock.leftp = tempalloc (expr->exprblock.leftp);
505: expr->exprblock.rightp = tempalloc (expr->exprblock.rightp);
506: break;
507:
508: case TADDR:
509: expr->addrblock.vleng = tempalloc (expr->addrblock.vleng);
510: expr->addrblock.memoffset = tempalloc (expr->addrblock.memoffset);
511: break;
512:
513: case TLIST:
514: for (t = expr->listblock.listp; t; t = t->nextp)
515: t->datap = (tagptr) tempalloc (t->datap);
516: break;
517:
518: case TTEMP:
519: return (expptr) cpexpr (altmpn (expr));
520: break;
521:
522: default:
523: break;
524: }
525: return expr;
526: }
527:
528:
529: /********************* debugging routines *********************/
530:
531:
532:
533: Announce (s,q)
534: char *s;
535: expptr q;
536:
537: {
538: fprintf (diagfile,"\nAn expression [%s]----->\n",s);
539: showexpr(q,0);
540: fprintf (diagfile,"\n-------------end of expr--------------\n");
541: }
542:
543:
544:
545: /*
546: * dump the basic block buffer, including expressions, mnemonically
547: */
548:
549: showbuffer ()
550:
551: {
552: Slotp sl;
553: Bblockp bb;
554: int i;
555:
556: fprintf (diagfile,"Basic blocks with first and last slots ----------\n");
557: for (i=1, bb = firstblock; bb; i++, bb = bb->next)
558: fprintf (diagfile,"%2d. %d %d\n",i,bb->first,bb->last);
559: fprintf (diagfile,"\n");
560:
561: fprintf (diagfile,"Slots and expressions ----------\n");
562:
563: fprintf (diagfile,"tag pointer vtype vclass vstg vleng\n");
564: fprintf (diagfile," ADDR memno memoffset istemp ntempelt varleng\n");
565: fprintf (diagfile," TEMP memalloc istemp ntempelt varleng\n");
566: fprintf (diagfile," EXPR opcode leftp rightp\n");
567: fprintf (diagfile," LIST type listp\n");
568: fprintf (diagfile,"\n");
569:
570: for (i=1, sl = firstslot; sl; i++, sl = sl->next)
571: {
572: fprintf (diagfile,"%2d. ",i);
573: showslt (sl);
574: }
575: fprintf (diagfile,"---------- End of showbuffer ----------\n");
576: }
577:
578:
579:
580: /*
581: * dumps a single slot in the code buffer
582: */
583:
584: LOCAL charptr Zslot[] = {"NULL",
585: "IFN","GOTO","LABEL","EQ","CALL","CMGOTO","STOP","DOHEAD",
586: "ENDDO","ARIF","RETURN","ASGOTO","PAUSE","ASSIGN","IOIFN","FRTEMP"};
587:
588:
589:
590: showslt (sl)
591: Slotp sl;
592:
593: {
594: fprintf (diagfile,"(%2d) %d %s %d\n",
595: sl->lineno,sl,Zslot[sl->type],sl->label);
596: showexpr (sl->expr,0);
597: fprintf (diagfile,"\n");
598: }
599:
600:
601:
602: showslottype (type)
603: int type;
604:
605: {
606: fprintf (diagfile,"%s\n",Zslot[type]);
607: }
608:
609:
610:
611: /*
612: * displays the given expression at the given indentation, showing
613: * its subexpressions at further indentations
614: */
615:
616: LOCAL charptr Ztag[] = {"----",
617: "NAME","CONST","EXPR","ADDR","TEMP","PRIM","LIST","IMPLDO","ERROR"};
618: LOCAL charptr Zstg[] = {"unk",
619: "ARG","AUTO","BSS","INIT","CONST","EXT","INTR","STFUNCT",
620: "COMMON","EQUIV","REG","LENG","NULL","PREG"};
621: LOCAL charptr Zclass[] = {"unk",
622: "PARAM","VAR","ENTRY","MAIN","BLOCK","PROC","NAMELIST"};
623: LOCAL charptr Zop[] = {"----",
624: "PLUS","MINUS","STAR","SLASH","POWER","NEG","OR","AND","EQV",
625: "NEQV","NOT","CONCAT","LT","EQ","GT","LE","NE","GE","CALL",
626: "CCALL","ASSIGN","PLUSEQ","STAREQ","CONV","LSHIFT","MOD",
627: "COMMA","QUEST","COLON","ABS","MIN","MAX","ADDR","INDIRECT",
628: "BITOR","BITAND","BITXOR","BITNOT","RSHIFT","PAREN"};
629: LOCAL charptr Ztype[] = {"unk",
630: "ADDR","SHORT","LONG","REAL","DREAL","COMPLEX","DCOMPLEX",
631: "LOGICAL","CHAR","SUBR","ERROR"};
632:
633:
634: showexpr(p,indent)
635: tagptr p;
636: int indent;
637:
638: {
639: int i;
640: int type;
641: chainp q;
642:
643: #define PRHEAD(q) fprintf(diagfile,"%s %d %s %s %s %d", \
644: Ztag[q->tag], q, Ztype[q->headblock.vtype], \
645: Zclass[q->headblock.vclass], Zstg[q->headblock.vstg], \
646: q->headblock.vleng);
647: #define SHOWEXPR(p) showexpr(p,indent+2)
648:
649:
650:
651: if(p == NULL)
652: return;
653:
654: for (i=0; i<indent; i++)
655: putc(' ',diagfile);
656:
657: switch(p->tag)
658: {
659: case TCONST:
660: PRHEAD(p);
661:
662: type=p->constblock.vtype;
663: if (ISCHAR(p))
664: {
665: fprintf(diagfile," ISCHAR ccp= %d\n",
666: p->constblock.const.ccp);
667: SHOWEXPR(p->constblock.vleng);
668: }
669: else if( ISINT(type) )
670: fprintf(diagfile," ci= %d\n",p->constblock.const.ci);
671: else if( ISREAL(type) )
672: fprintf(diagfile," cd[0]= %e\n",p->constblock.const.cd[0]);
673: else fprintf(diagfile," cd[0]= %e cd[1]= %e\n",
674: p->constblock.const.cd[0],
675: p->constblock.const.cd[1] );
676: break;
677:
678: case TADDR:
679: PRHEAD(p);
680: fprintf(diagfile,
681: " memno= %d %d %d %d %d\n",
682: p->addrblock.memno,p->addrblock.memoffset,p->addrblock.istemp,
683: p->addrblock.ntempelt,p->addrblock.varleng);
684: SHOWEXPR(p->addrblock.vleng);
685: SHOWEXPR(p->addrblock.memoffset);
686: break;
687:
688: case TTEMP:
689: fprintf(diagfile,"%s %d %s %s %d",
690: Ztag[p->tag], p, Ztype[p->headblock.vtype],
691: Zclass[p->headblock.vclass],
692: p->headblock.vleng);
693: fprintf(diagfile,
694: " memalloc= %d %d %d %d\n",
695: p->tempblock.memalloc,p->tempblock.istemp,
696: p->tempblock.ntempelt,p->tempblock.varleng);
697: SHOWEXPR(p->tempblock.vleng);
698: SHOWEXPR(p->tempblock.memalloc);
699: break;
700:
701: case TERROR:
702: fprintf(diagfile,"ERROR %d\n",p);
703: break;
704:
705: case TNAME:
706: fprintf(diagfile,"NAME %d\n",p);
707: return;
708:
709: case TPRIM:
710: fprintf(diagfile,"PRIM %d --- not implemented\n",p);
711: break;
712:
713: case TEXPR:
714: PRHEAD(p);
715: fprintf(diagfile," opcode= %s %d %d\n",
716: Zop[p->exprblock.opcode],p->exprblock.leftp,
717: p->exprblock.rightp);
718: SHOWEXPR(p->exprblock.leftp);
719: if(p->exprblock.rightp)
720: SHOWEXPR(p->exprblock.rightp);
721: break;
722:
723: case TLIST:
724: fprintf(diagfile,"LIST %d %s %d\n",p,
725: Ztype[p->listblock.vtype],p->listblock.listp);
726: for(q= p->listblock.listp ; q ; q = q->nextp)
727: SHOWEXPR(q->datap);
728: for (i=0; i<indent; i++)
729: putc (' ',diagfile);
730: fprintf(diagfile,"END LIST %d\n",p);
731: break;
732:
733: default:
734: fprintf(diagfile,"showexpr BAD TAG= %d at %d \n",p->tag,p);
735: }
736: }
737:
738:
739:
740: selective()/************************************/
741: {
742: int i;
743: Slotp sl;
744:
745: i=0;
746: fprintf (stderr,"SELECTIVE OUTPUT\n");
747: for (sl=firstslot;sl;sl=sl->next)
748: {
749: i++;
750: if (i>=176 && i<184)
751: {
752: fprintf (stderr,"%d. ",i);
753: showslt(sl);
754: }
755: }
756: }
757:
758:
759:
760:
761: LOCAL containscall(p)
762: expptr p;
763: {
764: chainp cp;
765:
766: if (p == NULL)
767: return NO;
768:
769: switch (p->tag)
770: {
771: case TADDR:
772: if (containscall(p->addrblock.vleng)
773: || containscall(p->addrblock.memoffset))
774: return YES;
775: else
776: return NO;
777:
778: case TCONST:
779: return NO;
780:
781: case TERROR:
782: return NO;
783:
784: case TEXPR:
785: if (p->exprblock.opcode == OPCALL ||
786: p->exprblock.opcode == OPCCALL)
787: return YES;
788: if (containscall(p->exprblock.vleng) ||
789: containscall(p->exprblock.leftp) ||
790: containscall(p->exprblock.rightp))
791: return YES;
792: else
793: return NO;
794:
795: case TLIST:
796: cp = p->listblock.listp;
797: while (cp)
798: {
799: if (containscall(cp->datap))
800: return YES;
801: cp = cp->nextp;
802: }
803: return NO;
804:
805: default:
806: return YES;
807: }
808: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.