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