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