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