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