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