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