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