122869Smckusick /*
222869Smckusick  * Copyright (c) 1980 Regents of the University of California.
322869Smckusick  * All rights reserved.  The Berkeley software License Agreement
422869Smckusick  * specifies the terms and conditions for redistribution.
522869Smckusick  */
622869Smckusick 
722869Smckusick #ifndef lint
8*25104Sdonn static char sccsid[] = "@(#)regalloc.c	5.3 (Berkeley) 10/06/85";
922869Smckusick #endif not lint
1022869Smckusick 
1122869Smckusick /*
1222869Smckusick  * regalloc.c
1322869Smckusick  *
1422869Smckusick  * Register optimization routines for f77 compiler, pass 1
1522869Smckusick  *
1622869Smckusick  * University of Utah CS Dept modification history:
1722869Smckusick  *
1822869Smckusick  * $History$
1922869Smckusick  * $Log:	regalloc.c,v $
20*25104Sdonn  * Revision 5.3  85/09/27  19:58:16  root
21*25104Sdonn  * Ended PCC confusion with sizes of objects in registers by forcing SHORT
22*25104Sdonn  * values in registers to be converted to INT.
23*25104Sdonn  *
24*25104Sdonn  * Revision 5.2  85/09/26  19:36:22  donn
25*25104Sdonn  * Added a fix for a bug that allowed character variables which were
26*25104Sdonn  * arguments to subroutines to be made eligible to be register variables.
27*25104Sdonn  *
28*25104Sdonn  * Revision 5.1  85/08/10  03:49:35  donn
29*25104Sdonn  * 4.3 alpha
30*25104Sdonn  *
3122869Smckusick  * Revision 2.9  85/03/18  21:35:05  donn
3222869Smckusick  * Bob Corbett's hack to prevent conflicts between subroutine side effects
3322869Smckusick  * and register assignment.  Makes the code a lot worse...
3422869Smckusick  *
3522869Smckusick  * Revision 2.8  85/02/22  02:14:08  donn
3622869Smckusick  * In code like 'x = foo(x)', alreg() would copy the memory version of the
3722869Smckusick  * variable 'x' into the register version after the assignment, clobbering
3822869Smckusick  * the result.  A small change to regwrite() seems to prevent this.
3922869Smckusick  *
4022869Smckusick  * Revision 2.7  85/02/16  03:32:45  donn
4122869Smckusick  * Fixed a bug where the loop test and increment were having register
4222869Smckusick  * substitution performed twice, once in the environment of the current
4322869Smckusick  * loop and once in the environment of the containing loop.  If the
4422869Smckusick  * containing loop puts (say) the inner loop's index variable in register
4522869Smckusick  * but the inner loop does not, havoc results.
4622869Smckusick  *
4722869Smckusick  * Revision 2.6  85/02/14  23:21:45  donn
4822869Smckusick  * Don't permit variable references of the form 'a(i)' to be put in register
4922869Smckusick  * if array 'a' is in common.  This is because there is no good way to
5022869Smckusick  * identify instances of this sort without getting confused with other
5122869Smckusick  * variables in the same common block which are in register.  Sigh.
5222869Smckusick  *
5322869Smckusick  * Revision 2.5  85/01/11  21:08:00  donn
5422869Smckusick  * Made changes so that we pay attention to SAVE statements.  Added a new
5522869Smckusick  * gensetreturn() function to implement this.
5622869Smckusick  *
5722869Smckusick  * Revision 2.4  84/09/03  22:37:28  donn
5822869Smckusick  * Changed the treatment of SKRETURN in alreg() so that all variables in
5922869Smckusick  * register, not just COMMON variables, get written out to memory before a
6022869Smckusick  * RETURN.  This was causing the return value of a function to get lost when
6122869Smckusick  * a RETURN was done from inside a loop (among other problems).
6222869Smckusick  *
6322869Smckusick  * Revision 2.3  84/08/04  20:52:42  donn
6422869Smckusick  * Added fixes for EXTERNAL parameters from Jerry Berkman.
6522869Smckusick  *
6622869Smckusick  * Revision 2.2  84/08/04  20:34:29  donn
6722869Smckusick  * Fixed a stupidity pointed out by Jerry Berkman -- the 'floats in register'
6822869Smckusick  * stuff applies if the TARGET is a VAX, not if the local machine is a VAX.
6922869Smckusick  *
7022869Smckusick  * Revision 2.1  84/07/19  12:04:47  donn
7122869Smckusick  * Changed comment headers for UofU.
7222869Smckusick  *
7322869Smckusick  * Revision 1.5  83/11/27  19:25:41  donn
7422869Smckusick  * Added REAL to the list of types which may appear in registers (VAXen only).
7522869Smckusick  *
7622869Smckusick  * Revision 1.4  83/11/13  02:38:39  donn
7722869Smckusick  * Bug fixed in alreg()'s handling of computed goto's.  A '<=' in place of a
7822869Smckusick  * '<' led to core dumps when we walked off the end of the list of labels...
7922869Smckusick  *
8022869Smckusick  * Revision 1.3  83/11/12  01:25:57  donn
8122869Smckusick  * Bug in redundant register assignment code, mistakenly carried over some old
8222869Smckusick  * code that sometimes rewound a slot pointer even when a redundant slot wasn't
8322869Smckusick  * deleted; this caused an infinite loop...  Seems to work now.
8422869Smckusick  *
8522869Smckusick  * Revision 1.2  83/11/09  14:58:12  donn
8622869Smckusick  * Took out broken code dealing with redundant register initializations.
8722869Smckusick  * Couldn't see what to do about redundantly initializing a DO variable but
8822869Smckusick  * I did fix things so that an assignment from a register into the same
8922869Smckusick  * register is always deleted.
9022869Smckusick  *
9122869Smckusick  */
9222869Smckusick 
9322869Smckusick #include "defs.h"
9422869Smckusick #include "optim.h"
9522869Smckusick 
9622869Smckusick #define LABTABSIZE 101
9722869Smckusick #define VARTABSIZE 1009
9822869Smckusick #define TABLELIMIT 12
9922869Smckusick 
10022869Smckusick #if TARGET==VAX
10122869Smckusick #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG) | M(TYREAL)
10222869Smckusick #else
10322869Smckusick #define MSKREGTYPES M(TYLOGICAL) | M(TYADDR) | M(TYSHORT) | M(TYLONG)
10422869Smckusick #endif
10522869Smckusick 
10622869Smckusick #define ISREGTYPE(x) ONEOF(x, MSKREGTYPES)
10722869Smckusick 
10822869Smckusick #define MSKVARS M(STGAUTO) | M(STGBSS) | M(STGINIT) | M(STGCONST) |\
10922869Smckusick 		M(STGEQUIV) | M(STGARG) | M(STGCOMMON)
11022869Smckusick 
11122869Smckusick #define ISVAR(x) ((((expptr) x)->headblock.vclass == CLVAR || \
11222869Smckusick 			((expptr) x)->headblock.vclass == CLUNKNOWN) \
11322869Smckusick                   && ONEOF(((expptr) x)->headblock.vstg, MSKVARS))
11422869Smckusick 
11522869Smckusick 
11622869Smckusick typedef
11722869Smckusick   struct regdata
11822869Smckusick     {
11922869Smckusick       field vstg;
12022869Smckusick       field vtype;
12122869Smckusick       int memno;
12222869Smckusick       int memoffset;
12322869Smckusick       int refs;
12422869Smckusick       Addrp stgp;
12522869Smckusick       unsigned isarrayarg : 1;
12622869Smckusick       unsigned istemp : 1;
12722869Smckusick       unsigned isset : 1;
12822869Smckusick       unsigned setfirst : 1;
12922869Smckusick     } REGDATA;
13022869Smckusick 
13122869Smckusick 
13222869Smckusick typedef
13322869Smckusick   struct labelnode
13422869Smckusick     {
13522869Smckusick       struct labelnode *link;
13622869Smckusick       int labelno;
13722869Smckusick     } LABELNODE;
13822869Smckusick 
13922869Smckusick 
14022869Smckusick 
14122869Smckusick typedef
14222869Smckusick   struct varnode
14322869Smckusick     {
14422869Smckusick       struct varnode *link;
14522869Smckusick       int memoffset;
14622869Smckusick       unsigned isset : 1;
14722869Smckusick       unsigned isused : 1;
14822869Smckusick       unsigned setfirst : 1;
14922869Smckusick       unsigned unusable : 1;
15022869Smckusick       int refs;
15122869Smckusick       Addrp stgp;
15222869Smckusick     } VARNODE;
15322869Smckusick 
15422869Smckusick 
15522869Smckusick typedef
15622869Smckusick   struct addrnode
15722869Smckusick     {
15822869Smckusick       struct addrnode *link;
15922869Smckusick       field vtype;
16022869Smckusick       field vstg;
16122869Smckusick       int memno;
16222869Smckusick       unsigned istemp : 1;
16322869Smckusick       unsigned isset : 1;
16422869Smckusick       unsigned freeuse : 1;
16522869Smckusick       unsigned mixedtype : 1;
16622869Smckusick       unsigned fixed : 1;
16722869Smckusick       int refs;
16822869Smckusick       struct addrnode *commonlink;
16922869Smckusick       VARNODE *varlist;
17022869Smckusick     } ADDRNODE;
17122869Smckusick 
17222869Smckusick 
17322869Smckusick typedef
17422869Smckusick   struct setnode
17522869Smckusick     {
17622869Smckusick       struct setnode *link;
17722869Smckusick       field vstg;
17822869Smckusick       int memno;
17922869Smckusick       int memoffset;
18022869Smckusick     } SETNODE;
18122869Smckusick 
18222869Smckusick 
18322869Smckusick typedef
18422869Smckusick   struct doqueue
18522869Smckusick     {
18622869Smckusick       struct doqueue *up, *down;
18722869Smckusick       Slotp dohead, doend;
18822869Smckusick       int nregvars;
18922869Smckusick       REGNODE *reg[MAXREGVAR];
19022869Smckusick     }  DOQUEUE;
19122869Smckusick 
19222869Smckusick LOCAL DOQUEUE *dqptr, *dqtop, *dqbottom;
19322869Smckusick 
19422869Smckusick 
19522869Smckusick LOCAL Slotp dohead;
19622869Smckusick LOCAL Slotp doend;
19722869Smckusick LOCAL Slotp newcode;
19822869Smckusick 
19922869Smckusick 
20022869Smckusick 
20122869Smckusick LOCAL LABELNODE *labeltable[LABTABSIZE];
20222869Smckusick LOCAL ADDRNODE *vartable[VARTABSIZE];
20322869Smckusick LOCAL ADDRNODE *commonvars;
20422869Smckusick LOCAL SETNODE *setlist;
20522869Smckusick LOCAL int topregvar;
20622869Smckusick LOCAL int toplcv;
20722869Smckusick LOCAL int allset;
20822869Smckusick LOCAL ADDRNODE *currentaddr;
20922869Smckusick LOCAL int loopcost;
21022869Smckusick LOCAL REGDATA *regtab[MAXREGVAR];
21122869Smckusick LOCAL REGDATA *rt[TABLELIMIT];
21222869Smckusick LOCAL int tabletop;
21322869Smckusick LOCAL int linearcode;
21422869Smckusick LOCAL int globalbranch;
21522869Smckusick LOCAL int commonunusable;
21622869Smckusick LOCAL int regdefined[MAXREGVAR];
21722869Smckusick LOCAL int memdefined[MAXREGVAR];
21822869Smckusick LOCAL int regaltered[MAXREGVAR];
21922869Smckusick 
22022869Smckusick 
22122869Smckusick 
22222869Smckusick LOCAL insertlabel(l)
22322869Smckusick int l;
22422869Smckusick 
22522869Smckusick {
22622869Smckusick   int key;
22722869Smckusick   LABELNODE *p;
22822869Smckusick 
22922869Smckusick   key = l % LABTABSIZE;
23022869Smckusick   for (p = labeltable[key]; p; p = p->link)
23122869Smckusick     if (p->labelno == l) return;
23222869Smckusick   p = labeltable[key];
23322869Smckusick   labeltable[key] = ALLOC(labelnode);
23422869Smckusick   labeltable[key]->link = p;
23522869Smckusick   labeltable[key]->labelno = l;
23622869Smckusick   return;
23722869Smckusick }
23822869Smckusick 
23922869Smckusick 
24022869Smckusick 
24122869Smckusick LOCAL int locallabel(l)
24222869Smckusick int l;
24322869Smckusick 
24422869Smckusick {
24522869Smckusick   int key;
24622869Smckusick   LABELNODE *p;
24722869Smckusick 
24822869Smckusick   key = l % LABTABSIZE;
24922869Smckusick   for (p = labeltable[key]; p; p = p->link)
25022869Smckusick     if (p->labelno == l) return YES;
25122869Smckusick 
25222869Smckusick   return NO;
25322869Smckusick }
25422869Smckusick 
25522869Smckusick 
25622869Smckusick 
25722869Smckusick LOCAL freelabtab()
25822869Smckusick 
25922869Smckusick {
26022869Smckusick   int i;
26122869Smckusick   LABELNODE *p, *q;
26222869Smckusick 
26322869Smckusick   for (i = 0; i < LABTABSIZE; i++)
26422869Smckusick     if (labeltable[i])
26522869Smckusick       {
26622869Smckusick 	p = labeltable[i];
26722869Smckusick 	labeltable[i] = NULL;
26822869Smckusick 	while (p)
26922869Smckusick 	  {
27022869Smckusick 	    q = p->link;
27122869Smckusick 	    free(p);
27222869Smckusick 	    p = q;
27322869Smckusick 	  }
27422869Smckusick       }
27522869Smckusick   return;
27622869Smckusick }
27722869Smckusick 
27822869Smckusick 
27922869Smckusick 
28022869Smckusick LOCAL ADDRNODE *getaddr(ap)
28122869Smckusick Addrp ap;
28222869Smckusick 
28322869Smckusick {
28422869Smckusick   int key;
28522869Smckusick   field vstg;
28622869Smckusick   int memno;
28722869Smckusick   register ADDRNODE *q;
28822869Smckusick   ADDRNODE *q1;
28922869Smckusick 
29022869Smckusick   if (!ISVAR(ap))
29122869Smckusick     fatal("regalloc: bad data sent to getaddr");
29222869Smckusick   vstg = ap->vstg;
29322869Smckusick   memno = ap->memno;
29422869Smckusick   key = (256*vstg + memno) % VARTABSIZE;
29522869Smckusick 
29622869Smckusick   for (q = vartable[key]; q; q = q->link)
29722869Smckusick     if ((q->vstg == vstg) && (q->memno == memno))
29822869Smckusick       {
29922869Smckusick 	if (ap->istemp) q->istemp = YES;
30022869Smckusick 	if (ap->vtype != q->vtype)
30122869Smckusick 	  q->mixedtype = YES;
30222869Smckusick 	if (!fixedaddress(ap))
30322869Smckusick 	  q->fixed = NO;
30422869Smckusick 	return q;
30522869Smckusick       }
30622869Smckusick 
30722869Smckusick   q1 = vartable[key];
30822869Smckusick   vartable[key] = q = ALLOC(addrnode);
30922869Smckusick   q->link = q1;
31022869Smckusick   q->vstg = vstg;
31122869Smckusick   q->memno = memno;
31222869Smckusick   if (ap->istemp) q->istemp = YES;
31322869Smckusick   if (fixedaddress(ap)) q->fixed = YES;
31422869Smckusick   q->vtype = ap->vtype;
31522869Smckusick   q->varlist = NULL;
31622869Smckusick   if (vstg == STGCOMMON)
31722869Smckusick     {
31822869Smckusick       q->commonlink = commonvars;
31922869Smckusick       commonvars = q;
32022869Smckusick     }
32122869Smckusick   return q;
32222869Smckusick }
32322869Smckusick 
32422869Smckusick 
32522869Smckusick 
32622869Smckusick LOCAL VARNODE *getvar(ainfo, ap)
32722869Smckusick ADDRNODE *ainfo;
32822869Smckusick Addrp ap;
32922869Smckusick 
33022869Smckusick {
33122869Smckusick   register VARNODE *q;
33222869Smckusick   VARNODE *q1;
33322869Smckusick   int memoffset;
33422869Smckusick 
33522869Smckusick   if (!ISVAR(ap))
33622869Smckusick     fatal("regalloc:  bad data sent to getvar");
33722869Smckusick 
33822869Smckusick   memoffset = ap->memoffset->constblock.const.ci;
33922869Smckusick 
34022869Smckusick   for (q = ainfo->varlist; q; q = q->link)
34122869Smckusick     if (q->memoffset == memoffset)
34222869Smckusick       return q;
34322869Smckusick 
34422869Smckusick   q1 = ainfo->varlist;
34522869Smckusick   ainfo->varlist = q = ALLOC(varnode);
34622869Smckusick   q->link = q1;
34722869Smckusick   q->memoffset = memoffset;
34822869Smckusick   q->stgp = (Addrp) cpexpr(ap);
34922869Smckusick   return q;
35022869Smckusick }
35122869Smckusick 
35222869Smckusick 
35322869Smckusick LOCAL ADDRNODE *lookupaddr(vstg, memno)
35422869Smckusick field vstg;
35522869Smckusick int memno;
35622869Smckusick 
35722869Smckusick {
35822869Smckusick   int key;
35922869Smckusick   register ADDRNODE *q;
36022869Smckusick 
36122869Smckusick   key = (256*vstg + memno) % VARTABSIZE;
36222869Smckusick 
36322869Smckusick   for (q = vartable[key]; q; q = q->link)
36422869Smckusick     if ((q->vstg == vstg) && (q->memno == memno))
36522869Smckusick       return q;
36622869Smckusick 
36722869Smckusick   fatal("regalloc:  lookupaddr");
36822869Smckusick }
36922869Smckusick 
37022869Smckusick 
37122869Smckusick LOCAL VARNODE *lookupvar(ainfo, memoffset)
37222869Smckusick ADDRNODE *ainfo;
37322869Smckusick int memoffset;
37422869Smckusick 
37522869Smckusick {
37622869Smckusick   register VARNODE *q;
37722869Smckusick 
37822869Smckusick   for (q = ainfo->varlist; q; q = q->link)
37922869Smckusick     if (q->memoffset == memoffset)
38022869Smckusick       return q;
38122869Smckusick 
38222869Smckusick   fatal("regalloc:  lookupvar");
38322869Smckusick }
38422869Smckusick 
38522869Smckusick 
38622869Smckusick 
38722869Smckusick LOCAL int invartable(p)
38822869Smckusick REGNODE *p;
38922869Smckusick 
39022869Smckusick {
39122869Smckusick   field vstg;
39222869Smckusick   int memno;
39322869Smckusick   int key;
39422869Smckusick   register ADDRNODE *q;
39522869Smckusick 
39622869Smckusick   vstg = p->vstg;
39722869Smckusick   memno = p->memno;
39822869Smckusick   key = (256*vstg + memno) % VARTABSIZE;
39922869Smckusick 
40022869Smckusick   for (q = vartable[key]; q; q = q->link)
40122869Smckusick     if ((q->vstg == vstg) && (q->memno == memno))
40222869Smckusick       return YES;
40322869Smckusick 
40422869Smckusick   return NO;
40522869Smckusick }
40622869Smckusick 
40722869Smckusick 
40822869Smckusick 
40922869Smckusick LOCAL freevartab()
41022869Smckusick 
41122869Smckusick {
41222869Smckusick   register ADDRNODE *p;
41322869Smckusick   ADDRNODE *p1;
41422869Smckusick   register VARNODE *q;
41522869Smckusick   VARNODE *q1;
41622869Smckusick   register int i;
41722869Smckusick 
41822869Smckusick   for (i = 0; i < VARTABSIZE; i++)
41922869Smckusick     if (vartable[i])
42022869Smckusick       {
42122869Smckusick 	p = vartable[i];
42222869Smckusick 	vartable[i] = NULL;
42322869Smckusick 
42422869Smckusick 	while (p)
42522869Smckusick 	  {
42622869Smckusick 	    for (q = p->varlist; q; q = q1)
42722869Smckusick 	      {
42822869Smckusick 		q1 = q->link;
42922869Smckusick 		frexpr(q->stgp);
43022869Smckusick 		free ((char *) q);
43122869Smckusick 	      }
43222869Smckusick 	    p1 = p->link;
43322869Smckusick 	    free((char *) p);
43422869Smckusick 	    p = p1;
43522869Smckusick 	  }
43622869Smckusick       }
43722869Smckusick }
43822869Smckusick 
43922869Smckusick 
44022869Smckusick 
44122869Smckusick LOCAL insertset(vstg, memno, memoffset)
44222869Smckusick field vstg;
44322869Smckusick int memno;
44422869Smckusick int memoffset;
44522869Smckusick 
44622869Smckusick {
44722869Smckusick   register SETNODE *p;
44822869Smckusick   SETNODE *q;
44922869Smckusick 
45022869Smckusick   if (allset) return;
45122869Smckusick   for (p = setlist; p; p = p->link)
45222869Smckusick     if((p->vstg == vstg) && (p->memno == memno) && (p->memoffset == memoffset))
45322869Smckusick       return;
45422869Smckusick 
45522869Smckusick   q = p;
45622869Smckusick   setlist = p = ALLOC(setnode);
45722869Smckusick   p->link = q;
45822869Smckusick   p->vstg = vstg;
45922869Smckusick   p->memno = memno;
46022869Smckusick   p->memoffset = memoffset;
46122869Smckusick   return;
46222869Smckusick }
46322869Smckusick 
46422869Smckusick 
46522869Smckusick 
46622869Smckusick LOCAL int insetlist(vstg, memno, memoffset)
46722869Smckusick field vstg;
46822869Smckusick int memno;
46922869Smckusick int memoffset;
47022869Smckusick 
47122869Smckusick {
47222869Smckusick   register SETNODE *p;
47322869Smckusick 
47422869Smckusick   if (allset) return YES;
47522869Smckusick   for (p = setlist; p; p = p->link)
47622869Smckusick     if((p->vstg == vstg) && (p->memno == memno) && (p->memoffset == memoffset))
47722869Smckusick       return YES;
47822869Smckusick 
47922869Smckusick   return NO;
48022869Smckusick }
48122869Smckusick 
48222869Smckusick 
48322869Smckusick 
48422869Smckusick LOCAL clearsets()
48522869Smckusick 
48622869Smckusick {
48722869Smckusick   register SETNODE *p, *q;
48822869Smckusick 
48922869Smckusick   allset = NO;
49022869Smckusick 
49122869Smckusick   p = setlist;
49222869Smckusick   while (p)
49322869Smckusick     {
49422869Smckusick       q = p->link;
49522869Smckusick       free ((char *) p);
49622869Smckusick       p = q;
49722869Smckusick     }
49822869Smckusick   setlist = NULL;
49922869Smckusick   return;
50022869Smckusick }
50122869Smckusick 
50222869Smckusick 
50322869Smckusick 
50422869Smckusick LOCAL alreg()
50522869Smckusick 
50622869Smckusick {
50722869Smckusick   register Slotp sp;
50822869Smckusick   register int i;
50922869Smckusick   register ADDRNODE *p;
51022869Smckusick   register VARNODE *q;
51122869Smckusick   Slotp sp1, sp2;
51222869Smckusick   ADDRNODE *addrinfo;
51322869Smckusick   VARNODE *varinfo;
51422869Smckusick   int docount;
51522869Smckusick   struct Labelblock **lp;
51622869Smckusick   int toptrack;
51722869Smckusick   int track[MAXREGVAR];
51822869Smckusick   Addrp ap, ap1;
51922869Smckusick   DOQUEUE *dqp;
52022869Smckusick   REGDATA *rp;
52122869Smckusick   REGNODE *regp;
52222869Smckusick 
52322869Smckusick   if (nregvar >= maxregvar) return;
52422869Smckusick 
52522869Smckusick   commonvars = NULL;
52622869Smckusick 
52722869Smckusick   for (sp = dohead; sp != doend->next; sp = sp->next)
52822869Smckusick     switch (sp->type)
52922869Smckusick       {
53022869Smckusick       case SKLABEL:
53122869Smckusick 	insertlabel(sp->label);
53222869Smckusick 	break;
53322869Smckusick 
53422869Smckusick       case SKARIF:
53522869Smckusick       case SKASGOTO:
53622869Smckusick       case SKCALL:
53722869Smckusick       case SKCMGOTO:
53822869Smckusick       case SKEQ:
53922869Smckusick       case SKIFN:
54022869Smckusick       case SKIOIFN:
54122869Smckusick       case SKSTOP:
54222869Smckusick       case SKPAUSE:
54322869Smckusick       case SKRETURN:
54422869Smckusick 	scanvars(sp->expr);
54522869Smckusick 	break;
54622869Smckusick 
54722869Smckusick       case SKNULL:
54822869Smckusick       case SKGOTO:
54922869Smckusick       case SKDOHEAD:
55022869Smckusick       case SKENDDO:
55122869Smckusick       case SKASSIGN:
55222869Smckusick 	break;
55322869Smckusick 
55422869Smckusick       default:
55522869Smckusick 	badthing ("SKtype", "alreg-1", sp->type);
55622869Smckusick       }
55722869Smckusick 
55822869Smckusick   loopcost = 0;
55922869Smckusick   docount = 1;
56022869Smckusick   commonunusable = NO;
56122869Smckusick   if (! dohead->nullslot) fatal ("missing dohead->nullslot -cbb");
56222869Smckusick   for (sp = dohead->next, globalbranch = NO;
56322869Smckusick        docount;
56422869Smckusick        sp = sp->next, clearsets(), globalbranch = NO)
56522869Smckusick     if (docount > 1)
56622869Smckusick       switch (sp->type)
56722869Smckusick 	{
56822869Smckusick 	case SKDOHEAD:
56922869Smckusick 	  docount++;
57022869Smckusick 	  break;
57122869Smckusick 
57222869Smckusick 	case SKENDDO:
57322869Smckusick 	  docount--;
57422869Smckusick 
57522869Smckusick 	default:
57622869Smckusick 	  break;
57722869Smckusick 	}
57822869Smckusick     else
57922869Smckusick       switch (sp->type)
58022869Smckusick 	{
58122869Smckusick 	case SKARIF:
58222869Smckusick #define LM   ((struct Labelblock * *)sp->ctlinfo)[0]->labelno
58322869Smckusick #define LZ   ((struct Labelblock * *)sp->ctlinfo)[1]->labelno
58422869Smckusick #define LP   ((struct Labelblock * *)sp->ctlinfo)[2]->labelno
58522869Smckusick 
58622869Smckusick 	  if (!locallabel(LM) || !locallabel(LZ) || !locallabel(LP))
58722869Smckusick 	    {
58822869Smckusick 	      setall();
58922869Smckusick 	      globalbranch = YES;
59022869Smckusick 	    }
59122869Smckusick 	  countrefs(sp->expr);
59222869Smckusick 	  break;
59322869Smckusick 
59422869Smckusick 	case SKASGOTO:
59522869Smckusick 	  setall();
59622869Smckusick 	  globalbranch = YES;
59722869Smckusick 	  countrefs(sp->expr);
59822869Smckusick 	  break;
59922869Smckusick 
60022869Smckusick 	case SKCMGOTO:
60122869Smckusick 	  lp = (struct Labelblock **) sp->ctlinfo;
60222869Smckusick 	  for (i = 0; i < sp->label; i++, lp++)
60322869Smckusick 	    if (!locallabel((*lp)->labelno))
60422869Smckusick 	      {
60522869Smckusick 		setall();
60622869Smckusick 		globalbranch = YES;
60722869Smckusick 		break;
60822869Smckusick 	      }
60922869Smckusick 	  countrefs(sp->expr);
61022869Smckusick 	  break;
61122869Smckusick 
61222869Smckusick 	case SKDOHEAD:
61322869Smckusick 	  globalbranch = YES;
61422869Smckusick 	  loopcost = 2;
61522869Smckusick 	  docount++;
61622869Smckusick 	  break;
61722869Smckusick 
61822869Smckusick 	case SKENDDO:
61922869Smckusick 	  docount = 0;
62022869Smckusick 	  break;
62122869Smckusick 
62222869Smckusick 	case SKGOTO:
62322869Smckusick 	  if (!locallabel(sp->label))
62422869Smckusick 	    {
62522869Smckusick 	      setall();
62622869Smckusick 	      globalbranch = YES;
62722869Smckusick 	    }
62822869Smckusick 	  break;
62922869Smckusick 
63022869Smckusick 	case SKIFN:
63122869Smckusick 	case SKIOIFN:
63222869Smckusick 	  if (!locallabel(sp->label))
63322869Smckusick 	    {
63422869Smckusick 	      setall();
63522869Smckusick 	      globalbranch = YES;
63622869Smckusick 	    }
63722869Smckusick 	  countrefs(sp->expr);
63822869Smckusick 	  break;
63922869Smckusick 
64022869Smckusick 	case SKEQ:
64122869Smckusick 	case SKCALL:
64222869Smckusick 	case SKSTOP:
64322869Smckusick 	case SKPAUSE:
64422869Smckusick 	  linearcode = YES;
64522869Smckusick 	  countrefs(sp->expr);
64622869Smckusick 	  linearcode = NO;
64722869Smckusick 	  break;
64822869Smckusick 	}
64922869Smckusick 
65022869Smckusick   topregvar = toplcv = nregvar - 1;
65122869Smckusick 
65222869Smckusick   for (i = 0; i < nregvar; i++)
65322869Smckusick     {
65422869Smckusick       ap = memversion(regnamep[i]);
65522869Smckusick       regtab[i] = rp = ALLOC(regdata);
65622869Smckusick       rp->vstg = ap->vstg;
65722869Smckusick       rp->vtype = ap->vtype;
65822869Smckusick       rp->memno = ap->memno;
65922869Smckusick       rp->memoffset = ap->memoffset->constblock.const.ci;
66022869Smckusick       rp->isarrayarg = NO;
66122869Smckusick       rp->stgp = ap;
66222869Smckusick     }
66322869Smckusick 
66422869Smckusick   for (i = 0; i < MAXREGVAR; i++)
66522869Smckusick     track[i] = YES;
66622869Smckusick 
66722869Smckusick   for (dqp = dqptr->down; dqp; dqp = dqp->down)
66822869Smckusick     {
66922869Smckusick       if (dqp->nregvars - 1 > topregvar)
67022869Smckusick 	topregvar = dqp->nregvars -1;
67122869Smckusick       for (i = toplcv + 1; i < dqp->nregvars; i++)
67222869Smckusick 	if (track[i])
67322869Smckusick 	  if (regp = dqp->reg[i])
67422869Smckusick 	    if (rp = regtab[i])
67522869Smckusick 	      {
67622869Smckusick 		if (!samevar(rp, regp))
67722869Smckusick 		  track[i] = NO;
67822869Smckusick 	      }
67922869Smckusick 	    else if (invartable(regp))
68022869Smckusick 	      {
68122869Smckusick 		regtab[i] = rp = ALLOC(regdata);
68222869Smckusick 		rp->vstg = regp->vstg;
68322869Smckusick 		rp->vtype = regp->vtype;
68422869Smckusick 		rp->memno = regp->memno;
68522869Smckusick 		rp->memoffset = regp->memoffset;
68622869Smckusick 		addrinfo = lookupaddr(rp->vstg, rp->memno);
68722869Smckusick 		if (regp->isarrayarg)
68822869Smckusick 		  {
68922869Smckusick 		    rp->isarrayarg = YES;
69022869Smckusick 		    rp->refs = addrinfo->refs;
69122869Smckusick 		  }
69222869Smckusick 		else
69322869Smckusick 		  {
69422869Smckusick 		    varinfo = lookupvar(addrinfo, regp->memoffset);
69522869Smckusick 		    rp->refs = varinfo->refs;
69622869Smckusick 		    rp->stgp = (Addrp) cpexpr(varinfo->stgp);
69722869Smckusick 		    rp->istemp = addrinfo->istemp;
69822869Smckusick 		    rp->isset = varinfo->isset;
69922869Smckusick 		    rp->setfirst = varinfo->setfirst;
70022869Smckusick 		  }
70122869Smckusick 	      }
70222869Smckusick 	    else
70322869Smckusick               track[i] = NO;
70422869Smckusick 	  else
70522869Smckusick 	    track[i] = NO;
70622869Smckusick     }
70722869Smckusick 
70822869Smckusick   toptrack = topregvar;
70922869Smckusick 
71022869Smckusick   for (i = toplcv + 1; i <= topregvar; i++)
71122869Smckusick     if (regtab[i])
71222869Smckusick       if ((track[i] == NO) || (regtab[i]->refs <= 0))
71322869Smckusick         {
71422869Smckusick 	  free((char *) regtab[i]);
71522869Smckusick 	  regtab[i] = NULL;
71622869Smckusick         }
71722869Smckusick 
71822869Smckusick   tabletop = -1;
71922869Smckusick   if (topregvar < maxregvar - 1)
72022869Smckusick     for (i = 0; i < VARTABSIZE; i++)
72122869Smckusick       for (p = vartable[i]; p; p = p->link)
72222869Smckusick 	{
72322869Smckusick 	  entableaddr(p);
72422869Smckusick 	  if ((!p->mixedtype) &&
72522869Smckusick 	      (p->vstg != STGARG) &&
72622869Smckusick 	      !((p->vstg == STGCOMMON) && ((!p->fixed) || commonunusable)))
72722869Smckusick 	    for (q = p->varlist; q; q = q->link)
72822869Smckusick 	      entablevar(q);
72922869Smckusick 	}
73022869Smckusick 
73122869Smckusick   for (i = 0; (i <= tabletop) && (topregvar + 1 < maxregvar); i++)
73222869Smckusick     {
73322869Smckusick       if (inregtab(rt[i]) || (loopcost && rt[i]->isset))
73422869Smckusick 	continue;
73522869Smckusick       topregvar++;
73622869Smckusick       regtab[topregvar] = rp = ALLOC(regdata);
73722869Smckusick       rp->vstg = rt[i]->vstg;
73822869Smckusick       rp->vtype = rt[i]->vtype;
73922869Smckusick       rp->memno = rt[i]->memno;
74022869Smckusick       rp->memoffset = rt[i]->memoffset;
74122869Smckusick       rp->refs = rt[i]->refs;
74222869Smckusick       rp->stgp = (Addrp) cpexpr(rt[i]->stgp);
74322869Smckusick       rp->isarrayarg = rt[i]->isarrayarg;
74422869Smckusick       rp->istemp = rt[i]->istemp;
74522869Smckusick       rp->isset = rt[i]->isset;
74622869Smckusick       rp->setfirst = rt[i]->setfirst;
74722869Smckusick     }
74822869Smckusick 
74922869Smckusick   for (i = toplcv + 1; i <= topregvar; i++)
75022869Smckusick     {
75122869Smckusick       if (rp = regtab[i])
75222869Smckusick 	if (rp->isarrayarg)
75322869Smckusick 	  {
75422869Smckusick 	    ap = ALLOC(Addrblock);
75522869Smckusick 	    ap->tag = TADDR;
75622869Smckusick 	    ap->vstg = STGREG;
75722869Smckusick 	    ap->vtype = TYADDR;
75822869Smckusick 	    ap->vclass = CLVAR;
75922869Smckusick 	    ap->memno = regnum[i];
76022869Smckusick 	    ap->memoffset = ICON(0);
76122869Smckusick 
76222869Smckusick 	    ap1 = ALLOC(Addrblock);
76322869Smckusick 	    ap1->tag = TADDR;
76422869Smckusick 	    ap1->vstg = rp->vstg;
76522869Smckusick 	    ap1->vtype = rp->vtype;
76622869Smckusick 	    ap1->vclass = CLVAR;
76722869Smckusick 	    ap1->memno = rp->memno;
76822869Smckusick 	    ap1->memoffset = ICON(0);
76922869Smckusick 
77022869Smckusick 	    insertassign(dohead, ap, addrof(ap1));
77122869Smckusick 	  }
77222869Smckusick         else if (!(rp->setfirst && rp->istemp))
77322869Smckusick 	  {
77422869Smckusick 	    if (rp->istemp)
77522869Smckusick 	      for (sp = newcode; sp && sp != dohead; sp = sp->next)
77622869Smckusick 	        if (sp->type == SKEQ)
77722869Smckusick 		  {
77822869Smckusick 		    ap = (Addrp) sp->expr->exprblock.leftp;
77922869Smckusick 		    if ((ap->vstg == rp->vstg) && (ap->memno == rp->memno) &&
78022869Smckusick 			fixedaddress(ap) &&
78122869Smckusick 			(ap->memoffset->constblock.const.ci == rp->memoffset))
78222869Smckusick 		      {
78322869Smckusick 			changetoreg(ap, i);
78422869Smckusick 			goto L1;
78522869Smckusick 		      }
78622869Smckusick 		  }
78722869Smckusick 	    ap = (Addrp) cpexpr(rp->stgp);
78822869Smckusick 	    changetoreg(ap, i);
78922869Smckusick 	    insertassign(dohead, ap, cpexpr(rp->stgp));
79022869Smckusick 	  }
79122869Smckusick L1:;
79222869Smckusick     }
79322869Smckusick 
79422869Smckusick   for (i = toplcv + 1; i <= topregvar; i++)
79522869Smckusick     if (rp = regtab[i])
79622869Smckusick       if (rp->isset && !(rp->istemp || rp->isarrayarg))
79722869Smckusick 	{
79822869Smckusick 	  ap = (Addrp) cpexpr(rp->stgp);
79922869Smckusick 	  changetoreg(ap, i);
80022869Smckusick 	  appendassign(doend, cpexpr(rp->stgp), ap);
80122869Smckusick 	}
80222869Smckusick 
80322869Smckusick   docount = 1;
80422869Smckusick   clearmems();
80522869Smckusick   setregs();
80622869Smckusick   sp = dohead->next;
80722869Smckusick   if (loopcost)
80822869Smckusick     for (i = toptrack + 1; i <= topregvar; i++)
80922869Smckusick       if ((rp = regtab[i]) && !rp->isarrayarg)
81022869Smckusick 	{
81122869Smckusick 	  ap = (Addrp) cpexpr(rp->stgp);
81222869Smckusick 	  changetoreg(ap, i);
81322869Smckusick 	  insertassign(sp, cpexpr(rp->stgp), ap);
81422869Smckusick 	}
81522869Smckusick 
81622869Smckusick   for ( sp = dohead->next;
81722869Smckusick 	docount || sp->type != SKNULL;
81822869Smckusick 	sp = sp->next)
81922869Smckusick     if (docount > 1)
82022869Smckusick       switch (sp->type)
82122869Smckusick 	{
82222869Smckusick 	case SKDOHEAD:
82322869Smckusick 	  docount++;
82422869Smckusick 	  break;
82522869Smckusick 
82622869Smckusick 	case SKENDDO:
82722869Smckusick 	  if (--docount == 1)
82822869Smckusick 	    {
82922869Smckusick 	      /*
83022869Smckusick 	       * Remove redundant stores to memory.
83122869Smckusick 	       */
83222869Smckusick 	      sp1 = sp->nullslot->next;
83322869Smckusick 	      while (sp1)
83422869Smckusick 		{
83522869Smckusick 		  if (regtomem(sp1))
83622869Smckusick 		    {
83722869Smckusick 		      ap = (Addrp) sp1->expr->exprblock.rightp;
83822869Smckusick 		      sp2 = sp1->next;
83922869Smckusick 		      for (i = toplcv + 2; i <= toptrack; i++)
84022869Smckusick 			if (regtab[i] && (regnum[i] == ap->memno))
84122869Smckusick 			  {
84222869Smckusick 			    deleteslot(sp1);
84322869Smckusick 			    break;
84422869Smckusick 			  }
84522869Smckusick 		      sp1 = sp2;
84622869Smckusick 		    }
84722869Smckusick 		  else
84822869Smckusick 		    sp1 = NULL;
84922869Smckusick 		}
85022869Smckusick 
85122869Smckusick 	      /*
85222869Smckusick 	       * Restore register variables (complement to DOHEAD code).
85322869Smckusick 	       */
85422869Smckusick 	      sp1 = sp->nullslot->next;
85522869Smckusick 	      for (i = toplcv + 1; i <= topregvar; i++)
85622869Smckusick 		if (rp = regtab[i])
85722869Smckusick 		  if (!regdefined[i])
85822869Smckusick 		    if (i >= dqp->nregvars || !samevar(rp, dqp->reg[i]))
85922869Smckusick 		      {
86022869Smckusick 			ap = (Addrp) cpexpr(rp->stgp);
86122869Smckusick 			changetoreg(ap, i);
86222869Smckusick 			insertassign(sp1, ap, cpexpr(rp->stgp));
86322869Smckusick 			regdefined[i] = YES;
86422869Smckusick 		      }
86522869Smckusick 
86622869Smckusick 	      clearmems();
86722869Smckusick 	      if (toplcv + 1 < maxregvar)
86822869Smckusick 		memdefined[toplcv + 1] = YES;
86922869Smckusick 	      sp = sp1->prev;
87022869Smckusick 	    }
87122869Smckusick 	  break;
87222869Smckusick 	}
87322869Smckusick       else
87422869Smckusick 	{
87522869Smckusick 	  setregs();
87622869Smckusick 	  for (i = 0; i <= MAXREGVAR; i++)
87722869Smckusick 	    regaltered[i] = NO;
87822869Smckusick 	  globalbranch = NO;
87922869Smckusick 
88022869Smckusick 	  switch (sp->type)
88122869Smckusick 	    {
88222869Smckusick 	    case SKLABEL:
88322869Smckusick 	      clearmems();
88422869Smckusick 	      break;
88522869Smckusick 
88622869Smckusick 	    case SKGOTO:
88722869Smckusick 	      if (!locallabel(sp->label))
88822869Smckusick 		gensetall(sp);
88922869Smckusick 	      break;
89022869Smckusick 
89122869Smckusick 	    case SKENDDO:
89222869Smckusick 	      docount = 0;
89322869Smckusick 	      break;
89422869Smckusick 
89522869Smckusick 	    case SKRETURN:
89622869Smckusick 	      gensetreturn(sp);
89722869Smckusick 	      linearcode = YES;
89822869Smckusick 	      regwrite(sp, sp->expr);
89922869Smckusick 	      linearcode = NO;
90022869Smckusick 	      break;
90122869Smckusick 
90222869Smckusick 	    case SKDOHEAD:
90322869Smckusick 	      /*
90422869Smckusick 	       * If one of the current loop's register variables is not in
90522869Smckusick 	       * register in an inner loop, we must save it.  It's a pity
90622869Smckusick 	       * we don't save enough info to optimize this properly...
90722869Smckusick 	       */
90822869Smckusick 	      for (dqp = dqptr->down; dqp; dqp = dqp->down)
90922869Smckusick 		if (dqp->dohead == sp)
91022869Smckusick 		  break;
91122869Smckusick 	      if (dqp == NULL)
91222869Smckusick 		fatal("confused in alreg loop analysis");
91322869Smckusick 	      for (i = toplcv + 1; i <= topregvar; i++)
91422869Smckusick 		if (rp = regtab[i])
91522869Smckusick 		  if (!memdefined[i])
91622869Smckusick 		    if (i >= dqp->nregvars || !samevar(rp, dqp->reg[i]))
91722869Smckusick 		      {
91822869Smckusick 			ap = (Addrp) cpexpr(rp->stgp);
91922869Smckusick 			changetoreg(ap, i);
92022869Smckusick 			insertassign(sp, cpexpr(rp->stgp), ap);
92122869Smckusick 			memdefined[i] = YES;
92222869Smckusick 			regdefined[i] = NO;
92322869Smckusick 		      }
92422869Smckusick 
92522869Smckusick 	      docount++;
92622869Smckusick 	      globalbranch = YES;
92722869Smckusick 	      break;
92822869Smckusick 
92922869Smckusick 	    case SKEQ:
93022869Smckusick 	    case SKCALL:
93122869Smckusick 	    case SKSTOP:
93222869Smckusick 	    case SKPAUSE:
93322869Smckusick 	      linearcode = YES;
93422869Smckusick 	      regwrite(sp, sp->expr);
93522869Smckusick 	      for (i = toplcv + 1; i <= topregvar; i++)
93622869Smckusick 		if (!regdefined[i] && ((rp = regtab[i]) && rp->isset))
93722869Smckusick 		  {
93822869Smckusick 		    ap = (Addrp) cpexpr(rp->stgp);
93922869Smckusick 		    changetoreg(ap, i);
94022869Smckusick 		    appendassign(sp, ap, cpexpr(rp->stgp));
94122869Smckusick 		    sp = sp->next;
94222869Smckusick 		    regdefined[i] = YES;
94322869Smckusick 		  }
94422869Smckusick 	      linearcode = NO;
94522869Smckusick 
94622869Smckusick 	      /*
94722869Smckusick 	       * Eliminate redundant register moves.
94822869Smckusick 	       */
94922869Smckusick 	      if (regtoreg(sp))
95022869Smckusick 		{
95122869Smckusick 		  ap = (Addrp) sp->expr->exprblock.leftp;
95222869Smckusick 	          sp1 = sp->prev;
95322869Smckusick 		  for (i = toplcv + 1; i <= toptrack; i++)
95422869Smckusick 		    if (regtab[i] && (regnum[i] == ap->memno))
95522869Smckusick 		      {
95622869Smckusick 			deleteslot(sp);
95722869Smckusick 			sp = sp1;
95822869Smckusick 			break;
95922869Smckusick 		      }
96022869Smckusick 		}
96122869Smckusick 	      break;
96222869Smckusick 
96322869Smckusick 	    case SKARIF:
96422869Smckusick 	      if (!locallabel(LM) || !locallabel(LZ) || !locallabel(LP))
96522869Smckusick 		{
96622869Smckusick 		  gensetall(sp);
96722869Smckusick 		  globalbranch = YES;
96822869Smckusick 		}
96922869Smckusick 	      regwrite(sp, sp->expr);
97022869Smckusick 	      break;
97122869Smckusick 
97222869Smckusick 	    case SKASGOTO:
97322869Smckusick 	      gensetall(sp);
97422869Smckusick 	      globalbranch = YES;
97522869Smckusick 	      regwrite(sp, sp->expr);
97622869Smckusick 	      break;
97722869Smckusick 
97822869Smckusick 	    case SKCMGOTO:
97922869Smckusick 	      lp = (struct Labelblock **) sp->ctlinfo;
98022869Smckusick 	      for (i = 0; i < sp->label; i++, lp++)
98122869Smckusick 		if (!locallabel((*lp)->labelno))
98222869Smckusick 		  {
98322869Smckusick 		    gensetall(sp);
98422869Smckusick 		    globalbranch = YES;
98522869Smckusick 		    break;
98622869Smckusick 		  }
98722869Smckusick 	      regwrite(sp, sp->expr);
98822869Smckusick 	      break;
98922869Smckusick 
99022869Smckusick 	    case SKIFN:
99122869Smckusick 	    case SKIOIFN:
99222869Smckusick 	      if (!locallabel(sp->label))
99322869Smckusick 		{
99422869Smckusick 		  gensetall(sp);
99522869Smckusick 		  globalbranch = YES;
99622869Smckusick 		}
99722869Smckusick 	      regwrite(sp, sp->expr);
99822869Smckusick 	      break;
99922869Smckusick 
100022869Smckusick 	    case SKNULL:
100122869Smckusick 	    case SKASSIGN:
100222869Smckusick 	      break;
100322869Smckusick 
100422869Smckusick 	    default:
100522869Smckusick 	      badthing ("SKtype","alreg-3",sp->type);
100622869Smckusick 	    }
100722869Smckusick 
100822869Smckusick 	  for (i = toplcv + 1; i <= topregvar; i++)
100922869Smckusick 	    if (regaltered[i])
101022869Smckusick 	      memdefined[i] = NO;
101122869Smckusick 	}
101222869Smckusick 
101322869Smckusick   if (topregvar + 1 > highregvar)
101422869Smckusick     highregvar = topregvar + 1;
101522869Smckusick   dqptr->nregvars = topregvar + 1;
101622869Smckusick   for (i = 0; i <= topregvar; i++)
101722869Smckusick     if (rp = regtab[i])
101822869Smckusick       {
101922869Smckusick 	dqptr->reg[i] = regp = ALLOC(regnode);
102022869Smckusick 	regp->vstg = rp->vstg;
102122869Smckusick 	regp->vtype = rp->vtype;
102222869Smckusick 	regp->memno = rp->memno;
102322869Smckusick 	regp->memoffset = rp->memoffset;
102422869Smckusick 	regp->isarrayarg = rp->isarrayarg;
102522869Smckusick 	frexpr(rp->stgp);
102622869Smckusick 	free((char *) rp);
102722869Smckusick 	regtab[i] = NULL;
102822869Smckusick       }
102922869Smckusick 
103022869Smckusick   while (tabletop >= 0)
103122869Smckusick     free((char *) rt[tabletop--]);
103222869Smckusick   freelabtab();
103322869Smckusick   freevartab();
103422869Smckusick   return;
103522869Smckusick }
103622869Smckusick 
103722869Smckusick 
103822869Smckusick 
103922869Smckusick LOCAL scanvars(p)
104022869Smckusick expptr p;
104122869Smckusick 
104222869Smckusick {
104322869Smckusick   Addrp ap;
104422869Smckusick   ADDRNODE *addrinfo;
104522869Smckusick   VARNODE *varinfo;
104622869Smckusick   chainp args;
104722869Smckusick   VARNODE *q;
104822869Smckusick 
104922869Smckusick   if (p == NULL) return;
105022869Smckusick 
105122869Smckusick   switch (p->tag)
105222869Smckusick     {
105322869Smckusick     case TCONST:
105422869Smckusick       return;
105522869Smckusick 
105622869Smckusick     case TEXPR:
105722869Smckusick       switch (p->exprblock.opcode)
105822869Smckusick 	{
105922869Smckusick 	case OPASSIGN:
106022869Smckusick 	  scanassign(p);
106122869Smckusick 	  return;
106222869Smckusick 
106322869Smckusick 	case OPPLUSEQ:
106422869Smckusick 	case OPSTAREQ:
106522869Smckusick 	  scanopeq(p);
106622869Smckusick 	  return;
106722869Smckusick 
106822869Smckusick 	case OPCALL:
106922869Smckusick 	  scancall(p);
107022869Smckusick 	  return;
107122869Smckusick 
107222869Smckusick 	default:
107322869Smckusick 	  scanvars(p->exprblock.vleng);
107422869Smckusick 	  scanvars(p->exprblock.leftp);
107522869Smckusick 	  scanvars(p->exprblock.rightp);
107622869Smckusick 	  return;
107722869Smckusick 	}
107822869Smckusick 
107922869Smckusick     case TADDR:
108022869Smckusick       ap = (Addrp) p;
108122869Smckusick       scanvars(ap->vleng);
108222869Smckusick       scanvars(ap->memoffset);
108322869Smckusick       if (!ISVAR(ap)) return;
108422869Smckusick 
108522869Smckusick       addrinfo = getaddr(ap);
108622869Smckusick       if (fixedaddress(ap))
108722869Smckusick 	{
108822869Smckusick 	  if (ISREGTYPE(ap->vtype))
108922869Smckusick 	    {
109022869Smckusick 	      varinfo = getvar(addrinfo, ap);
109122869Smckusick 	      varinfo->isused = YES;
109222869Smckusick 	    }
109322869Smckusick 	}
109422869Smckusick       else
109522869Smckusick 	{
109622869Smckusick 	  addrinfo->freeuse = YES;
109722869Smckusick 	  for (q = addrinfo->varlist; q; q = q->link)
109822869Smckusick 	    q->isused = YES;
109922869Smckusick 	}
110022869Smckusick       return;
110122869Smckusick 
110222869Smckusick     case TLIST:
110322869Smckusick       for (args = p->listblock.listp; args; args = args->nextp)
110422869Smckusick 	scanvars(args->datap);
110522869Smckusick       return;
110622869Smckusick 
110722869Smckusick     default:
110822869Smckusick       badtag ("regalloc:scanvars", p->tag);
110922869Smckusick     }
111022869Smckusick }
111122869Smckusick 
111222869Smckusick 
111322869Smckusick 
111422869Smckusick LOCAL scanassign(ep)
111522869Smckusick Exprp ep;
111622869Smckusick 
111722869Smckusick {
111822869Smckusick   Addrp lhs;
111922869Smckusick   VARNODE *varinfo;
112022869Smckusick   ADDRNODE *addrinfo;
112122869Smckusick 
112222869Smckusick   scanvars(ep->rightp);
112322869Smckusick   if (ep->leftp->tag == TADDR)
112422869Smckusick     {
112522869Smckusick       lhs = (Addrp) ep->leftp;
112622869Smckusick       scanvars(lhs->vleng);
112722869Smckusick       scanvars(lhs->memoffset);
112822869Smckusick       if ((lhs->vstg == STGREG) || (lhs->vstg == STGPREG))
112922869Smckusick 	return;
113022869Smckusick       if (ISVAR(lhs))
113122869Smckusick 	{
113222869Smckusick           addrinfo = getaddr(lhs);
113322869Smckusick           addrinfo->isset = YES;
113422869Smckusick           if (fixedaddress(lhs) && ISREGTYPE(lhs->vtype))
113522869Smckusick 	    {
113622869Smckusick 	      varinfo = getvar(addrinfo, lhs);
113722869Smckusick 	      if (addrinfo->freeuse) varinfo->isused = YES;
113822869Smckusick 	      varinfo->isset = YES;
113922869Smckusick 	      if (!addrinfo->freeuse && !varinfo->isused)
114022869Smckusick 	        varinfo->setfirst = YES;
114122869Smckusick 	    }
114222869Smckusick         }
114322869Smckusick     }
114422869Smckusick   else
114522869Smckusick     badtag ("regalloc:scanassign", ep->leftp->tag);
114622869Smckusick }
114722869Smckusick 
114822869Smckusick 
114922869Smckusick 
115022869Smckusick LOCAL scanopeq(ep)
115122869Smckusick Exprp ep;
115222869Smckusick 
115322869Smckusick {
115422869Smckusick   Addrp lhs;
115522869Smckusick   ADDRNODE *addrinfo;
115622869Smckusick   VARNODE *varinfo;
115722869Smckusick 
115822869Smckusick   scanvars(ep->rightp);
115922869Smckusick   if (ep->leftp->tag == TADDR)
116022869Smckusick     {
116122869Smckusick       lhs = (Addrp) ep->leftp;
116222869Smckusick       scanvars(lhs->vleng);
116322869Smckusick       scanvars(lhs->memoffset);
116422869Smckusick       if ((lhs->vstg == STGREG) || (lhs->vstg == STGPREG))
116522869Smckusick 	return;
116622869Smckusick       if (ISVAR(lhs))
116722869Smckusick 	{
116822869Smckusick           addrinfo = getaddr(lhs);
116922869Smckusick           addrinfo->isset = YES;
117022869Smckusick           if (fixedaddress(lhs))
117122869Smckusick 	    {
117222869Smckusick 	      if (ISREGTYPE(lhs->vtype))
117322869Smckusick 	        {
117422869Smckusick 	          varinfo = getvar(addrinfo, lhs);
117522869Smckusick 	          varinfo->isused = YES;
117622869Smckusick 	          varinfo->isset = YES;
117722869Smckusick 	        }
117822869Smckusick 	    }
117922869Smckusick         }
118022869Smckusick       else
118122869Smckusick 	addrinfo->freeuse = YES;
118222869Smckusick     }
118322869Smckusick   else
118422869Smckusick     badtag ("regalloc:scanopeq", ep->leftp->tag);
118522869Smckusick }
118622869Smckusick 
118722869Smckusick 
118822869Smckusick 
118922869Smckusick LOCAL scancall(ep)
119022869Smckusick Exprp ep;
119122869Smckusick 
119222869Smckusick {
119322869Smckusick   Addrp lhs;
119422869Smckusick   chainp args;
119522869Smckusick   Addrp ap;
119622869Smckusick   VARNODE *varinfo;
119722869Smckusick   ADDRNODE *addrinfo;
119822869Smckusick 
119922869Smckusick   lhs = (Addrp) ep->leftp;
120022869Smckusick   scanvars(lhs->vleng);
120122869Smckusick   scanvars(lhs->memoffset);
120222869Smckusick 
120322869Smckusick   if (ep->rightp == NULL) return;
120422869Smckusick 
120522869Smckusick   if (lhs->vstg != STGINTR)
120622869Smckusick     {
120722869Smckusick       args = ep->rightp->listblock.listp;
120822869Smckusick       for (; args; args = args->nextp)
120922869Smckusick 	{
121022869Smckusick 	  if (args->datap->tag == TADDR)
121122869Smckusick 	    {
121222869Smckusick 	      ap = (Addrp) args->datap;
121322869Smckusick 	      scanvars(ap->vleng);
121422869Smckusick 	      scanvars(ap->memoffset);
121522869Smckusick 	      if (!ISVAR(ap)) continue;
121622869Smckusick 
121722869Smckusick 	      addrinfo = getaddr(ap);
121822869Smckusick 	      addrinfo->isset = YES;
1219*25104Sdonn 	      if (fixedaddress(ap) && ISREGTYPE(ap->vtype))
122022869Smckusick 		{
122122869Smckusick 		  varinfo = getvar(addrinfo, ap);
122222869Smckusick 		  if (ap->vstg != STGCONST)
122322869Smckusick 		    varinfo->isset = YES;
122422869Smckusick 		  varinfo->isused = YES;
122522869Smckusick 		}
122622869Smckusick 	      else
122722869Smckusick 		addrinfo->freeuse = YES;
122822869Smckusick 	    }
122922869Smckusick 	  else
123022869Smckusick 	    scanvars(args->datap);
123122869Smckusick 	}
123222869Smckusick     }
123322869Smckusick   else
123422869Smckusick     scanvars(ep->rightp);
123522869Smckusick 
123622869Smckusick   return;
123722869Smckusick }
123822869Smckusick 
123922869Smckusick 
124022869Smckusick 
124122869Smckusick LOCAL int fixedaddress(ap)
124222869Smckusick Addrp ap;
124322869Smckusick 
124422869Smckusick {
124522869Smckusick   if (!ap->memoffset)
124622869Smckusick     return NO;
124722869Smckusick   return (ISCONST(ap->memoffset) && ISINT(ap->memoffset->headblock.vtype));
124822869Smckusick }
124922869Smckusick 
125022869Smckusick 
125122869Smckusick 
125222869Smckusick LOCAL countrefs(p)
125322869Smckusick expptr p;
125422869Smckusick 
125522869Smckusick {
125622869Smckusick   Addrp ap;
125722869Smckusick   ADDRNODE *addrinfo;
125822869Smckusick   VARNODE *varinfo;
125922869Smckusick   VARNODE *vp;
126022869Smckusick   chainp args;
126122869Smckusick 
126222869Smckusick   if (p == NULL) return;
126322869Smckusick 
126422869Smckusick   switch (p->tag)
126522869Smckusick     {
126622869Smckusick     case TCONST:
126722869Smckusick       return;
126822869Smckusick 
126922869Smckusick     case TEXPR:
127022869Smckusick       switch (p->exprblock.opcode)
127122869Smckusick 	{
127222869Smckusick 	case OPCALL:
127322869Smckusick 	  if (p->exprblock.leftp->tag != TADDR)
127422869Smckusick 	    badtag ("regalloc:countrefs", p->exprblock.leftp->tag);
127522869Smckusick 	  countrefs(p->exprblock.leftp->addrblock.vleng);
127622869Smckusick 	  countrefs(p->exprblock.leftp->addrblock.memoffset);
127722869Smckusick 
127822869Smckusick 	  if (p->exprblock.leftp->addrblock.vstg != STGINTR)
127922869Smckusick 	    {
128022869Smckusick 	      if (!commonunusable)
128122869Smckusick 		if (linearcode)
128222869Smckusick 		  setcommon();
128322869Smckusick 	        else
128422869Smckusick 		  commonunusable = YES;
128522869Smckusick 	      if (p->exprblock.rightp == NULL) return;
128622869Smckusick 	      args = p->exprblock.rightp->listblock.listp;
128722869Smckusick 	      for (; args; args = args->nextp)
128822869Smckusick 		if (args->datap->tag == TADDR)
128922869Smckusick 		  {
129022869Smckusick 		    ap = (Addrp) args->datap;
129122869Smckusick 		    countrefs(ap->vleng);
129222869Smckusick 		    countrefs(ap->memoffset);
129322869Smckusick 		    if (!ISVAR(ap) || ap->vstg == STGCONST) continue;
129422869Smckusick 		    addrinfo = lookupaddr(ap->vstg, ap->memno);
129522869Smckusick 		    if (ap->vstg == STGARG)
129622869Smckusick 		      addrinfo->refs++;
129722869Smckusick 		    for (vp = addrinfo->varlist; vp; vp = vp->link)
129822869Smckusick 		      if (linearcode)
129922869Smckusick 		        if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
130022869Smckusick 			  if (addrinfo->istemp)
130122869Smckusick 			    vp->refs--;
130222869Smckusick 			  else
130322869Smckusick 			    {
130422869Smckusick 			      vp->refs -= 2;
130522869Smckusick 			      insertset(ap->vstg, ap->memno, vp->memoffset);
130622869Smckusick 			    }
130722869Smckusick 		        else
130822869Smckusick 			  vp->refs--;
130922869Smckusick 		      else
131022869Smckusick 			{
131122869Smckusick 			  if (!addrinfo->istemp)
131222869Smckusick 			    vp->unusable = YES;
131322869Smckusick 			}
131422869Smckusick 		  }
131522869Smckusick 		else
131622869Smckusick 		  countrefs(args->datap);
131722869Smckusick             }
131822869Smckusick 	  else
131922869Smckusick 	    {
132022869Smckusick 	      if (p->exprblock.rightp == NULL) return;
132122869Smckusick 	      args = p->exprblock.rightp->listblock.listp;
132222869Smckusick 	      for (; args; args = args->nextp)
132322869Smckusick 		if (args->datap->tag == TADDR)
132422869Smckusick 		  {
132522869Smckusick 		    ap = (Addrp) args->datap;
132622869Smckusick 		    countrefs(ap->vleng);
132722869Smckusick 		    countrefs(ap->memoffset);
132822869Smckusick 		    if (!ISVAR(ap) || ap->vstg == STGCONST) continue;
132922869Smckusick 		    addrinfo = lookupaddr(ap->vstg, ap->memno);
133022869Smckusick 		    addrinfo->refs++;
133122869Smckusick 		    for (vp = addrinfo->varlist; vp; vp = vp->link)
133222869Smckusick 		      if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
133322869Smckusick 			{
133422869Smckusick 			  vp->refs--;
133522869Smckusick 			  insertset(ap->vstg, ap->memno, vp->memoffset);
133622869Smckusick 			}
133722869Smckusick 		  }
133822869Smckusick 		else
133922869Smckusick 		  countrefs(args->datap);
134022869Smckusick 	    }
134122869Smckusick 	  return;
134222869Smckusick 
134322869Smckusick 	case OPASSIGN:
134422869Smckusick 	case OPPLUSEQ:
134522869Smckusick 	case OPSTAREQ:
134622869Smckusick 	  countrefs(p->exprblock.vleng);
134722869Smckusick 	  countrefs(p->exprblock.rightp);
134822869Smckusick 	  ap = (Addrp) p->exprblock.leftp;
134922869Smckusick 	  if (fixedaddress(ap))
135022869Smckusick 	    if (globalbranch)
135122869Smckusick 	      {
135222869Smckusick 		countrefs(ap->vleng);
135322869Smckusick 		countrefs(ap->memoffset);
135422869Smckusick 	      }
135522869Smckusick 	    else
135622869Smckusick 	      countrefs(ap);
135722869Smckusick 	  else if (linearcode)
135822869Smckusick 	    {
135922869Smckusick 	      countrefs(ap);
136022869Smckusick 	      for (vp = lookupaddr(ap->vstg, ap->memno)->varlist;
136122869Smckusick 		   vp;
136222869Smckusick 		   vp = vp->link)
136322869Smckusick 		vp->refs--;
136422869Smckusick 	    }
136522869Smckusick 	  else
136622869Smckusick 	    {
136722869Smckusick 	      countrefs(ap);
136822869Smckusick 	      for (vp = lookupaddr(ap->vstg, ap->memno)->varlist;
136922869Smckusick 		   vp;
137022869Smckusick 		   vp = vp->link)
137122869Smckusick 		vp->unusable = YES;
137222869Smckusick 	    }
137322869Smckusick 	  return;
137422869Smckusick 
137522869Smckusick 	default:
137622869Smckusick 	  countrefs(p->exprblock.vleng);
137722869Smckusick 	  countrefs(p->exprblock.leftp);
137822869Smckusick 	  countrefs(p->exprblock.rightp);
137922869Smckusick 	  return;
138022869Smckusick 	}
138122869Smckusick 
138222869Smckusick     case TADDR:
138322869Smckusick       ap = (Addrp) p;
138422869Smckusick       countrefs(ap->vleng);
138522869Smckusick       countrefs(ap->memoffset);
138622869Smckusick       if (!ISVAR(ap)) return;
138722869Smckusick 
138822869Smckusick       addrinfo = lookupaddr(ap->vstg, ap->memno);
138922869Smckusick       if (ap->vstg == STGARG)
139022869Smckusick 	addrinfo->refs++;
139122869Smckusick 
139222869Smckusick       if (fixedaddress(ap))
139322869Smckusick 	{
139422869Smckusick 	  if (ISREGTYPE(ap->vtype))
139522869Smckusick 	    {
139622869Smckusick 	      varinfo = lookupvar(addrinfo, ap->memoffset->constblock.const.ci);
139722869Smckusick 	      varinfo->refs++;
139822869Smckusick 	    }
139922869Smckusick 	}
140022869Smckusick       else
140122869Smckusick 	for (vp = addrinfo->varlist; vp; vp = vp->link)
140222869Smckusick 	  if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
140322869Smckusick 	    {
140422869Smckusick 	      vp->refs--;
140522869Smckusick 	      insertset(ap->vstg, ap->memno, vp->memoffset);
140622869Smckusick 	    }
140722869Smckusick       return;
140822869Smckusick 
140922869Smckusick     case TLIST:
141022869Smckusick       args = p->listblock.listp;
141122869Smckusick       for (; args; args = args->nextp)
141222869Smckusick 	countrefs(args->datap);
141322869Smckusick       return;
141422869Smckusick 
141522869Smckusick     default:
141622869Smckusick       badtag ("regalloc:countrefs", p->tag);
141722869Smckusick     }
141822869Smckusick }
141922869Smckusick 
142022869Smckusick 
142122869Smckusick 
142222869Smckusick LOCAL regwrite(sp, p)
142322869Smckusick Slotp sp;
142422869Smckusick expptr p;
142522869Smckusick 
142622869Smckusick {
142722869Smckusick   register int i;
142822869Smckusick   REGDATA *rp;
142922869Smckusick   chainp args;
143022869Smckusick   Addrp ap, ap1;
143122869Smckusick   int memoffset;
143222869Smckusick 
143322869Smckusick   if (p == NULL) return;
143422869Smckusick 
143522869Smckusick   switch (p->tag)
143622869Smckusick     {
143722869Smckusick     case TCONST:
143822869Smckusick       return;
143922869Smckusick 
144022869Smckusick     case TEXPR:
144122869Smckusick       switch (p->exprblock.opcode)
144222869Smckusick 	{
144322869Smckusick 	case OPCALL:
144422869Smckusick 	  ap = (Addrp) p->exprblock.leftp;
144522869Smckusick 	  regwrite(sp, ap->vleng);
144622869Smckusick 	  regwrite(sp, ap->memoffset);
144722869Smckusick 	  if (ap->vstg != STGINTR)
144822869Smckusick 	    {
144922869Smckusick 	      if (linearcode)
145022869Smckusick 		{
145122869Smckusick 		  gensetcommon(sp);
145222869Smckusick 		  for (i = toplcv + 1; i <= topregvar; i++)
145322869Smckusick 		    if ((rp = regtab[i]) && (rp->vstg == STGCOMMON))
145422869Smckusick 		      regdefined[i] = NO;
145522869Smckusick 		}
145622869Smckusick 	      if (p->exprblock.rightp == NULL) return;
145722869Smckusick 	      args = p->exprblock.rightp->listblock.listp;
145822869Smckusick 	      for (; args; args = args->nextp)
145922869Smckusick 		if (args->datap->tag == TADDR)
146022869Smckusick 		  {
146122869Smckusick 		    ap = (Addrp) args->datap;
146222869Smckusick 		    regwrite(sp, ap->vleng);
146322869Smckusick 		    regwrite(sp, ap->memoffset);
146422869Smckusick 		    for (i = toplcv + 1; i <= topregvar; i++)
146522869Smckusick 		      if ((rp = regtab[i]) &&
146622869Smckusick 			  !rp->isarrayarg &&
146722869Smckusick 			  !rp->istemp &&
146822869Smckusick 			  (rp->vstg == ap->vstg) &&
146922869Smckusick 			  (rp->memno == ap->memno))
147022869Smckusick 			{
147122869Smckusick 			  regdefined[i] = NO;
147222869Smckusick 			  if (!memdefined[i])
147322869Smckusick 			    {
147422869Smckusick 			      ap1 = (Addrp) cpexpr(rp->stgp);
147522869Smckusick 			      changetoreg(ap1, i);
147622869Smckusick 			      insertassign(sp, cpexpr(rp->stgp), ap1);
147722869Smckusick 			      memdefined[i] = YES;
147822869Smckusick 			    }
147922869Smckusick 			}
148022869Smckusick 		      else if (rp->isarrayarg &&
148122869Smckusick 			       (ap->vstg == STGARG) &&
148222869Smckusick 			       (ap->memno == rp->memno))
148322869Smckusick 			{
148422869Smckusick 			  ap->vstg = STGPREG;
148522869Smckusick 			  ap->memno = regnum[i];
148622869Smckusick 			}
148722869Smckusick 		  }
148822869Smckusick 		else
148922869Smckusick 		  regwrite(sp, args->datap);
149022869Smckusick 	    }
149122869Smckusick 	  else
149222869Smckusick 	    {
149322869Smckusick 	      if (p->exprblock.rightp == NULL) return;
149422869Smckusick 	      args = p->exprblock.rightp->listblock.listp;
149522869Smckusick 	      for (; args; args = args->nextp)
149622869Smckusick 		if (args->datap->tag == TADDR)
149722869Smckusick 		  {
149822869Smckusick 		    ap = (Addrp) args->datap;
149922869Smckusick 		    regwrite(sp, ap->vleng);
150022869Smckusick 		    regwrite(sp, ap->memoffset);
150122869Smckusick 		    for (i = toplcv + 1; i <= topregvar; i++)
150222869Smckusick 		      if ((rp = regtab[i]) &&
150322869Smckusick 			  !rp->isarrayarg &&
150422869Smckusick 			  !rp->istemp &&
150522869Smckusick 			  (rp->vstg == ap->vstg) &&
150622869Smckusick 			  (rp->memno == ap->memno) &&
150722869Smckusick 			  !memdefined[i])
150822869Smckusick 			{
150922869Smckusick 			  ap1 = (Addrp) cpexpr(rp->stgp);
151022869Smckusick 			  changetoreg(ap1, i);
151122869Smckusick 			  insertassign(sp, cpexpr(rp->stgp), ap1);
151222869Smckusick 			  memdefined[i] = YES;
151322869Smckusick 			}
151422869Smckusick 		      else if (rp->isarrayarg &&
151522869Smckusick 			       (ap->vstg == STGARG) &&
151622869Smckusick 			       (rp->memno == ap->memno))
151722869Smckusick 			{
151822869Smckusick 			  ap->vstg = STGPREG;
151922869Smckusick 			  ap->memno = regnum[i];
152022869Smckusick 			}
152122869Smckusick 		  }
152222869Smckusick 		else
152322869Smckusick 		  {
152422869Smckusick 		    regwrite(sp, args->datap);
152522869Smckusick 		  }
152622869Smckusick 	    }
152722869Smckusick 	  return;
152822869Smckusick 
152922869Smckusick 	case OPASSIGN:
153022869Smckusick 	case OPPLUSEQ:
153122869Smckusick 	case OPSTAREQ:
153222869Smckusick 	  regwrite(sp, p->exprblock.vleng);
153322869Smckusick 	  regwrite(sp, p->exprblock.rightp);
153422869Smckusick 	  ap = (Addrp) p->exprblock.leftp;
153522869Smckusick 	  regwrite(sp, ap->vleng);
153622869Smckusick 	  regwrite(sp, ap->memoffset);
153722869Smckusick 
153822869Smckusick 	  if (ap->vstg == STGARG)
153922869Smckusick 	    for (i = toplcv + 1; i<=topregvar; i++)
154022869Smckusick 	      if ((rp = regtab[i]) &&
154122869Smckusick 		  rp->isarrayarg &&
154222869Smckusick 		  (rp->memno == ap->memno))
154322869Smckusick 		{
154422869Smckusick 		  ap->vstg = STGPREG;
154522869Smckusick 		  ap->memno = regnum[i];
154622869Smckusick 		  return;
154722869Smckusick 		}
154822869Smckusick 
154922869Smckusick 	  if (fixedaddress(ap))
155022869Smckusick 	    {
155122869Smckusick 	      memoffset = ap->memoffset->constblock.const.ci;
155222869Smckusick 	      for (i = toplcv + 1; i <= topregvar; i++)
155322869Smckusick 		if ((rp = regtab[i]) &&
155422869Smckusick 		    !rp->isarrayarg &&
155522869Smckusick 		    (rp->vstg == ap->vstg) &&
155622869Smckusick 		    (rp->memno == ap->memno) &&
155722869Smckusick 		    (rp->memoffset == memoffset))
155822869Smckusick 		  {
155922869Smckusick 		    changetoreg(ap, i);
156022869Smckusick 		    if (globalbranch)
156122869Smckusick 		      {
156222869Smckusick 			p->exprblock.rightp = (expptr) cpexpr(p);
156322869Smckusick 			p->exprblock.leftp = (expptr) cpexpr(rp->stgp);
156422869Smckusick 			p->exprblock.opcode = OPASSIGN;
156522869Smckusick 			memdefined[i] = YES;
156622869Smckusick 		      }
156722869Smckusick 		    else
156822869Smckusick 		      {
156922869Smckusick 			regaltered[i] = YES;
157022869Smckusick 			regdefined[i] = YES;
157122869Smckusick 		      }
157222869Smckusick 		  }
157322869Smckusick 	      return;
157422869Smckusick 	    }
157522869Smckusick 
157622869Smckusick 	  if (linearcode)
157722869Smckusick 	    for (i = toplcv + 1; i <= topregvar; i++)
157822869Smckusick 	      if ((rp = regtab[i]) &&
157922869Smckusick 		  !rp->isarrayarg &&
158022869Smckusick 		  (rp->vstg == ap->vstg) &&
158122869Smckusick 		  (rp->memno == ap->memno))
158222869Smckusick 		regdefined[i] = NO;
158322869Smckusick 	  return;
158422869Smckusick 
158522869Smckusick 	default:
158622869Smckusick 	  regwrite(sp, p->exprblock.vleng);
158722869Smckusick 	  regwrite(sp, p->exprblock.leftp);
158822869Smckusick 	  regwrite(sp, p->exprblock.rightp);
158922869Smckusick 	  return;
159022869Smckusick 	}
159122869Smckusick 
159222869Smckusick     case TADDR:
159322869Smckusick       ap = (Addrp) p;
159422869Smckusick       regwrite(sp, ap->vleng);
159522869Smckusick       regwrite(sp, ap->memoffset);
159622869Smckusick 
159722869Smckusick       if (ap->vstg == STGARG)
159822869Smckusick 	for (i = toplcv + 1; i <= topregvar; i++)
159922869Smckusick 	  if ((rp = regtab[i]) &&
160022869Smckusick 	      rp->isarrayarg &&
160122869Smckusick 	      (rp->memno == ap->memno))
160222869Smckusick 	    {
160322869Smckusick 	      ap->vstg = STGPREG;
160422869Smckusick 	      ap->memno = regnum[i];
160522869Smckusick 	      return;
160622869Smckusick 	    }
160722869Smckusick 
160822869Smckusick       if (fixedaddress(ap))
160922869Smckusick 	{
161022869Smckusick           memoffset = ap->memoffset->constblock.const.ci;
161122869Smckusick 	  for (i = toplcv + 1; i <= topregvar; i++)
161222869Smckusick 	    if ((rp = regtab[i]) &&
161322869Smckusick 		!rp->isarrayarg &&
161422869Smckusick 		(rp->vstg == ap->vstg) &&
161522869Smckusick 		(rp->memno == ap->memno) &&
161622869Smckusick 		(rp->memoffset == memoffset))
161722869Smckusick 	      {
161822869Smckusick 		changetoreg(ap, i);
161922869Smckusick 		return;
162022869Smckusick 	      }
162122869Smckusick 	}
162222869Smckusick       else
162322869Smckusick 	{
162422869Smckusick 	  for (i = toplcv + 1; i <= topregvar; i++)
162522869Smckusick 	    if ((rp = regtab[i]) &&
162622869Smckusick 		!rp->isarrayarg &&
162722869Smckusick 		(rp->vstg == ap->vstg) &&
162822869Smckusick 		(rp->memno == ap->memno) &&
162922869Smckusick 		!memdefined[i])
163022869Smckusick 	      {
163122869Smckusick 		ap1 = (Addrp) cpexpr(rp->stgp);
163222869Smckusick 		changetoreg(ap1, i);
163322869Smckusick 		insertassign(sp, cpexpr(rp->stgp), ap1);
163422869Smckusick 		memdefined[i] = YES;
163522869Smckusick 	      }
163622869Smckusick 	}
163722869Smckusick       return;
163822869Smckusick 
163922869Smckusick     case TLIST:
164022869Smckusick       for (args = p->listblock.listp; args; args = args->nextp)
164122869Smckusick 	regwrite(sp, args->datap);
164222869Smckusick       return;
164322869Smckusick 
164422869Smckusick     default:
164522869Smckusick       badtag ("regalloc:regwrite", p->tag);
164622869Smckusick     }
164722869Smckusick }
164822869Smckusick 
164922869Smckusick 
165022869Smckusick 
165122869Smckusick LOCAL setcommon()
165222869Smckusick 
165322869Smckusick {
165422869Smckusick   ADDRNODE *ap;
165522869Smckusick   VARNODE *vp;
165622869Smckusick 
165722869Smckusick   for (ap = commonvars; ap; ap = ap->commonlink)
165822869Smckusick     for (vp = ap->varlist; vp; vp = vp->link)
165922869Smckusick       if (!insetlist(ap->vstg, ap->memno, vp->memoffset))
166022869Smckusick 	{
166122869Smckusick 	  vp->refs -= 2;
166222869Smckusick 	  insertset(ap->vstg, ap->memno, vp->memoffset);
166322869Smckusick 	}
166422869Smckusick       else
166522869Smckusick 	vp->refs--;
166622869Smckusick 
166722869Smckusick   return;
166822869Smckusick }
166922869Smckusick 
167022869Smckusick 
167122869Smckusick 
167222869Smckusick LOCAL setall()
167322869Smckusick 
167422869Smckusick {
167522869Smckusick   register int i;
167622869Smckusick   register ADDRNODE *p;
167722869Smckusick   register VARNODE *q;
167822869Smckusick 
167922869Smckusick   for (i = 0; i < VARTABSIZE; i++)
168022869Smckusick     for (p = vartable[i]; p; p = p->link)
168122869Smckusick       if (p->istemp || !p->isset)
168222869Smckusick 	break;
168322869Smckusick       else
168422869Smckusick 	for (q = p->varlist; q; q = q->link)
168522869Smckusick 	  if (q->isset && !insetlist(p->vstg, p->memno, q->memoffset))
168622869Smckusick 	    q->refs--;
168722869Smckusick 
168822869Smckusick   allset = YES;
168922869Smckusick   return;
169022869Smckusick }
169122869Smckusick 
169222869Smckusick 
169322869Smckusick 
169422869Smckusick LOCAL int samevar(r1, r2)
169522869Smckusick register REGDATA *r1;
169622869Smckusick register REGNODE *r2;
169722869Smckusick 
169822869Smckusick {
169922869Smckusick   if ((r1->vstg != r2->vstg) ||
170022869Smckusick       (r1->memno != r2->memno) ||
170122869Smckusick       (r1->isarrayarg != r2->isarrayarg))
170222869Smckusick     return NO;
170322869Smckusick   if (r1->isarrayarg)
170422869Smckusick     return YES;
170522869Smckusick   return (r1->memoffset == r2->memoffset);
170622869Smckusick }
170722869Smckusick 
170822869Smckusick 
170922869Smckusick 
171022869Smckusick LOCAL entableaddr(p)
171122869Smckusick ADDRNODE *p;
171222869Smckusick 
171322869Smckusick {
171422869Smckusick   int refs;
171522869Smckusick   Addrp ap;
171622869Smckusick   register int i;
171722869Smckusick 
171822869Smckusick   if (p->vstg != STGARG)
171922869Smckusick     {
172022869Smckusick       currentaddr = p;
172122869Smckusick       return;
172222869Smckusick     }
172322869Smckusick 
172422869Smckusick   refs = p->refs;
172522869Smckusick   if (refs <= 0) return;
172622869Smckusick 
172722869Smckusick   if (tabletop < 0)
172822869Smckusick     tabletop = i = 0;
172922869Smckusick   else if (refs > rt[tabletop]->refs)
173022869Smckusick     {
173122869Smckusick       if (tabletop + 1 < TABLELIMIT)
173222869Smckusick 	tabletop++;
173322869Smckusick       else
173422869Smckusick 	{
173522869Smckusick 	  frexpr(rt[tabletop]->stgp);
173622869Smckusick 	  free((char *) rt[tabletop]);
173722869Smckusick 	}
173822869Smckusick 
173922869Smckusick       for (i = tabletop; i > 0; i--)
174022869Smckusick 	if (refs > rt[i - 1]->refs)
174122869Smckusick 	  rt[i] = rt[i - 1];
174222869Smckusick 	else
174322869Smckusick 	  break;
174422869Smckusick     }
174522869Smckusick   else if (tabletop + 1 < TABLELIMIT)
174622869Smckusick     i = ++tabletop;
174722869Smckusick   else
174822869Smckusick     return;
174922869Smckusick 
175022869Smckusick   rt[i] = ALLOC(regdata);
175122869Smckusick   rt[i]->vstg = p->vstg;
175222869Smckusick   rt[i]->vtype = p->vtype;
175322869Smckusick   rt[i]->memno = p->memno;
175422869Smckusick   rt[i]->refs = refs;
175522869Smckusick   rt[i]->isarrayarg = YES;
175622869Smckusick 
175722869Smckusick   return;
175822869Smckusick }
175922869Smckusick 
176022869Smckusick 
176122869Smckusick 
176222869Smckusick 
176322869Smckusick LOCAL entablevar(p)
176422869Smckusick VARNODE *p;
176522869Smckusick 
176622869Smckusick {
176722869Smckusick   int refs;
176822869Smckusick   register int i;
176922869Smckusick 
177022869Smckusick   if (p->unusable) return;
177122869Smckusick   refs = p->refs - loopcost;
177222869Smckusick   if (refs <= 0) return;
177322869Smckusick 
177422869Smckusick   if (tabletop < 0)
177522869Smckusick     tabletop = i = 0;
177622869Smckusick   else if (refs > rt[tabletop]->refs)
177722869Smckusick     {
177822869Smckusick       if (tabletop + 1 < TABLELIMIT)
177922869Smckusick         tabletop++;
178022869Smckusick       else
178122869Smckusick 	{
178222869Smckusick 	  frexpr(rt[tabletop]->stgp);
178322869Smckusick           free((char *) rt[tabletop]);
178422869Smckusick 	}
178522869Smckusick 
178622869Smckusick       for (i = tabletop; i > 0; i--)
178722869Smckusick         if (refs > rt[i - 1]->refs)
178822869Smckusick           rt[i] = rt[i - 1];
178922869Smckusick         else
179022869Smckusick           break;
179122869Smckusick     }
179222869Smckusick   else if (tabletop + 1 < TABLELIMIT)
179322869Smckusick     i = ++tabletop;
179422869Smckusick   else
179522869Smckusick     return;
179622869Smckusick 
179722869Smckusick   rt[i] = ALLOC(regdata);
179822869Smckusick   rt[i]->vstg = currentaddr->vstg;
179922869Smckusick   rt[i]->vtype = currentaddr->vtype;
180022869Smckusick   rt[i]->memno = currentaddr->memno;
180122869Smckusick   rt[i]->memoffset = p->memoffset;
180222869Smckusick   rt[i]->refs = refs;
180322869Smckusick   rt[i]->stgp = (Addrp) cpexpr(p->stgp);
180422869Smckusick   rt[i]->isarrayarg = NO;
180522869Smckusick   rt[i]->istemp = currentaddr->istemp;
180622869Smckusick   rt[i]->isset = p->isset;
180722869Smckusick   rt[i]->setfirst = p->setfirst;
180822869Smckusick 
180922869Smckusick   return;
181022869Smckusick }
181122869Smckusick 
181222869Smckusick 
181322869Smckusick 
181422869Smckusick LOCAL int inregtab(p)
181522869Smckusick register REGDATA *p;
181622869Smckusick 
181722869Smckusick {
181822869Smckusick   register REGDATA *rp;
181922869Smckusick   register int i;
182022869Smckusick 
182122869Smckusick   for (i = 0; i <= topregvar; i++)
182222869Smckusick     if (rp = regtab[i])
182322869Smckusick       if ((rp->vstg == p->vstg) &&
182422869Smckusick 	  (rp->memno == p->memno) &&
182522869Smckusick 	  (rp->isarrayarg == p->isarrayarg))
182622869Smckusick 	if (rp->isarrayarg)
182722869Smckusick           return YES;
182822869Smckusick         else if (rp->memoffset == p->memoffset)
182922869Smckusick           return YES;
183022869Smckusick 
183122869Smckusick   return NO;
183222869Smckusick }
183322869Smckusick 
183422869Smckusick 
183522869Smckusick 
183622869Smckusick LOCAL changetoreg(ap, i)
183722869Smckusick register Addrp ap;
183822869Smckusick int i;
183922869Smckusick 
184022869Smckusick {
184122869Smckusick   ap->vstg = STGREG;
184222869Smckusick   ap->memno = regnum[i];
184322869Smckusick   frexpr(ap->memoffset);
184422869Smckusick   ap->memoffset = ICON(0);
184525047Sbloom #if FAMILY == PCC && SZSHORT < SZINT
184625047Sbloom   /*
184725047Sbloom    * Handle PCC bogosity that values in registers must be at least INT width.
184825047Sbloom    */
184925047Sbloom   if (ap->vtype == TYSHORT)
185025047Sbloom     ap->vtype = TYINT;
185125047Sbloom #endif
185222869Smckusick   ap->istemp = NO;
185322869Smckusick   return;
185422869Smckusick }
185522869Smckusick 
185622869Smckusick 
185722869Smckusick 
185822869Smckusick LOCAL insertassign(sp, dest, src)
185922869Smckusick Slotp sp;
186022869Smckusick Addrp dest;
186122869Smckusick expptr src;
186222869Smckusick 
186322869Smckusick {
186422869Smckusick   Slotp newslot;
186522869Smckusick   expptr p;
186622869Smckusick 
186722869Smckusick   p = mkexpr(OPASSIGN, dest, src);
186822869Smckusick   newslot = optinsert (SKEQ,p,0,0,sp);
186922869Smckusick 
187022869Smckusick   if (sp == dohead)
187122869Smckusick     if (!newcode)
187222869Smckusick       newcode = newslot;
187322869Smckusick 
187422869Smckusick   return;
187522869Smckusick }
187622869Smckusick 
187722869Smckusick 
187822869Smckusick LOCAL appendassign(sp, dest, src)
187922869Smckusick Slotp sp;
188022869Smckusick Addrp dest;
188122869Smckusick expptr src;
188222869Smckusick 
188322869Smckusick {
188422869Smckusick   Slotp newslot;
188522869Smckusick   expptr p;
188622869Smckusick 
188722869Smckusick   if (!sp)
188822869Smckusick     fatal ("regalloc:appendassign");
188922869Smckusick 
189022869Smckusick   p = mkexpr(OPASSIGN, dest, src);
189122869Smckusick   newslot = optinsert (SKEQ,p,0,0,sp->next);
189222869Smckusick 
189322869Smckusick   return;
189422869Smckusick }
189522869Smckusick 
189622869Smckusick 
189722869Smckusick 
189822869Smckusick LOCAL int regtomem(sp)
189922869Smckusick Slotp sp;
190022869Smckusick 
190122869Smckusick {
190222869Smckusick   expptr p, l, r;
190322869Smckusick   int i;
190422869Smckusick 
190522869Smckusick   if (sp->type != SKEQ) return NO;
190622869Smckusick 
190722869Smckusick   p = sp->expr;
190822869Smckusick   if ((p->tag != TEXPR) || (p->exprblock.opcode != OPASSIGN))
190922869Smckusick     return NO;
191022869Smckusick 
191122869Smckusick   r = p->exprblock.rightp;
191222869Smckusick   if ((r->tag != TADDR) || (r->addrblock.vstg != STGREG))
191322869Smckusick     return NO;
191422869Smckusick 
191522869Smckusick   l = p->exprblock.leftp;
191622869Smckusick   if (l->tag != TADDR)
191722869Smckusick     return NO;
191822869Smckusick   i = r->addrblock.memno;
191922869Smckusick   if (regtab[i] &&
192022869Smckusick       (l->addrblock.vstg == regtab[i]->vstg) &&
192122869Smckusick       (l->addrblock.memno == regtab[i]->memno) &&
192222869Smckusick       fixedaddress(l) &&
192322869Smckusick       (l->addrblock.memoffset->constblock.const.ci == regtab[i]->memoffset))
192422869Smckusick     return YES;
192522869Smckusick 
192622869Smckusick   return NO;
192722869Smckusick }
192822869Smckusick 
192922869Smckusick 
193022869Smckusick 
193122869Smckusick LOCAL int regtoreg(sp)
193222869Smckusick Slotp sp;
193322869Smckusick 
193422869Smckusick {
193522869Smckusick   expptr p, l, r;
193622869Smckusick 
193722869Smckusick   if (sp->type != SKEQ) return NO;
193822869Smckusick 
193922869Smckusick   p = sp->expr;
194022869Smckusick   if ((p->tag != TEXPR) || (p->exprblock.opcode != OPASSIGN))
194122869Smckusick     return NO;
194222869Smckusick 
194322869Smckusick   l = p->exprblock.leftp;
194422869Smckusick   if ((l->tag != TADDR) || (l->addrblock.vstg != STGREG))
194522869Smckusick     return NO;
194622869Smckusick 
194722869Smckusick   r = p->exprblock.rightp;
194822869Smckusick   if ((r->tag == TADDR) &&
194922869Smckusick       (r->addrblock.vstg == STGREG) &&
195022869Smckusick       (r->addrblock.memno == l->addrblock.memno))
195122869Smckusick     return YES;
195222869Smckusick 
195322869Smckusick   return NO;
195422869Smckusick }
195522869Smckusick 
195622869Smckusick 
195722869Smckusick 
195822869Smckusick LOCAL deleteslot(sp)
195922869Smckusick Slotp sp;
196022869Smckusick 
196122869Smckusick {
196222869Smckusick   if (newcode == sp)
196322869Smckusick     {
196422869Smckusick       newcode = sp->next;
196522869Smckusick       if (newcode == dohead)
196622869Smckusick 	newcode = NULL;
196722869Smckusick     }
196822869Smckusick 
196922869Smckusick   delslot (sp);
197022869Smckusick   return;
197122869Smckusick }
197222869Smckusick 
197322869Smckusick 
197422869Smckusick 
197522869Smckusick LOCAL gensetall(sp)
197622869Smckusick Slotp sp;
197722869Smckusick 
197822869Smckusick {
197922869Smckusick   register int i;
198022869Smckusick   register REGDATA *rp;
198122869Smckusick   register Addrp ap;
198222869Smckusick 
198322869Smckusick   for (i = toplcv + 1; i <= topregvar; i++)
198422869Smckusick     if (rp = regtab[i])
198522869Smckusick       if (rp->isset && !(rp->istemp || rp->isarrayarg))
198622869Smckusick 	if (!memdefined[i])
198722869Smckusick 	  {
198822869Smckusick 	    ap = (Addrp) cpexpr(rp->stgp);
198922869Smckusick 	    changetoreg(ap, i);
199022869Smckusick 	    insertassign(sp, cpexpr(rp->stgp), ap);
199122869Smckusick 	    memdefined[i] = YES;
199222869Smckusick 	  }
199322869Smckusick 
199422869Smckusick   return;
199522869Smckusick }
199622869Smckusick 
199722869Smckusick 
199822869Smckusick LOCAL gensetcommon(sp)
199922869Smckusick Slotp sp;
200022869Smckusick 
200122869Smckusick {
200222869Smckusick   register int i;
200322869Smckusick   register REGDATA *rp;
200422869Smckusick   register Addrp ap;
200522869Smckusick 
200622869Smckusick   for (i = toplcv + 1; i <= topregvar; i++)
200722869Smckusick     if (rp = regtab[i])
200822869Smckusick       if ((rp->vstg == STGCOMMON) && !rp->isarrayarg)
200922869Smckusick 	if (!memdefined[i])
201022869Smckusick 	  {
201122869Smckusick 	    ap = (Addrp) cpexpr(rp->stgp);
201222869Smckusick 	    changetoreg(ap, i);
201322869Smckusick 	    insertassign(sp, cpexpr(rp->stgp), ap);
201422869Smckusick 	    memdefined[i] = YES;
201522869Smckusick 	  }
201622869Smckusick 
201722869Smckusick   return;
201822869Smckusick }
201922869Smckusick 
202022869Smckusick 
202122869Smckusick LOCAL gensetreturn(sp)
202222869Smckusick Slotp sp;
202322869Smckusick 
202422869Smckusick {
202522869Smckusick   register int i;
202622869Smckusick   register REGDATA *rp;
202722869Smckusick   register Addrp ap;
202822869Smckusick 
202922869Smckusick   for (i = toplcv + 1; i <= topregvar; i++)
203022869Smckusick     if (rp = regtab[i])
203122869Smckusick       if (((rp->vstg == STGCOMMON) && !rp->isarrayarg)
203222869Smckusick       || (rp->isset && (saveall || rp->stgp->issaved) && !(rp->istemp || rp->isarrayarg)))
203322869Smckusick 	if (!memdefined[i])
203422869Smckusick 	  {
203522869Smckusick 	    ap = (Addrp) cpexpr(rp->stgp);
203622869Smckusick 	    changetoreg(ap, i);
203722869Smckusick 	    insertassign(sp, cpexpr(rp->stgp), ap);
203822869Smckusick 	    memdefined[i] = YES;
203922869Smckusick 	  }
204022869Smckusick 
204122869Smckusick   return;
204222869Smckusick }
204322869Smckusick 
204422869Smckusick 
204522869Smckusick 
204622869Smckusick LOCAL clearmems()
204722869Smckusick 
204822869Smckusick {
204922869Smckusick   REGDATA *rp;
205022869Smckusick   register int i;
205122869Smckusick 
205222869Smckusick   for (i = 0; i <= toplcv; i++)
205322869Smckusick     memdefined[i] = YES;
205422869Smckusick   for (; i <= topregvar; i++)
205522869Smckusick     if ((rp = regtab[i]) && rp->isset)
205622869Smckusick       memdefined[i] = NO;
205722869Smckusick     else
205822869Smckusick       memdefined[i] = YES;
205922869Smckusick   return;
206022869Smckusick }
206122869Smckusick 
206222869Smckusick 
206322869Smckusick LOCAL setregs()
206422869Smckusick 
206522869Smckusick {
206622869Smckusick   register int i;
206722869Smckusick 
206822869Smckusick   for (i = 0; i <= topregvar; i++)
206922869Smckusick     regdefined[i] = YES;
207022869Smckusick   return;
207122869Smckusick }
207222869Smckusick 
207322869Smckusick 
207422869Smckusick 
207522869Smckusick regalloc()
207622869Smckusick 
207722869Smckusick {
207822869Smckusick int	match;
207922869Smckusick Slotp	nextslot;
208022869Smckusick Slotp	sl1,sl2;
208122869Smckusick Slotp	lastlabslot;
208222869Smckusick 
208322869Smckusick if (! optimflag) return;
208422869Smckusick 
208522869Smckusick lastlabslot = NULL;
208622869Smckusick for (sl1 = firstslot; sl1; sl1 = nextslot)
208722869Smckusick 	{
208822869Smckusick 	nextslot = sl1->next;
208922869Smckusick 	switch (sl1->type)
209022869Smckusick 	    {
209122869Smckusick 
209222869Smckusick /* temporarily commented out -----
209322869Smckusick 	    case SKLABEL:
209422869Smckusick 		lastlabslot = sl1;
209522869Smckusick 		break;
209622869Smckusick 
209722869Smckusick 	    case SKGOTO:
209822869Smckusick 		if (lastlabslot && sl1->label == lastlabslot->label)
209922869Smckusick 			{
210022869Smckusick 			dohead = lastlabslot;
210122869Smckusick 			doend = sl1;
210222869Smckusick 			alreg ();
210322869Smckusick 			}
210422869Smckusick 		break;
210522869Smckusick ----- */
210622869Smckusick 
210722869Smckusick 	    case SKDOHEAD:
210822869Smckusick 		pushq (sl1);
210922869Smckusick 		break;
211022869Smckusick 
211122869Smckusick 	    case SKENDDO:
211222869Smckusick 		match = 0;
211322869Smckusick 		for (sl2 = sl1; sl2; sl2 = sl2->prev)
211422869Smckusick 			{
211522869Smckusick 			if (sl2->type == SKDOHEAD) match++;
211622869Smckusick 			else if (sl2->type == SKENDDO) match--;
211722869Smckusick 			if (match == 0) break;
211822869Smckusick 			}
211922869Smckusick 		if (sl2)
212022869Smckusick 			dohead = sl2;
212122869Smckusick 		else
212222869Smckusick 			fatal ("unmatched enddo in code buffer");
212322869Smckusick 		if (sl2->type != SKDOHEAD)
212422869Smckusick 			fatal ("internal error in regalloc");
212522869Smckusick 
212622869Smckusick 		for (dqptr = dqbottom; dqptr; dqptr = dqptr->up)
212722869Smckusick 			{
212822869Smckusick 			if (dqptr->dohead == dohead)
212922869Smckusick 				break;
213022869Smckusick 			}
213122869Smckusick 
213222869Smckusick 		if (!dqptr)
213322869Smckusick 			fatal ("garbled doqueue in regalloc");
213422869Smckusick 
213522869Smckusick 		/*  sl1 now points to the SKENDDO slot; the SKNULL slot
213622869Smckusick 		 *  is reached through sl1->nullslot
213722869Smckusick 		 */
213822869Smckusick 		doend = (Slotp) sl1->nullslot;
213922869Smckusick 
214022869Smckusick 		alreg ();
214122869Smckusick 		break;
214222869Smckusick 
214322869Smckusick 	    default:
214422869Smckusick 		break;
214522869Smckusick 	    }
214622869Smckusick 	}
214722869Smckusick 
214822869Smckusick while (dqtop)
214922869Smckusick 	popq (dqtop->dohead);
215022869Smckusick 
215122869Smckusick return;
215222869Smckusick }
215322869Smckusick 
215422869Smckusick 
215522869Smckusick 
215622869Smckusick LOCAL pushq(sp)
215722869Smckusick Slotp sp;
215822869Smckusick 
215922869Smckusick {
216022869Smckusick   DOQUEUE *t;
216122869Smckusick 
216222869Smckusick   if (sp->type != SKDOHEAD)
216322869Smckusick     fatal("regalloc:pushq:  DO statement expected");
216422869Smckusick 
216522869Smckusick   if (dqbottom)
216622869Smckusick     {
216722869Smckusick       t = ALLOC(doqueue);
216822869Smckusick       t->up = dqbottom;
216922869Smckusick       dqbottom->down = t;
217022869Smckusick       dqbottom = t;
217122869Smckusick     }
217222869Smckusick   else
217322869Smckusick     dqtop = dqbottom = ALLOC(doqueue);
217422869Smckusick 
217522869Smckusick   dqbottom->dohead = sp;
217622869Smckusick }
217722869Smckusick 
217822869Smckusick 
217922869Smckusick LOCAL popq(sp)
218022869Smckusick Slotp sp;
218122869Smckusick 
218222869Smckusick {
218322869Smckusick   DOQUEUE *t;
218422869Smckusick   register int i;
218522869Smckusick 
218622869Smckusick   if (!dqtop)
218722869Smckusick     fatal("regalloc:popq:  empty DO queue");
218822869Smckusick   if (dqtop->dohead != sp)
218922869Smckusick     fatal("regalloc:popq:  garbled DO queue");
219022869Smckusick 
219122869Smckusick   t = dqtop;
219222869Smckusick 
219322869Smckusick   dqtop = t->down;
219422869Smckusick   if (dqtop)
219522869Smckusick     dqtop->up = NULL;
219622869Smckusick   else
219722869Smckusick     dqbottom = NULL;
219822869Smckusick   for (i = 0; i < MAXREGVAR; i++)
219922869Smckusick     if (t->reg[i])
220022869Smckusick       free((char *) t->reg[i]);
220122869Smckusick   free(t);
220222869Smckusick }
2203