1*47951Sbostic /*-
2*47951Sbostic * Copyright (c) 1980 The Regents of the University of California.
3*47951Sbostic * All rights reserved.
4*47951Sbostic *
5*47951Sbostic * %sccs.include.proprietary.c%
643223Sbostic */
743223Sbostic
843223Sbostic #ifndef lint
9*47951Sbostic static char sccsid[] = "@(#)regalloc.c 5.3 (Berkeley) 04/12/91";
10*47951Sbostic #endif /* not lint */
1143223Sbostic
1243223Sbostic /*
1343223Sbostic * regalloc.c
1443223Sbostic *
1543223Sbostic * Register optimization routines for f77 compiler, pass 1
1643223Sbostic *
1743223Sbostic * University of Utah CS Dept modification history:
1843223Sbostic *
1943223Sbostic * $History$
2043223Sbostic * $Log: regalloc.c,v $
2143223Sbostic * Revision 1.4 86/02/12 15:29:16 rcs
2243223Sbostic * 4.3 F77. C. Keating.
2343223Sbostic *
2443223Sbostic * Revision 2.9 85/03/18 21:35:05 donn
2543223Sbostic * Bob Corbett's hack to prevent conflicts between subroutine side effects
2643223Sbostic * and register assignment. Makes the code a lot worse...
2743223Sbostic *
2843223Sbostic * Revision 2.8 85/02/22 02:14:08 donn
2943223Sbostic * In code like 'x = foo(x)', alreg() would copy the memory version of the
3043223Sbostic * variable 'x' into the register version after the assignment, clobbering
3143223Sbostic * the result. A small change to regwrite() seems to prevent this.
3243223Sbostic *
3343223Sbostic * Revision 2.7 85/02/16 03:32:45 donn
3443223Sbostic * Fixed a bug where the loop test and increment were having register
3543223Sbostic * substitution performed twice, once in the environment of the current
3643223Sbostic * loop and once in the environment of the containing loop. If the
3743223Sbostic * containing loop puts (say) the inner loop's index variable in register
3843223Sbostic * but the inner loop does not, havoc results.
3943223Sbostic *
4043223Sbostic * Revision 2.6 85/02/14 23:21:45 donn
4143223Sbostic * Don't permit variable references of the form 'a(i)' to be put in register
4243223Sbostic * if array 'a' is in common. This is because there is no good way to
4343223Sbostic * identify instances of this sort without getting confused with other
4443223Sbostic * variables in the same common block which are in register. Sigh.
4543223Sbostic *
4643223Sbostic * Revision 2.5 85/01/11 21:08:00 donn
4743223Sbostic * Made changes so that we pay attention to SAVE statements. Added a new
4843223Sbostic * gensetreturn() function to implement this.
4943223Sbostic *
5043223Sbostic * Revision 2.4 84/09/03 22:37:28 donn
5143223Sbostic * Changed the treatment of SKRETURN in alreg() so that all variables in
5243223Sbostic * register, not just COMMON variables, get written out to memory before a
5343223Sbostic * RETURN. This was causing the return value of a function to get lost when
5443223Sbostic * a RETURN was done from inside a loop (among other problems).
5543223Sbostic *
5643223Sbostic * Revision 2.3 84/08/04 20:52:42 donn
5743223Sbostic * Added fixes for EXTERNAL parameters from Jerry Berkman.
5843223Sbostic *
5943223Sbostic * Revision 2.2 84/08/04 20:34:29 donn
6043223Sbostic * Fixed a stupidity pointed out by Jerry Berkman -- the 'floats in register'
6143223Sbostic * stuff applies if the TARGET is a VAX, not if the local machine is a VAX.
6243223Sbostic *
6343223Sbostic * Revision 2.1 84/07/19 12:04:47 donn
6443223Sbostic * Changed comment headers for UofU.
6543223Sbostic *
6643223Sbostic * Revision 1.5 83/11/27 19:25:41 donn
6743223Sbostic * Added REAL to the list of types which may appear in registers (VAXen only).
6843223Sbostic *
6943223Sbostic * Revision 1.4 83/11/13 02:38:39 donn
7043223Sbostic * Bug fixed in alreg()'s handling of computed goto's. A '<=' in place of a
7143223Sbostic * '<' led to core dumps when we walked off the end of the list of labels...
7243223Sbostic *
7343223Sbostic * Revision 1.3 83/11/12 01:25:57 donn
7443223Sbostic * Bug in redundant register assignment code, mistakenly carried over some old
7543223Sbostic * code that sometimes rewound a slot pointer even when a redundant slot wasn't
7643223Sbostic * deleted; this caused an infinite loop... Seems to work now.
7743223Sbostic *
7843223Sbostic * Revision 1.2 83/11/09 14:58:12 donn
7943223Sbostic * Took out broken code dealing with redundant register initializations.
8043223Sbostic * Couldn't see what to do about redundantly initializing a DO variable but
8143223Sbostic * I did fix things so that an assignment from a register into the same
8243223Sbostic * register is always deleted.
8343223Sbostic *
8443223Sbostic */
8543223Sbostic
8643223Sbostic #include "defs.h"
8743223Sbostic #include "optim.h"
8843223Sbostic
8943223Sbostic #define LABTABSIZE 101
9043223Sbostic #define VARTABSIZE 1009
9143223Sbostic #define TABLELIMIT 12
9243223Sbostic
9343223Sbostic #if TARGET==VAX || TARGET==TAHOE
9443223Sbostic #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) | M(TYREAL)
9543223Sbostic #if TARGET==TAHOE
9643223Sbostic #define BUMPREALS /* put floats last */
9743223Sbostic #endif
9843223Sbostic #else
9943223Sbostic #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG)
10043223Sbostic #endif
10143223Sbostic
10243223Sbostic
10343223Sbostic #define ISREGTYPE(x) ONEOF(x, MSKREGTYPES)
10443223Sbostic
10543223Sbostic #define MSKVARS M(STGAUTO) | M(STGBSS) | M(STGINIT) | M(STGCONST) |\
10643223Sbostic M(STGEQUIV) | M(STGARG) | M(STGCOMMON)
10743223Sbostic
10843223Sbostic #define ISVAR(x) ((((expptr) x)->headblock.vclass == CLVAR || \
10943223Sbostic ((expptr) x)->headblock.vclass == CLUNKNOWN) \
11043223Sbostic && ONEOF(((expptr) x)->headblock.vstg, MSKVARS))
11143223Sbostic
11243223Sbostic
11343223Sbostic typedef
11443223Sbostic struct regdata
11543223Sbostic {
11643223Sbostic field vstg;
11743223Sbostic field vtype;
11843223Sbostic int memno;
11943223Sbostic int memoffset;
12043223Sbostic int refs;
12143223Sbostic Addrp stgp;
12243223Sbostic unsigned isarrayarg : 1;
12343223Sbostic unsigned istemp : 1;
12443223Sbostic unsigned isset : 1;
12543223Sbostic unsigned setfirst : 1;
12643223Sbostic } REGDATA;
12743223Sbostic
12843223Sbostic
12943223Sbostic typedef
13043223Sbostic struct labelnode
13143223Sbostic {
13243223Sbostic struct labelnode *link;
13343223Sbostic int labelno;
13443223Sbostic } LABELNODE;
13543223Sbostic
13643223Sbostic
13743223Sbostic
13843223Sbostic typedef
13943223Sbostic struct varnode
14043223Sbostic {
14143223Sbostic struct varnode *link;
14243223Sbostic int memoffset;
14343223Sbostic unsigned isset : 1;
14443223Sbostic unsigned isused : 1;
14543223Sbostic unsigned setfirst : 1;
14643223Sbostic unsigned unusable : 1;
14743223Sbostic int refs;
14843223Sbostic Addrp stgp;
14943223Sbostic } VARNODE;
15043223Sbostic
15143223Sbostic
15243223Sbostic typedef
15343223Sbostic struct addrnode
15443223Sbostic {
15543223Sbostic struct addrnode *link;
15643223Sbostic field vtype;
15743223Sbostic field vstg;
15843223Sbostic int memno;
15943223Sbostic unsigned istemp : 1;
16043223Sbostic unsigned isset : 1;
16143223Sbostic unsigned loopset :1;
16243223Sbostic unsigned freeuse : 1;
16343223Sbostic unsigned mixedtype : 1;
16443223Sbostic unsigned fixed : 1;
16543223Sbostic int refs;
16643223Sbostic struct addrnode *commonlink;
16743223Sbostic VARNODE *varlist;
16843223Sbostic } ADDRNODE;
16943223Sbostic
17043223Sbostic
17143223Sbostic typedef
17243223Sbostic struct setnode
17343223Sbostic {
17443223Sbostic struct setnode *link;
17543223Sbostic field vstg;
17643223Sbostic int memno;
17743223Sbostic int memoffset;
17843223Sbostic } SETNODE;
17943223Sbostic
18043223Sbostic
18143223Sbostic typedef
18243223Sbostic struct doqueue
18343223Sbostic {
18443223Sbostic struct doqueue *up, *down;
18543223Sbostic Slotp dohead, doend;
18643223Sbostic int nregvars;
18743223Sbostic REGNODE *reg[MAXREGVAR];
18843223Sbostic } DOQUEUE;
18943223Sbostic
19043223Sbostic LOCAL DOQUEUE *dqptr, *dqtop, *dqbottom;
19143223Sbostic
19243223Sbostic
19343223Sbostic LOCAL Slotp dohead;
19443223Sbostic LOCAL Slotp doend;
19543223Sbostic LOCAL Slotp newcode;
19643223Sbostic
19743223Sbostic
19843223Sbostic
19943223Sbostic LOCAL LABELNODE *labeltable[LABTABSIZE];
20043223Sbostic LOCAL ADDRNODE *vartable[VARTABSIZE];
20143223Sbostic LOCAL ADDRNODE *commonvars;
20243223Sbostic LOCAL SETNODE *setlist;
20343223Sbostic LOCAL int topregvar;
20443223Sbostic LOCAL int toplcv;
20543223Sbostic LOCAL int allset;
20643223Sbostic LOCAL ADDRNODE *currentaddr;
20743223Sbostic LOCAL int loopcost;
20843223Sbostic LOCAL REGDATA *regtab[MAXREGVAR];
20943223Sbostic LOCAL REGDATA *rt[TABLELIMIT];
21043223Sbostic LOCAL int tabletop;
21143223Sbostic LOCAL int linearcode;
21243223Sbostic LOCAL int docount;
21343223Sbostic LOCAL int globalbranch;
21443223Sbostic LOCAL int commonunusable;
21543223Sbostic LOCAL int regdefined[MAXREGVAR];
21643223Sbostic LOCAL int memdefined[MAXREGVAR];
21743223Sbostic LOCAL int regaltered[MAXREGVAR];
21843223Sbostic
21943223Sbostic
22043223Sbostic
insertlabel(l)22143223Sbostic LOCAL insertlabel(l)
22243223Sbostic int l;
22343223Sbostic
22443223Sbostic {
22543223Sbostic int key;
22643223Sbostic LABELNODE *p;
22743223Sbostic
22843223Sbostic key = l % LABTABSIZE;
22943223Sbostic for (p = labeltable[key]; p; p = p->link)
23043223Sbostic if (p->labelno == l) return;
23143223Sbostic p = labeltable[key];
23243223Sbostic labeltable[key] = ALLOC(labelnode);
23343223Sbostic labeltable[key]->link = p;
23443223Sbostic labeltable[key]->labelno = l;
23543223Sbostic return;
23643223Sbostic }
23743223Sbostic
23843223Sbostic
23943223Sbostic
locallabel(l)24043223Sbostic LOCAL int locallabel(l)
24143223Sbostic int l;
24243223Sbostic
24343223Sbostic {
24443223Sbostic int key;
24543223Sbostic LABELNODE *p;
24643223Sbostic
24743223Sbostic key = l % LABTABSIZE;
24843223Sbostic for (p = labeltable[key]; p; p = p->link)
24943223Sbostic if (p->labelno == l) return YES;
25043223Sbostic
25143223Sbostic return NO;
25243223Sbostic }
25343223Sbostic
25443223Sbostic
25543223Sbostic
freelabtab()25643223Sbostic LOCAL freelabtab()
25743223Sbostic
25843223Sbostic {
25943223Sbostic int i;
26043223Sbostic LABELNODE *p, *q;
26143223Sbostic
26243223Sbostic for (i = 0; i < LABTABSIZE; i++)
26343223Sbostic if (labeltable[i])
26443223Sbostic {
26543223Sbostic p = labeltable[i];
26643223Sbostic labeltable[i] = NULL;
26743223Sbostic while (p)
26843223Sbostic {
26943223Sbostic q = p->link;
27043223Sbostic free(p);
27143223Sbostic p = q;
27243223Sbostic }
27343223Sbostic }
27443223Sbostic return;
27543223Sbostic }
27643223Sbostic
27743223Sbostic
27843223Sbostic
getaddr(ap)27943223Sbostic LOCAL ADDRNODE *getaddr(ap)
28043223Sbostic Addrp ap;
28143223Sbostic
28243223Sbostic {
28343223Sbostic int key;
28443223Sbostic field vstg;
28543223Sbostic int memno;
28643223Sbostic register ADDRNODE *q;
28743223Sbostic ADDRNODE *q1;
28843223Sbostic
28943223Sbostic if (!ISVAR(ap))
29043223Sbostic fatal("regalloc: bad data sent to getaddr");
29143223Sbostic vstg = ap->vstg;
29243223Sbostic memno = ap->memno;
29343223Sbostic key = (256*vstg + memno) % VARTABSIZE;
29443223Sbostic
29543223Sbostic for (q = vartable[key]; q; q = q->link)
29643223Sbostic if ((q->vstg == vstg) && (q->memno == memno))
29743223Sbostic {
29843223Sbostic if (ap->istemp) q->istemp = YES;
29943223Sbostic if (ap->vtype != q->vtype)
30043223Sbostic q->mixedtype = YES;
30143223Sbostic if (!fixedaddress(ap))
30243223Sbostic q->fixed = NO;
30343223Sbostic return q;
30443223Sbostic }
30543223Sbostic
30643223Sbostic q1 = vartable[key];
30743223Sbostic vartable[key] = q = ALLOC(addrnode);
30843223Sbostic q->link = q1;
30943223Sbostic q->vstg = vstg;
31043223Sbostic q->memno = memno;
31143223Sbostic if (ap->istemp) q->istemp = YES;
31243223Sbostic if (fixedaddress(ap)) q->fixed = YES;
31343223Sbostic q->vtype = ap->vtype;
31443223Sbostic q->varlist = NULL;
31543223Sbostic if (vstg == STGCOMMON)
31643223Sbostic {
31743223Sbostic q->commonlink = commonvars;
31843223Sbostic commonvars = q;
31943223Sbostic }
32043223Sbostic return q;
32143223Sbostic }
32243223Sbostic
32343223Sbostic
32443223Sbostic
getvar(ainfo,ap)32543223Sbostic LOCAL VARNODE *getvar(ainfo, ap)
32643223Sbostic ADDRNODE *ainfo;
32743223Sbostic Addrp ap;
32843223Sbostic
32943223Sbostic {
33043223Sbostic register VARNODE *q;
33143223Sbostic register VARNODE *q1;
33243223Sbostic
33343223Sbostic int memoffset;
33443223Sbostic
33543223Sbostic if (!ISVAR(ap))
33643223Sbostic fatal("regalloc: bad data sent to getvar");
33743223Sbostic
33846307Sbostic memoffset = ap->memoffset->constblock.constant.ci;
33943223Sbostic
34043223Sbostic for (q = ainfo->varlist; q; q = q->link)
34143223Sbostic if (q->memoffset == memoffset)
34243223Sbostic return q;
34343223Sbostic
34443223Sbostic q1 = ainfo->varlist;
34543223Sbostic ainfo->varlist = q = ALLOC(varnode);
34643223Sbostic q->link = q1;
34743223Sbostic q->memoffset = memoffset;
34843223Sbostic q->stgp = (Addrp) cpexpr(ap);
34943223Sbostic return q;
35043223Sbostic }
35143223Sbostic
35243223Sbostic
lookupaddr(vstg,memno)35343223Sbostic LOCAL ADDRNODE *lookupaddr(vstg, memno)
35443223Sbostic field vstg;
35543223Sbostic int memno;
35643223Sbostic
35743223Sbostic {
35843223Sbostic int key;
35943223Sbostic register ADDRNODE *q;
36043223Sbostic
36143223Sbostic key = (256*vstg + memno) % VARTABSIZE;
36243223Sbostic
36343223Sbostic for (q = vartable[key]; q; q = q->link)
36443223Sbostic if ((q->vstg == vstg) && (q->memno == memno))
36543223Sbostic return q;
36643223Sbostic
36743223Sbostic fatal("regalloc: lookupaddr");
36843223Sbostic }
36943223Sbostic
37043223Sbostic
lookupvar(ainfo,memoffset)37143223Sbostic LOCAL VARNODE *lookupvar(ainfo, memoffset)
37243223Sbostic ADDRNODE *ainfo;
37343223Sbostic int memoffset;
37443223Sbostic
37543223Sbostic {
37643223Sbostic register VARNODE *q;
37743223Sbostic
37843223Sbostic for (q = ainfo->varlist; q; q = q->link)
37943223Sbostic if (q->memoffset == memoffset)
38043223Sbostic return q;
38143223Sbostic
38243223Sbostic fatal("regalloc: lookupvar");
38343223Sbostic }
38443223Sbostic
38543223Sbostic
38643223Sbostic
invartable(p)38743223Sbostic LOCAL int invartable(p)
38843223Sbostic REGNODE *p;
38943223Sbostic
39043223Sbostic {
39143223Sbostic field vstg;
39243223Sbostic int memno;
39343223Sbostic int key;
39443223Sbostic register ADDRNODE *q;
39543223Sbostic
39643223Sbostic vstg = p->vstg;
39743223Sbostic memno = p->memno;
39843223Sbostic key = (256*vstg + memno) % VARTABSIZE;
39943223Sbostic
40043223Sbostic for (q = vartable[key]; q; q = q->link)
40143223Sbostic if ((q->vstg == vstg) && (q->memno == memno))
40243223Sbostic return YES;
40343223Sbostic
40443223Sbostic return NO;
40543223Sbostic }
40643223Sbostic
40743223Sbostic
40843223Sbostic
freevartab()40943223Sbostic LOCAL freevartab()
41043223Sbostic
41143223Sbostic {
41243223Sbostic register ADDRNODE *p;
41343223Sbostic ADDRNODE *p1;
41443223Sbostic register VARNODE *q;
41543223Sbostic VARNODE *q1;
41643223Sbostic register int i;
41743223Sbostic
41843223Sbostic for (i = 0; i < VARTABSIZE; i++)
41943223Sbostic if (vartable[i])
42043223Sbostic {
42143223Sbostic p = vartable[i];
42243223Sbostic vartable[i] = NULL;
42343223Sbostic
42443223Sbostic while (p)
42543223Sbostic {
42643223Sbostic for (q = p->varlist; q; q = q1)
42743223Sbostic {
42843223Sbostic q1 = q->link;
42943223Sbostic frexpr(q->stgp);
43043223Sbostic free ((char *) q);
43143223Sbostic }
43243223Sbostic p1 = p->link;
43343223Sbostic free((char *) p);
43443223Sbostic p = p1;
43543223Sbostic }
43643223Sbostic }
43743223Sbostic }
43843223Sbostic
43943223Sbostic
44043223Sbostic
insertset(vstg,memno,memoffset)44143223Sbostic LOCAL insertset(vstg, memno, memoffset)
44243223Sbostic field vstg;
44343223Sbostic int memno;
44443223Sbostic int memoffset;
44543223Sbostic
44643223Sbostic {
44743223Sbostic register SETNODE *p;
44843223Sbostic SETNODE *q;
44943223Sbostic
45043223Sbostic if (allset) return;
45143223Sbostic for (p = setlist; p; p = p->link)
45243223Sbostic if((p->vstg == vstg) && (p->memno == memno) && (p->memoffset == memoffset))
45343223Sbostic return;
45443223Sbostic
45543223Sbostic q = p;
45643223Sbostic setlist = p = ALLOC(setnode);
45743223Sbostic p->link = q;
45843223Sbostic p->vstg = vstg;
45943223Sbostic p->memno = memno;
46043223Sbostic p->memoffset = memoffset;
46143223Sbostic return;
46243223Sbostic }
46343223Sbostic
46443223Sbostic
46543223Sbostic
insetlist(vstg,memno,memoffset)46643223Sbostic LOCAL int insetlist(vstg, memno, memoffset)
46743223Sbostic field vstg;
46843223Sbostic int memno;
46943223Sbostic int memoffset;
47043223Sbostic
47143223Sbostic {
47243223Sbostic register SETNODE *p;
47343223Sbostic
47443223Sbostic if (allset) return YES;
47543223Sbostic for (p = setlist; p; p = p->link)
47643223Sbostic if((p->vstg == vstg) && (p->memno == memno) && (p->memoffset == memoffset))
47743223Sbostic return YES;
47843223Sbostic
47943223Sbostic return NO;
48043223Sbostic }
48143223Sbostic
48243223Sbostic
48343223Sbostic
clearsets()48443223Sbostic LOCAL clearsets()
48543223Sbostic
48643223Sbostic {
48743223Sbostic register SETNODE *p, *q;
48843223Sbostic
48943223Sbostic allset = NO;
49043223Sbostic
49143223Sbostic p = setlist;
49243223Sbostic while (p)
49343223Sbostic {
49443223Sbostic q = p->link;
49543223Sbostic free ((char *) p);
49643223Sbostic p = q;
49743223Sbostic }
49843223Sbostic setlist = NULL;
49943223Sbostic return;
50043223Sbostic }
50143223Sbostic
50243223Sbostic
50343223Sbostic
alreg()50443223Sbostic LOCAL alreg()
50543223Sbostic
50643223Sbostic {
50743223Sbostic register Slotp sp;
50843223Sbostic register int i;
50943223Sbostic register ADDRNODE *p;
51043223Sbostic register VARNODE *q;
51143223Sbostic Slotp sp1, sp2;
51243223Sbostic ADDRNODE *addrinfo;
51343223Sbostic VARNODE *varinfo;
51443223Sbostic struct Labelblock **lp;
51543223Sbostic int toptrack;
51643223Sbostic int track[MAXREGVAR];
51743223Sbostic Addrp ap, ap1;
51843223Sbostic DOQUEUE *dqp;
51943223Sbostic REGDATA *rp;
52043223Sbostic REGNODE *regp;
52143223Sbostic
52243223Sbostic if (nregvar >= maxregvar) return;
52343223Sbostic
52443223Sbostic commonvars = NULL;
52543223Sbostic docount = 0;
52643223Sbostic
52743223Sbostic for (sp = dohead; sp != doend->next; sp = sp->next)
52843223Sbostic switch (sp->type)
52943223Sbostic {
53043223Sbostic case SKLABEL:
53143223Sbostic insertlabel(sp->label);
53243223Sbostic break;
53343223Sbostic
53443223Sbostic case SKARIF:
53543223Sbostic case SKASGOTO:
53643223Sbostic case SKCALL:
53743223Sbostic case SKCMGOTO:
53843223Sbostic case SKEQ:
53943223Sbostic case SKIFN:
54043223Sbostic case SKIOIFN:
54143223Sbostic case SKSTOP:
54243223Sbostic case SKPAUSE:
54343223Sbostic case SKRETURN:
54443223Sbostic scanvars(sp->expr);
54543223Sbostic break;
54643223Sbostic
54743223Sbostic case SKDOHEAD:
54843223Sbostic ++docount;
54943223Sbostic break;
55043223Sbostic
55143223Sbostic case SKENDDO:
55243223Sbostic --docount;
55343223Sbostic break;
55443223Sbostic
55543223Sbostic case SKNULL:
55643223Sbostic case SKGOTO:
55743223Sbostic case SKASSIGN:
55843223Sbostic break;
55943223Sbostic
56043223Sbostic default:
56143223Sbostic badthing ("SKtype", "alreg-1", sp->type);
56243223Sbostic }
56343223Sbostic
56443223Sbostic loopcost = 0;
56543223Sbostic docount = 1;
56643223Sbostic commonunusable = NO;
56743223Sbostic if (! dohead->nullslot) fatal ("missing dohead->nullslot -cbb");
56843223Sbostic for (sp = dohead->next, globalbranch = NO;
56943223Sbostic docount;
57043223Sbostic sp = sp->next, clearsets(), globalbranch = NO)
57143223Sbostic if (docount > 1)
57243223Sbostic switch (sp->type)
57343223Sbostic {
57443223Sbostic case SKDOHEAD:
57543223Sbostic docount++;
57643223Sbostic break;
57743223Sbostic
57843223Sbostic case SKENDDO:
57943223Sbostic docount--;
58043223Sbostic
58143223Sbostic default:
58243223Sbostic break;
58343223Sbostic }
58443223Sbostic else
58543223Sbostic switch (sp->type)
58643223Sbostic {
58743223Sbostic case SKARIF:
58843223Sbostic #define LM ((struct Labelblock * *)sp->ctlinfo)[0]->labelno
58943223Sbostic #define LZ ((struct Labelblock * *)sp->ctlinfo)[1]->labelno
59043223Sbostic #define LP ((struct Labelblock * *)sp->ctlinfo)[2]->labelno
59143223Sbostic
59243223Sbostic if (!locallabel(LM) || !locallabel(LZ) || !locallabel(LP))
59343223Sbostic {
59443223Sbostic setall();
59543223Sbostic globalbranch = YES;
59643223Sbostic }
59743223Sbostic countrefs(sp->expr);
59843223Sbostic break;
59943223Sbostic
60043223Sbostic case SKASGOTO:
60143223Sbostic setall();
60243223Sbostic globalbranch = YES;
60343223Sbostic countrefs(sp->expr);
60443223Sbostic break;
60543223Sbostic
60643223Sbostic case SKCMGOTO:
60743223Sbostic lp = (struct Labelblock **) sp->ctlinfo;
60843223Sbostic for (i = 0; i < sp->label; i++, lp++)
60943223Sbostic if (!locallabel((*lp)->labelno))
61043223Sbostic {
61143223Sbostic setall();
61243223Sbostic globalbranch = YES;
61343223Sbostic break;
61443223Sbostic }
61543223Sbostic countrefs(sp->expr);
61643223Sbostic break;
61743223Sbostic
61843223Sbostic case SKDOHEAD:
61943223Sbostic globalbranch = YES;
62043223Sbostic loopcost = 2;
62143223Sbostic docount++;
62243223Sbostic break;
62343223Sbostic
62443223Sbostic case SKENDDO:
62543223Sbostic docount = 0;
62643223Sbostic break;
62743223Sbostic
62843223Sbostic case SKGOTO:
62943223Sbostic if (!locallabel(sp->label))
63043223Sbostic {
63143223Sbostic setall();
63243223Sbostic globalbranch = YES;
63343223Sbostic }
63443223Sbostic break;
63543223Sbostic
63643223Sbostic case SKIFN:
63743223Sbostic case SKIOIFN:
63843223Sbostic if (!locallabel(sp->label))
63943223Sbostic {
64043223Sbostic setall();
64143223Sbostic globalbranch = YES;
64243223Sbostic }
64343223Sbostic countrefs(sp->expr);
64443223Sbostic break;
64543223Sbostic
64643223Sbostic case SKEQ:
64743223Sbostic case SKCALL:
64843223Sbostic case SKSTOP:
64943223Sbostic case SKPAUSE:
65043223Sbostic linearcode = YES;
65143223Sbostic countrefs(sp->expr);
65243223Sbostic linearcode = NO;
65343223Sbostic break;
65443223Sbostic }
65543223Sbostic
65643223Sbostic topregvar = toplcv = nregvar - 1;
65743223Sbostic
65843223Sbostic for (i = 0; i < nregvar; i++)
65943223Sbostic {
66043223Sbostic ap = memversion(regnamep[i]);
66143223Sbostic regtab[i] = rp = ALLOC(regdata);
66243223Sbostic rp->vstg = ap->vstg;
66343223Sbostic rp->vtype = ap->vtype;
66443223Sbostic rp->memno = ap->memno;
66546307Sbostic rp->memoffset = ap->memoffset->constblock.constant.ci;
66643223Sbostic rp->isarrayarg = NO;
66743223Sbostic rp->stgp = ap;
66843223Sbostic }
66943223Sbostic
67043223Sbostic for (i = 0; i < MAXREGVAR; i++)
67143223Sbostic track[i] = YES;
67243223Sbostic
67343223Sbostic for (dqp = dqptr->down; dqp; dqp = dqp->down)
67443223Sbostic {
67543223Sbostic if (dqp->nregvars - 1 > topregvar)
67643223Sbostic topregvar = dqp->nregvars -1;
67743223Sbostic for (i = toplcv + 1; i < dqp->nregvars; i++)
67843223Sbostic if (track[i])
67943223Sbostic if (regp = dqp->reg[i])
68043223Sbostic if (rp = regtab[i])
68143223Sbostic {
68243223Sbostic if (!samevar(rp, regp))
68343223Sbostic track[i] = NO;
68443223Sbostic }
68543223Sbostic else if (invartable(regp))
68643223Sbostic {
68743223Sbostic regtab[i] = rp = ALLOC(regdata);
68843223Sbostic rp->vstg = regp->vstg;
68943223Sbostic rp->vtype = regp->vtype;
69043223Sbostic rp->memno = regp->memno;
69143223Sbostic rp->memoffset = regp->memoffset;
69243223Sbostic addrinfo = lookupaddr(rp->vstg, rp->memno);
69343223Sbostic if (regp->isarrayarg)
69443223Sbostic {
69543223Sbostic rp->isarrayarg = YES;
69643223Sbostic rp->refs = addrinfo->refs;
69743223Sbostic }
69843223Sbostic else
69943223Sbostic {
70043223Sbostic varinfo = lookupvar(addrinfo, regp->memoffset);
70143223Sbostic rp->refs = varinfo->refs;
70243223Sbostic rp->stgp = (Addrp) cpexpr(varinfo->stgp);
70343223Sbostic rp->istemp = addrinfo->istemp;
70443223Sbostic rp->isset = varinfo->isset;
70543223Sbostic rp->setfirst = varinfo->setfirst;
70643223Sbostic }
70743223Sbostic }
70843223Sbostic else
70943223Sbostic track[i] = NO;
71043223Sbostic else
71143223Sbostic track[i] = NO;
71243223Sbostic }
71343223Sbostic
71443223Sbostic toptrack = topregvar;
71543223Sbostic
71643223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
71743223Sbostic if (regtab[i])
71843223Sbostic if ((track[i] == NO) || (regtab[i]->refs <= 0))
71943223Sbostic {
72043223Sbostic free((char *) regtab[i]);
72143223Sbostic regtab[i] = NULL;
72243223Sbostic }
72343223Sbostic
72443223Sbostic tabletop = -1;
72543223Sbostic if (topregvar < maxregvar - 1)
72643223Sbostic for (i = 0; i < VARTABSIZE; i++)
72743223Sbostic for (p = vartable[i]; p; p = p->link)
72843223Sbostic {
72943223Sbostic entableaddr(p);
73043223Sbostic if ((!p->loopset) &&
73143223Sbostic (!p->mixedtype) &&
73243223Sbostic (p->vstg != STGARG) &&
73343223Sbostic !((p->vstg == STGCOMMON) && ((!p->fixed) || commonunusable)))
73443223Sbostic for (q = p->varlist; q; q = q->link)
73543223Sbostic entablevar(q);
73643223Sbostic }
73743223Sbostic
73843223Sbostic for (i = 0; (i <= tabletop) && (topregvar + 1 < maxregvar); i++)
73943223Sbostic {
74043223Sbostic if (inregtab(rt[i]) || (loopcost && rt[i]->isset))
74143223Sbostic continue;
74243223Sbostic topregvar++;
74343223Sbostic regtab[topregvar] = rp = ALLOC(regdata);
74443223Sbostic rp->vstg = rt[i]->vstg;
74543223Sbostic rp->vtype = rt[i]->vtype;
74643223Sbostic rp->memno = rt[i]->memno;
74743223Sbostic rp->memoffset = rt[i]->memoffset;
74843223Sbostic rp->refs = rt[i]->refs;
74943223Sbostic rp->stgp = (Addrp) cpexpr(rt[i]->stgp);
75043223Sbostic rp->isarrayarg = rt[i]->isarrayarg;
75143223Sbostic rp->istemp = rt[i]->istemp;
75243223Sbostic rp->isset = rt[i]->isset;
75343223Sbostic rp->setfirst = rt[i]->setfirst;
75443223Sbostic }
75543223Sbostic
75643223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
75743223Sbostic {
75843223Sbostic if (rp = regtab[i])
75943223Sbostic if (rp->isarrayarg)
76043223Sbostic {
76143223Sbostic ap = ALLOC(Addrblock);
76243223Sbostic ap->tag = TADDR;
76343223Sbostic ap->vstg = STGREG;
76443223Sbostic ap->vtype = TYADDR;
76543223Sbostic ap->vclass = CLVAR;
76643223Sbostic ap->memno = regnum[i];
76743223Sbostic ap->memoffset = ICON(0);
76843223Sbostic
76943223Sbostic ap1 = ALLOC(Addrblock);
77043223Sbostic ap1->tag = TADDR;
77143223Sbostic ap1->vstg = rp->vstg;
77243223Sbostic ap1->vtype = rp->vtype;
77343223Sbostic ap1->vclass = CLVAR;
77443223Sbostic ap1->memno = rp->memno;
77543223Sbostic ap1->memoffset = ICON(0);
77643223Sbostic
77743223Sbostic insertassign(dohead, ap, addrof(ap1));
77843223Sbostic }
77943223Sbostic else if (!(rp->setfirst && rp->istemp))
78043223Sbostic {
78143223Sbostic if (rp->istemp)
78243223Sbostic for (sp = newcode; sp && sp != dohead; sp = sp->next)
78343223Sbostic if (sp->type == SKEQ)
78443223Sbostic {
78543223Sbostic ap = (Addrp) sp->expr->exprblock.leftp;
78643223Sbostic if ((ap->vstg == rp->vstg) && (ap->memno == rp->memno) &&
78743223Sbostic fixedaddress(ap) &&
78846307Sbostic (ap->memoffset->constblock.constant.ci == rp->memoffset))
78943223Sbostic {
79043223Sbostic changetoreg(ap, i);
79143223Sbostic goto L1;
79243223Sbostic }
79343223Sbostic }
79443223Sbostic ap = (Addrp) cpexpr(rp->stgp);
79543223Sbostic changetoreg(ap, i);
79643223Sbostic insertassign(dohead, ap, cpexpr(rp->stgp));
79743223Sbostic }
79843223Sbostic L1:;
79943223Sbostic }
80043223Sbostic
80143223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
80243223Sbostic if (rp = regtab[i])
80343223Sbostic if (rp->isset && !(rp->istemp || rp->isarrayarg))
80443223Sbostic {
80543223Sbostic ap = (Addrp) cpexpr(rp->stgp);
80643223Sbostic changetoreg(ap, i);
80743223Sbostic appendassign(doend, cpexpr(rp->stgp), ap);
80843223Sbostic }
80943223Sbostic
81043223Sbostic docount = 1;
81143223Sbostic clearmems();
81243223Sbostic setregs();
81343223Sbostic sp = dohead->next;
81443223Sbostic if (loopcost)
81543223Sbostic for (i = toptrack + 1; i <= topregvar; i++)
81643223Sbostic if ((rp = regtab[i]) && !rp->isarrayarg)
81743223Sbostic {
81843223Sbostic ap = (Addrp) cpexpr(rp->stgp);
81943223Sbostic changetoreg(ap, i);
82043223Sbostic insertassign(sp, cpexpr(rp->stgp), ap);
82143223Sbostic }
82243223Sbostic
82343223Sbostic for ( sp = dohead->next;
82443223Sbostic docount || sp->type != SKNULL;
82543223Sbostic sp = sp->next)
82643223Sbostic if (docount > 1)
82743223Sbostic switch (sp->type)
82843223Sbostic {
82943223Sbostic case SKDOHEAD:
83043223Sbostic docount++;
83143223Sbostic break;
83243223Sbostic
83343223Sbostic case SKENDDO:
83443223Sbostic if (--docount == 1)
83543223Sbostic {
83643223Sbostic /*
83743223Sbostic * Remove redundant stores to memory.
83843223Sbostic */
83943223Sbostic sp1 = sp->nullslot->next;
84043223Sbostic while (sp1)
84143223Sbostic {
84243223Sbostic if (regtomem(sp1))
84343223Sbostic {
84443223Sbostic ap = (Addrp) sp1->expr->exprblock.rightp;
84543223Sbostic sp2 = sp1->next;
84643223Sbostic for (i = toplcv + 2; i <= toptrack; i++)
84743223Sbostic if (regtab[i] && (regnum[i] == ap->memno))
84843223Sbostic {
84943223Sbostic deleteslot(sp1);
85043223Sbostic break;
85143223Sbostic }
85243223Sbostic sp1 = sp2;
85343223Sbostic }
85443223Sbostic else
85543223Sbostic sp1 = NULL;
85643223Sbostic }
85743223Sbostic
85843223Sbostic /*
85943223Sbostic * Restore register variables (complement to DOHEAD code).
86043223Sbostic */
86143223Sbostic sp1 = sp->nullslot->next;
86243223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
86343223Sbostic if (rp = regtab[i])
86443223Sbostic if (!regdefined[i])
86543223Sbostic if (i >= dqp->nregvars || !samevar(rp, dqp->reg[i]))
86643223Sbostic {
86743223Sbostic ap = (Addrp) cpexpr(rp->stgp);
86843223Sbostic changetoreg(ap, i);
86943223Sbostic insertassign(sp1, ap, cpexpr(rp->stgp));
87043223Sbostic regdefined[i] = YES;
87143223Sbostic }
87243223Sbostic
87343223Sbostic clearmems();
87443223Sbostic if (toplcv + 1 < maxregvar)
87543223Sbostic memdefined[toplcv + 1] = YES;
87643223Sbostic sp = sp1->prev;
87743223Sbostic }
87843223Sbostic break;
87943223Sbostic }
88043223Sbostic else
88143223Sbostic {
88243223Sbostic setregs();
88343223Sbostic for (i = 0; i <= MAXREGVAR; i++)
88443223Sbostic regaltered[i] = NO;
88543223Sbostic globalbranch = NO;
88643223Sbostic
88743223Sbostic switch (sp->type)
88843223Sbostic {
88943223Sbostic case SKLABEL:
89043223Sbostic clearmems();
89143223Sbostic break;
89243223Sbostic
89343223Sbostic case SKGOTO:
89443223Sbostic if (!locallabel(sp->label))
89543223Sbostic gensetall(sp);
89643223Sbostic break;
89743223Sbostic
89843223Sbostic case SKENDDO:
89943223Sbostic docount = 0;
90043223Sbostic break;
90143223Sbostic
90243223Sbostic case SKRETURN:
90343223Sbostic gensetreturn(sp);
90443223Sbostic linearcode = YES;
90543223Sbostic regwrite(sp, sp->expr);
90643223Sbostic linearcode = NO;
90743223Sbostic break;
90843223Sbostic
90943223Sbostic case SKDOHEAD:
91043223Sbostic /*
91143223Sbostic * If one of the current loop's register variables is not in
91243223Sbostic * register in an inner loop, we must save it. It's a pity
91343223Sbostic * we don't save enough info to optimize this properly...
91443223Sbostic */
91543223Sbostic for (dqp = dqptr->down; dqp; dqp = dqp->down)
91643223Sbostic if (dqp->dohead == sp)
91743223Sbostic break;
91843223Sbostic if (dqp == NULL)
91943223Sbostic fatal("confused in alreg loop analysis");
92043223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
92143223Sbostic if (rp = regtab[i])
92243223Sbostic if (!memdefined[i])
92343223Sbostic if (i >= dqp->nregvars || !samevar(rp, dqp->reg[i]))
92443223Sbostic {
92543223Sbostic ap = (Addrp) cpexpr(rp->stgp);
92643223Sbostic changetoreg(ap, i);
92743223Sbostic insertassign(sp, cpexpr(rp->stgp), ap);
92843223Sbostic memdefined[i] = YES;
92943223Sbostic regdefined[i] = NO;
93043223Sbostic }
93143223Sbostic
93243223Sbostic docount++;
93343223Sbostic globalbranch = YES;
93443223Sbostic break;
93543223Sbostic
93643223Sbostic case SKEQ:
93743223Sbostic case SKCALL:
93843223Sbostic case SKSTOP:
93943223Sbostic case SKPAUSE:
94043223Sbostic linearcode = YES;
94143223Sbostic regwrite(sp, sp->expr);
94243223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
94343223Sbostic if (!regdefined[i] && ((rp = regtab[i]) && rp->isset))
94443223Sbostic {
94543223Sbostic ap = (Addrp) cpexpr(rp->stgp);
94643223Sbostic changetoreg(ap, i);
94743223Sbostic appendassign(sp, ap, cpexpr(rp->stgp));
94843223Sbostic sp = sp->next;
94943223Sbostic regdefined[i] = YES;
95043223Sbostic }
95143223Sbostic linearcode = NO;
95243223Sbostic
95343223Sbostic /*
95443223Sbostic * Eliminate redundant register moves.
95543223Sbostic */
95643223Sbostic if (regtoreg(sp))
95743223Sbostic {
95843223Sbostic ap = (Addrp) sp->expr->exprblock.leftp;
95943223Sbostic sp1 = sp->prev;
96043223Sbostic for (i = toplcv + 1; i <= toptrack; i++)
96143223Sbostic if (regtab[i] && (regnum[i] == ap->memno))
96243223Sbostic {
96343223Sbostic deleteslot(sp);
96443223Sbostic sp = sp1;
96543223Sbostic break;
96643223Sbostic }
96743223Sbostic }
96843223Sbostic break;
96943223Sbostic
97043223Sbostic case SKARIF:
97143223Sbostic if (!locallabel(LM) || !locallabel(LZ) || !locallabel(LP))
97243223Sbostic {
97343223Sbostic gensetall(sp);
97443223Sbostic globalbranch = YES;
97543223Sbostic }
97643223Sbostic regwrite(sp, sp->expr);
97743223Sbostic break;
97843223Sbostic
97943223Sbostic case SKASGOTO:
98043223Sbostic gensetall(sp);
98143223Sbostic globalbranch = YES;
98243223Sbostic regwrite(sp, sp->expr);
98343223Sbostic break;
98443223Sbostic
98543223Sbostic case SKCMGOTO:
98643223Sbostic lp = (struct Labelblock **) sp->ctlinfo;
98743223Sbostic for (i = 0; i < sp->label; i++, lp++)
98843223Sbostic if (!locallabel((*lp)->labelno))
98943223Sbostic {
99043223Sbostic gensetall(sp);
99143223Sbostic globalbranch = YES;
99243223Sbostic break;
99343223Sbostic }
99443223Sbostic regwrite(sp, sp->expr);
99543223Sbostic break;
99643223Sbostic
99743223Sbostic case SKIFN:
99843223Sbostic case SKIOIFN:
99943223Sbostic if (!locallabel(sp->label))
100043223Sbostic {
100143223Sbostic gensetall(sp);
100243223Sbostic globalbranch = YES;
100343223Sbostic }
100443223Sbostic regwrite(sp, sp->expr);
100543223Sbostic break;
100643223Sbostic
100743223Sbostic case SKNULL:
100843223Sbostic case SKASSIGN:
100943223Sbostic break;
101043223Sbostic
101143223Sbostic default:
101243223Sbostic badthing ("SKtype","alreg-3",sp->type);
101343223Sbostic }
101443223Sbostic
101543223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
101643223Sbostic if (regaltered[i])
101743223Sbostic memdefined[i] = NO;
101843223Sbostic }
101943223Sbostic
102043223Sbostic if (topregvar + 1 > highregvar)
102143223Sbostic highregvar = topregvar + 1;
102243223Sbostic dqptr->nregvars = topregvar + 1;
102343223Sbostic for (i = 0; i <= topregvar; i++)
102443223Sbostic if (rp = regtab[i])
102543223Sbostic {
102643223Sbostic dqptr->reg[i] = regp = ALLOC(regnode);
102743223Sbostic regp->vstg = rp->vstg;
102843223Sbostic regp->vtype = rp->vtype;
102943223Sbostic regp->memno = rp->memno;
103043223Sbostic regp->memoffset = rp->memoffset;
103143223Sbostic regp->isarrayarg = rp->isarrayarg;
103243223Sbostic frexpr(rp->stgp);
103343223Sbostic free((char *) rp);
103443223Sbostic regtab[i] = NULL;
103543223Sbostic }
103643223Sbostic
103743223Sbostic while (tabletop >= 0)
103843223Sbostic free((char *) rt[tabletop--]);
103943223Sbostic freelabtab();
104043223Sbostic freevartab();
104143223Sbostic return;
104243223Sbostic }
104343223Sbostic
104443223Sbostic
104543223Sbostic
scanvars(p)104643223Sbostic LOCAL scanvars(p)
104743223Sbostic expptr p;
104843223Sbostic
104943223Sbostic {
105043223Sbostic Addrp ap;
105143223Sbostic ADDRNODE *addrinfo;
105243223Sbostic VARNODE *varinfo;
105343223Sbostic chainp args;
105443223Sbostic VARNODE *q;
105543223Sbostic
105643223Sbostic if (p == NULL) return;
105743223Sbostic
105843223Sbostic switch (p->tag)
105943223Sbostic {
106043223Sbostic case TCONST:
106143223Sbostic return;
106243223Sbostic
106343223Sbostic case TEXPR:
106443223Sbostic switch (p->exprblock.opcode)
106543223Sbostic {
106643223Sbostic case OPASSIGN:
106743223Sbostic scanassign(p);
106843223Sbostic return;
106943223Sbostic
107043223Sbostic case OPPLUSEQ:
107143223Sbostic case OPSTAREQ:
107243223Sbostic scanopeq(p);
107343223Sbostic return;
107443223Sbostic
107543223Sbostic case OPCALL:
107643223Sbostic scancall(p);
107743223Sbostic return;
107843223Sbostic
107943223Sbostic default:
108043223Sbostic scanvars(p->exprblock.vleng);
108143223Sbostic scanvars(p->exprblock.leftp);
108243223Sbostic scanvars(p->exprblock.rightp);
108343223Sbostic return;
108443223Sbostic }
108543223Sbostic
108643223Sbostic case TADDR:
108743223Sbostic ap = (Addrp) p;
108843223Sbostic scanvars(ap->vleng);
108943223Sbostic scanvars(ap->memoffset);
109043223Sbostic if (!ISVAR(ap)) return;
109143223Sbostic
109243223Sbostic addrinfo = getaddr(ap);
109343223Sbostic if (fixedaddress(ap))
109443223Sbostic {
109543223Sbostic if (ISREGTYPE(ap->vtype))
109643223Sbostic {
109743223Sbostic varinfo = getvar(addrinfo, ap);
109843223Sbostic varinfo->isused = YES;
109943223Sbostic }
110043223Sbostic }
110143223Sbostic else
110243223Sbostic {
110343223Sbostic addrinfo->freeuse = YES;
110443223Sbostic for (q = addrinfo->varlist; q; q = q->link)
110543223Sbostic q->isused = YES;
110643223Sbostic }
110743223Sbostic return;
110843223Sbostic
110943223Sbostic case TLIST:
111043223Sbostic for (args = p->listblock.listp; args; args = args->nextp)
111143223Sbostic scanvars(args->datap);
111243223Sbostic return;
111343223Sbostic
111443223Sbostic default:
111543223Sbostic badtag ("regalloc:scanvars", p->tag);
111643223Sbostic }
111743223Sbostic }
111843223Sbostic
111943223Sbostic
112043223Sbostic
scanassign(ep)112143223Sbostic LOCAL scanassign(ep)
112243223Sbostic Exprp ep;
112343223Sbostic
112443223Sbostic {
112543223Sbostic Addrp lhs;
112643223Sbostic VARNODE *varinfo;
112743223Sbostic ADDRNODE *addrinfo;
112843223Sbostic
112943223Sbostic scanvars(ep->rightp);
113043223Sbostic if (ep->leftp->tag == TADDR)
113143223Sbostic {
113243223Sbostic lhs = (Addrp) ep->leftp;
113343223Sbostic scanvars(lhs->vleng);
113443223Sbostic scanvars(lhs->memoffset);
113543223Sbostic if ((lhs->vstg == STGREG) || (lhs->vstg == STGPREG))
113643223Sbostic return;
113743223Sbostic if (ISVAR(lhs))
113843223Sbostic {
113943223Sbostic addrinfo = getaddr(lhs);
114043223Sbostic addrinfo->isset = YES;
114143223Sbostic if (docount > 1)
114243223Sbostic addrinfo->loopset = YES;
114343223Sbostic if (fixedaddress(lhs) && ISREGTYPE(lhs->vtype))
114443223Sbostic {
114543223Sbostic varinfo = getvar(addrinfo, lhs);
114643223Sbostic if (addrinfo->freeuse) varinfo->isused = YES;
114743223Sbostic varinfo->isset = YES;
114843223Sbostic if (!addrinfo->freeuse && !varinfo->isused)
114943223Sbostic varinfo->setfirst = YES;
115043223Sbostic }
115143223Sbostic }
115243223Sbostic }
115343223Sbostic else
115443223Sbostic badtag ("regalloc:scanassign", ep->leftp->tag);
115543223Sbostic }
115643223Sbostic
115743223Sbostic
115843223Sbostic
scanopeq(ep)115943223Sbostic LOCAL scanopeq(ep)
116043223Sbostic Exprp ep;
116143223Sbostic
116243223Sbostic {
116343223Sbostic Addrp lhs;
116443223Sbostic ADDRNODE *addrinfo;
116543223Sbostic VARNODE *varinfo;
116643223Sbostic
116743223Sbostic scanvars(ep->rightp);
116843223Sbostic if (ep->leftp->tag == TADDR)
116943223Sbostic {
117043223Sbostic lhs = (Addrp) ep->leftp;
117143223Sbostic scanvars(lhs->vleng);
117243223Sbostic scanvars(lhs->memoffset);
117343223Sbostic if ((lhs->vstg == STGREG) || (lhs->vstg == STGPREG))
117443223Sbostic return;
117543223Sbostic if (ISVAR(lhs))
117643223Sbostic {
117743223Sbostic addrinfo = getaddr(lhs);
117843223Sbostic addrinfo->isset = YES;
117943223Sbostic if (docount > 1)
118043223Sbostic addrinfo->loopset = YES;
118143223Sbostic if (fixedaddress(lhs))
118243223Sbostic {
118343223Sbostic if (ISREGTYPE(lhs->vtype))
118443223Sbostic {
118543223Sbostic varinfo = getvar(addrinfo, lhs);
118643223Sbostic varinfo->isused = YES;
118743223Sbostic varinfo->isset = YES;
118843223Sbostic }
118943223Sbostic }
119043223Sbostic }
119143223Sbostic else
119243223Sbostic addrinfo->freeuse = YES;
119343223Sbostic }
119443223Sbostic else
119543223Sbostic badtag ("regalloc:scanopeq", ep->leftp->tag);
119643223Sbostic }
119743223Sbostic
119843223Sbostic
119943223Sbostic
scancall(ep)120043223Sbostic LOCAL scancall(ep)
120143223Sbostic Exprp ep;
120243223Sbostic
120343223Sbostic {
120443223Sbostic Addrp lhs;
120543223Sbostic chainp args;
120643223Sbostic Addrp ap;
120743223Sbostic VARNODE *varinfo;
120843223Sbostic ADDRNODE *addrinfo;
120943223Sbostic
121043223Sbostic lhs = (Addrp) ep->leftp;
121143223Sbostic scanvars(lhs->vleng);
121243223Sbostic scanvars(lhs->memoffset);
121343223Sbostic
121443223Sbostic if (ep->rightp == NULL) return;
121543223Sbostic
121643223Sbostic if (lhs->vstg != STGINTR)
121743223Sbostic {
121843223Sbostic args = ep->rightp->listblock.listp;
121943223Sbostic for (; args; args = args->nextp)
122043223Sbostic {
122143223Sbostic if (args->datap->tag == TADDR)
122243223Sbostic {
122343223Sbostic ap = (Addrp) args->datap;
122443223Sbostic scanvars(ap->vleng);
122543223Sbostic scanvars(ap->memoffset);
122643223Sbostic if (!ISVAR(ap)) continue;
122743223Sbostic
122843223Sbostic addrinfo = getaddr(ap);
122943223Sbostic addrinfo->isset = YES;
123043223Sbostic if (docount > 1)
123143223Sbostic addrinfo->loopset = YES;
123243223Sbostic if (fixedaddress(ap))
123343223Sbostic {
123443223Sbostic varinfo = getvar(addrinfo, ap);
123543223Sbostic if (ap->vstg != STGCONST)
123643223Sbostic varinfo->isset = YES;
123743223Sbostic varinfo->isused = YES;
123843223Sbostic }
123943223Sbostic else
124043223Sbostic addrinfo->freeuse = YES;
124143223Sbostic }
124243223Sbostic else
124343223Sbostic scanvars(args->datap);
124443223Sbostic }
124543223Sbostic }
124643223Sbostic else
124743223Sbostic scanvars(ep->rightp);
124843223Sbostic
124943223Sbostic return;
125043223Sbostic }
125143223Sbostic
125243223Sbostic
125343223Sbostic
fixedaddress(ap)125443223Sbostic LOCAL int fixedaddress(ap)
125543223Sbostic Addrp ap;
125643223Sbostic
125743223Sbostic {
125843223Sbostic if (!ap->memoffset)
125943223Sbostic return NO;
126043223Sbostic return (ISCONST(ap->memoffset) && ISINT(ap->memoffset->headblock.vtype));
126143223Sbostic }
126243223Sbostic
126343223Sbostic
126443223Sbostic
countrefs(p)126543223Sbostic LOCAL countrefs(p)
126643223Sbostic expptr p;
126743223Sbostic
126843223Sbostic {
126943223Sbostic Addrp ap;
127043223Sbostic ADDRNODE *addrinfo;
127143223Sbostic VARNODE *varinfo;
127243223Sbostic VARNODE *vp;
127343223Sbostic chainp args;
127443223Sbostic
127543223Sbostic if (p == NULL) return;
127643223Sbostic
127743223Sbostic switch (p->tag)
127843223Sbostic {
127943223Sbostic case TCONST:
128043223Sbostic return;
128143223Sbostic
128243223Sbostic case TEXPR:
128343223Sbostic switch (p->exprblock.opcode)
128443223Sbostic {
128543223Sbostic case OPCALL:
128643223Sbostic if (p->exprblock.leftp->tag != TADDR)
128743223Sbostic badtag ("regalloc:countrefs", p->exprblock.leftp->tag);
128843223Sbostic countrefs(p->exprblock.leftp->addrblock.vleng);
128943223Sbostic countrefs(p->exprblock.leftp->addrblock.memoffset);
129043223Sbostic
129143223Sbostic if (p->exprblock.leftp->addrblock.vstg != STGINTR)
129243223Sbostic {
129343223Sbostic if (!commonunusable)
129443223Sbostic if (linearcode)
129543223Sbostic setcommon();
129643223Sbostic else
129743223Sbostic commonunusable = YES;
129843223Sbostic if (p->exprblock.rightp == NULL) return;
129943223Sbostic args = p->exprblock.rightp->listblock.listp;
130043223Sbostic for (; args; args = args->nextp)
130143223Sbostic if (args->datap->tag == TADDR)
130243223Sbostic {
130343223Sbostic ap = (Addrp) args->datap;
130443223Sbostic countrefs(ap->vleng);
130543223Sbostic countrefs(ap->memoffset);
130643223Sbostic if (!ISVAR(ap) || ap->vstg == STGCONST) continue;
130743223Sbostic addrinfo = lookupaddr(ap->vstg, ap->memno);
130843223Sbostic if (ap->vstg == STGARG)
130943223Sbostic addrinfo->refs++;
131043223Sbostic for (vp = addrinfo->varlist; vp; vp = vp->link)
131143223Sbostic if (linearcode)
131243223Sbostic if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
131343223Sbostic if (addrinfo->istemp)
131443223Sbostic vp->refs--;
131543223Sbostic else
131643223Sbostic {
131743223Sbostic vp->refs -= 2;
131843223Sbostic insertset(ap->vstg, ap->memno, vp->memoffset);
131943223Sbostic }
132043223Sbostic else
132143223Sbostic vp->refs--;
132243223Sbostic else
132343223Sbostic {
132443223Sbostic if (!addrinfo->istemp)
132543223Sbostic vp->unusable = YES;
132643223Sbostic }
132743223Sbostic }
132843223Sbostic else
132943223Sbostic countrefs(args->datap);
133043223Sbostic }
133143223Sbostic else
133243223Sbostic {
133343223Sbostic if (p->exprblock.rightp == NULL) return;
133443223Sbostic args = p->exprblock.rightp->listblock.listp;
133543223Sbostic for (; args; args = args->nextp)
133643223Sbostic if (args->datap->tag == TADDR)
133743223Sbostic {
133843223Sbostic ap = (Addrp) args->datap;
133943223Sbostic countrefs(ap->vleng);
134043223Sbostic countrefs(ap->memoffset);
134143223Sbostic if (!ISVAR(ap) || ap->vstg == STGCONST) continue;
134243223Sbostic addrinfo = lookupaddr(ap->vstg, ap->memno);
134343223Sbostic addrinfo->refs++;
134443223Sbostic for (vp = addrinfo->varlist; vp; vp = vp->link)
134543223Sbostic if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
134643223Sbostic {
134743223Sbostic vp->refs--;
134843223Sbostic insertset(ap->vstg, ap->memno, vp->memoffset);
134943223Sbostic }
135043223Sbostic }
135143223Sbostic else
135243223Sbostic countrefs(args->datap);
135343223Sbostic }
135443223Sbostic return;
135543223Sbostic
135643223Sbostic case OPASSIGN:
135743223Sbostic case OPPLUSEQ:
135843223Sbostic case OPSTAREQ:
135943223Sbostic countrefs(p->exprblock.vleng);
136043223Sbostic countrefs(p->exprblock.rightp);
136143223Sbostic ap = (Addrp) p->exprblock.leftp;
136243223Sbostic if (fixedaddress(ap))
136343223Sbostic if (globalbranch)
136443223Sbostic {
136543223Sbostic countrefs(ap->vleng);
136643223Sbostic countrefs(ap->memoffset);
136743223Sbostic }
136843223Sbostic else
136943223Sbostic countrefs(ap);
137043223Sbostic else if (linearcode)
137143223Sbostic {
137243223Sbostic countrefs(ap);
137343223Sbostic for (vp = lookupaddr(ap->vstg, ap->memno)->varlist;
137443223Sbostic vp;
137543223Sbostic vp = vp->link)
137643223Sbostic vp->refs--;
137743223Sbostic }
137843223Sbostic else
137943223Sbostic {
138043223Sbostic countrefs(ap);
138143223Sbostic for (vp = lookupaddr(ap->vstg, ap->memno)->varlist;
138243223Sbostic vp;
138343223Sbostic vp = vp->link)
138443223Sbostic vp->unusable = YES;
138543223Sbostic }
138643223Sbostic return;
138743223Sbostic
138843223Sbostic default:
138943223Sbostic countrefs(p->exprblock.vleng);
139043223Sbostic countrefs(p->exprblock.leftp);
139143223Sbostic countrefs(p->exprblock.rightp);
139243223Sbostic return;
139343223Sbostic }
139443223Sbostic
139543223Sbostic case TADDR:
139643223Sbostic ap = (Addrp) p;
139743223Sbostic countrefs(ap->vleng);
139843223Sbostic countrefs(ap->memoffset);
139943223Sbostic if (!ISVAR(ap)) return;
140043223Sbostic
140143223Sbostic addrinfo = lookupaddr(ap->vstg, ap->memno);
140243223Sbostic if (ap->vstg == STGARG)
140343223Sbostic addrinfo->refs++;
140443223Sbostic
140543223Sbostic if (fixedaddress(ap))
140643223Sbostic {
140743223Sbostic if (ISREGTYPE(ap->vtype))
140843223Sbostic {
140946307Sbostic varinfo = lookupvar(addrinfo, ap->memoffset->constblock.constant.ci);
141043223Sbostic varinfo->refs++;
141143223Sbostic }
141243223Sbostic }
141343223Sbostic else
141443223Sbostic for (vp = addrinfo->varlist; vp; vp = vp->link)
141543223Sbostic if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
141643223Sbostic {
141743223Sbostic vp->refs--;
141843223Sbostic insertset(ap->vstg, ap->memno, vp->memoffset);
141943223Sbostic }
142043223Sbostic return;
142143223Sbostic
142243223Sbostic case TLIST:
142343223Sbostic args = p->listblock.listp;
142443223Sbostic for (; args; args = args->nextp)
142543223Sbostic countrefs(args->datap);
142643223Sbostic return;
142743223Sbostic
142843223Sbostic default:
142943223Sbostic badtag ("regalloc:countrefs", p->tag);
143043223Sbostic }
143143223Sbostic }
143243223Sbostic
143343223Sbostic
143443223Sbostic
regwrite(sp,p)143543223Sbostic LOCAL regwrite(sp, p)
143643223Sbostic Slotp sp;
143743223Sbostic expptr p;
143843223Sbostic
143943223Sbostic {
144043223Sbostic register int i;
144143223Sbostic REGDATA *rp;
144243223Sbostic chainp args;
144343223Sbostic Addrp ap, ap1;
144443223Sbostic int memoffset;
144543223Sbostic
144643223Sbostic if (p == NULL) return;
144743223Sbostic
144843223Sbostic switch (p->tag)
144943223Sbostic {
145043223Sbostic case TCONST:
145143223Sbostic return;
145243223Sbostic
145343223Sbostic case TEXPR:
145443223Sbostic switch (p->exprblock.opcode)
145543223Sbostic {
145643223Sbostic case OPCALL:
145743223Sbostic ap = (Addrp) p->exprblock.leftp;
145843223Sbostic regwrite(sp, ap->vleng);
145943223Sbostic regwrite(sp, ap->memoffset);
146043223Sbostic if (ap->vstg != STGINTR)
146143223Sbostic {
146243223Sbostic if (linearcode)
146343223Sbostic {
146443223Sbostic gensetcommon(sp);
146543223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
146643223Sbostic if ((rp = regtab[i]) && (rp->vstg == STGCOMMON))
146743223Sbostic regdefined[i] = NO;
146843223Sbostic }
146943223Sbostic if (p->exprblock.rightp == NULL) return;
147043223Sbostic args = p->exprblock.rightp->listblock.listp;
147143223Sbostic for (; args; args = args->nextp)
147243223Sbostic if (args->datap->tag == TADDR)
147343223Sbostic {
147443223Sbostic ap = (Addrp) args->datap;
147543223Sbostic regwrite(sp, ap->vleng);
147643223Sbostic regwrite(sp, ap->memoffset);
147743223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
147843223Sbostic if ((rp = regtab[i]) &&
147943223Sbostic !rp->isarrayarg &&
148043223Sbostic !rp->istemp &&
148143223Sbostic (rp->vstg == ap->vstg) &&
148243223Sbostic (rp->memno == ap->memno))
148343223Sbostic {
148443223Sbostic regdefined[i] = NO;
148543223Sbostic if (!memdefined[i])
148643223Sbostic {
148743223Sbostic ap1 = (Addrp) cpexpr(rp->stgp);
148843223Sbostic changetoreg(ap1, i);
148943223Sbostic insertassign(sp, cpexpr(rp->stgp), ap1);
149043223Sbostic memdefined[i] = YES;
149143223Sbostic }
149243223Sbostic }
149343223Sbostic else if (rp->isarrayarg &&
149443223Sbostic (ap->vstg == STGARG) &&
149543223Sbostic (ap->memno == rp->memno))
149643223Sbostic {
149743223Sbostic ap->vstg = STGPREG;
149843223Sbostic ap->memno = regnum[i];
149943223Sbostic }
150043223Sbostic }
150143223Sbostic else
150243223Sbostic regwrite(sp, args->datap);
150343223Sbostic }
150443223Sbostic else
150543223Sbostic {
150643223Sbostic if (p->exprblock.rightp == NULL) return;
150743223Sbostic args = p->exprblock.rightp->listblock.listp;
150843223Sbostic for (; args; args = args->nextp)
150943223Sbostic if (args->datap->tag == TADDR)
151043223Sbostic {
151143223Sbostic ap = (Addrp) args->datap;
151243223Sbostic regwrite(sp, ap->vleng);
151343223Sbostic regwrite(sp, ap->memoffset);
151443223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
151543223Sbostic if ((rp = regtab[i]) &&
151643223Sbostic !rp->isarrayarg &&
151743223Sbostic !rp->istemp &&
151843223Sbostic (rp->vstg == ap->vstg) &&
151943223Sbostic (rp->memno == ap->memno) &&
152043223Sbostic !memdefined[i])
152143223Sbostic {
152243223Sbostic ap1 = (Addrp) cpexpr(rp->stgp);
152343223Sbostic changetoreg(ap1, i);
152443223Sbostic insertassign(sp, cpexpr(rp->stgp), ap1);
152543223Sbostic memdefined[i] = YES;
152643223Sbostic }
152743223Sbostic else if (rp->isarrayarg &&
152843223Sbostic (ap->vstg == STGARG) &&
152943223Sbostic (rp->memno == ap->memno))
153043223Sbostic {
153143223Sbostic ap->vstg = STGPREG;
153243223Sbostic ap->memno = regnum[i];
153343223Sbostic }
153443223Sbostic }
153543223Sbostic else
153643223Sbostic {
153743223Sbostic regwrite(sp, args->datap);
153843223Sbostic }
153943223Sbostic }
154043223Sbostic return;
154143223Sbostic
154243223Sbostic case OPASSIGN:
154343223Sbostic case OPPLUSEQ:
154443223Sbostic case OPSTAREQ:
154543223Sbostic regwrite(sp, p->exprblock.vleng);
154643223Sbostic regwrite(sp, p->exprblock.rightp);
154743223Sbostic ap = (Addrp) p->exprblock.leftp;
154843223Sbostic regwrite(sp, ap->vleng);
154943223Sbostic regwrite(sp, ap->memoffset);
155043223Sbostic
155143223Sbostic if (ap->vstg == STGARG)
155243223Sbostic for (i = toplcv + 1; i<=topregvar; i++)
155343223Sbostic if ((rp = regtab[i]) &&
155443223Sbostic rp->isarrayarg &&
155543223Sbostic (rp->memno == ap->memno))
155643223Sbostic {
155743223Sbostic ap->vstg = STGPREG;
155843223Sbostic ap->memno = regnum[i];
155943223Sbostic return;
156043223Sbostic }
156143223Sbostic
156243223Sbostic if (fixedaddress(ap))
156343223Sbostic {
156446307Sbostic memoffset = ap->memoffset->constblock.constant.ci;
156543223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
156643223Sbostic if ((rp = regtab[i]) &&
156743223Sbostic !rp->isarrayarg &&
156843223Sbostic (rp->vstg == ap->vstg) &&
156943223Sbostic (rp->memno == ap->memno) &&
157043223Sbostic (rp->memoffset == memoffset))
157143223Sbostic {
157243223Sbostic changetoreg(ap, i);
157343223Sbostic if (globalbranch)
157443223Sbostic {
157543223Sbostic p->exprblock.rightp = (expptr) cpexpr(p);
157643223Sbostic p->exprblock.leftp = (expptr) cpexpr(rp->stgp);
157743223Sbostic p->exprblock.opcode = OPASSIGN;
157843223Sbostic memdefined[i] = YES;
157943223Sbostic }
158043223Sbostic else
158143223Sbostic {
158243223Sbostic regaltered[i] = YES;
158343223Sbostic regdefined[i] = YES;
158443223Sbostic }
158543223Sbostic }
158643223Sbostic return;
158743223Sbostic }
158843223Sbostic
158943223Sbostic if (linearcode)
159043223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
159143223Sbostic if ((rp = regtab[i]) &&
159243223Sbostic !rp->isarrayarg &&
159343223Sbostic (rp->vstg == ap->vstg) &&
159443223Sbostic (rp->memno == ap->memno))
159543223Sbostic regdefined[i] = NO;
159643223Sbostic return;
159743223Sbostic
159843223Sbostic default:
159943223Sbostic regwrite(sp, p->exprblock.vleng);
160043223Sbostic regwrite(sp, p->exprblock.leftp);
160143223Sbostic regwrite(sp, p->exprblock.rightp);
160243223Sbostic return;
160343223Sbostic }
160443223Sbostic
160543223Sbostic case TADDR:
160643223Sbostic ap = (Addrp) p;
160743223Sbostic regwrite(sp, ap->vleng);
160843223Sbostic regwrite(sp, ap->memoffset);
160943223Sbostic
161043223Sbostic if (ap->vstg == STGARG)
161143223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
161243223Sbostic if ((rp = regtab[i]) &&
161343223Sbostic rp->isarrayarg &&
161443223Sbostic (rp->memno == ap->memno))
161543223Sbostic {
161643223Sbostic ap->vstg = STGPREG;
161743223Sbostic ap->memno = regnum[i];
161843223Sbostic return;
161943223Sbostic }
162043223Sbostic
162143223Sbostic if (fixedaddress(ap))
162243223Sbostic {
162346307Sbostic memoffset = ap->memoffset->constblock.constant.ci;
162443223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
162543223Sbostic if ((rp = regtab[i]) &&
162643223Sbostic !rp->isarrayarg &&
162743223Sbostic (rp->vstg == ap->vstg) &&
162843223Sbostic (rp->memno == ap->memno) &&
162943223Sbostic (rp->memoffset == memoffset))
163043223Sbostic {
163143223Sbostic changetoreg(ap, i);
163243223Sbostic return;
163343223Sbostic }
163443223Sbostic }
163543223Sbostic else
163643223Sbostic {
163743223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
163843223Sbostic if ((rp = regtab[i]) &&
163943223Sbostic !rp->isarrayarg &&
164043223Sbostic (rp->vstg == ap->vstg) &&
164143223Sbostic (rp->memno == ap->memno) &&
164243223Sbostic !memdefined[i])
164343223Sbostic {
164443223Sbostic ap1 = (Addrp) cpexpr(rp->stgp);
164543223Sbostic changetoreg(ap1, i);
164643223Sbostic insertassign(sp, cpexpr(rp->stgp), ap1);
164743223Sbostic memdefined[i] = YES;
164843223Sbostic }
164943223Sbostic }
165043223Sbostic return;
165143223Sbostic
165243223Sbostic case TLIST:
165343223Sbostic for (args = p->listblock.listp; args; args = args->nextp)
165443223Sbostic regwrite(sp, args->datap);
165543223Sbostic return;
165643223Sbostic
165743223Sbostic default:
165843223Sbostic badtag ("regalloc:regwrite", p->tag);
165943223Sbostic }
166043223Sbostic }
166143223Sbostic
166243223Sbostic
166343223Sbostic
setcommon()166443223Sbostic LOCAL setcommon()
166543223Sbostic
166643223Sbostic {
166743223Sbostic ADDRNODE *ap;
166843223Sbostic VARNODE *vp;
166943223Sbostic
167043223Sbostic for (ap = commonvars; ap; ap = ap->commonlink)
167143223Sbostic for (vp = ap->varlist; vp; vp = vp->link)
167243223Sbostic if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
167343223Sbostic {
167443223Sbostic vp->refs -= 2;
167543223Sbostic insertset(ap->vstg, ap->memno, vp->memoffset);
167643223Sbostic }
167743223Sbostic else
167843223Sbostic vp->refs--;
167943223Sbostic
168043223Sbostic return;
168143223Sbostic }
168243223Sbostic
168343223Sbostic
168443223Sbostic
setall()168543223Sbostic LOCAL setall()
168643223Sbostic
168743223Sbostic {
168843223Sbostic register int i;
168943223Sbostic register ADDRNODE *p;
169043223Sbostic register VARNODE *q;
169143223Sbostic
169243223Sbostic for (i = 0; i < VARTABSIZE; i++)
169343223Sbostic for (p = vartable[i]; p; p = p->link)
169443223Sbostic if (p->istemp || !p->isset)
169543223Sbostic break;
169643223Sbostic else
169743223Sbostic for (q = p->varlist; q; q = q->link)
169843223Sbostic if (q->isset && !insetlist(p->vstg, p->memno, q->memoffset))
169943223Sbostic q->refs--;
170043223Sbostic
170143223Sbostic allset = YES;
170243223Sbostic return;
170343223Sbostic }
170443223Sbostic
170543223Sbostic
170643223Sbostic
samevar(r1,r2)170743223Sbostic LOCAL int samevar(r1, r2)
170843223Sbostic register REGDATA *r1;
170943223Sbostic register REGNODE *r2;
171043223Sbostic
171143223Sbostic {
171243223Sbostic if ((r1->vstg != r2->vstg) ||
171343223Sbostic (r1->memno != r2->memno) ||
171443223Sbostic (r1->isarrayarg != r2->isarrayarg))
171543223Sbostic return NO;
171643223Sbostic if (r1->isarrayarg)
171743223Sbostic return YES;
171843223Sbostic return (r1->memoffset == r2->memoffset);
171943223Sbostic }
172043223Sbostic
172143223Sbostic
172243223Sbostic
entableaddr(p)172343223Sbostic LOCAL entableaddr(p)
172443223Sbostic ADDRNODE *p;
172543223Sbostic
172643223Sbostic {
172743223Sbostic int refs;
172843223Sbostic Addrp ap;
172943223Sbostic register int i;
173043223Sbostic
173143223Sbostic if (p->vstg != STGARG)
173243223Sbostic {
173343223Sbostic currentaddr = p;
173443223Sbostic return;
173543223Sbostic }
173643223Sbostic
173743223Sbostic refs = p->refs;
173843223Sbostic if (refs <= 0) return;
173943223Sbostic
174043223Sbostic if (tabletop < 0)
174143223Sbostic tabletop = i = 0;
174243223Sbostic else if (refs > rt[tabletop]->refs)
174343223Sbostic {
174443223Sbostic if (tabletop + 1 < TABLELIMIT)
174543223Sbostic tabletop++;
174643223Sbostic else
174743223Sbostic {
174843223Sbostic frexpr(rt[tabletop]->stgp);
174943223Sbostic free((char *) rt[tabletop]);
175043223Sbostic }
175143223Sbostic
175243223Sbostic for (i = tabletop; i > 0; i--)
175343223Sbostic if (refs > rt[i - 1]->refs)
175443223Sbostic rt[i] = rt[i - 1];
175543223Sbostic else
175643223Sbostic break;
175743223Sbostic }
175843223Sbostic else if (tabletop + 1 < TABLELIMIT)
175943223Sbostic i = ++tabletop;
176043223Sbostic else
176143223Sbostic return;
176243223Sbostic
176343223Sbostic rt[i] = ALLOC(regdata);
176443223Sbostic rt[i]->vstg = p->vstg;
176543223Sbostic rt[i]->vtype = p->vtype;
176643223Sbostic rt[i]->memno = p->memno;
176743223Sbostic rt[i]->refs = refs;
176843223Sbostic rt[i]->isarrayarg = YES;
176943223Sbostic
177043223Sbostic return;
177143223Sbostic }
177243223Sbostic
177343223Sbostic
177443223Sbostic
177543223Sbostic
entablevar(p)177643223Sbostic LOCAL entablevar(p)
177743223Sbostic VARNODE *p;
177843223Sbostic
177943223Sbostic {
178043223Sbostic int refs;
178143223Sbostic register int i;
178243223Sbostic
178343223Sbostic if (p->unusable) return;
178443223Sbostic refs = p->refs - loopcost;
178543223Sbostic if (refs <= 0) return;
178643223Sbostic
178743223Sbostic if (tabletop < 0)
178843223Sbostic tabletop = i = 0;
178943223Sbostic else if (refs > rt[tabletop]->refs
179043223Sbostic #ifdef BUMPREALS /* put floats last */
179143223Sbostic || currentaddr->vtype!=TYREAL && rt[tabletop]->vtype==TYREAL && !rt[tabletop]->isarrayarg
179243223Sbostic #endif
179343223Sbostic ){
179443223Sbostic if (tabletop + 1 < TABLELIMIT)
179543223Sbostic tabletop++;
179643223Sbostic else
179743223Sbostic {
179843223Sbostic frexpr(rt[tabletop]->stgp);
179943223Sbostic free((char *) rt[tabletop]);
180043223Sbostic }
180143223Sbostic
180243223Sbostic for (i = tabletop; i > 0; i--)
180343223Sbostic if (refs > rt[i - 1]->refs
180443223Sbostic #ifdef BUMPREALS /* put floats last */
180543223Sbostic || currentaddr->vtype!=TYREAL && rt[i-1]->vtype==TYREAL && !rt[i-1]->isarrayarg
180643223Sbostic #endif
180743223Sbostic )
180843223Sbostic rt[i] = rt[i - 1];
180943223Sbostic else
181043223Sbostic break;
181143223Sbostic }
181243223Sbostic else if (tabletop + 1 < TABLELIMIT)
181343223Sbostic i = ++tabletop;
181443223Sbostic else
181543223Sbostic return;
181643223Sbostic
181743223Sbostic rt[i] = ALLOC(regdata);
181843223Sbostic rt[i]->vstg = currentaddr->vstg;
181943223Sbostic rt[i]->vtype = currentaddr->vtype;
182043223Sbostic rt[i]->memno = currentaddr->memno;
182143223Sbostic rt[i]->memoffset = p->memoffset;
182243223Sbostic rt[i]->refs = refs;
182343223Sbostic rt[i]->stgp = (Addrp) cpexpr(p->stgp);
182443223Sbostic rt[i]->isarrayarg = NO;
182543223Sbostic rt[i]->istemp = currentaddr->istemp;
182643223Sbostic rt[i]->isset = p->isset;
182743223Sbostic rt[i]->setfirst = p->setfirst;
182843223Sbostic
182943223Sbostic return;
183043223Sbostic }
183143223Sbostic
183243223Sbostic
183343223Sbostic
inregtab(p)183443223Sbostic LOCAL int inregtab(p)
183543223Sbostic register REGDATA *p;
183643223Sbostic
183743223Sbostic {
183843223Sbostic register REGDATA *rp;
183943223Sbostic register int i;
184043223Sbostic
184143223Sbostic for (i = 0; i <= topregvar; i++)
184243223Sbostic if (rp = regtab[i])
184343223Sbostic if ((rp->vstg == p->vstg) &&
184443223Sbostic (rp->memno == p->memno) &&
184543223Sbostic (rp->isarrayarg == p->isarrayarg))
184643223Sbostic if (rp->isarrayarg)
184743223Sbostic return YES;
184843223Sbostic else if (rp->memoffset == p->memoffset)
184943223Sbostic return YES;
185043223Sbostic
185143223Sbostic return NO;
185243223Sbostic }
185343223Sbostic
185443223Sbostic
185543223Sbostic
changetoreg(ap,i)185643223Sbostic LOCAL changetoreg(ap, i)
185743223Sbostic register Addrp ap;
185843223Sbostic int i;
185943223Sbostic
186043223Sbostic {
186143223Sbostic ap->vstg = STGREG;
186243223Sbostic ap->memno = regnum[i];
186343223Sbostic frexpr(ap->memoffset);
186443223Sbostic ap->memoffset = ICON(0);
186543223Sbostic ap->istemp = NO;
186643223Sbostic return;
186743223Sbostic }
186843223Sbostic
186943223Sbostic
187043223Sbostic
insertassign(sp,dest,src)187143223Sbostic LOCAL insertassign(sp, dest, src)
187243223Sbostic Slotp sp;
187343223Sbostic Addrp dest;
187443223Sbostic expptr src;
187543223Sbostic
187643223Sbostic {
187743223Sbostic Slotp newslot;
187843223Sbostic expptr p;
187943223Sbostic
188043223Sbostic p = mkexpr(OPASSIGN, dest, src);
188143223Sbostic newslot = optinsert (SKEQ,p,0,0,sp);
188243223Sbostic
188343223Sbostic if (sp == dohead)
188443223Sbostic if (!newcode)
188543223Sbostic newcode = newslot;
188643223Sbostic
188743223Sbostic return;
188843223Sbostic }
188943223Sbostic
189043223Sbostic
appendassign(sp,dest,src)189143223Sbostic LOCAL appendassign(sp, dest, src)
189243223Sbostic Slotp sp;
189343223Sbostic Addrp dest;
189443223Sbostic expptr src;
189543223Sbostic
189643223Sbostic {
189743223Sbostic Slotp newslot;
189843223Sbostic expptr p;
189943223Sbostic
190043223Sbostic if (!sp)
190143223Sbostic fatal ("regalloc:appendassign");
190243223Sbostic
190343223Sbostic p = mkexpr(OPASSIGN, dest, src);
190443223Sbostic newslot = optinsert (SKEQ,p,0,0,sp->next);
190543223Sbostic
190643223Sbostic return;
190743223Sbostic }
190843223Sbostic
190943223Sbostic
191043223Sbostic
regtomem(sp)191143223Sbostic LOCAL int regtomem(sp)
191243223Sbostic Slotp sp;
191343223Sbostic
191443223Sbostic {
191543223Sbostic expptr p, l, r;
191643223Sbostic int i;
191743223Sbostic
191843223Sbostic if (sp->type != SKEQ) return NO;
191943223Sbostic
192043223Sbostic p = sp->expr;
192143223Sbostic if ((p->tag != TEXPR) || (p->exprblock.opcode != OPASSIGN))
192243223Sbostic return NO;
192343223Sbostic
192443223Sbostic r = p->exprblock.rightp;
192543223Sbostic if ((r->tag != TADDR) || (r->addrblock.vstg != STGREG))
192643223Sbostic return NO;
192743223Sbostic
192843223Sbostic l = p->exprblock.leftp;
192943223Sbostic if (l->tag != TADDR)
193043223Sbostic return NO;
193143223Sbostic i = r->addrblock.memno;
193243223Sbostic if (regtab[i] &&
193343223Sbostic (l->addrblock.vstg == regtab[i]->vstg) &&
193443223Sbostic (l->addrblock.memno == regtab[i]->memno) &&
193543223Sbostic fixedaddress(l) &&
193646307Sbostic (l->addrblock.memoffset->constblock.constant.ci == regtab[i]->memoffset))
193743223Sbostic return YES;
193843223Sbostic
193943223Sbostic return NO;
194043223Sbostic }
194143223Sbostic
194243223Sbostic
194343223Sbostic
regtoreg(sp)194443223Sbostic LOCAL int regtoreg(sp)
194543223Sbostic Slotp sp;
194643223Sbostic
194743223Sbostic {
194843223Sbostic expptr p, l, r;
194943223Sbostic
195043223Sbostic if (sp->type != SKEQ) return NO;
195143223Sbostic
195243223Sbostic p = sp->expr;
195343223Sbostic if ((p->tag != TEXPR) || (p->exprblock.opcode != OPASSIGN))
195443223Sbostic return NO;
195543223Sbostic
195643223Sbostic l = p->exprblock.leftp;
195743223Sbostic if ((l->tag != TADDR) || (l->addrblock.vstg != STGREG))
195843223Sbostic return NO;
195943223Sbostic
196043223Sbostic r = p->exprblock.rightp;
196143223Sbostic if ((r->tag == TADDR) &&
196243223Sbostic (r->addrblock.vstg == STGREG) &&
196343223Sbostic (r->addrblock.memno == l->addrblock.memno))
196443223Sbostic return YES;
196543223Sbostic
196643223Sbostic if ((r->tag == TEXPR) &&
196743223Sbostic (r->exprblock.opcode == OPADDR) &&
196843223Sbostic (r->exprblock.leftp->tag == TADDR) &&
196943223Sbostic (r->exprblock.leftp->addrblock.vstg == STGPREG) &&
197043223Sbostic (r->exprblock.leftp->addrblock.memno == l->addrblock.memno))
197143223Sbostic return YES;
197243223Sbostic
197343223Sbostic return NO;
197443223Sbostic }
197543223Sbostic
197643223Sbostic
197743223Sbostic
deleteslot(sp)197843223Sbostic LOCAL deleteslot(sp)
197943223Sbostic Slotp sp;
198043223Sbostic
198143223Sbostic {
198243223Sbostic if (newcode == sp)
198343223Sbostic {
198443223Sbostic newcode = sp->next;
198543223Sbostic if (newcode == dohead)
198643223Sbostic newcode = NULL;
198743223Sbostic }
198843223Sbostic
198943223Sbostic delslot (sp);
199043223Sbostic return;
199143223Sbostic }
199243223Sbostic
199343223Sbostic
199443223Sbostic
gensetall(sp)199543223Sbostic LOCAL gensetall(sp)
199643223Sbostic Slotp sp;
199743223Sbostic
199843223Sbostic {
199943223Sbostic register int i;
200043223Sbostic register REGDATA *rp;
200143223Sbostic register Addrp ap;
200243223Sbostic
200343223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
200443223Sbostic if (rp = regtab[i])
200543223Sbostic if (rp->isset && !(rp->istemp || rp->isarrayarg))
200643223Sbostic if (!memdefined[i])
200743223Sbostic {
200843223Sbostic ap = (Addrp) cpexpr(rp->stgp);
200943223Sbostic changetoreg(ap, i);
201043223Sbostic insertassign(sp, cpexpr(rp->stgp), ap);
201143223Sbostic memdefined[i] = YES;
201243223Sbostic }
201343223Sbostic
201443223Sbostic return;
201543223Sbostic }
201643223Sbostic
201743223Sbostic
gensetcommon(sp)201843223Sbostic LOCAL gensetcommon(sp)
201943223Sbostic Slotp sp;
202043223Sbostic
202143223Sbostic {
202243223Sbostic register int i;
202343223Sbostic register REGDATA *rp;
202443223Sbostic register Addrp ap;
202543223Sbostic
202643223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
202743223Sbostic if (rp = regtab[i])
202843223Sbostic if ((rp->vstg == STGCOMMON) && !rp->isarrayarg)
202943223Sbostic if (!memdefined[i])
203043223Sbostic {
203143223Sbostic ap = (Addrp) cpexpr(rp->stgp);
203243223Sbostic changetoreg(ap, i);
203343223Sbostic insertassign(sp, cpexpr(rp->stgp), ap);
203443223Sbostic memdefined[i] = YES;
203543223Sbostic }
203643223Sbostic
203743223Sbostic return;
203843223Sbostic }
203943223Sbostic
204043223Sbostic
gensetreturn(sp)204143223Sbostic LOCAL gensetreturn(sp)
204243223Sbostic Slotp sp;
204343223Sbostic
204443223Sbostic {
204543223Sbostic register int i;
204643223Sbostic register REGDATA *rp;
204743223Sbostic register Addrp ap;
204843223Sbostic
204943223Sbostic for (i = toplcv + 1; i <= topregvar; i++)
205043223Sbostic if (rp = regtab[i])
205143223Sbostic if (((rp->vstg == STGCOMMON) && !rp->isarrayarg)
205243223Sbostic || (rp->isset && (saveall || rp->stgp->issaved) && !(rp->istemp || rp->isarrayarg)))
205343223Sbostic if (!memdefined[i])
205443223Sbostic {
205543223Sbostic ap = (Addrp) cpexpr(rp->stgp);
205643223Sbostic changetoreg(ap, i);
205743223Sbostic insertassign(sp, cpexpr(rp->stgp), ap);
205843223Sbostic memdefined[i] = YES;
205943223Sbostic }
206043223Sbostic
206143223Sbostic return;
206243223Sbostic }
206343223Sbostic
206443223Sbostic
206543223Sbostic
clearmems()206643223Sbostic LOCAL clearmems()
206743223Sbostic
206843223Sbostic {
206943223Sbostic REGDATA *rp;
207043223Sbostic register int i;
207143223Sbostic
207243223Sbostic for (i = 0; i <= toplcv; i++)
207343223Sbostic memdefined[i] = YES;
207443223Sbostic for (; i <= topregvar; i++)
207543223Sbostic if ((rp = regtab[i]) && rp->isset)
207643223Sbostic memdefined[i] = NO;
207743223Sbostic else
207843223Sbostic memdefined[i] = YES;
207943223Sbostic return;
208043223Sbostic }
208143223Sbostic
208243223Sbostic
setregs()208343223Sbostic LOCAL setregs()
208443223Sbostic
208543223Sbostic {
208643223Sbostic register int i;
208743223Sbostic
208843223Sbostic for (i = 0; i <= topregvar; i++)
208943223Sbostic regdefined[i] = YES;
209043223Sbostic return;
209143223Sbostic }
209243223Sbostic
209343223Sbostic
209443223Sbostic
regalloc()209543223Sbostic regalloc()
209643223Sbostic
209743223Sbostic {
209843223Sbostic int match;
209943223Sbostic Slotp nextslot;
210043223Sbostic Slotp sl1,sl2;
210143223Sbostic Slotp lastlabslot;
210243223Sbostic
210343223Sbostic if (! optimflag) return;
210443223Sbostic
210543223Sbostic docount = 0;
210643223Sbostic lastlabslot = NULL;
210743223Sbostic for (sl1 = firstslot; sl1; sl1 = nextslot)
210843223Sbostic {
210943223Sbostic nextslot = sl1->next;
211043223Sbostic switch (sl1->type)
211143223Sbostic {
211243223Sbostic
211343223Sbostic /* temporarily commented out -----
211443223Sbostic case SKLABEL:
211543223Sbostic lastlabslot = sl1;
211643223Sbostic break;
211743223Sbostic
211843223Sbostic case SKGOTO:
211943223Sbostic if (lastlabslot && sl1->label == lastlabslot->label)
212043223Sbostic {
212143223Sbostic dohead = lastlabslot;
212243223Sbostic doend = sl1;
212343223Sbostic alreg ();
212443223Sbostic }
212543223Sbostic break;
212643223Sbostic ----- */
212743223Sbostic
212843223Sbostic case SKDOHEAD:
212943223Sbostic ++docount;
213043223Sbostic pushq (sl1);
213143223Sbostic break;
213243223Sbostic
213343223Sbostic case SKENDDO:
213443223Sbostic --docount;
213543223Sbostic match = 0;
213643223Sbostic for (sl2 = sl1; sl2; sl2 = sl2->prev)
213743223Sbostic {
213843223Sbostic if (sl2->type == SKDOHEAD) match++;
213943223Sbostic else if (sl2->type == SKENDDO) match--;
214043223Sbostic if (match == 0) break;
214143223Sbostic }
214243223Sbostic if (sl2)
214343223Sbostic dohead = sl2;
214443223Sbostic else
214543223Sbostic fatal ("unmatched enddo in code buffer");
214643223Sbostic if (sl2->type != SKDOHEAD)
214743223Sbostic fatal ("internal error in regalloc");
214843223Sbostic
214943223Sbostic for (dqptr = dqbottom; dqptr; dqptr = dqptr->up)
215043223Sbostic {
215143223Sbostic if (dqptr->dohead == dohead)
215243223Sbostic break;
215343223Sbostic }
215443223Sbostic
215543223Sbostic if (!dqptr)
215643223Sbostic fatal ("garbled doqueue in regalloc");
215743223Sbostic
215843223Sbostic /* sl1 now points to the SKENDDO slot; the SKNULL slot
215943223Sbostic * is reached through sl1->nullslot
216043223Sbostic */
216143223Sbostic dqptr->doend = (Slotp) sl1->nullslot;
216243223Sbostic if (docount == 0)
216343223Sbostic {
216443223Sbostic for (dqptr = dqbottom; dqptr; dqptr = dqptr->up)
216543223Sbostic {
216643223Sbostic dohead = dqptr->dohead;
216743223Sbostic doend = dqptr->doend;
216843223Sbostic alreg();
216943223Sbostic }
217043223Sbostic while (dqtop)
217143223Sbostic popq(dqtop->dohead);
217243223Sbostic docount = 0;
217343223Sbostic }
217443223Sbostic break;
217543223Sbostic
217643223Sbostic default:
217743223Sbostic break;
217843223Sbostic }
217943223Sbostic }
218043223Sbostic
218143223Sbostic return;
218243223Sbostic }
218343223Sbostic
218443223Sbostic
218543223Sbostic
pushq(sp)218643223Sbostic LOCAL pushq(sp)
218743223Sbostic Slotp sp;
218843223Sbostic
218943223Sbostic {
219043223Sbostic DOQUEUE *t;
219143223Sbostic
219243223Sbostic if (sp->type != SKDOHEAD)
219343223Sbostic fatal("regalloc:pushq: DO statement expected");
219443223Sbostic
219543223Sbostic if (dqbottom)
219643223Sbostic {
219743223Sbostic t = ALLOC(doqueue);
219843223Sbostic t->up = dqbottom;
219943223Sbostic dqbottom->down = t;
220043223Sbostic dqbottom = t;
220143223Sbostic }
220243223Sbostic else
220343223Sbostic dqtop = dqbottom = ALLOC(doqueue);
220443223Sbostic
220543223Sbostic dqbottom->dohead = sp;
220643223Sbostic }
220743223Sbostic
220843223Sbostic
popq(sp)220943223Sbostic LOCAL popq(sp)
221043223Sbostic Slotp sp;
221143223Sbostic
221243223Sbostic {
221343223Sbostic DOQUEUE *t;
221443223Sbostic register int i;
221543223Sbostic
221643223Sbostic if (!dqtop)
221743223Sbostic fatal("regalloc:popq: empty DO queue");
221843223Sbostic if (dqtop->dohead != sp)
221943223Sbostic fatal("regalloc:popq: garbled DO queue");
222043223Sbostic
222143223Sbostic t = dqtop;
222243223Sbostic
222343223Sbostic dqtop = t->down;
222443223Sbostic if (dqtop)
222543223Sbostic dqtop->up = NULL;
222643223Sbostic else
222743223Sbostic dqbottom = NULL;
222843223Sbostic for (i = 0; i < MAXREGVAR; i++)
222943223Sbostic if (t->reg[i])
223043223Sbostic free((char *) t->reg[i]);
223143223Sbostic free(t);
223243223Sbostic }
2233