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