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