|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)regalloc.c 5.1 (Berkeley) 6/7/85";
9: #endif not lint
10:
11: /*
12: * regalloc.c
13: *
14: * Register optimization routines for f77 compiler, pass 1
15: *
16: * University of Utah CS Dept modification history:
17: *
18: * $History$
19: * $Log: regalloc.c,v $
20: * Revision 1.4 86/02/12 15:29:16 rcs
21: * 4.3 F77. C. Keating.
22: *
23: * Revision 2.9 85/03/18 21:35:05 donn
24: * Bob Corbett's hack to prevent conflicts between subroutine side effects
25: * and register assignment. Makes the code a lot worse...
26: *
27: * Revision 2.8 85/02/22 02:14:08 donn
28: * In code like 'x = foo(x)', alreg() would copy the memory version of the
29: * variable 'x' into the register version after the assignment, clobbering
30: * the result. A small change to regwrite() seems to prevent this.
31: *
32: * Revision 2.7 85/02/16 03:32:45 donn
33: * Fixed a bug where the loop test and increment were having register
34: * substitution performed twice, once in the environment of the current
35: * loop and once in the environment of the containing loop. If the
36: * containing loop puts (say) the inner loop's index variable in register
37: * but the inner loop does not, havoc results.
38: *
39: * Revision 2.6 85/02/14 23:21:45 donn
40: * Don't permit variable references of the form 'a(i)' to be put in register
41: * if array 'a' is in common. This is because there is no good way to
42: * identify instances of this sort without getting confused with other
43: * variables in the same common block which are in register. Sigh.
44: *
45: * Revision 2.5 85/01/11 21:08:00 donn
46: * Made changes so that we pay attention to SAVE statements. Added a new
47: * gensetreturn() function to implement this.
48: *
49: * Revision 2.4 84/09/03 22:37:28 donn
50: * Changed the treatment of SKRETURN in alreg() so that all variables in
51: * register, not just COMMON variables, get written out to memory before a
52: * RETURN. This was causing the return value of a function to get lost when
53: * a RETURN was done from inside a loop (among other problems).
54: *
55: * Revision 2.3 84/08/04 20:52:42 donn
56: * Added fixes for EXTERNAL parameters from Jerry Berkman.
57: *
58: * Revision 2.2 84/08/04 20:34:29 donn
59: * Fixed a stupidity pointed out by Jerry Berkman -- the 'floats in register'
60: * stuff applies if the TARGET is a VAX, not if the local machine is a VAX.
61: *
62: * Revision 2.1 84/07/19 12:04:47 donn
63: * Changed comment headers for UofU.
64: *
65: * Revision 1.5 83/11/27 19:25:41 donn
66: * Added REAL to the list of types which may appear in registers (VAXen only).
67: *
68: * Revision 1.4 83/11/13 02:38:39 donn
69: * Bug fixed in alreg()'s handling of computed goto's. A '<=' in place of a
70: * '<' led to core dumps when we walked off the end of the list of labels...
71: *
72: * Revision 1.3 83/11/12 01:25:57 donn
73: * Bug in redundant register assignment code, mistakenly carried over some old
74: * code that sometimes rewound a slot pointer even when a redundant slot wasn't
75: * deleted; this caused an infinite loop... Seems to work now.
76: *
77: * Revision 1.2 83/11/09 14:58:12 donn
78: * Took out broken code dealing with redundant register initializations.
79: * Couldn't see what to do about redundantly initializing a DO variable but
80: * I did fix things so that an assignment from a register into the same
81: * register is always deleted.
82: *
83: */
84:
85: #include "defs.h"
86: #include "optim.h"
87:
88: #define LABTABSIZE 101
89: #define VARTABSIZE 1009
90: #define TABLELIMIT 12
91:
92: #if TARGET==VAX || TARGET==TAHOE
93: #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) | M(TYREAL)
94: #if TARGET==TAHOE
95: #define BUMPREALS /* put floats last */
96: #endif
97: #else
98: #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG)
99: #endif
100:
101:
102: #define ISREGTYPE(x) ONEOF(x, MSKREGTYPES)
103:
104: #define MSKVARS M(STGAUTO) | M(STGBSS) | M(STGINIT) | M(STGCONST) |\
105: M(STGEQUIV) | M(STGARG) | M(STGCOMMON)
106:
107: #define ISVAR(x) ((((expptr) x)->headblock.vclass == CLVAR || \
108: ((expptr) x)->headblock.vclass == CLUNKNOWN) \
109: && ONEOF(((expptr) x)->headblock.vstg, MSKVARS))
110:
111:
112: typedef
113: struct regdata
114: {
115: field vstg;
116: field vtype;
117: int memno;
118: int memoffset;
119: int refs;
120: Addrp stgp;
121: unsigned isarrayarg : 1;
122: unsigned istemp : 1;
123: unsigned isset : 1;
124: unsigned setfirst : 1;
125: } REGDATA;
126:
127:
128: typedef
129: struct labelnode
130: {
131: struct labelnode *link;
132: int labelno;
133: } LABELNODE;
134:
135:
136:
137: typedef
138: struct varnode
139: {
140: struct varnode *link;
141: int memoffset;
142: unsigned isset : 1;
143: unsigned isused : 1;
144: unsigned setfirst : 1;
145: unsigned unusable : 1;
146: int refs;
147: Addrp stgp;
148: } VARNODE;
149:
150:
151: typedef
152: struct addrnode
153: {
154: struct addrnode *link;
155: field vtype;
156: field vstg;
157: int memno;
158: unsigned istemp : 1;
159: unsigned isset : 1;
160: unsigned loopset :1;
161: unsigned freeuse : 1;
162: unsigned mixedtype : 1;
163: unsigned fixed : 1;
164: int refs;
165: struct addrnode *commonlink;
166: VARNODE *varlist;
167: } ADDRNODE;
168:
169:
170: typedef
171: struct setnode
172: {
173: struct setnode *link;
174: field vstg;
175: int memno;
176: int memoffset;
177: } SETNODE;
178:
179:
180: typedef
181: struct doqueue
182: {
183: struct doqueue *up, *down;
184: Slotp dohead, doend;
185: int nregvars;
186: REGNODE *reg[MAXREGVAR];
187: } DOQUEUE;
188:
189: LOCAL DOQUEUE *dqptr, *dqtop, *dqbottom;
190:
191:
192: LOCAL Slotp dohead;
193: LOCAL Slotp doend;
194: LOCAL Slotp newcode;
195:
196:
197:
198: LOCAL LABELNODE *labeltable[LABTABSIZE];
199: LOCAL ADDRNODE *vartable[VARTABSIZE];
200: LOCAL ADDRNODE *commonvars;
201: LOCAL SETNODE *setlist;
202: LOCAL int topregvar;
203: LOCAL int toplcv;
204: LOCAL int allset;
205: LOCAL ADDRNODE *currentaddr;
206: LOCAL int loopcost;
207: LOCAL REGDATA *regtab[MAXREGVAR];
208: LOCAL REGDATA *rt[TABLELIMIT];
209: LOCAL int tabletop;
210: LOCAL int linearcode;
211: LOCAL int docount;
212: LOCAL int globalbranch;
213: LOCAL int commonunusable;
214: LOCAL int regdefined[MAXREGVAR];
215: LOCAL int memdefined[MAXREGVAR];
216: LOCAL int regaltered[MAXREGVAR];
217:
218:
219:
220: LOCAL insertlabel(l)
221: int l;
222:
223: {
224: int key;
225: LABELNODE *p;
226:
227: key = l % LABTABSIZE;
228: for (p = labeltable[key]; p; p = p->link)
229: if (p->labelno == l) return;
230: p = labeltable[key];
231: labeltable[key] = ALLOC(labelnode);
232: labeltable[key]->link = p;
233: labeltable[key]->labelno = l;
234: return;
235: }
236:
237:
238:
239: LOCAL int locallabel(l)
240: int l;
241:
242: {
243: int key;
244: LABELNODE *p;
245:
246: key = l % LABTABSIZE;
247: for (p = labeltable[key]; p; p = p->link)
248: if (p->labelno == l) return YES;
249:
250: return NO;
251: }
252:
253:
254:
255: LOCAL freelabtab()
256:
257: {
258: int i;
259: LABELNODE *p, *q;
260:
261: for (i = 0; i < LABTABSIZE; i++)
262: if (labeltable[i])
263: {
264: p = labeltable[i];
265: labeltable[i] = NULL;
266: while (p)
267: {
268: q = p->link;
269: free(p);
270: p = q;
271: }
272: }
273: return;
274: }
275:
276:
277:
278: LOCAL ADDRNODE *getaddr(ap)
279: Addrp ap;
280:
281: {
282: int key;
283: field vstg;
284: int memno;
285: register ADDRNODE *q;
286: ADDRNODE *q1;
287:
288: if (!ISVAR(ap))
289: fatal("regalloc: bad data sent to getaddr");
290: vstg = ap->vstg;
291: memno = ap->memno;
292: key = (256*vstg + memno) % VARTABSIZE;
293:
294: for (q = vartable[key]; q; q = q->link)
295: if ((q->vstg == vstg) && (q->memno == memno))
296: {
297: if (ap->istemp) q->istemp = YES;
298: if (ap->vtype != q->vtype)
299: q->mixedtype = YES;
300: if (!fixedaddress(ap))
301: q->fixed = NO;
302: return q;
303: }
304:
305: q1 = vartable[key];
306: vartable[key] = q = ALLOC(addrnode);
307: q->link = q1;
308: q->vstg = vstg;
309: q->memno = memno;
310: if (ap->istemp) q->istemp = YES;
311: if (fixedaddress(ap)) q->fixed = YES;
312: q->vtype = ap->vtype;
313: q->varlist = NULL;
314: if (vstg == STGCOMMON)
315: {
316: q->commonlink = commonvars;
317: commonvars = q;
318: }
319: return q;
320: }
321:
322:
323:
324: LOCAL VARNODE *getvar(ainfo, ap)
325: ADDRNODE *ainfo;
326: Addrp ap;
327:
328: {
329: register VARNODE *q;
330: register VARNODE *q1;
331:
332: int memoffset;
333:
334: if (!ISVAR(ap))
335: fatal("regalloc: bad data sent to getvar");
336:
337: memoffset = ap->memoffset->constblock.const.ci;
338:
339: for (q = ainfo->varlist; q; q = q->link)
340: if (q->memoffset == memoffset)
341: return q;
342:
343: q1 = ainfo->varlist;
344: ainfo->varlist = q = ALLOC(varnode);
345: q->link = q1;
346: q->memoffset = memoffset;
347: q->stgp = (Addrp) cpexpr(ap);
348: return q;
349: }
350:
351:
352: LOCAL ADDRNODE *lookupaddr(vstg, memno)
353: field vstg;
354: int memno;
355:
356: {
357: int key;
358: register ADDRNODE *q;
359:
360: key = (256*vstg + memno) % VARTABSIZE;
361:
362: for (q = vartable[key]; q; q = q->link)
363: if ((q->vstg == vstg) && (q->memno == memno))
364: return q;
365:
366: fatal("regalloc: lookupaddr");
367: }
368:
369:
370: LOCAL VARNODE *lookupvar(ainfo, memoffset)
371: ADDRNODE *ainfo;
372: int memoffset;
373:
374: {
375: register VARNODE *q;
376:
377: for (q = ainfo->varlist; q; q = q->link)
378: if (q->memoffset == memoffset)
379: return q;
380:
381: fatal("regalloc: lookupvar");
382: }
383:
384:
385:
386: LOCAL int invartable(p)
387: REGNODE *p;
388:
389: {
390: field vstg;
391: int memno;
392: int key;
393: register ADDRNODE *q;
394:
395: vstg = p->vstg;
396: memno = p->memno;
397: key = (256*vstg + memno) % VARTABSIZE;
398:
399: for (q = vartable[key]; q; q = q->link)
400: if ((q->vstg == vstg) && (q->memno == memno))
401: return YES;
402:
403: return NO;
404: }
405:
406:
407:
408: LOCAL freevartab()
409:
410: {
411: register ADDRNODE *p;
412: ADDRNODE *p1;
413: register VARNODE *q;
414: VARNODE *q1;
415: register int i;
416:
417: for (i = 0; i < VARTABSIZE; i++)
418: if (vartable[i])
419: {
420: p = vartable[i];
421: vartable[i] = NULL;
422:
423: while (p)
424: {
425: for (q = p->varlist; q; q = q1)
426: {
427: q1 = q->link;
428: frexpr(q->stgp);
429: free ((char *) q);
430: }
431: p1 = p->link;
432: free((char *) p);
433: p = p1;
434: }
435: }
436: }
437:
438:
439:
440: LOCAL insertset(vstg, memno, memoffset)
441: field vstg;
442: int memno;
443: int memoffset;
444:
445: {
446: register SETNODE *p;
447: SETNODE *q;
448:
449: if (allset) return;
450: for (p = setlist; p; p = p->link)
451: if((p->vstg == vstg) && (p->memno == memno) && (p->memoffset == memoffset))
452: return;
453:
454: q = p;
455: setlist = p = ALLOC(setnode);
456: p->link = q;
457: p->vstg = vstg;
458: p->memno = memno;
459: p->memoffset = memoffset;
460: return;
461: }
462:
463:
464:
465: LOCAL int insetlist(vstg, memno, memoffset)
466: field vstg;
467: int memno;
468: int memoffset;
469:
470: {
471: register SETNODE *p;
472:
473: if (allset) return YES;
474: for (p = setlist; p; p = p->link)
475: if((p->vstg == vstg) && (p->memno == memno) && (p->memoffset == memoffset))
476: return YES;
477:
478: return NO;
479: }
480:
481:
482:
483: LOCAL clearsets()
484:
485: {
486: register SETNODE *p, *q;
487:
488: allset = NO;
489:
490: p = setlist;
491: while (p)
492: {
493: q = p->link;
494: free ((char *) p);
495: p = q;
496: }
497: setlist = NULL;
498: return;
499: }
500:
501:
502:
503: LOCAL alreg()
504:
505: {
506: register Slotp sp;
507: register int i;
508: register ADDRNODE *p;
509: register VARNODE *q;
510: Slotp sp1, sp2;
511: ADDRNODE *addrinfo;
512: VARNODE *varinfo;
513: struct Labelblock **lp;
514: int toptrack;
515: int track[MAXREGVAR];
516: Addrp ap, ap1;
517: DOQUEUE *dqp;
518: REGDATA *rp;
519: REGNODE *regp;
520:
521: if (nregvar >= maxregvar) return;
522:
523: commonvars = NULL;
524: docount = 0;
525:
526: for (sp = dohead; sp != doend->next; sp = sp->next)
527: switch (sp->type)
528: {
529: case SKLABEL:
530: insertlabel(sp->label);
531: break;
532:
533: case SKARIF:
534: case SKASGOTO:
535: case SKCALL:
536: case SKCMGOTO:
537: case SKEQ:
538: case SKIFN:
539: case SKIOIFN:
540: case SKSTOP:
541: case SKPAUSE:
542: case SKRETURN:
543: scanvars(sp->expr);
544: break;
545:
546: case SKDOHEAD:
547: ++docount;
548: break;
549:
550: case SKENDDO:
551: --docount;
552: break;
553:
554: case SKNULL:
555: case SKGOTO:
556: case SKASSIGN:
557: break;
558:
559: default:
560: badthing ("SKtype", "alreg-1", sp->type);
561: }
562:
563: loopcost = 0;
564: docount = 1;
565: commonunusable = NO;
566: if (! dohead->nullslot) fatal ("missing dohead->nullslot -cbb");
567: for (sp = dohead->next, globalbranch = NO;
568: docount;
569: sp = sp->next, clearsets(), globalbranch = NO)
570: if (docount > 1)
571: switch (sp->type)
572: {
573: case SKDOHEAD:
574: docount++;
575: break;
576:
577: case SKENDDO:
578: docount--;
579:
580: default:
581: break;
582: }
583: else
584: switch (sp->type)
585: {
586: case SKARIF:
587: #define LM ((struct Labelblock * *)sp->ctlinfo)[0]->labelno
588: #define LZ ((struct Labelblock * *)sp->ctlinfo)[1]->labelno
589: #define LP ((struct Labelblock * *)sp->ctlinfo)[2]->labelno
590:
591: if (!locallabel(LM) || !locallabel(LZ) || !locallabel(LP))
592: {
593: setall();
594: globalbranch = YES;
595: }
596: countrefs(sp->expr);
597: break;
598:
599: case SKASGOTO:
600: setall();
601: globalbranch = YES;
602: countrefs(sp->expr);
603: break;
604:
605: case SKCMGOTO:
606: lp = (struct Labelblock **) sp->ctlinfo;
607: for (i = 0; i < sp->label; i++, lp++)
608: if (!locallabel((*lp)->labelno))
609: {
610: setall();
611: globalbranch = YES;
612: break;
613: }
614: countrefs(sp->expr);
615: break;
616:
617: case SKDOHEAD:
618: globalbranch = YES;
619: loopcost = 2;
620: docount++;
621: break;
622:
623: case SKENDDO:
624: docount = 0;
625: break;
626:
627: case SKGOTO:
628: if (!locallabel(sp->label))
629: {
630: setall();
631: globalbranch = YES;
632: }
633: break;
634:
635: case SKIFN:
636: case SKIOIFN:
637: if (!locallabel(sp->label))
638: {
639: setall();
640: globalbranch = YES;
641: }
642: countrefs(sp->expr);
643: break;
644:
645: case SKEQ:
646: case SKCALL:
647: case SKSTOP:
648: case SKPAUSE:
649: linearcode = YES;
650: countrefs(sp->expr);
651: linearcode = NO;
652: break;
653: }
654:
655: topregvar = toplcv = nregvar - 1;
656:
657: for (i = 0; i < nregvar; i++)
658: {
659: ap = memversion(regnamep[i]);
660: regtab[i] = rp = ALLOC(regdata);
661: rp->vstg = ap->vstg;
662: rp->vtype = ap->vtype;
663: rp->memno = ap->memno;
664: rp->memoffset = ap->memoffset->constblock.const.ci;
665: rp->isarrayarg = NO;
666: rp->stgp = ap;
667: }
668:
669: for (i = 0; i < MAXREGVAR; i++)
670: track[i] = YES;
671:
672: for (dqp = dqptr->down; dqp; dqp = dqp->down)
673: {
674: if (dqp->nregvars - 1 > topregvar)
675: topregvar = dqp->nregvars -1;
676: for (i = toplcv + 1; i < dqp->nregvars; i++)
677: if (track[i])
678: if (regp = dqp->reg[i])
679: if (rp = regtab[i])
680: {
681: if (!samevar(rp, regp))
682: track[i] = NO;
683: }
684: else if (invartable(regp))
685: {
686: regtab[i] = rp = ALLOC(regdata);
687: rp->vstg = regp->vstg;
688: rp->vtype = regp->vtype;
689: rp->memno = regp->memno;
690: rp->memoffset = regp->memoffset;
691: addrinfo = lookupaddr(rp->vstg, rp->memno);
692: if (regp->isarrayarg)
693: {
694: rp->isarrayarg = YES;
695: rp->refs = addrinfo->refs;
696: }
697: else
698: {
699: varinfo = lookupvar(addrinfo, regp->memoffset);
700: rp->refs = varinfo->refs;
701: rp->stgp = (Addrp) cpexpr(varinfo->stgp);
702: rp->istemp = addrinfo->istemp;
703: rp->isset = varinfo->isset;
704: rp->setfirst = varinfo->setfirst;
705: }
706: }
707: else
708: track[i] = NO;
709: else
710: track[i] = NO;
711: }
712:
713: toptrack = topregvar;
714:
715: for (i = toplcv + 1; i <= topregvar; i++)
716: if (regtab[i])
717: if ((track[i] == NO) || (regtab[i]->refs <= 0))
718: {
719: free((char *) regtab[i]);
720: regtab[i] = NULL;
721: }
722:
723: tabletop = -1;
724: if (topregvar < maxregvar - 1)
725: for (i = 0; i < VARTABSIZE; i++)
726: for (p = vartable[i]; p; p = p->link)
727: {
728: entableaddr(p);
729: if ((!p->loopset) &&
730: (!p->mixedtype) &&
731: (p->vstg != STGARG) &&
732: !((p->vstg == STGCOMMON) && ((!p->fixed) || commonunusable)))
733: for (q = p->varlist; q; q = q->link)
734: entablevar(q);
735: }
736:
737: for (i = 0; (i <= tabletop) && (topregvar + 1 < maxregvar); i++)
738: {
739: if (inregtab(rt[i]) || (loopcost && rt[i]->isset))
740: continue;
741: topregvar++;
742: regtab[topregvar] = rp = ALLOC(regdata);
743: rp->vstg = rt[i]->vstg;
744: rp->vtype = rt[i]->vtype;
745: rp->memno = rt[i]->memno;
746: rp->memoffset = rt[i]->memoffset;
747: rp->refs = rt[i]->refs;
748: rp->stgp = (Addrp) cpexpr(rt[i]->stgp);
749: rp->isarrayarg = rt[i]->isarrayarg;
750: rp->istemp = rt[i]->istemp;
751: rp->isset = rt[i]->isset;
752: rp->setfirst = rt[i]->setfirst;
753: }
754:
755: for (i = toplcv + 1; i <= topregvar; i++)
756: {
757: if (rp = regtab[i])
758: if (rp->isarrayarg)
759: {
760: ap = ALLOC(Addrblock);
761: ap->tag = TADDR;
762: ap->vstg = STGREG;
763: ap->vtype = TYADDR;
764: ap->vclass = CLVAR;
765: ap->memno = regnum[i];
766: ap->memoffset = ICON(0);
767:
768: ap1 = ALLOC(Addrblock);
769: ap1->tag = TADDR;
770: ap1->vstg = rp->vstg;
771: ap1->vtype = rp->vtype;
772: ap1->vclass = CLVAR;
773: ap1->memno = rp->memno;
774: ap1->memoffset = ICON(0);
775:
776: insertassign(dohead, ap, addrof(ap1));
777: }
778: else if (!(rp->setfirst && rp->istemp))
779: {
780: if (rp->istemp)
781: for (sp = newcode; sp && sp != dohead; sp = sp->next)
782: if (sp->type == SKEQ)
783: {
784: ap = (Addrp) sp->expr->exprblock.leftp;
785: if ((ap->vstg == rp->vstg) && (ap->memno == rp->memno) &&
786: fixedaddress(ap) &&
787: (ap->memoffset->constblock.const.ci == rp->memoffset))
788: {
789: changetoreg(ap, i);
790: goto L1;
791: }
792: }
793: ap = (Addrp) cpexpr(rp->stgp);
794: changetoreg(ap, i);
795: insertassign(dohead, ap, cpexpr(rp->stgp));
796: }
797: L1:;
798: }
799:
800: for (i = toplcv + 1; i <= topregvar; i++)
801: if (rp = regtab[i])
802: if (rp->isset && !(rp->istemp || rp->isarrayarg))
803: {
804: ap = (Addrp) cpexpr(rp->stgp);
805: changetoreg(ap, i);
806: appendassign(doend, cpexpr(rp->stgp), ap);
807: }
808:
809: docount = 1;
810: clearmems();
811: setregs();
812: sp = dohead->next;
813: if (loopcost)
814: for (i = toptrack + 1; i <= topregvar; i++)
815: if ((rp = regtab[i]) && !rp->isarrayarg)
816: {
817: ap = (Addrp) cpexpr(rp->stgp);
818: changetoreg(ap, i);
819: insertassign(sp, cpexpr(rp->stgp), ap);
820: }
821:
822: for ( sp = dohead->next;
823: docount || sp->type != SKNULL;
824: sp = sp->next)
825: if (docount > 1)
826: switch (sp->type)
827: {
828: case SKDOHEAD:
829: docount++;
830: break;
831:
832: case SKENDDO:
833: if (--docount == 1)
834: {
835: /*
836: * Remove redundant stores to memory.
837: */
838: sp1 = sp->nullslot->next;
839: while (sp1)
840: {
841: if (regtomem(sp1))
842: {
843: ap = (Addrp) sp1->expr->exprblock.rightp;
844: sp2 = sp1->next;
845: for (i = toplcv + 2; i <= toptrack; i++)
846: if (regtab[i] && (regnum[i] == ap->memno))
847: {
848: deleteslot(sp1);
849: break;
850: }
851: sp1 = sp2;
852: }
853: else
854: sp1 = NULL;
855: }
856:
857: /*
858: * Restore register variables (complement to DOHEAD code).
859: */
860: sp1 = sp->nullslot->next;
861: for (i = toplcv + 1; i <= topregvar; i++)
862: if (rp = regtab[i])
863: if (!regdefined[i])
864: if (i >= dqp->nregvars || !samevar(rp, dqp->reg[i]))
865: {
866: ap = (Addrp) cpexpr(rp->stgp);
867: changetoreg(ap, i);
868: insertassign(sp1, ap, cpexpr(rp->stgp));
869: regdefined[i] = YES;
870: }
871:
872: clearmems();
873: if (toplcv + 1 < maxregvar)
874: memdefined[toplcv + 1] = YES;
875: sp = sp1->prev;
876: }
877: break;
878: }
879: else
880: {
881: setregs();
882: for (i = 0; i <= MAXREGVAR; i++)
883: regaltered[i] = NO;
884: globalbranch = NO;
885:
886: switch (sp->type)
887: {
888: case SKLABEL:
889: clearmems();
890: break;
891:
892: case SKGOTO:
893: if (!locallabel(sp->label))
894: gensetall(sp);
895: break;
896:
897: case SKENDDO:
898: docount = 0;
899: break;
900:
901: case SKRETURN:
902: gensetreturn(sp);
903: linearcode = YES;
904: regwrite(sp, sp->expr);
905: linearcode = NO;
906: break;
907:
908: case SKDOHEAD:
909: /*
910: * If one of the current loop's register variables is not in
911: * register in an inner loop, we must save it. It's a pity
912: * we don't save enough info to optimize this properly...
913: */
914: for (dqp = dqptr->down; dqp; dqp = dqp->down)
915: if (dqp->dohead == sp)
916: break;
917: if (dqp == NULL)
918: fatal("confused in alreg loop analysis");
919: for (i = toplcv + 1; i <= topregvar; i++)
920: if (rp = regtab[i])
921: if (!memdefined[i])
922: if (i >= dqp->nregvars || !samevar(rp, dqp->reg[i]))
923: {
924: ap = (Addrp) cpexpr(rp->stgp);
925: changetoreg(ap, i);
926: insertassign(sp, cpexpr(rp->stgp), ap);
927: memdefined[i] = YES;
928: regdefined[i] = NO;
929: }
930:
931: docount++;
932: globalbranch = YES;
933: break;
934:
935: case SKEQ:
936: case SKCALL:
937: case SKSTOP:
938: case SKPAUSE:
939: linearcode = YES;
940: regwrite(sp, sp->expr);
941: for (i = toplcv + 1; i <= topregvar; i++)
942: if (!regdefined[i] && ((rp = regtab[i]) && rp->isset))
943: {
944: ap = (Addrp) cpexpr(rp->stgp);
945: changetoreg(ap, i);
946: appendassign(sp, ap, cpexpr(rp->stgp));
947: sp = sp->next;
948: regdefined[i] = YES;
949: }
950: linearcode = NO;
951:
952: /*
953: * Eliminate redundant register moves.
954: */
955: if (regtoreg(sp))
956: {
957: ap = (Addrp) sp->expr->exprblock.leftp;
958: sp1 = sp->prev;
959: for (i = toplcv + 1; i <= toptrack; i++)
960: if (regtab[i] && (regnum[i] == ap->memno))
961: {
962: deleteslot(sp);
963: sp = sp1;
964: break;
965: }
966: }
967: break;
968:
969: case SKARIF:
970: if (!locallabel(LM) || !locallabel(LZ) || !locallabel(LP))
971: {
972: gensetall(sp);
973: globalbranch = YES;
974: }
975: regwrite(sp, sp->expr);
976: break;
977:
978: case SKASGOTO:
979: gensetall(sp);
980: globalbranch = YES;
981: regwrite(sp, sp->expr);
982: break;
983:
984: case SKCMGOTO:
985: lp = (struct Labelblock **) sp->ctlinfo;
986: for (i = 0; i < sp->label; i++, lp++)
987: if (!locallabel((*lp)->labelno))
988: {
989: gensetall(sp);
990: globalbranch = YES;
991: break;
992: }
993: regwrite(sp, sp->expr);
994: break;
995:
996: case SKIFN:
997: case SKIOIFN:
998: if (!locallabel(sp->label))
999: {
1000: gensetall(sp);
1001: globalbranch = YES;
1002: }
1003: regwrite(sp, sp->expr);
1004: break;
1005:
1006: case SKNULL:
1007: case SKASSIGN:
1008: break;
1009:
1010: default:
1011: badthing ("SKtype","alreg-3",sp->type);
1012: }
1013:
1014: for (i = toplcv + 1; i <= topregvar; i++)
1015: if (regaltered[i])
1016: memdefined[i] = NO;
1017: }
1018:
1019: if (topregvar + 1 > highregvar)
1020: highregvar = topregvar + 1;
1021: dqptr->nregvars = topregvar + 1;
1022: for (i = 0; i <= topregvar; i++)
1023: if (rp = regtab[i])
1024: {
1025: dqptr->reg[i] = regp = ALLOC(regnode);
1026: regp->vstg = rp->vstg;
1027: regp->vtype = rp->vtype;
1028: regp->memno = rp->memno;
1029: regp->memoffset = rp->memoffset;
1030: regp->isarrayarg = rp->isarrayarg;
1031: frexpr(rp->stgp);
1032: free((char *) rp);
1033: regtab[i] = NULL;
1034: }
1035:
1036: while (tabletop >= 0)
1037: free((char *) rt[tabletop--]);
1038: freelabtab();
1039: freevartab();
1040: return;
1041: }
1042:
1043:
1044:
1045: LOCAL scanvars(p)
1046: expptr p;
1047:
1048: {
1049: Addrp ap;
1050: ADDRNODE *addrinfo;
1051: VARNODE *varinfo;
1052: chainp args;
1053: VARNODE *q;
1054:
1055: if (p == NULL) return;
1056:
1057: switch (p->tag)
1058: {
1059: case TCONST:
1060: return;
1061:
1062: case TEXPR:
1063: switch (p->exprblock.opcode)
1064: {
1065: case OPASSIGN:
1066: scanassign(p);
1067: return;
1068:
1069: case OPPLUSEQ:
1070: case OPSTAREQ:
1071: scanopeq(p);
1072: return;
1073:
1074: case OPCALL:
1075: scancall(p);
1076: return;
1077:
1078: default:
1079: scanvars(p->exprblock.vleng);
1080: scanvars(p->exprblock.leftp);
1081: scanvars(p->exprblock.rightp);
1082: return;
1083: }
1084:
1085: case TADDR:
1086: ap = (Addrp) p;
1087: scanvars(ap->vleng);
1088: scanvars(ap->memoffset);
1089: if (!ISVAR(ap)) return;
1090:
1091: addrinfo = getaddr(ap);
1092: if (fixedaddress(ap))
1093: {
1094: if (ISREGTYPE(ap->vtype))
1095: {
1096: varinfo = getvar(addrinfo, ap);
1097: varinfo->isused = YES;
1098: }
1099: }
1100: else
1101: {
1102: addrinfo->freeuse = YES;
1103: for (q = addrinfo->varlist; q; q = q->link)
1104: q->isused = YES;
1105: }
1106: return;
1107:
1108: case TLIST:
1109: for (args = p->listblock.listp; args; args = args->nextp)
1110: scanvars(args->datap);
1111: return;
1112:
1113: default:
1114: badtag ("regalloc:scanvars", p->tag);
1115: }
1116: }
1117:
1118:
1119:
1120: LOCAL scanassign(ep)
1121: Exprp ep;
1122:
1123: {
1124: Addrp lhs;
1125: VARNODE *varinfo;
1126: ADDRNODE *addrinfo;
1127:
1128: scanvars(ep->rightp);
1129: if (ep->leftp->tag == TADDR)
1130: {
1131: lhs = (Addrp) ep->leftp;
1132: scanvars(lhs->vleng);
1133: scanvars(lhs->memoffset);
1134: if ((lhs->vstg == STGREG) || (lhs->vstg == STGPREG))
1135: return;
1136: if (ISVAR(lhs))
1137: {
1138: addrinfo = getaddr(lhs);
1139: addrinfo->isset = YES;
1140: if (docount > 1)
1141: addrinfo->loopset = YES;
1142: if (fixedaddress(lhs) && ISREGTYPE(lhs->vtype))
1143: {
1144: varinfo = getvar(addrinfo, lhs);
1145: if (addrinfo->freeuse) varinfo->isused = YES;
1146: varinfo->isset = YES;
1147: if (!addrinfo->freeuse && !varinfo->isused)
1148: varinfo->setfirst = YES;
1149: }
1150: }
1151: }
1152: else
1153: badtag ("regalloc:scanassign", ep->leftp->tag);
1154: }
1155:
1156:
1157:
1158: LOCAL scanopeq(ep)
1159: Exprp ep;
1160:
1161: {
1162: Addrp lhs;
1163: ADDRNODE *addrinfo;
1164: VARNODE *varinfo;
1165:
1166: scanvars(ep->rightp);
1167: if (ep->leftp->tag == TADDR)
1168: {
1169: lhs = (Addrp) ep->leftp;
1170: scanvars(lhs->vleng);
1171: scanvars(lhs->memoffset);
1172: if ((lhs->vstg == STGREG) || (lhs->vstg == STGPREG))
1173: return;
1174: if (ISVAR(lhs))
1175: {
1176: addrinfo = getaddr(lhs);
1177: addrinfo->isset = YES;
1178: if (docount > 1)
1179: addrinfo->loopset = YES;
1180: if (fixedaddress(lhs))
1181: {
1182: if (ISREGTYPE(lhs->vtype))
1183: {
1184: varinfo = getvar(addrinfo, lhs);
1185: varinfo->isused = YES;
1186: varinfo->isset = YES;
1187: }
1188: }
1189: }
1190: else
1191: addrinfo->freeuse = YES;
1192: }
1193: else
1194: badtag ("regalloc:scanopeq", ep->leftp->tag);
1195: }
1196:
1197:
1198:
1199: LOCAL scancall(ep)
1200: Exprp ep;
1201:
1202: {
1203: Addrp lhs;
1204: chainp args;
1205: Addrp ap;
1206: VARNODE *varinfo;
1207: ADDRNODE *addrinfo;
1208:
1209: lhs = (Addrp) ep->leftp;
1210: scanvars(lhs->vleng);
1211: scanvars(lhs->memoffset);
1212:
1213: if (ep->rightp == NULL) return;
1214:
1215: if (lhs->vstg != STGINTR)
1216: {
1217: args = ep->rightp->listblock.listp;
1218: for (; args; args = args->nextp)
1219: {
1220: if (args->datap->tag == TADDR)
1221: {
1222: ap = (Addrp) args->datap;
1223: scanvars(ap->vleng);
1224: scanvars(ap->memoffset);
1225: if (!ISVAR(ap)) continue;
1226:
1227: addrinfo = getaddr(ap);
1228: addrinfo->isset = YES;
1229: if (docount > 1)
1230: addrinfo->loopset = YES;
1231: if (fixedaddress(ap))
1232: {
1233: varinfo = getvar(addrinfo, ap);
1234: if (ap->vstg != STGCONST)
1235: varinfo->isset = YES;
1236: varinfo->isused = YES;
1237: }
1238: else
1239: addrinfo->freeuse = YES;
1240: }
1241: else
1242: scanvars(args->datap);
1243: }
1244: }
1245: else
1246: scanvars(ep->rightp);
1247:
1248: return;
1249: }
1250:
1251:
1252:
1253: LOCAL int fixedaddress(ap)
1254: Addrp ap;
1255:
1256: {
1257: if (!ap->memoffset)
1258: return NO;
1259: return (ISCONST(ap->memoffset) && ISINT(ap->memoffset->headblock.vtype));
1260: }
1261:
1262:
1263:
1264: LOCAL countrefs(p)
1265: expptr p;
1266:
1267: {
1268: Addrp ap;
1269: ADDRNODE *addrinfo;
1270: VARNODE *varinfo;
1271: VARNODE *vp;
1272: chainp args;
1273:
1274: if (p == NULL) return;
1275:
1276: switch (p->tag)
1277: {
1278: case TCONST:
1279: return;
1280:
1281: case TEXPR:
1282: switch (p->exprblock.opcode)
1283: {
1284: case OPCALL:
1285: if (p->exprblock.leftp->tag != TADDR)
1286: badtag ("regalloc:countrefs", p->exprblock.leftp->tag);
1287: countrefs(p->exprblock.leftp->addrblock.vleng);
1288: countrefs(p->exprblock.leftp->addrblock.memoffset);
1289:
1290: if (p->exprblock.leftp->addrblock.vstg != STGINTR)
1291: {
1292: if (!commonunusable)
1293: if (linearcode)
1294: setcommon();
1295: else
1296: commonunusable = YES;
1297: if (p->exprblock.rightp == NULL) return;
1298: args = p->exprblock.rightp->listblock.listp;
1299: for (; args; args = args->nextp)
1300: if (args->datap->tag == TADDR)
1301: {
1302: ap = (Addrp) args->datap;
1303: countrefs(ap->vleng);
1304: countrefs(ap->memoffset);
1305: if (!ISVAR(ap) || ap->vstg == STGCONST) continue;
1306: addrinfo = lookupaddr(ap->vstg, ap->memno);
1307: if (ap->vstg == STGARG)
1308: addrinfo->refs++;
1309: for (vp = addrinfo->varlist; vp; vp = vp->link)
1310: if (linearcode)
1311: if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
1312: if (addrinfo->istemp)
1313: vp->refs--;
1314: else
1315: {
1316: vp->refs -= 2;
1317: insertset(ap->vstg, ap->memno, vp->memoffset);
1318: }
1319: else
1320: vp->refs--;
1321: else
1322: {
1323: if (!addrinfo->istemp)
1324: vp->unusable = YES;
1325: }
1326: }
1327: else
1328: countrefs(args->datap);
1329: }
1330: else
1331: {
1332: if (p->exprblock.rightp == NULL) return;
1333: args = p->exprblock.rightp->listblock.listp;
1334: for (; args; args = args->nextp)
1335: if (args->datap->tag == TADDR)
1336: {
1337: ap = (Addrp) args->datap;
1338: countrefs(ap->vleng);
1339: countrefs(ap->memoffset);
1340: if (!ISVAR(ap) || ap->vstg == STGCONST) continue;
1341: addrinfo = lookupaddr(ap->vstg, ap->memno);
1342: addrinfo->refs++;
1343: for (vp = addrinfo->varlist; vp; vp = vp->link)
1344: if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
1345: {
1346: vp->refs--;
1347: insertset(ap->vstg, ap->memno, vp->memoffset);
1348: }
1349: }
1350: else
1351: countrefs(args->datap);
1352: }
1353: return;
1354:
1355: case OPASSIGN:
1356: case OPPLUSEQ:
1357: case OPSTAREQ:
1358: countrefs(p->exprblock.vleng);
1359: countrefs(p->exprblock.rightp);
1360: ap = (Addrp) p->exprblock.leftp;
1361: if (fixedaddress(ap))
1362: if (globalbranch)
1363: {
1364: countrefs(ap->vleng);
1365: countrefs(ap->memoffset);
1366: }
1367: else
1368: countrefs(ap);
1369: else if (linearcode)
1370: {
1371: countrefs(ap);
1372: for (vp = lookupaddr(ap->vstg, ap->memno)->varlist;
1373: vp;
1374: vp = vp->link)
1375: vp->refs--;
1376: }
1377: else
1378: {
1379: countrefs(ap);
1380: for (vp = lookupaddr(ap->vstg, ap->memno)->varlist;
1381: vp;
1382: vp = vp->link)
1383: vp->unusable = YES;
1384: }
1385: return;
1386:
1387: default:
1388: countrefs(p->exprblock.vleng);
1389: countrefs(p->exprblock.leftp);
1390: countrefs(p->exprblock.rightp);
1391: return;
1392: }
1393:
1394: case TADDR:
1395: ap = (Addrp) p;
1396: countrefs(ap->vleng);
1397: countrefs(ap->memoffset);
1398: if (!ISVAR(ap)) return;
1399:
1400: addrinfo = lookupaddr(ap->vstg, ap->memno);
1401: if (ap->vstg == STGARG)
1402: addrinfo->refs++;
1403:
1404: if (fixedaddress(ap))
1405: {
1406: if (ISREGTYPE(ap->vtype))
1407: {
1408: varinfo = lookupvar(addrinfo, ap->memoffset->constblock.const.ci);
1409: varinfo->refs++;
1410: }
1411: }
1412: else
1413: for (vp = addrinfo->varlist; vp; vp = vp->link)
1414: if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
1415: {
1416: vp->refs--;
1417: insertset(ap->vstg, ap->memno, vp->memoffset);
1418: }
1419: return;
1420:
1421: case TLIST:
1422: args = p->listblock.listp;
1423: for (; args; args = args->nextp)
1424: countrefs(args->datap);
1425: return;
1426:
1427: default:
1428: badtag ("regalloc:countrefs", p->tag);
1429: }
1430: }
1431:
1432:
1433:
1434: LOCAL regwrite(sp, p)
1435: Slotp sp;
1436: expptr p;
1437:
1438: {
1439: register int i;
1440: REGDATA *rp;
1441: chainp args;
1442: Addrp ap, ap1;
1443: int memoffset;
1444:
1445: if (p == NULL) return;
1446:
1447: switch (p->tag)
1448: {
1449: case TCONST:
1450: return;
1451:
1452: case TEXPR:
1453: switch (p->exprblock.opcode)
1454: {
1455: case OPCALL:
1456: ap = (Addrp) p->exprblock.leftp;
1457: regwrite(sp, ap->vleng);
1458: regwrite(sp, ap->memoffset);
1459: if (ap->vstg != STGINTR)
1460: {
1461: if (linearcode)
1462: {
1463: gensetcommon(sp);
1464: for (i = toplcv + 1; i <= topregvar; i++)
1465: if ((rp = regtab[i]) && (rp->vstg == STGCOMMON))
1466: regdefined[i] = NO;
1467: }
1468: if (p->exprblock.rightp == NULL) return;
1469: args = p->exprblock.rightp->listblock.listp;
1470: for (; args; args = args->nextp)
1471: if (args->datap->tag == TADDR)
1472: {
1473: ap = (Addrp) args->datap;
1474: regwrite(sp, ap->vleng);
1475: regwrite(sp, ap->memoffset);
1476: for (i = toplcv + 1; i <= topregvar; i++)
1477: if ((rp = regtab[i]) &&
1478: !rp->isarrayarg &&
1479: !rp->istemp &&
1480: (rp->vstg == ap->vstg) &&
1481: (rp->memno == ap->memno))
1482: {
1483: regdefined[i] = NO;
1484: if (!memdefined[i])
1485: {
1486: ap1 = (Addrp) cpexpr(rp->stgp);
1487: changetoreg(ap1, i);
1488: insertassign(sp, cpexpr(rp->stgp), ap1);
1489: memdefined[i] = YES;
1490: }
1491: }
1492: else if (rp->isarrayarg &&
1493: (ap->vstg == STGARG) &&
1494: (ap->memno == rp->memno))
1495: {
1496: ap->vstg = STGPREG;
1497: ap->memno = regnum[i];
1498: }
1499: }
1500: else
1501: regwrite(sp, args->datap);
1502: }
1503: else
1504: {
1505: if (p->exprblock.rightp == NULL) return;
1506: args = p->exprblock.rightp->listblock.listp;
1507: for (; args; args = args->nextp)
1508: if (args->datap->tag == TADDR)
1509: {
1510: ap = (Addrp) args->datap;
1511: regwrite(sp, ap->vleng);
1512: regwrite(sp, ap->memoffset);
1513: for (i = toplcv + 1; i <= topregvar; i++)
1514: if ((rp = regtab[i]) &&
1515: !rp->isarrayarg &&
1516: !rp->istemp &&
1517: (rp->vstg == ap->vstg) &&
1518: (rp->memno == ap->memno) &&
1519: !memdefined[i])
1520: {
1521: ap1 = (Addrp) cpexpr(rp->stgp);
1522: changetoreg(ap1, i);
1523: insertassign(sp, cpexpr(rp->stgp), ap1);
1524: memdefined[i] = YES;
1525: }
1526: else if (rp->isarrayarg &&
1527: (ap->vstg == STGARG) &&
1528: (rp->memno == ap->memno))
1529: {
1530: ap->vstg = STGPREG;
1531: ap->memno = regnum[i];
1532: }
1533: }
1534: else
1535: {
1536: regwrite(sp, args->datap);
1537: }
1538: }
1539: return;
1540:
1541: case OPASSIGN:
1542: case OPPLUSEQ:
1543: case OPSTAREQ:
1544: regwrite(sp, p->exprblock.vleng);
1545: regwrite(sp, p->exprblock.rightp);
1546: ap = (Addrp) p->exprblock.leftp;
1547: regwrite(sp, ap->vleng);
1548: regwrite(sp, ap->memoffset);
1549:
1550: if (ap->vstg == STGARG)
1551: for (i = toplcv + 1; i<=topregvar; i++)
1552: if ((rp = regtab[i]) &&
1553: rp->isarrayarg &&
1554: (rp->memno == ap->memno))
1555: {
1556: ap->vstg = STGPREG;
1557: ap->memno = regnum[i];
1558: return;
1559: }
1560:
1561: if (fixedaddress(ap))
1562: {
1563: memoffset = ap->memoffset->constblock.const.ci;
1564: for (i = toplcv + 1; i <= topregvar; i++)
1565: if ((rp = regtab[i]) &&
1566: !rp->isarrayarg &&
1567: (rp->vstg == ap->vstg) &&
1568: (rp->memno == ap->memno) &&
1569: (rp->memoffset == memoffset))
1570: {
1571: changetoreg(ap, i);
1572: if (globalbranch)
1573: {
1574: p->exprblock.rightp = (expptr) cpexpr(p);
1575: p->exprblock.leftp = (expptr) cpexpr(rp->stgp);
1576: p->exprblock.opcode = OPASSIGN;
1577: memdefined[i] = YES;
1578: }
1579: else
1580: {
1581: regaltered[i] = YES;
1582: regdefined[i] = YES;
1583: }
1584: }
1585: return;
1586: }
1587:
1588: if (linearcode)
1589: for (i = toplcv + 1; i <= topregvar; i++)
1590: if ((rp = regtab[i]) &&
1591: !rp->isarrayarg &&
1592: (rp->vstg == ap->vstg) &&
1593: (rp->memno == ap->memno))
1594: regdefined[i] = NO;
1595: return;
1596:
1597: default:
1598: regwrite(sp, p->exprblock.vleng);
1599: regwrite(sp, p->exprblock.leftp);
1600: regwrite(sp, p->exprblock.rightp);
1601: return;
1602: }
1603:
1604: case TADDR:
1605: ap = (Addrp) p;
1606: regwrite(sp, ap->vleng);
1607: regwrite(sp, ap->memoffset);
1608:
1609: if (ap->vstg == STGARG)
1610: for (i = toplcv + 1; i <= topregvar; i++)
1611: if ((rp = regtab[i]) &&
1612: rp->isarrayarg &&
1613: (rp->memno == ap->memno))
1614: {
1615: ap->vstg = STGPREG;
1616: ap->memno = regnum[i];
1617: return;
1618: }
1619:
1620: if (fixedaddress(ap))
1621: {
1622: memoffset = ap->memoffset->constblock.const.ci;
1623: for (i = toplcv + 1; i <= topregvar; i++)
1624: if ((rp = regtab[i]) &&
1625: !rp->isarrayarg &&
1626: (rp->vstg == ap->vstg) &&
1627: (rp->memno == ap->memno) &&
1628: (rp->memoffset == memoffset))
1629: {
1630: changetoreg(ap, i);
1631: return;
1632: }
1633: }
1634: else
1635: {
1636: for (i = toplcv + 1; i <= topregvar; i++)
1637: if ((rp = regtab[i]) &&
1638: !rp->isarrayarg &&
1639: (rp->vstg == ap->vstg) &&
1640: (rp->memno == ap->memno) &&
1641: !memdefined[i])
1642: {
1643: ap1 = (Addrp) cpexpr(rp->stgp);
1644: changetoreg(ap1, i);
1645: insertassign(sp, cpexpr(rp->stgp), ap1);
1646: memdefined[i] = YES;
1647: }
1648: }
1649: return;
1650:
1651: case TLIST:
1652: for (args = p->listblock.listp; args; args = args->nextp)
1653: regwrite(sp, args->datap);
1654: return;
1655:
1656: default:
1657: badtag ("regalloc:regwrite", p->tag);
1658: }
1659: }
1660:
1661:
1662:
1663: LOCAL setcommon()
1664:
1665: {
1666: ADDRNODE *ap;
1667: VARNODE *vp;
1668:
1669: for (ap = commonvars; ap; ap = ap->commonlink)
1670: for (vp = ap->varlist; vp; vp = vp->link)
1671: if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
1672: {
1673: vp->refs -= 2;
1674: insertset(ap->vstg, ap->memno, vp->memoffset);
1675: }
1676: else
1677: vp->refs--;
1678:
1679: return;
1680: }
1681:
1682:
1683:
1684: LOCAL setall()
1685:
1686: {
1687: register int i;
1688: register ADDRNODE *p;
1689: register VARNODE *q;
1690:
1691: for (i = 0; i < VARTABSIZE; i++)
1692: for (p = vartable[i]; p; p = p->link)
1693: if (p->istemp || !p->isset)
1694: break;
1695: else
1696: for (q = p->varlist; q; q = q->link)
1697: if (q->isset && !insetlist(p->vstg, p->memno, q->memoffset))
1698: q->refs--;
1699:
1700: allset = YES;
1701: return;
1702: }
1703:
1704:
1705:
1706: LOCAL int samevar(r1, r2)
1707: register REGDATA *r1;
1708: register REGNODE *r2;
1709:
1710: {
1711: if ((r1->vstg != r2->vstg) ||
1712: (r1->memno != r2->memno) ||
1713: (r1->isarrayarg != r2->isarrayarg))
1714: return NO;
1715: if (r1->isarrayarg)
1716: return YES;
1717: return (r1->memoffset == r2->memoffset);
1718: }
1719:
1720:
1721:
1722: LOCAL entableaddr(p)
1723: ADDRNODE *p;
1724:
1725: {
1726: int refs;
1727: Addrp ap;
1728: register int i;
1729:
1730: if (p->vstg != STGARG)
1731: {
1732: currentaddr = p;
1733: return;
1734: }
1735:
1736: refs = p->refs;
1737: if (refs <= 0) return;
1738:
1739: if (tabletop < 0)
1740: tabletop = i = 0;
1741: else if (refs > rt[tabletop]->refs)
1742: {
1743: if (tabletop + 1 < TABLELIMIT)
1744: tabletop++;
1745: else
1746: {
1747: frexpr(rt[tabletop]->stgp);
1748: free((char *) rt[tabletop]);
1749: }
1750:
1751: for (i = tabletop; i > 0; i--)
1752: if (refs > rt[i - 1]->refs)
1753: rt[i] = rt[i - 1];
1754: else
1755: break;
1756: }
1757: else if (tabletop + 1 < TABLELIMIT)
1758: i = ++tabletop;
1759: else
1760: return;
1761:
1762: rt[i] = ALLOC(regdata);
1763: rt[i]->vstg = p->vstg;
1764: rt[i]->vtype = p->vtype;
1765: rt[i]->memno = p->memno;
1766: rt[i]->refs = refs;
1767: rt[i]->isarrayarg = YES;
1768:
1769: return;
1770: }
1771:
1772:
1773:
1774:
1775: LOCAL entablevar(p)
1776: VARNODE *p;
1777:
1778: {
1779: int refs;
1780: register int i;
1781:
1782: if (p->unusable) return;
1783: refs = p->refs - loopcost;
1784: if (refs <= 0) return;
1785:
1786: if (tabletop < 0)
1787: tabletop = i = 0;
1788: else if (refs > rt[tabletop]->refs
1789: #ifdef BUMPREALS /* put floats last */
1790: || currentaddr->vtype!=TYREAL && rt[tabletop]->vtype==TYREAL && !rt[tabletop]->isarrayarg
1791: #endif
1792: ){
1793: if (tabletop + 1 < TABLELIMIT)
1794: tabletop++;
1795: else
1796: {
1797: frexpr(rt[tabletop]->stgp);
1798: free((char *) rt[tabletop]);
1799: }
1800:
1801: for (i = tabletop; i > 0; i--)
1802: if (refs > rt[i - 1]->refs
1803: #ifdef BUMPREALS /* put floats last */
1804: || currentaddr->vtype!=TYREAL && rt[i-1]->vtype==TYREAL && !rt[i-1]->isarrayarg
1805: #endif
1806: )
1807: rt[i] = rt[i - 1];
1808: else
1809: break;
1810: }
1811: else if (tabletop + 1 < TABLELIMIT)
1812: i = ++tabletop;
1813: else
1814: return;
1815:
1816: rt[i] = ALLOC(regdata);
1817: rt[i]->vstg = currentaddr->vstg;
1818: rt[i]->vtype = currentaddr->vtype;
1819: rt[i]->memno = currentaddr->memno;
1820: rt[i]->memoffset = p->memoffset;
1821: rt[i]->refs = refs;
1822: rt[i]->stgp = (Addrp) cpexpr(p->stgp);
1823: rt[i]->isarrayarg = NO;
1824: rt[i]->istemp = currentaddr->istemp;
1825: rt[i]->isset = p->isset;
1826: rt[i]->setfirst = p->setfirst;
1827:
1828: return;
1829: }
1830:
1831:
1832:
1833: LOCAL int inregtab(p)
1834: register REGDATA *p;
1835:
1836: {
1837: register REGDATA *rp;
1838: register int i;
1839:
1840: for (i = 0; i <= topregvar; i++)
1841: if (rp = regtab[i])
1842: if ((rp->vstg == p->vstg) &&
1843: (rp->memno == p->memno) &&
1844: (rp->isarrayarg == p->isarrayarg))
1845: if (rp->isarrayarg)
1846: return YES;
1847: else if (rp->memoffset == p->memoffset)
1848: return YES;
1849:
1850: return NO;
1851: }
1852:
1853:
1854:
1855: LOCAL changetoreg(ap, i)
1856: register Addrp ap;
1857: int i;
1858:
1859: {
1860: ap->vstg = STGREG;
1861: ap->memno = regnum[i];
1862: frexpr(ap->memoffset);
1863: ap->memoffset = ICON(0);
1864: ap->istemp = NO;
1865: return;
1866: }
1867:
1868:
1869:
1870: LOCAL insertassign(sp, dest, src)
1871: Slotp sp;
1872: Addrp dest;
1873: expptr src;
1874:
1875: {
1876: Slotp newslot;
1877: expptr p;
1878:
1879: p = mkexpr(OPASSIGN, dest, src);
1880: newslot = optinsert (SKEQ,p,0,0,sp);
1881:
1882: if (sp == dohead)
1883: if (!newcode)
1884: newcode = newslot;
1885:
1886: return;
1887: }
1888:
1889:
1890: LOCAL appendassign(sp, dest, src)
1891: Slotp sp;
1892: Addrp dest;
1893: expptr src;
1894:
1895: {
1896: Slotp newslot;
1897: expptr p;
1898:
1899: if (!sp)
1900: fatal ("regalloc:appendassign");
1901:
1902: p = mkexpr(OPASSIGN, dest, src);
1903: newslot = optinsert (SKEQ,p,0,0,sp->next);
1904:
1905: return;
1906: }
1907:
1908:
1909:
1910: LOCAL int regtomem(sp)
1911: Slotp sp;
1912:
1913: {
1914: expptr p, l, r;
1915: int i;
1916:
1917: if (sp->type != SKEQ) return NO;
1918:
1919: p = sp->expr;
1920: if ((p->tag != TEXPR) || (p->exprblock.opcode != OPASSIGN))
1921: return NO;
1922:
1923: r = p->exprblock.rightp;
1924: if ((r->tag != TADDR) || (r->addrblock.vstg != STGREG))
1925: return NO;
1926:
1927: l = p->exprblock.leftp;
1928: if (l->tag != TADDR)
1929: return NO;
1930: i = r->addrblock.memno;
1931: if (regtab[i] &&
1932: (l->addrblock.vstg == regtab[i]->vstg) &&
1933: (l->addrblock.memno == regtab[i]->memno) &&
1934: fixedaddress(l) &&
1935: (l->addrblock.memoffset->constblock.const.ci == regtab[i]->memoffset))
1936: return YES;
1937:
1938: return NO;
1939: }
1940:
1941:
1942:
1943: LOCAL int regtoreg(sp)
1944: Slotp sp;
1945:
1946: {
1947: expptr p, l, r;
1948:
1949: if (sp->type != SKEQ) return NO;
1950:
1951: p = sp->expr;
1952: if ((p->tag != TEXPR) || (p->exprblock.opcode != OPASSIGN))
1953: return NO;
1954:
1955: l = p->exprblock.leftp;
1956: if ((l->tag != TADDR) || (l->addrblock.vstg != STGREG))
1957: return NO;
1958:
1959: r = p->exprblock.rightp;
1960: if ((r->tag == TADDR) &&
1961: (r->addrblock.vstg == STGREG) &&
1962: (r->addrblock.memno == l->addrblock.memno))
1963: return YES;
1964:
1965: if ((r->tag == TEXPR) &&
1966: (r->exprblock.opcode == OPADDR) &&
1967: (r->exprblock.leftp->tag == TADDR) &&
1968: (r->exprblock.leftp->addrblock.vstg == STGPREG) &&
1969: (r->exprblock.leftp->addrblock.memno == l->addrblock.memno))
1970: return YES;
1971:
1972: return NO;
1973: }
1974:
1975:
1976:
1977: LOCAL deleteslot(sp)
1978: Slotp sp;
1979:
1980: {
1981: if (newcode == sp)
1982: {
1983: newcode = sp->next;
1984: if (newcode == dohead)
1985: newcode = NULL;
1986: }
1987:
1988: delslot (sp);
1989: return;
1990: }
1991:
1992:
1993:
1994: LOCAL gensetall(sp)
1995: Slotp sp;
1996:
1997: {
1998: register int i;
1999: register REGDATA *rp;
2000: register Addrp ap;
2001:
2002: for (i = toplcv + 1; i <= topregvar; i++)
2003: if (rp = regtab[i])
2004: if (rp->isset && !(rp->istemp || rp->isarrayarg))
2005: if (!memdefined[i])
2006: {
2007: ap = (Addrp) cpexpr(rp->stgp);
2008: changetoreg(ap, i);
2009: insertassign(sp, cpexpr(rp->stgp), ap);
2010: memdefined[i] = YES;
2011: }
2012:
2013: return;
2014: }
2015:
2016:
2017: LOCAL gensetcommon(sp)
2018: Slotp sp;
2019:
2020: {
2021: register int i;
2022: register REGDATA *rp;
2023: register Addrp ap;
2024:
2025: for (i = toplcv + 1; i <= topregvar; i++)
2026: if (rp = regtab[i])
2027: if ((rp->vstg == STGCOMMON) && !rp->isarrayarg)
2028: if (!memdefined[i])
2029: {
2030: ap = (Addrp) cpexpr(rp->stgp);
2031: changetoreg(ap, i);
2032: insertassign(sp, cpexpr(rp->stgp), ap);
2033: memdefined[i] = YES;
2034: }
2035:
2036: return;
2037: }
2038:
2039:
2040: LOCAL gensetreturn(sp)
2041: Slotp sp;
2042:
2043: {
2044: register int i;
2045: register REGDATA *rp;
2046: register Addrp ap;
2047:
2048: for (i = toplcv + 1; i <= topregvar; i++)
2049: if (rp = regtab[i])
2050: if (((rp->vstg == STGCOMMON) && !rp->isarrayarg)
2051: || (rp->isset && (saveall || rp->stgp->issaved) && !(rp->istemp || rp->isarrayarg)))
2052: if (!memdefined[i])
2053: {
2054: ap = (Addrp) cpexpr(rp->stgp);
2055: changetoreg(ap, i);
2056: insertassign(sp, cpexpr(rp->stgp), ap);
2057: memdefined[i] = YES;
2058: }
2059:
2060: return;
2061: }
2062:
2063:
2064:
2065: LOCAL clearmems()
2066:
2067: {
2068: REGDATA *rp;
2069: register int i;
2070:
2071: for (i = 0; i <= toplcv; i++)
2072: memdefined[i] = YES;
2073: for (; i <= topregvar; i++)
2074: if ((rp = regtab[i]) && rp->isset)
2075: memdefined[i] = NO;
2076: else
2077: memdefined[i] = YES;
2078: return;
2079: }
2080:
2081:
2082: LOCAL setregs()
2083:
2084: {
2085: register int i;
2086:
2087: for (i = 0; i <= topregvar; i++)
2088: regdefined[i] = YES;
2089: return;
2090: }
2091:
2092:
2093:
2094: regalloc()
2095:
2096: {
2097: int match;
2098: Slotp nextslot;
2099: Slotp sl1,sl2;
2100: Slotp lastlabslot;
2101:
2102: if (! optimflag) return;
2103:
2104: docount = 0;
2105: lastlabslot = NULL;
2106: for (sl1 = firstslot; sl1; sl1 = nextslot)
2107: {
2108: nextslot = sl1->next;
2109: switch (sl1->type)
2110: {
2111:
2112: /* temporarily commented out -----
2113: case SKLABEL:
2114: lastlabslot = sl1;
2115: break;
2116:
2117: case SKGOTO:
2118: if (lastlabslot && sl1->label == lastlabslot->label)
2119: {
2120: dohead = lastlabslot;
2121: doend = sl1;
2122: alreg ();
2123: }
2124: break;
2125: ----- */
2126:
2127: case SKDOHEAD:
2128: ++docount;
2129: pushq (sl1);
2130: break;
2131:
2132: case SKENDDO:
2133: --docount;
2134: match = 0;
2135: for (sl2 = sl1; sl2; sl2 = sl2->prev)
2136: {
2137: if (sl2->type == SKDOHEAD) match++;
2138: else if (sl2->type == SKENDDO) match--;
2139: if (match == 0) break;
2140: }
2141: if (sl2)
2142: dohead = sl2;
2143: else
2144: fatal ("unmatched enddo in code buffer");
2145: if (sl2->type != SKDOHEAD)
2146: fatal ("internal error in regalloc");
2147:
2148: for (dqptr = dqbottom; dqptr; dqptr = dqptr->up)
2149: {
2150: if (dqptr->dohead == dohead)
2151: break;
2152: }
2153:
2154: if (!dqptr)
2155: fatal ("garbled doqueue in regalloc");
2156:
2157: /* sl1 now points to the SKENDDO slot; the SKNULL slot
2158: * is reached through sl1->nullslot
2159: */
2160: dqptr->doend = (Slotp) sl1->nullslot;
2161: if (docount == 0)
2162: {
2163: for (dqptr = dqbottom; dqptr; dqptr = dqptr->up)
2164: {
2165: dohead = dqptr->dohead;
2166: doend = dqptr->doend;
2167: alreg();
2168: }
2169: while (dqtop)
2170: popq(dqtop->dohead);
2171: docount = 0;
2172: }
2173: break;
2174:
2175: default:
2176: break;
2177: }
2178: }
2179:
2180: return;
2181: }
2182:
2183:
2184:
2185: LOCAL pushq(sp)
2186: Slotp sp;
2187:
2188: {
2189: DOQUEUE *t;
2190:
2191: if (sp->type != SKDOHEAD)
2192: fatal("regalloc:pushq: DO statement expected");
2193:
2194: if (dqbottom)
2195: {
2196: t = ALLOC(doqueue);
2197: t->up = dqbottom;
2198: dqbottom->down = t;
2199: dqbottom = t;
2200: }
2201: else
2202: dqtop = dqbottom = ALLOC(doqueue);
2203:
2204: dqbottom->dohead = sp;
2205: }
2206:
2207:
2208: LOCAL popq(sp)
2209: Slotp sp;
2210:
2211: {
2212: DOQUEUE *t;
2213: register int i;
2214:
2215: if (!dqtop)
2216: fatal("regalloc:popq: empty DO queue");
2217: if (dqtop->dohead != sp)
2218: fatal("regalloc:popq: garbled DO queue");
2219:
2220: t = dqtop;
2221:
2222: dqtop = t->down;
2223: if (dqtop)
2224: dqtop->up = NULL;
2225: else
2226: dqbottom = NULL;
2227: for (i = 0; i < MAXREGVAR; i++)
2228: if (t->reg[i])
2229: free((char *) t->reg[i]);
2230: free(t);
2231: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.