X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fralloc.c;h=2a627aade38fade32b735d965faa979edbcdd4f7;hb=bb226788dab3832b0ec0cda70874ce3fce4eebc6;hp=e377d6f186d71f2e912efdd3765307f297f4fc76;hpb=feb3b4c002df1dafd6d19a2d782b72ad19d877c9;p=fw%2Fsdcc diff --git a/src/mcs51/ralloc.c b/src/mcs51/ralloc.c index e377d6f1..2a627aad 100644 --- a/src/mcs51/ralloc.c +++ b/src/mcs51/ralloc.c @@ -8,19 +8,19 @@ under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - + In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! + what you give them. Help stamp out software-hoarding! -------------------------------------------------------------------------*/ #include "common.h" @@ -37,6 +37,7 @@ /*-----------------------------------------------------------------*/ extern void gen51Code (iCode *); +#define D(x) /* Global data */ static struct @@ -44,38 +45,53 @@ static struct bitVect *spiltSet; set *stackSpil; bitVect *regAssigned; + bitVect *totRegAssigned; /* final set of LRs that got into registers */ short blockSpil; int slocNum; - bitVect *funcrUsed; /* registers used in a function */ + bitVect *funcrUsed; /* registers used in a function */ int stackExtend; int dataExtend; + bitVect *allBitregs; /* all bit registers */ } _G; /* Shared with gen.c */ -int mcs51_ptrRegReq; /* one byte pointer register required */ +int mcs51_ptrRegReq; /* one byte pointer register required */ /* 8051 registers */ regs regs8051[] = { - {REG_GPR, R2_IDX, REG_GPR, "r2", "ar2", "0", 2, 1}, - {REG_GPR, R3_IDX, REG_GPR, "r3", "ar3", "0", 3, 1}, - {REG_GPR, R4_IDX, REG_GPR, "r4", "ar4", "0", 4, 1}, - {REG_GPR, R5_IDX, REG_GPR, "r5", "ar5", "0", 5, 1}, - {REG_GPR, R6_IDX, REG_GPR, "r6", "ar6", "0", 6, 1}, - {REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1}, - {REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1}, - {REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1}, - {REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 1}, - {REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 1}, + {REG_GPR, R2_IDX, REG_GPR, "r2", "ar2", "0", 2, 1}, + {REG_GPR, R3_IDX, REG_GPR, "r3", "ar3", "0", 3, 1}, + {REG_GPR, R4_IDX, REG_GPR, "r4", "ar4", "0", 4, 1}, + {REG_GPR, R5_IDX, REG_GPR, "r5", "ar5", "0", 5, 1}, + {REG_GPR, R6_IDX, REG_GPR, "r6", "ar6", "0", 6, 1}, + {REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1}, + {REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1}, + {REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1}, + {REG_BIT, B0_IDX, REG_BIT, "b0", "b0", "bits", 0, 1}, + {REG_BIT, B1_IDX, REG_BIT, "b1", "b1", "bits", 1, 1}, + {REG_BIT, B2_IDX, REG_BIT, "b2", "b2", "bits", 2, 1}, + {REG_BIT, B3_IDX, REG_BIT, "b3", "b3", "bits", 3, 1}, + {REG_BIT, B4_IDX, REG_BIT, "b4", "b4", "bits", 4, 1}, + {REG_BIT, B5_IDX, REG_BIT, "b5", "b5", "bits", 5, 1}, + {REG_BIT, B6_IDX, REG_BIT, "b6", "b6", "bits", 6, 1}, + {REG_BIT, B7_IDX, REG_BIT, "b7", "b7", "bits", 7, 1}, + {REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 1}, + {REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 1}, {REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 1}, {REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 1}, {REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 1}, - {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, 1}, + {REG_CND, CND_IDX, REG_CND, "C", "psw", "0xd0", 0, 1}, + {0, DPL_IDX, 0, "dpl", "dpl", "0x82", 0, 0}, + {0, DPH_IDX, 0, "dph", "dph", "0x83", 0, 0}, + {0, B_IDX, 0, "b", "b", "0xf0", 0, 0}, + {0, A_IDX, 0, "a", "acc", "0xe0", 0, 0}, }; -int mcs51_nRegs = 13; +int mcs51_nRegs = 16; static void spillThis (symbol *); +static void freeAllRegs (); /*-----------------------------------------------------------------*/ /* allocReg - allocates register of given type */ @@ -91,43 +107,60 @@ allocReg (short type) /* if type is given as 0 then any free register will do */ if (!type && - regs8051[i].isFree) - { - regs8051[i].isFree = 0; - if (currFunc) - currFunc->regsUsed = - bitVectSetBit (currFunc->regsUsed, i); - return ®s8051[i]; - } + regs8051[i].isFree) + { + regs8051[i].isFree = 0; + if (currFunc) + currFunc->regsUsed = + bitVectSetBit (currFunc->regsUsed, i); + return ®s8051[i]; + } /* other wise look for specific type of register */ if (regs8051[i].isFree && - regs8051[i].type == type) - { - regs8051[i].isFree = 0; - if (currFunc) - currFunc->regsUsed = - bitVectSetBit (currFunc->regsUsed, i); - return ®s8051[i]; - } + regs8051[i].type == type) + { + regs8051[i].isFree = 0; + if (currFunc) + currFunc->regsUsed = + bitVectSetBit (currFunc->regsUsed, i); + return ®s8051[i]; + } } return NULL; } /*-----------------------------------------------------------------*/ -/* mcs51_regWithIdx - returns pointer to register wit index number */ +/* allocThisReg - allocates a particular register (if free) */ +/*-----------------------------------------------------------------*/ +static regs * +allocThisReg (regs * reg) +{ + if (!reg->isFree) + return NULL; + + reg->isFree = 0; + if (currFunc) + currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, reg->rIdx); + + return reg; +} + + +/*-----------------------------------------------------------------*/ +/* mcs51_regWithIdx - returns pointer to register with index number*/ /*-----------------------------------------------------------------*/ regs * mcs51_regWithIdx (int idx) { int i; - for (i = 0; i < mcs51_nRegs; i++) + for (i = 0; i < sizeof(regs8051)/sizeof(regs); i++) if (regs8051[i].rIdx == idx) return ®s8051[i]; werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "regWithIdx not found"); + "regWithIdx not found"); exit (1); } @@ -140,7 +173,7 @@ freeReg (regs * reg) if (!reg) { werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "freeReg - Freeing NULL register"); + "freeReg - Freeing NULL register"); exit (1); } @@ -173,37 +206,19 @@ nfreeRegsType (int type) if (type == REG_PTR) { if ((nfr = nFreeRegs (type)) == 0) - return nFreeRegs (REG_GPR); + return nFreeRegs (REG_GPR); } return nFreeRegs (type); } - /*-----------------------------------------------------------------*/ -/* allDefsOutOfRange - all definitions are out of a range */ +/* useReg - marks a register as used */ /*-----------------------------------------------------------------*/ -static bool -allDefsOutOfRange (bitVect * defs, int fseq, int toseq) +static void +useReg (regs * reg) { - int i; - - if (!defs) - return TRUE; - - for (i = 0; i < defs->size; i++) - { - iCode *ic; - - if (bitVectBitValue (defs, i) && - (ic = hTabItemWithKey (iCodehTab, i)) && - (ic->seq >= fseq && ic->seq <= toseq)) - - return FALSE; - - } - - return TRUE; + reg->isFree = 0; } /*-----------------------------------------------------------------*/ @@ -214,24 +229,33 @@ computeSpillable (iCode * ic) { bitVect *spillable; - /* spillable live ranges are those that are live at this + /* spillable live ranges are those that are live at this point . the following categories need to be subtracted - from this set. + from this set. a) - those that are already spilt b) - if being used by this one c) - defined by this one */ spillable = bitVectCopy (ic->rlive); spillable = - bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */ + bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */ spillable = - bitVectCplAnd (spillable, ic->uses); /* used in this one */ + bitVectCplAnd (spillable, ic->uses); /* used in this one */ bitVectUnSetBit (spillable, ic->defKey); spillable = bitVectIntersect (spillable, _G.regAssigned); return spillable; } +/*-----------------------------------------------------------------*/ +/* bitType - will return 1 if the symbol has type REG_BIT */ +/*-----------------------------------------------------------------*/ +static int +bitType (symbol * sym, eBBlock * ebp, iCode * ic) +{ + return (sym->regType == REG_BIT ? 1 : 0); +} + /*-----------------------------------------------------------------*/ /* noSpilLoc - return true if a variable has no spil location */ /*-----------------------------------------------------------------*/ @@ -251,7 +275,7 @@ hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic) } /*-----------------------------------------------------------------*/ -/* directSpilLoc - will return 1 if the splilocation is in direct */ +/* directSpilLoc - will return 1 if the spillocation is in direct */ /*-----------------------------------------------------------------*/ static int directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic) @@ -282,17 +306,6 @@ rematable (symbol * sym, eBBlock * ebp, iCode * ic) return sym->remat; } -/*-----------------------------------------------------------------*/ -/* notUsedInBlock - not used in this block */ -/*-----------------------------------------------------------------*/ -static int -notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic) -{ - return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) && - allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq)); -/* return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */ -} - /*-----------------------------------------------------------------*/ /* notUsedInRemaining - not used or defined in remain of the block */ /*-----------------------------------------------------------------*/ @@ -300,7 +313,7 @@ static int notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic) { return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) && - allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq)); + allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq)); } /*-----------------------------------------------------------------*/ @@ -317,7 +330,7 @@ allLRs (symbol * sym, eBBlock * ebp, iCode * ic) /*-----------------------------------------------------------------*/ static set * liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *), - eBBlock * ebp, iCode * ic) + eBBlock * ebp, iCode * ic) { set *rset = NULL; int i; @@ -329,19 +342,19 @@ liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *), { symbol *sym; if (!bitVectBitValue (lrs, i)) - continue; + continue; - /* if we don't find it in the live range + /* if we don't find it in the live range hash table we are in serious trouble */ if (!(sym = hTabItemWithKey (liveRanges, i))) - { - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "liveRangesWith could not find liveRange"); - exit (1); - } + { + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "liveRangesWith could not find liveRange"); + exit (1); + } if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key)) - addSetHead (&rset, sym); + addSetHead (&rset, sym); } return rset; @@ -365,18 +378,18 @@ leastUsedLR (set * sset) { /* if usage is the same then prefer - the spill the smaller of the two */ + to spill the smaller of the two */ if (lsym->used == sym->used) - if (getSize (lsym->type) < getSize (sym->type)) - sym = lsym; + if (getSize (lsym->type) < getSize (sym->type)) + sym = lsym; /* if less usage */ if (lsym->used < sym->used) - sym = lsym; + sym = lsym; } - setToNull ((void **) &sset); + setToNull ((void *) &sset); sym->blockSpil = 0; return sym; } @@ -389,13 +402,11 @@ noOverLap (set * itmpStack, symbol * fsym) { symbol *sym; - for (sym = setFirstItem (itmpStack); sym; sym = setNextItem (itmpStack)) { - if (bitVectBitValue(sym->clashes,fsym->key)) return 0; + if (bitVectBitValue(sym->clashes,fsym->key)) return 0; } - return 1; } @@ -452,22 +463,22 @@ spillLRWithPtrReg (symbol * forSym) int j; /* if no registers assigned to it or spilt */ - /* if it does not overlap with this then - not need to spill it */ + /* if it does not overlap this then + no need to spill it */ if (lrsym->isspilt || !lrsym->nRegs || - (lrsym->liveTo < forSym->liveFrom)) - continue; + (lrsym->liveTo < forSym->liveFrom)) + continue; /* go thru the registers : if it is either - r0 or r1 then spil it */ + r0 or r1 then spill it */ for (j = 0; j < lrsym->nRegs; j++) - if (lrsym->regs[j] == r0 || - lrsym->regs[j] == r1) - { - spillThis (lrsym); - break; - } + if (lrsym->regs[j] == r0 || + lrsym->regs[j] == r1) + { + spillThis (lrsym); + break; + } } } @@ -483,7 +494,7 @@ createStackSpil (symbol * sym) char slocBuffer[30]; - /* first go try and find a free one that is already + /* first go try and find a free one that is already existing on the stack */ if (applyToSet (_G.stackSpil, isFree, &sloc, sym)) { @@ -499,10 +510,11 @@ createStackSpil (symbol * sym) we need to allocate this on the stack : this is really a hack!! but cannot think of anything better at this time */ - if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer)) + if (SNPRINTF (slocBuffer, sizeof(slocBuffer), + "sloc%d", _G.slocNum++) >= sizeof (slocBuffer)) { fprintf (stderr, "***Internal error: slocBuffer overflowed: %s:%d\n", - __FILE__, __LINE__); + __FILE__, __LINE__); exit (1); } @@ -511,11 +523,20 @@ createStackSpil (symbol * sym) /* set the type to the spilling symbol */ sloc->type = copyLinkChain (sym->type); sloc->etype = getSpec (sloc->type); - SPEC_SCLS (sloc->etype) = S_DATA; + if (!IS_BIT (sloc->etype)) + { + SPEC_SCLS (sloc->etype) = S_DATA; + } + else if (SPEC_SCLS (sloc->etype) == S_SBIT) + { + SPEC_SCLS (sloc->etype) = S_BIT; + } SPEC_EXTR (sloc->etype) = 0; SPEC_STAT (sloc->etype) = 0; + SPEC_VOLATILE(sloc->etype) = 0; + SPEC_ABSA(sloc->etype) = 0; - /* we don't allow it to be allocated` + /* we don't allow it to be allocated onto the external stack since : so we temporarily turn it off ; we also turn off memory model to prevent @@ -533,7 +554,7 @@ createStackSpil (symbol * sym) options.useXstack = useXstack; options.model = model; /* options.noOverlay = noOverlay; */ - sloc->isref = 1; /* to prevent compiler warning */ + sloc->isref = 1; /* to prevent compiler warning */ /* if it is on the stack then update the stack */ if (IN_STACK (sloc->etype)) @@ -549,7 +570,7 @@ createStackSpil (symbol * sym) sym->usl.spillLoc = sloc; sym->stackSpil = 1; - /* add it to the set of itempStack set + /* add it to the set of itempStack set of the spill location */ addSetHead (&sloc->usl.itmpStack, sym); return sym; @@ -557,6 +578,7 @@ createStackSpil (symbol * sym) /*-----------------------------------------------------------------*/ /* isSpiltOnStack - returns true if the spil location is on stack */ +/* or otherwise needs a pointer register */ /*-----------------------------------------------------------------*/ static bool isSpiltOnStack (symbol * sym) @@ -575,6 +597,9 @@ isSpiltOnStack (symbol * sym) if (!sym->usl.spillLoc) return FALSE; + if (sym->usl.spillLoc->onStack || sym->usl.spillLoc->iaccess) + return TRUE; + etype = getSpec (sym->usl.spillLoc->type); if (IN_STACK (etype)) return TRUE; @@ -595,22 +620,22 @@ spillThis (symbol * sym) if (!(sym->remat || sym->usl.spillLoc)) createStackSpil (sym); - /* mark it has spilt & put it in the spilt set */ - sym->isspilt = 1; + sym->isspilt = sym->spillA = 1; _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key); bitVectUnSetBit (_G.regAssigned, sym->key); + bitVectUnSetBit (_G.totRegAssigned, sym->key); for (i = 0; i < sym->nRegs; i++) if (sym->regs[i]) { - freeReg (sym->regs[i]); - sym->regs[i] = NULL; + freeReg (sym->regs[i]); + sym->regs[i] = NULL; } - /* if spilt on stack then free up r0 & r1 + /* if spilt on stack then free up r0 & r1 if they could have been assigned to some LIVE ranges */ if (!mcs51_ptrRegReq && isSpiltOnStack (sym)) @@ -620,7 +645,7 @@ spillThis (symbol * sym) } if (sym->usl.spillLoc && !sym->remat) - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return; } @@ -637,10 +662,20 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) /* get the spillable live ranges */ lrcs = computeSpillable (ic); - /* get all live ranges that are rematerizable */ - if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic))) + /* remove incompatible registers */ + if ((forSym->regType == REG_PTR) || (forSym->regType == REG_GPR)) { + selectS = liveRangesWith (lrcs, bitType, ebp, ic); + + for (sym = setFirstItem (selectS); sym; sym = setNextItem (selectS)) + { + bitVectUnSetBit (lrcs, sym->key); + } + } + /* get all live ranges that are rematerializable */ + if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic))) + { /* return the least used of these */ return leastUsedLR (selectS); } @@ -649,66 +684,66 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic))) { sym = leastUsedLR (selectS); - strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ? - sym->usl.spillLoc->rname : - sym->usl.spillLoc->name)); + strncpyz (sym->rname, + sym->usl.spillLoc->rname[0] ? + sym->usl.spillLoc->rname : sym->usl.spillLoc->name, + sizeof(sym->rname)); sym->spildir = 1; /* mark it as allocation required */ - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } /* if the symbol is local to the block then */ if (forSym->liveTo < ebp->lSeq) { - /* check if there are any live ranges allocated to registers that are not used in this block */ if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic))) - { - sym = leastUsedLR (selectS); - /* if this is not rematerializable */ - if (!sym->remat) - { - _G.blockSpil++; - sym->blockSpil = 1; - } - return sym; - } + { + sym = leastUsedLR (selectS); + /* if this is not rematerializable */ + if (!sym->remat) + { + _G.blockSpil++; + sym->blockSpil = 1; + } + return sym; + } /* check if there are any live ranges that not used in the remainder of the block */ - if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic))) - { - sym = leastUsedLR (selectS); - if (sym != forSym) - { - if (!sym->remat) - { - sym->remainSpil = 1; - _G.blockSpil++; - } - return sym; - } - } + if (!_G.blockSpil && + !isiCodeInFunctionCall (ic) && + (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic))) + { + sym = leastUsedLR (selectS); + if (sym != forSym) + { + if (!sym->remat) + { + sym->remainSpil = 1; + _G.blockSpil++; + } + return sym; + } + } } /* find live ranges with spillocation && not used as pointers */ if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic))) { - sym = leastUsedLR (selectS); /* mark this as allocation required */ - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } /* find live ranges with spillocation */ if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic))) { - sym = leastUsedLR (selectS); - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } @@ -717,10 +752,9 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) used ofcourse */ if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic))) { - /* return a created spil location */ sym = createStackSpil (leastUsedLR (selectS)); - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } @@ -744,19 +778,20 @@ spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym) ssym = selectSpil (ic, ebp, forSym); /* mark it as spilt */ - ssym->isspilt = 1; + ssym->isspilt = ssym->spillA = 1; _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key); /* mark it as not register assigned & take it away from the set */ bitVectUnSetBit (_G.regAssigned, ssym->key); + bitVectUnSetBit (_G.totRegAssigned, ssym->key); /* mark the registers as free */ for (i = 0; i < ssym->nRegs; i++) if (ssym->regs[i]) freeReg (ssym->regs[i]); - /* if spilt on stack then free up r0 & r1 + /* if spilt on stack then free up r0 & r1 if they could have been assigned to as gprs */ if (!mcs51_ptrRegReq && isSpiltOnStack (ssym)) { @@ -764,14 +799,14 @@ spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym) spillLRWithPtrReg (ssym); } - /* if this was a block level spil then insert push & pop + /* if this was a block level spil then insert push & pop at the start & end of block respectively */ if (ssym->blockSpil) { iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL); /* add push to the start of the block */ addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ? - ebp->sch->next : ebp->sch)); + ebp->sch->next : ebp->sch)); nic = newiCode (IPOP, operandFromSymbol (ssym), NULL); /* add pop to the end of the block */ addiCodeToeBBlock (ebp, nic, NULL); @@ -805,6 +840,7 @@ static regs * getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym) { regs *reg; + int j; tryAgain: /* try for a ptr type */ @@ -819,7 +855,12 @@ tryAgain: if (!spilSomething (ic, ebp, sym)) return NULL; - /* this looks like an infinite loop but + /* make sure partially assigned registers aren't reused */ + for (j=0; j<=sym->nRegs; j++) + if (sym->regs[j]) + sym->regs[j]->isFree = 0; + + /* this looks like an infinite loop but in really selectSpil will abort */ goto tryAgain; } @@ -831,6 +872,7 @@ static regs * getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym) { regs *reg; + int j; tryAgain: /* try for gpr type */ @@ -845,11 +887,93 @@ tryAgain: if (!spilSomething (ic, ebp, sym)) return NULL; - /* this looks like an infinite loop but + /* make sure partially assigned registers aren't reused */ + for (j=0; j<=sym->nRegs; j++) + if (sym->regs[j]) + sym->regs[j]->isFree = 0; + + /* this looks like an infinite loop but in really selectSpil will abort */ goto tryAgain; } +/*-----------------------------------------------------------------*/ +/* getRegBit - will try for Bit if not spill this */ +/*-----------------------------------------------------------------*/ +static regs *getRegBit (symbol * sym) +{ + regs *reg; + + /* try for a bit type */ + if ((reg = allocReg (REG_BIT))) + return reg; + + spillThis (sym); + return 0; +} + +/*-----------------------------------------------------------------*/ +/* getRegPtrNoSpil - get it cannot be spilt */ +/*-----------------------------------------------------------------*/ +static regs *getRegPtrNoSpil() +{ + regs *reg; + + /* try for a ptr type */ + if ((reg = allocReg (REG_PTR))) + return reg; + + /* try for gpr type */ + if ((reg = allocReg (REG_GPR))) + return reg; + + assert(0); + + /* just to make the compiler happy */ + return 0; +} + +/*-----------------------------------------------------------------*/ +/* getRegGprNoSpil - get it cannot be spilt */ +/*-----------------------------------------------------------------*/ +static regs *getRegGprNoSpil() +{ + + regs *reg; + if ((reg = allocReg (REG_GPR))) + return reg; + + if (!mcs51_ptrRegReq) + if ((reg = allocReg (REG_PTR))) + return reg; + + assert(0); + + /* just to make the compiler happy */ + return 0; +} + +/*-----------------------------------------------------------------*/ +/* getRegBitNoSpil - get it cannot be spilt */ +/*-----------------------------------------------------------------*/ +static regs *getRegBitNoSpil() +{ + regs *reg; + + /* try for a ptr type */ + if ((reg = allocReg (REG_BIT))) + return reg; + + /* try for gpr type */ + if ((reg = allocReg (REG_GPR))) + return reg; + + assert(0); + + /* just to make the compiler happy */ + return 0; +} + /*-----------------------------------------------------------------*/ /* symHasReg - symbol has a given register */ /*-----------------------------------------------------------------*/ @@ -865,6 +989,29 @@ symHasReg (symbol * sym, regs * reg) return FALSE; } +/*-----------------------------------------------------------------*/ +/* updateRegUsage - update the registers in use at the start of */ +/* this icode */ +/*-----------------------------------------------------------------*/ +static void +updateRegUsage (iCode * ic) +{ + int reg; + + for (reg=0; regriu &= ~(1<riu |= (1<= 8); + } + } +} + /*-----------------------------------------------------------------*/ /* deassignLRs - check the live to and if they have registers & are */ /* not spilt then free up the registers */ @@ -883,87 +1030,89 @@ deassignLRs (iCode * ic, eBBlock * ebp) symbol *psym = NULL; /* if it does not end here */ if (sym->liveTo > ic->seq) - continue; + continue; - /* if it was spilt on stack then we can + /* if it was spilt on stack then we can mark the stack spil location as free */ if (sym->isspilt) - { - if (sym->stackSpil) - { - sym->usl.spillLoc->isFree = 1; - sym->stackSpil = 0; - } - continue; - } + { + if (sym->stackSpil) + { + sym->usl.spillLoc->isFree = 1; + sym->stackSpil = 0; + } + continue; + } if (!bitVectBitValue (_G.regAssigned, sym->key)) - continue; + continue; /* special case check if this is an IFX & - the privious one was a pop and the + the privious one was a pop and the previous one was not spilt then keep track of the symbol */ if (ic->op == IFX && ic->prev && - ic->prev->op == IPOP && - !ic->prev->parmPush && - !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt) - psym = OP_SYMBOL (IC_LEFT (ic->prev)); + ic->prev->op == IPOP && + !ic->prev->parmPush && + !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt) + psym = OP_SYMBOL (IC_LEFT (ic->prev)); if (sym->nRegs) - { - int i = 0; - - bitVectUnSetBit (_G.regAssigned, sym->key); - - /* if the result of this one needs registers - and does not have it then assign it right - away */ - if (IC_RESULT (ic) && - !(SKIP_IC2 (ic) || /* not a special icode */ - ic->op == JUMPTABLE || - ic->op == IFX || - ic->op == IPUSH || - ic->op == IPOP || - ic->op == RETURN || - POINTER_SET (ic)) && - (result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */ - result->liveTo > ic->seq && /* and will live beyond this */ - result->liveTo <= ebp->lSeq && /* does not go beyond this block */ - result->regType == sym->regType && /* same register types */ - result->nRegs && /* which needs registers */ - !result->isspilt && /* and does not already have them */ - !result->remat && - !bitVectBitValue (_G.regAssigned, result->key) && - /* the number of free regs + number of regs in this LR - can accomodate the what result Needs */ - ((nfreeRegsType (result->regType) + - sym->nRegs) >= result->nRegs) - ) - { - - for (i = 0; i < result->nRegs; i++) - if (i < sym->nRegs) - result->regs[i] = sym->regs[i]; - else - result->regs[i] = getRegGpr (ic, ebp, result); - - _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key); - - } - - /* free the remaining */ - for (; i < sym->nRegs; i++) - { - if (psym) - { - if (!symHasReg (psym, sym->regs[i])) - freeReg (sym->regs[i]); - } - else - freeReg (sym->regs[i]); - } - } + { + int i = 0; + + bitVectUnSetBit (_G.regAssigned, sym->key); + + /* if the result of this one needs registers + and does not have it then assign it right + away */ + if (IC_RESULT (ic) && + !(SKIP_IC2 (ic) || /* not a special icode */ + ic->op == JUMPTABLE || + ic->op == IFX || + ic->op == IPUSH || + ic->op == IPOP || + ic->op == RETURN || + POINTER_SET (ic)) && + (result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */ + result->liveTo > ic->seq && /* and will live beyond this */ + result->liveTo <= ebp->lSeq && /* does not go beyond this block */ + result->liveFrom == ic->seq && /* does not start before here */ + result->regType == sym->regType && /* same register types */ + result->nRegs && /* which needs registers */ + !result->isspilt && /* and does not already have them */ + !result->remat && + !bitVectBitValue (_G.regAssigned, result->key) && + /* the number of free regs + number of regs in this LR + can accomodate the what result Needs */ + ((nfreeRegsType (result->regType) + + sym->nRegs) >= result->nRegs) + ) + { + + for (i = 0; i < result->nRegs; i++) + if (i < sym->nRegs) + result->regs[i] = sym->regs[i]; + else + result->regs[i] = getRegGpr (ic, ebp, result); + + _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key); + _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key); + + } + + /* free the remaining */ + for (; i < sym->nRegs; i++) + { + if (psym) + { + if (!symHasReg (psym, sym->regs[i])) + freeReg (sym->regs[i]); + } + else + freeReg (sym->regs[i]); + } + } } } @@ -978,10 +1127,11 @@ reassignLR (operand * op) int i; /* not spilt any more */ - sym->isspilt = sym->blockSpil = sym->remainSpil = 0; + sym->isspilt = sym->spillA = sym->blockSpil = sym->remainSpil = 0; bitVectUnSetBit (_G.spiltSet, sym->key); _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key); + _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key); _G.blockSpil--; @@ -995,31 +1145,36 @@ reassignLR (operand * op) static int willCauseSpill (int nr, int rt) { - /* first check if there are any avlb registers - of te type required */ + /* first check if there are any available registers + of the type required */ if (rt == REG_PTR) { - /* special case for pointer type - if pointer type not avlb then + /* special case for pointer type + if pointer type not avlb then check for type gpr */ if (nFreeRegs (rt) >= nr) - return 0; + return 0; if (nFreeRegs (REG_GPR) >= nr) - return 0; + return 0; + } + else if (rt == REG_BIT) + { + if (nFreeRegs (rt) >= nr) + return 0; } else { if (mcs51_ptrRegReq) - { - if (nFreeRegs (rt) >= nr) - return 0; - } + { + if (nFreeRegs (rt) >= nr) + return 0; + } else - { - if (nFreeRegs (REG_PTR) + - nFreeRegs (REG_GPR) >= nr) - return 0; - } + { + if (nFreeRegs (REG_PTR) + + nFreeRegs (REG_GPR) >= nr) + return 0; + } } /* it will cause a spil */ @@ -1031,28 +1186,29 @@ willCauseSpill (int nr, int rt) /* ult and operand, if this happens make sure they are in the same */ /* position as the operand otherwise chaos results */ /*-----------------------------------------------------------------*/ -static void -positionRegs (symbol * result, symbol * opsym, int lineno) +static int +positionRegs (symbol * result, symbol * opsym) { int count = min (result->nRegs, opsym->nRegs); int i, j = 0, shared = 0; + int change = 0; /* if the result has been spilt then cannot share */ if (opsym->isspilt) - return; + return 0; again: shared = 0; /* first make sure that they actually share */ for (i = 0; i < count; i++) { for (j = 0; j < count; j++) - { - if (result->regs[i] == opsym->regs[j] && i != j) - { - shared = 1; - goto xchgPositions; - } - } + { + if (result->regs[i] == opsym->regs[j] && i != j) + { + shared = 1; + goto xchgPositions; + } + } } xchgPositions: if (shared) @@ -1060,161 +1216,480 @@ xchgPositions: regs *tmp = result->regs[i]; result->regs[i] = result->regs[j]; result->regs[j] = tmp; + change ++; goto again; } + return change; +} + +/*------------------------------------------------------------------*/ +/* verifyRegsAssigned - make sure an iTemp is properly initialized; */ +/* it should either have registers or have beed spilled. Otherwise, */ +/* there was an uninitialized variable, so just spill this to get */ +/* the operand in a valid state. */ +/*------------------------------------------------------------------*/ +static void +verifyRegsAssigned (operand *op, iCode * ic) +{ + symbol * sym; + + if (!op) return; + if (!IS_ITEMP (op)) return; + + sym = OP_SYMBOL (op); + if (sym->isspilt) return; + if (!sym->nRegs) return; + if (sym->regs[0]) return; + + werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT, + sym->prereqv ? sym->prereqv->name : sym->name); + spillThis (sym); } + /*-----------------------------------------------------------------*/ /* serialRegAssign - serially allocate registers to the variables */ /*-----------------------------------------------------------------*/ static void serialRegAssign (eBBlock ** ebbs, int count) { - int i; + int i; - /* for all blocks */ - for (i = 0; i < count; i++) { - - iCode *ic; - - if (ebbs[i]->noPath && - (ebbs[i]->entryLabel != entryLabel && - ebbs[i]->entryLabel != returnLabel)) - continue; - - /* of all instructions do */ - for (ic = ebbs[i]->sch; ic; ic = ic->next) { - - /* if this is an ipop that means some live - range will have to be assigned again */ - if (ic->op == IPOP) - reassignLR (IC_LEFT (ic)); - - /* if result is present && is a true symbol */ - if (IC_RESULT (ic) && ic->op != IFX && - IS_TRUE_SYMOP (IC_RESULT (ic))) - OP_SYMBOL (IC_RESULT (ic))->allocreq = 1; - - /* take away registers from live - ranges that end at this instruction */ - deassignLRs (ic, ebbs[i]); - - /* some don't need registers */ - if (SKIP_IC2 (ic) || - ic->op == JUMPTABLE || - ic->op == IFX || - ic->op == IPUSH || - ic->op == IPOP || - (IC_RESULT (ic) && POINTER_SET (ic))) - continue; - - /* now we need to allocate registers - only for the result */ - if (IC_RESULT (ic)) { - symbol *sym = OP_SYMBOL (IC_RESULT (ic)); - bitVect *spillable; - int willCS; - int j; - int ptrRegSet = 0; - - /* if it does not need or is spilt - or is already assigned to registers - or will not live beyond this instructions */ - if (!sym->nRegs || - sym->isspilt || - bitVectBitValue (_G.regAssigned, sym->key) || - sym->liveTo <= ic->seq) - continue; - - /* if some liverange has been spilt at the block level - and this one live beyond this block then spil this - to be safe */ - if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) { - spillThis (sym); - continue; - } - /* if trying to allocate this will cause - a spill and there is nothing to spill - or this one is rematerializable then - spill this one */ - willCS = willCauseSpill (sym->nRegs, sym->regType); - spillable = computeSpillable (ic); - if (sym->remat || (willCS && bitVectIsZero (spillable))) { - spillThis (sym); - continue; - } - - /* if it has a spillocation & is used less than - all other live ranges then spill this */ - if (willCS) { - if (sym->usl.spillLoc) { - symbol *leastUsed = leastUsedLR (liveRangesWith (spillable, - allLRs, ebbs[i], ic)); - if (leastUsed && leastUsed->used > sym->used) { - spillThis (sym); - continue; - } - } else { - /* if none of the liveRanges have a spillLocation then better - to spill this one than anything else already assigned to registers */ - if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) { - /* if this is local to this block then we might find a block spil */ - if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) { - spillThis (sym); - continue; - } - } - } - } - /* if we need ptr regs for the right side - then mark it */ - if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic)) - && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE) { - mcs51_ptrRegReq++; - ptrRegSet = 1; - } - /* else we assign registers to it */ - _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key); - - for (j = 0; j < sym->nRegs; j++) { - if (sym->regType == REG_PTR) - sym->regs[j] = getRegPtr (ic, ebbs[i], sym); - else - sym->regs[j] = getRegGpr (ic, ebbs[i], sym); - - /* if the allocation failed which means - this was spilt then break */ - if (!sym->regs[j]) { - if (j) { - fprintf (stderr, "%d reg(s) lost in %s:%d\n", - j, __FILE__,__LINE__); - } - break; - } - } - - /* if it shares registers with operands make sure - that they are in the same position */ - if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) && - OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') { - positionRegs (OP_SYMBOL (IC_RESULT (ic)), - OP_SYMBOL (IC_LEFT (ic)), ic->lineno); - } - /* do the same for the right operand */ - if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) && - OP_SYMBOL (IC_RIGHT (ic))->nRegs) { - positionRegs (OP_SYMBOL (IC_RESULT (ic)), - OP_SYMBOL (IC_RIGHT (ic)), ic->lineno); - } - - if (ptrRegSet) { - mcs51_ptrRegReq--; - ptrRegSet = 0; - } - - } - } + /* for all blocks */ + for (i = 0; i < count; i++) + { + + iCode *ic; + + if (ebbs[i]->noPath && + (ebbs[i]->entryLabel != entryLabel && + ebbs[i]->entryLabel != returnLabel)) + continue; + + /* for all instructions do */ + for (ic = ebbs[i]->sch; ic; ic = ic->next) + { + updateRegUsage(ic); + + /* if this is an ipop that means some live + range will have to be assigned again */ + if (ic->op == IPOP) + reassignLR (IC_LEFT (ic)); + + /* if result is present && is a true symbol */ + if (IC_RESULT (ic) && ic->op != IFX && + IS_TRUE_SYMOP (IC_RESULT (ic))) + OP_SYMBOL (IC_RESULT (ic))->allocreq++; + + /* take away registers from live + ranges that end at this instruction */ + deassignLRs (ic, ebbs[i]); + + /* some don't need registers */ + if (SKIP_IC2 (ic) || + ic->op == JUMPTABLE || + ic->op == IFX || + ic->op == IPUSH || + ic->op == IPOP || + (IC_RESULT (ic) && POINTER_SET (ic))) + continue; + + /* now we need to allocate registers + only for the result */ + if (IC_RESULT (ic)) { + symbol *sym = OP_SYMBOL (IC_RESULT (ic)); + bitVect *spillable; + int willCS; + int j; + int ptrRegSet = 0; + + /* Make sure any spill location is definitely allocated */ + if (sym->isspilt && !sym->remat && sym->usl.spillLoc && + !sym->usl.spillLoc->allocreq) + { + sym->usl.spillLoc->allocreq++; + } + + /* if it does not need or is spilt + or is already assigned to registers + or will not live beyond this instructions */ + if (!sym->nRegs || + sym->isspilt || + bitVectBitValue (_G.regAssigned, sym->key) || + sym->liveTo <= ic->seq) + continue; + + /* if some liverange has been spilt at the block level + and this one live beyond this block then spil this + to be safe */ + if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) { + spillThis (sym); + continue; + } + + willCS = willCauseSpill (sym->nRegs, sym->regType); + /* if this is a bit variable then don't use precious registers + along with expensive bit-to-char conversions but just spill + it */ + if (willCS && SPEC_NOUN(sym->etype) == V_BIT) { + spillThis (sym); + continue; + } + + /* if trying to allocate this will cause + a spill and there is nothing to spill + or this one is rematerializable then + spill this one */ + spillable = computeSpillable (ic); + if (sym->remat || (willCS && bitVectIsZero (spillable))) { + spillThis (sym); + continue; + } + + /* If the live range preceeds the point of definition + then ideally we must take into account registers that + have been allocated after sym->liveFrom but freed + before ic->seq. This is complicated, so spill this + symbol instead and let fillGaps handle the allocation. */ + if (sym->liveFrom < ic->seq) { + spillThis (sym); + continue; + } + + /* if it has a spillocation & is used less than + all other live ranges then spill this */ + if (willCS) { + if (sym->usl.spillLoc) { + symbol *leastUsed = leastUsedLR (liveRangesWith (spillable, + allLRs, ebbs[i], ic)); + if (leastUsed && leastUsed->used > sym->used) { + spillThis (sym); + continue; + } + } else { + /* if none of the liveRanges have a spillLocation then better + to spill this one than anything else already assigned to registers */ + if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) { + /* if this is local to this block then we might find a block spil */ + if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) { + spillThis (sym); + continue; + } + } + } + } + /* if we need ptr regs for the right side + then mark it */ + if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic)) + && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE) { + mcs51_ptrRegReq++; + ptrRegSet = 1; + } + if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) + && SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata) { + mcs51_ptrRegReq++; + ptrRegSet = 1; + } + if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) + && SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata) { + mcs51_ptrRegReq++; + ptrRegSet = 1; + } + + /* else we assign registers to it */ + _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key); + _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key); + + for (j = 0; j < sym->nRegs; j++) { + sym->regs[j] = NULL; + if (sym->regType == REG_PTR) + sym->regs[j] = getRegPtr (ic, ebbs[i], sym); + else if (sym->regType == REG_BIT) + sym->regs[j] = getRegBit (sym); + else + { + if (ic->op == CAST && IS_SYMOP (IC_RIGHT (ic))) + { + symbol * right = OP_SYMBOL (IC_RIGHT (ic)); + + if (right->regs[j] && (right->regType != REG_BIT)) + sym->regs[j] = allocThisReg (right->regs[j]); + } + if (!sym->regs[j]) + sym->regs[j] = getRegGpr (ic, ebbs[i], sym); + } + + /* if the allocation failed which means + this was spilt then break */ + if (!sym->regs[j]) + { + int i; + for (i=0; i < sym->nRegs ; i++ ) + sym->regs[i] = NULL; + break; + } + } + + if (!POINTER_SET(ic) && !POINTER_GET(ic)) { + /* if it shares registers with operands make sure + that they are in the same position */ + if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) && + OP_SYMBOL (IC_LEFT (ic))->nRegs) { + positionRegs (OP_SYMBOL (IC_RESULT (ic)), + OP_SYMBOL (IC_LEFT (ic))); + } + /* do the same for the right operand */ + if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) && + OP_SYMBOL (IC_RIGHT (ic))->nRegs) { + positionRegs (OP_SYMBOL (IC_RESULT (ic)), + OP_SYMBOL (IC_RIGHT (ic))); + } + } + + if (ptrRegSet) { + mcs51_ptrRegReq--; + ptrRegSet = 0; + } + + } + } } + + /* Check for and fix any problems with uninitialized operands */ + for (i = 0; i < count; i++) + { + iCode *ic; + + if (ebbs[i]->noPath && + (ebbs[i]->entryLabel != entryLabel && + ebbs[i]->entryLabel != returnLabel)) + continue; + + for (ic = ebbs[i]->sch; ic; ic = ic->next) + { + if (SKIP_IC2 (ic)) + continue; + + if (ic->op == IFX) + { + verifyRegsAssigned (IC_COND (ic), ic); + continue; + } + + if (ic->op == JUMPTABLE) + { + verifyRegsAssigned (IC_JTCOND (ic), ic); + continue; + } + + verifyRegsAssigned (IC_RESULT (ic), ic); + verifyRegsAssigned (IC_LEFT (ic), ic); + verifyRegsAssigned (IC_RIGHT (ic), ic); + } + } +} + +/*-----------------------------------------------------------------*/ +/* fillGaps - Try to fill in the Gaps left by Pass1 */ +/*-----------------------------------------------------------------*/ +static void fillGaps() +{ + symbol *sym =NULL; + int key =0; + int pass; + iCode *ic = NULL; + + if (getenv("DISABLE_FILL_GAPS")) return; + + /* look for liveranges that were spilt by the allocator */ + for (sym = hTabFirstItem(liveRanges,&key) ; sym ; + sym = hTabNextItem(liveRanges,&key)) { + + int i; + int pdone = 0; + + if (!sym->spillA || !sym->clashes || sym->remat) continue ; + + /* if spilt in direct space the original rname is lost */ + if (sym->usl.spillLoc && (IN_DIRSPACE (SPEC_OCLS (sym->usl.spillLoc->etype)))) + continue; + + /* find the liveRanges this one clashes with, that are + still assigned to registers & mark the registers as used*/ + for ( i = 0 ; i < sym->clashes->size ; i ++) { + int k; + symbol *clr; + + if (bitVectBitValue(sym->clashes,i) == 0 || /* those that clash with this */ + bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */ + continue ; + + clr = hTabItemWithKey(liveRanges,i); + assert(clr); + + /* mark these registers as used */ + for (k = 0 ; k < clr->nRegs ; k++ ) + useReg(clr->regs[k]); + } + + if (willCauseSpill(sym->nRegs,sym->regType)) { + /* NOPE :( clear all registers & and continue */ + freeAllRegs(); + continue ; + } + + ic = NULL; + for (i = 0 ; i < sym->defs->size ; i++ ) + { + if (bitVectBitValue(sym->defs,i)) + { + if (!(ic = hTabItemWithKey(iCodehTab,i))) + continue; + if (ic->op == CAST) + break; + } + } + + D(printf("Attempting fillGaps on %s: [",sym->name)); + /* THERE IS HOPE !!!! */ + for (i=0; i < sym->nRegs ; i++ ) { + if (sym->regType == REG_PTR) + sym->regs[i] = getRegPtrNoSpil (); + else if (sym->regType == REG_BIT) + sym->regs[i] = getRegBitNoSpil (); + else + { + sym->regs[i] = NULL; + if (ic && ic->op == CAST && IS_SYMOP (IC_RIGHT (ic))) + { + symbol * right = OP_SYMBOL (IC_RIGHT (ic)); + + if (right->regs[i]) + sym->regs[i] = allocThisReg (right->regs[i]); + } + if (!sym->regs[i]) + sym->regs[i] = getRegGprNoSpil (); + } + D(printf("%s ", sym->regs[i]->name)); + } + D(printf("]\n")); + + /* For all its definitions check if the registers + allocated needs positioning NOTE: we can position + only ONCE if more than One positioning required + then give up. + We may need to perform the checks twice; once to + position the registers as needed, the second to + verify any register repositioning is still + compatible. + */ + sym->isspilt = 0; + for (pass=0; pass<2; pass++) { + D(printf(" checking definitions\n")); + for (i = 0 ; i < sym->defs->size ; i++ ) { + if (bitVectBitValue(sym->defs,i)) { + if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; + D(printf(" ic->seq = %d\n", ic->seq)); + if (SKIP_IC(ic)) continue; + assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */ + /* if left is assigned to registers */ + if (IS_SYMOP(IC_LEFT(ic))) + { + D(printf(" left = ")); + D(printOperand(IC_LEFT(ic),NULL)); + } + if (IS_SYMOP(IC_LEFT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) { + pdone += (positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)))>0); + } + if (IS_SYMOP(IC_RIGHT(ic))) + { + D(printf(" right = ")); + D(printOperand(IC_RIGHT(ic),NULL)); + } + if (IS_SYMOP(IC_RIGHT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) { + pdone += (positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)))>0); + } + D(printf(" pdone = %d\n", pdone)); + if (pdone > 1) break; + } + } + D(printf(" checking uses\n")); + for (i = 0 ; i < sym->uses->size ; i++ ) { + if (bitVectBitValue(sym->uses,i)) { + iCode *ic; + if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; + D(printf(" ic->seq = %d\n", ic->seq)); + if (SKIP_IC(ic)) continue; + if (POINTER_SET(ic) || POINTER_GET(ic)) continue ; + + /* if result is assigned to registers */ + if (IS_SYMOP(IC_RESULT(ic))) + { + D(printf(" result = ")); + D(printOperand(IC_RESULT(ic),NULL)); + } + if (IS_SYMOP(IC_RESULT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) { + pdone += (positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)))>0); + } + D(printf(" pdone = %d\n", pdone)); + if (pdone > 1) break; + } + } + if (pdone == 0) break; /* second pass only if regs repositioned */ + if (pdone > 1) break; + } + D(printf(" sym->regs = [")); + for (i=0; i < sym->nRegs ; i++ ) + D(printf("%s ", sym->regs[i]->name)); + D(printf("]\n")); + /* had to position more than once GIVE UP */ + if (pdone > 1) { + /* UNDO all the changes we made to try this */ + sym->isspilt = 1; + for (i=0; i < sym->nRegs ; i++ ) { + sym->regs[i] = NULL; + } + freeAllRegs(); + D(printf ("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN")); + continue ; + } + D(printf ("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN")); + + _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key); + sym->isspilt = sym->spillA = 0 ; + sym->usl.spillLoc->allocreq--; + freeAllRegs(); + } +} + +/*-----------------------------------------------------------------*/ +/* findAllBitregs :- returns bit vector of all bit registers */ +/*-----------------------------------------------------------------*/ +static bitVect * +findAllBitregs (void) +{ + bitVect *rmask = newBitVect (mcs51_nRegs); + int j; + + for (j = 0; j < mcs51_nRegs; j++) + { + if (regs8051[j].type == REG_BIT) + rmask = bitVectSetBit (rmask, regs8051[j].rIdx); + } + + return rmask; +} + +/*-----------------------------------------------------------------*/ +/* mcs51_allBitregs :- returns bit vector of all bit registers */ +/*-----------------------------------------------------------------*/ +bitVect * +mcs51_allBitregs (void) +{ + return _G.allBitregs; } /*-----------------------------------------------------------------*/ @@ -1242,8 +1717,8 @@ mcs51_rUmaskForOp (operand * op) for (j = 0; j < sym->nRegs; j++) { - rumask = bitVectSetBit (rumask, - sym->regs[j]->rIdx); + if (sym->regs[j]) /* EEP - debug */ + rumask = bitVectSetBit (rumask, sym->regs[j]->rIdx); } return rumask; @@ -1261,7 +1736,7 @@ regsUsedIniCode (iCode * ic) if (ic->op == IFX) { rmask = bitVectUnion (rmask, - mcs51_rUmaskForOp (IC_COND (ic))); + mcs51_rUmaskForOp (IC_COND (ic))); goto ret; } @@ -1269,7 +1744,7 @@ regsUsedIniCode (iCode * ic) if (ic->op == JUMPTABLE) { rmask = bitVectUnion (rmask, - mcs51_rUmaskForOp (IC_JTCOND (ic))); + mcs51_rUmaskForOp (IC_JTCOND (ic))); goto ret; } @@ -1277,16 +1752,16 @@ regsUsedIniCode (iCode * ic) /* of all other cases */ if (IC_LEFT (ic)) rmask = bitVectUnion (rmask, - mcs51_rUmaskForOp (IC_LEFT (ic))); + mcs51_rUmaskForOp (IC_LEFT (ic))); if (IC_RIGHT (ic)) rmask = bitVectUnion (rmask, - mcs51_rUmaskForOp (IC_RIGHT (ic))); + mcs51_rUmaskForOp (IC_RIGHT (ic))); if (IC_RESULT (ic)) rmask = bitVectUnion (rmask, - mcs51_rUmaskForOp (IC_RESULT (ic))); + mcs51_rUmaskForOp (IC_RESULT (ic))); ret: return rmask; @@ -1306,58 +1781,59 @@ createRegMask (eBBlock ** ebbs, int count) iCode *ic; if (ebbs[i]->noPath && - (ebbs[i]->entryLabel != entryLabel && - ebbs[i]->entryLabel != returnLabel)) - continue; + (ebbs[i]->entryLabel != entryLabel && + ebbs[i]->entryLabel != returnLabel)) + continue; /* for all instructions */ for (ic = ebbs[i]->sch; ic; ic = ic->next) - { - - int j; - - if (SKIP_IC2 (ic) || !ic->rlive) - continue; - - /* first mark the registers used in this - instruction */ - ic->rUsed = regsUsedIniCode (ic); - _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed); - - /* now create the register mask for those - registers that are in use : this is a - super set of ic->rUsed */ - ic->rMask = newBitVect (mcs51_nRegs + 1); - - /* for all live Ranges alive at this point */ - for (j = 1; j < ic->rlive->size; j++) - { - symbol *sym; - int k; - - /* if not alive then continue */ - if (!bitVectBitValue (ic->rlive, j)) - continue; - - /* find the live range we are interested in */ - if (!(sym = hTabItemWithKey (liveRanges, j))) - { - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "createRegMask cannot find live range"); - exit (0); - } - - /* if no register assigned to it */ - if (!sym->nRegs || sym->isspilt) - continue; - - /* for all the registers allocated to it */ - for (k = 0; k < sym->nRegs; k++) - if (sym->regs[k]) - ic->rMask = - bitVectSetBit (ic->rMask, sym->regs[k]->rIdx); - } - } + { + + int j; + + if (SKIP_IC2 (ic) || !ic->rlive) + continue; + + /* first mark the registers used in this + instruction */ + ic->rUsed = regsUsedIniCode (ic); + _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed); + + /* now create the register mask for those + registers that are in use : this is a + super set of ic->rUsed */ + ic->rMask = newBitVect (mcs51_nRegs + 1); + + /* for all live Ranges alive at this point */ + for (j = 1; j < ic->rlive->size; j++) + { + symbol *sym; + int k; + + /* if not alive then continue */ + if (!bitVectBitValue (ic->rlive, j)) + continue; + + /* find the live range we are interested in */ + if (!(sym = hTabItemWithKey (liveRanges, j))) + { + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "createRegMask cannot find live range"); + fprintf(stderr, "\tmissing live range: key=%d\n", j); + exit (0); + } + + /* if no register assigned to it */ + if (!sym->nRegs || sym->isspilt) + continue; + + /* for all the registers allocated to it */ + for (k = 0; k < sym->nRegs; k++) + if (sym->regs[k]) + ic->rMask = + bitVectSetBit (ic->rMask, sym->regs[k]->rIdx); + } + } } } @@ -1367,32 +1843,48 @@ createRegMask (eBBlock ** ebbs, int count) static char * rematStr (symbol * sym) { - char *s = buffer; iCode *ic = sym->rematiCode; + int offset = 0; while (1) { - - /* if plus or minus print the right hand side */ - if (ic->op == '+' || ic->op == '-') - { - sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)), - ic->op); - s += strlen (s); - ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; - continue; - } + /* if plus adjust offset to right hand side */ + if (ic->op == '+') + { + offset += (int) operandLitValue (IC_RIGHT (ic)); + ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; + continue; + } + + /* if minus adjust offset to right hand side */ + if (ic->op == '-') + { + offset -= (int) operandLitValue (IC_RIGHT (ic)); + ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; + continue; + } /* cast then continue */ if (IS_CAST_ICODE(ic)) { - ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode; - continue; + ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode; + continue; } /* we reached the end */ - sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname); break; } + if (offset) + { + SNPRINTF (buffer, sizeof(buffer), + "(%s %c 0x%04x)", + OP_SYMBOL (IC_LEFT (ic))->rname, + offset >= 0 ? '+' : '-', + abs (offset) & 0xffff); + } + else + { + strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer)); + } return buffer; } @@ -1413,96 +1905,74 @@ regTypeNum (eBBlock *ebbs) /* if used zero times then no registers needed */ if ((sym->liveTo - sym->liveFrom) == 0) - continue; + continue; /* if the live range is a temporary */ if (sym->isitmp) - { - - /* if the type is marked as a conditional */ - if (sym->regType == REG_CND) - continue; - - /* if used in return only then we don't - need registers */ - if (sym->ruonly || sym->accuse) - { - if (IS_AGGREGATE (sym->type) || sym->isptr) - sym->type = aggrToPtr (sym->type, FALSE); - continue; - } - - /* if the symbol has only one definition & - that definition is a get_pointer and the - pointer we are getting is rematerializable and - in "data" space */ - - if (bitVectnBitsOn (sym->defs) == 1 && - (ic = hTabItemWithKey (iCodehTab, - bitVectFirstBit (sym->defs))) && - POINTER_GET (ic) && - !sym->noSpilLoc && - !IS_BITVAR (sym->etype)) - { - - - /* if remat in data space */ - if (OP_SYMBOL (IC_LEFT (ic))->remat && - !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) && - DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER) - { - /* create a psuedo symbol & force a spil */ - symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1); - psym->type = sym->type; - psym->etype = sym->etype; - strcpy (psym->rname, psym->name); - sym->isspilt = 1; - sym->usl.spillLoc = psym; -#if 0 // an alternative fix for bug #480076 - /* now this is a useless assignment to itself */ - remiCodeFromeBBlock (ebbs, ic); -#else - /* now this really is an assignment to itself, make it so; - it will be optimized out later */ - ic->op='='; - IC_RIGHT(ic)=IC_RESULT(ic); - IC_LEFT(ic)=NULL; -#endif - continue; - } - - /* if in data space or idata space then try to - allocate pointer register */ - - } - - /* if not then we require registers */ - sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ? - getSize (sym->type = aggrToPtr (sym->type, FALSE)) : - getSize (sym->type)); - - if (sym->nRegs > 4) - { - fprintf (stderr, "allocated more than 4 or 0 registers for type "); - printTypeChain (sym->type, stderr); - fprintf (stderr, "\n"); - } - - /* determine the type of register required */ - if (sym->nRegs == 1 && - IS_PTR (sym->type) && - sym->uptr) - sym->regType = REG_PTR; - else - sym->regType = REG_GPR; - - } + { + + /* if the type is marked as a conditional */ + if (sym->regType == REG_CND) + continue; + + /* if used in return only then we don't + need registers */ + if (sym->ruonly || sym->accuse) + { + if (IS_AGGREGATE (sym->type) || sym->isptr) + sym->type = aggrToPtr (sym->type, FALSE); + else if (IS_BIT(sym->type)) + sym->regType = REG_CND; + continue; + } + + /* if the symbol has only one definition & + that definition is a get_pointer */ + if (bitVectnBitsOn (sym->defs) == 1 && + (ic = hTabItemWithKey (iCodehTab, + bitVectFirstBit (sym->defs))) && + POINTER_GET (ic) && + !IS_BITVAR (sym->etype) && + (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) + { + + if (ptrPseudoSymSafe (sym, ic)) + { + ptrPseudoSymConvert (sym, ic, rematStr (OP_SYMBOL (IC_LEFT (ic)))); + continue; + } + + /* if in data space or idata space then try to + allocate pointer register */ + + } + + /* if not then we require registers */ + sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ? + getSize (sym->type = aggrToPtr (sym->type, FALSE)) : + getSize (sym->type)); + + if (sym->nRegs > 4) + { + fprintf (stderr, "allocated more than 4 or 0 registers for type "); + printTypeChain (sym->type, stderr); + fprintf (stderr, "\n"); + } + + /* determine the type of register required */ + if (sym->nRegs == 1 && IS_PTR (sym->type) && sym->uptr) + sym->regType = REG_PTR; + else if (IS_BIT(sym->type)) + sym->regType = REG_BIT; + else + sym->regType = REG_GPR; + } else - /* for the first run we don't provide */ - /* registers for true symbols we will */ - /* see how things go */ - sym->nRegs = 0; + /* for the first run we don't provide */ + /* registers for true symbols we will */ + /* see how things go */ + sym->nRegs = 0; } } @@ -1545,53 +2015,70 @@ farSpacePackable (iCode * ic) { /* if the definition is a call then no */ if ((dic->op == CALL || dic->op == PCALL) && - IC_RESULT (dic)->key == IC_RIGHT (ic)->key) - { - return NULL; - } + IC_RESULT (dic)->key == IC_RIGHT (ic)->key) + { + return NULL; + } /* if shift by unknown amount then not */ if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) && - IC_RESULT (dic)->key == IC_RIGHT (ic)->key) - return NULL; + IC_RESULT (dic)->key == IC_RIGHT (ic)->key) + return NULL; /* if pointer get and size > 1 */ if (POINTER_GET (dic) && - getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1) - return NULL; + getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1) + return NULL; if (POINTER_SET (dic) && - getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1) - return NULL; - - /* if any three is a true symbol in far space */ - if (IC_RESULT (dic) && - IS_TRUE_SYMOP (IC_RESULT (dic)) && - isOperandInFarSpace (IC_RESULT (dic))) - return NULL; - - if (IC_RIGHT (dic) && - IS_TRUE_SYMOP (IC_RIGHT (dic)) && - isOperandInFarSpace (IC_RIGHT (dic)) && - !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic))) - return NULL; - - if (IC_LEFT (dic) && - IS_TRUE_SYMOP (IC_LEFT (dic)) && - isOperandInFarSpace (IC_LEFT (dic)) && - !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic))) - return NULL; + getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1) + return NULL; + + if (dic->op == IFX) + { + if (IC_COND (dic) && + IS_TRUE_SYMOP (IC_COND (dic)) && + isOperandInFarSpace (IC_COND (dic))) + return NULL; + } + else if (dic->op == JUMPTABLE) + { + if (IC_JTCOND (dic) && + IS_TRUE_SYMOP (IC_JTCOND (dic)) && + isOperandInFarSpace (IC_JTCOND (dic))) + return NULL; + } + else + { + /* if any tree is a true symbol in far space */ + if (IC_RESULT (dic) && + IS_TRUE_SYMOP (IC_RESULT (dic)) && + isOperandInFarSpace (IC_RESULT (dic))) + return NULL; + + if (IC_RIGHT (dic) && + IS_TRUE_SYMOP (IC_RIGHT (dic)) && + isOperandInFarSpace (IC_RIGHT (dic)) && + !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic))) + return NULL; + + if (IC_LEFT (dic) && + IS_TRUE_SYMOP (IC_LEFT (dic)) && + isOperandInFarSpace (IC_LEFT (dic)) && + !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic))) + return NULL; + } if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic))) - { - if ((dic->op == LEFT_OP || - dic->op == RIGHT_OP || - dic->op == '-') && - IS_OP_LITERAL (IC_RIGHT (dic))) - return NULL; - else - return dic; - } + { + if ((dic->op == LEFT_OP || + dic->op == RIGHT_OP || + dic->op == '-') && + IS_OP_LITERAL (IC_RIGHT (dic))) + return NULL; + else + return dic; + } } return NULL; @@ -1604,12 +2091,10 @@ static int packRegsForAssign (iCode * ic, eBBlock * ebp) { iCode *dic, *sic; - //sym_link *etype = operandType (IC_RIGHT (ic)); if (!IS_ITEMP (IC_RIGHT (ic)) || OP_SYMBOL (IC_RIGHT (ic))->isind || - OP_LIVETO (IC_RIGHT (ic)) > ic->seq - /* why? || IS_BITFIELD (etype) */ ) + OP_LIVETO (IC_RIGHT (ic)) > ic->seq) { return 0; } @@ -1620,71 +2105,113 @@ packRegsForAssign (iCode * ic, eBBlock * ebp) return 0; } - /* find the definition of iTempNN scanning backwards if we find a - a use of the true symbol in before we find the definition then + /* find the definition of iTempNN scanning backwards if we find a + a use of the true symbol in before we find the definition then we cannot */ for (dic = ic->prev; dic; dic = dic->prev) { - /* if there is a function call then don't pack it */ + int crossedCall = 0; + + /* We can pack across a function call only if it's a local */ + /* variable or our parameter. Never pack global variables */ + /* or parameters to a function we call. */ if ((dic->op == CALL || dic->op == PCALL)) - { - dic = NULL; - break; - } + { + if (!OP_SYMBOL (IC_RESULT (ic))->ismyparm + && !OP_SYMBOL (IC_RESULT (ic))->islocal) + { + crossedCall = 1; + } + } + + /* Don't move an assignment out of a critical block */ + if (dic->op == CRITICAL) + { + dic = NULL; + break; + } if (SKIP_IC2 (dic)) - continue; - - if (IS_TRUE_SYMOP (IC_RESULT (dic)) && - IS_OP_VOLATILE (IC_RESULT (dic))) - { - dic = NULL; - break; - } - - if (IS_SYMOP (IC_RESULT (dic)) && - IC_RESULT (dic)->key == IC_RIGHT (ic)->key) - { - if (POINTER_SET (dic)) - dic = NULL; - - break; - } - - if (IS_SYMOP (IC_RIGHT (dic)) && - (IC_RIGHT (dic)->key == IC_RESULT (ic)->key || - IC_RIGHT (dic)->key == IC_RIGHT (ic)->key)) - { - dic = NULL; - break; - } - - if (IS_SYMOP (IC_LEFT (dic)) && - (IC_LEFT (dic)->key == IC_RESULT (ic)->key || - IC_LEFT (dic)->key == IC_RIGHT (ic)->key)) - { - dic = NULL; - break; - } - - if (POINTER_SET (dic) && - IC_RESULT (dic)->key == IC_RESULT (ic)->key) - { - dic = NULL; - break; - } + continue; + + if (dic->op == IFX) + { + if (IS_SYMOP (IC_COND (dic)) && + (IC_COND (dic)->key == IC_RESULT (ic)->key || + IC_COND (dic)->key == IC_RIGHT (ic)->key)) + { + dic = NULL; + break; + } + } + else + { + if (IS_TRUE_SYMOP (IC_RESULT (dic)) && + IS_OP_VOLATILE (IC_RESULT (dic))) + { + dic = NULL; + break; + } + + if (IS_SYMOP (IC_RESULT (dic)) && + IC_RESULT (dic)->key == IC_RIGHT (ic)->key) + { + if (POINTER_SET (dic)) + dic = NULL; + + break; + } + + if (IS_SYMOP (IC_RIGHT (dic)) && + (IC_RIGHT (dic)->key == IC_RESULT (ic)->key || + IC_RIGHT (dic)->key == IC_RIGHT (ic)->key)) + { + dic = NULL; + break; + } + + if (IS_SYMOP (IC_LEFT (dic)) && + (IC_LEFT (dic)->key == IC_RESULT (ic)->key || + IC_LEFT (dic)->key == IC_RIGHT (ic)->key)) + { + dic = NULL; + break; + } + + if (IS_SYMOP (IC_RESULT (dic)) && + IC_RESULT (dic)->key == IC_RESULT (ic)->key) + { + dic = NULL; + break; + } + + if (crossedCall) + { + dic = NULL; + break; + } + + } } if (!dic) - return 0; /* did not find */ + return 0; /* did not find */ /* if assignment then check that right is not a bit */ - if (ASSIGNMENT (dic) && !POINTER_SET (dic)) + if (ASSIGNMENT (ic) && !POINTER_SET (ic)) { - sym_link *etype = operandType (IC_RIGHT (dic)); + sym_link *etype = operandType (IC_RESULT (dic)); if (IS_BITFIELD (etype)) - return 0; + { + /* if result is a bit too then it's ok */ + etype = operandType (IC_RESULT (ic)); + if (!IS_BITFIELD (etype)) + { + return 0; + } + } } + /* if the result is on stack or iaccess then it must be the same atleast one of the operands */ if (OP_SYMBOL (IC_RESULT (ic))->onStack || @@ -1694,102 +2221,130 @@ packRegsForAssign (iCode * ic, eBBlock * ebp) /* the operation has only one symbol operator then we can pack */ if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) || - (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic)))) - goto pack; + (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic)))) + goto pack; if (!((IC_LEFT (dic) && - IC_RESULT (ic)->key == IC_LEFT (dic)->key) || - (IC_RIGHT (dic) && - IC_RESULT (ic)->key == IC_RIGHT (dic)->key))) - return 0; + IC_RESULT (ic)->key == IC_LEFT (dic)->key) || + (IC_RIGHT (dic) && + IC_RESULT (ic)->key == IC_RIGHT (dic)->key))) + return 0; } pack: /* found the definition */ /* replace the result with the result of */ /* this assignment and remove this assignment */ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - IC_RESULT (dic) = IC_RESULT (ic); + ReplaceOpWithCheaperOp(&IC_RESULT (dic), IC_RESULT (ic)); if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq) { OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq; } - /* delete from liverange table also + // TODO: and the otherway around? + + /* delete from liverange table also delete from all the points inbetween and the new one */ for (sic = dic; sic != ic; sic = sic->next) { bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key); if (IS_ITEMP (IC_RESULT (dic))) - bitVectSetBit (sic->rlive, IC_RESULT (dic)->key); + bitVectSetBit (sic->rlive, IC_RESULT (dic)->key); } remiCodeFromeBBlock (ebp, ic); bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key); hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); - OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); + OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); return 1; - } -/*-----------------------------------------------------------------*/ +/*------------------------------------------------------------------*/ /* findAssignToSym : scanning backwards looks for first assig found */ -/*-----------------------------------------------------------------*/ +/*------------------------------------------------------------------*/ static iCode * findAssignToSym (operand * op, iCode * ic) { iCode *dic; + /* This routine is used to find sequences like + iTempAA = FOO; + ...; (intervening ops don't use iTempAA or modify FOO) + blah = blah + iTempAA; + + and eliminate the use of iTempAA, freeing up its register for + other uses. + */ + for (dic = ic->prev; dic; dic = dic->prev) { /* if definition by assignment */ if (dic->op == '=' && - !POINTER_SET (dic) && - IC_RESULT (dic)->key == op->key + !POINTER_SET (dic) && + IC_RESULT (dic)->key == op->key /* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */ - ) - { + ) + break; /* found where this temp was defined */ - /* we are interested only if defined in far space */ - /* or in stack space in case of + & - */ + /* if we find an usage then we cannot delete it */ - /* if assigned to a non-symbol then return - FALSE */ - if (!IS_SYMOP (IC_RIGHT (dic))) - return NULL; + if (dic->op == IFX) + { + if (IC_COND (dic) && IC_COND (dic)->key == op->key) + return NULL; + } + else if (dic->op == JUMPTABLE) + { + if (IC_JTCOND (dic) && IC_JTCOND (dic)->key == op->key) + return NULL; + } + else + { + if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key) + return NULL; - /* if the symbol is in far space then - we should not */ - if (isOperandInFarSpace (IC_RIGHT (dic))) - return NULL; + if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key) + return NULL; - /* for + & - operations make sure that - if it is on the stack it is the same - as one of the three operands */ - if ((ic->op == '+' || ic->op == '-') && - OP_SYMBOL (IC_RIGHT (dic))->onStack) - { + if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key) + return NULL; + } + } - if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key && - IC_LEFT (ic)->key != IC_RIGHT (dic)->key && - IC_RIGHT (ic)->key != IC_RIGHT (dic)->key) - return NULL; - } + if (!dic) + return NULL; /* didn't find any assignment to op */ - break; + /* we are interested only if defined in far space */ + /* or in stack space in case of + & - */ - } + /* if assigned to a non-symbol then don't repack regs */ + if (!IS_SYMOP (IC_RIGHT (dic))) + return NULL; - /* if we find an usage then we cannot delete it */ - if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key) - return NULL; + /* if the symbol is volatile then we should not */ + if (isOperandVolatile (IC_RIGHT (dic), TRUE)) + return NULL; + /* XXX TODO --- should we be passing FALSE to isOperandVolatile()? + What does it mean for an iTemp to be volatile, anyway? Passing + TRUE is more cautious but may prevent possible optimizations */ - if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key) - return NULL; + /* if the symbol is in far space then we should not */ + if (isOperandInFarSpace (IC_RIGHT (dic))) + return NULL; + + /* for + & - operations make sure that + if it is on the stack it is the same + as one of the three operands */ + if ((ic->op == '+' || ic->op == '-') && + OP_SYMBOL (IC_RIGHT (dic))->onStack) + { - if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key) - return NULL; + if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key && + IC_LEFT (ic)->key != IC_RIGHT (dic)->key && + IC_RIGHT (ic)->key != IC_RIGHT (dic)->key) + return NULL; } /* now make sure that the right side of dic @@ -1799,24 +2354,61 @@ findAssignToSym (operand * op, iCode * ic) iCode *sic = dic->next; for (; sic != ic; sic = sic->next) - if (IC_RESULT (sic) && - IC_RESULT (sic)->key == IC_RIGHT (dic)->key) - return NULL; + if (IC_RESULT (sic) && + IC_RESULT (sic)->key == IC_RIGHT (dic)->key) + return NULL; } return dic; +} + +/*-----------------------------------------------------------------*/ +/* reassignAliasedSym - used by packRegsForSupport to replace */ +/* redundant iTemp with equivalent symbol */ +/*-----------------------------------------------------------------*/ +static void +reassignAliasedSym (eBBlock *ebp, iCode *assignment, iCode *use, operand *op) +{ + iCode *ic; + unsigned oldSymKey, newSymKey; + + oldSymKey = op->key; + newSymKey = IC_RIGHT(assignment)->key; + + /* only track live ranges of compiler-generated temporaries */ + if (!IS_ITEMP(IC_RIGHT(assignment))) + newSymKey = 0; + + /* update the live-value bitmaps */ + for (ic = assignment; ic != use; ic = ic->next) { + bitVectUnSetBit (ic->rlive, oldSymKey); + if (newSymKey != 0) + ic->rlive = bitVectSetBit (ic->rlive, newSymKey); + } + /* update the sym of the used operand */ + OP_SYMBOL(op) = OP_SYMBOL(IC_RIGHT(assignment)); + op->key = OP_SYMBOL(op)->key; + OP_SYMBOL(op)->accuse = 0; + /* update the sym's liverange */ + if ( OP_LIVETO(op) < ic->seq ) + setToRange(op, ic->seq, FALSE); + + /* remove the assignment iCode now that its result is unused */ + remiCodeFromeBBlock (ebp, assignment); + bitVectUnSetBit(OP_SYMBOL(IC_RESULT(assignment))->defs, assignment->key); + hTabDeleteItem (&iCodehTab, assignment->key, assignment, DELETE_ITEM, NULL); } + /*-----------------------------------------------------------------*/ /* packRegsForSupport :- reduce some registers for support calls */ /*-----------------------------------------------------------------*/ static int packRegsForSupport (iCode * ic, eBBlock * ebp) { - int change = 0; - iCode *dic, *sic; + iCode *dic; /* for the left & right operand :- look to see if the left was assigned a true symbol in far space in that @@ -1827,62 +2419,41 @@ packRegsForSupport (iCode * ic, eBBlock * ebp) { dic = findAssignToSym (IC_LEFT (ic), ic); - if (!dic) - goto right; - - /* found it we need to remove it from the - block */ - for (sic = dic; sic != ic; sic = sic->next) - bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key); - - OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic)); - IC_LEFT (ic)->key = OP_SYMBOL(IC_RIGHT (dic))->key; - remiCodeFromeBBlock (ebp, dic); - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); - change++; + if (dic) + { + /* found it we need to remove it from the block */ + reassignAliasedSym (ebp, dic, ic, IC_LEFT(ic)); + return 1; + } } /* do the same for the right operand */ - right: - if (!change && - IS_ITEMP (IC_RIGHT (ic)) && + if (IS_ITEMP (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq) { iCode *dic = findAssignToSym (IC_RIGHT (ic), ic); - iCode *sic; - - if (!dic) - return change; - - /* if this is a subtraction & the result - is a true symbol in far space then don't pack */ - if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic))) - { - sym_link *etype = getSpec (operandType (IC_RESULT (dic))); - if (IN_FARSPACE (SPEC_OCLS (etype))) - return change; - } - /* found it we need to remove it from the - block */ - for (sic = dic; sic != ic; sic = sic->next) - bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key); - - IC_RIGHT (ic)->operand.symOperand = - IC_RIGHT (dic)->operand.symOperand; - IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key; - - remiCodeFromeBBlock (ebp, dic); - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); - change++; + + if (dic) + { + /* if this is a subtraction & the result + is a true symbol in far space then don't pack */ + if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic))) + { + sym_link *etype = getSpec (operandType (IC_RESULT (dic))); + if (IN_FARSPACE (SPEC_OCLS (etype))) + return 0; + } + /* found it we need to remove it from the + block */ + reassignAliasedSym (ebp, dic, ic, IC_RIGHT(ic)); + + return 1; + } } - return change; + return 0; } -#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly) - /*-----------------------------------------------------------------*/ /* packRegsForOneuse : - will reduce some registers for single Use */ @@ -1890,11 +2461,14 @@ packRegsForSupport (iCode * ic, eBBlock * ebp) static iCode * packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) { - bitVect *uses; iCode *dic, *sic; /* if returning a literal then do nothing */ - if (!IS_SYMOP (op)) + if (!IS_ITEMP (op)) + return NULL; + + /* if rematerializable or already return use then do nothing */ + if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly) return NULL; /* only upto 2 bytes since we cannot predict @@ -1907,33 +2481,33 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) !POINTER_SET (ic) && !POINTER_GET (ic)) return NULL; - - /* this routine will mark the a symbol as used in one - instruction use only && if the defintion is local + + if (ic->op == SEND && ic->argreg != 1) return NULL; + + /* this routine will mark the symbol as used in one + instruction use only && if the definition is local (ie. within the basic block) && has only one definition && - that definiion is either a return value from a + that definition is either a return value from a function or does not contain any variables in far space */ - uses = bitVectCopy (OP_USES (op)); - bitVectUnSetBit (uses, ic->key); /* take away this iCode */ - if (!bitVectIsZero (uses)) /* has other uses */ + if (bitVectnBitsOn (OP_USES (op)) > 1) return NULL; - /* if it has only one defintion */ + /* if it has only one definition */ if (bitVectnBitsOn (OP_DEFS (op)) > 1) - return NULL; /* has more than one definition */ + return NULL; /* has more than one definition */ /* get that definition */ if (!(dic = - hTabItemWithKey (iCodehTab, - bitVectFirstBit (OP_DEFS (op))))) + hTabItemWithKey (iCodehTab, + bitVectFirstBit (OP_DEFS (op))))) return NULL; /* if that only usage is a cast */ if (dic->op == CAST) { /* to a bigger type */ - if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > - getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) { + if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > + getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) { /* than we can not, since we cannot predict the usage of b & acc */ return NULL; } @@ -1942,94 +2516,110 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) /* found the definition now check if it is local */ if (dic->seq < ebp->fSeq || dic->seq > ebp->lSeq) - return NULL; /* non-local */ + return NULL; /* non-local */ /* now check if it is the return from a function call */ if (dic->op == CALL || dic->op == PCALL) { - if (ic->op != SEND && ic->op != RETURN) - { - OP_SYMBOL (op)->ruonly = 1; - return dic; - } - dic = dic->next; + if (ic->op != SEND && ic->op != RETURN && + !POINTER_SET(ic) && !POINTER_GET(ic)) + { + OP_SYMBOL (op)->ruonly = 1; + return dic; + } } + else + { + /* otherwise check that the definition does + not contain any symbols in far space */ + if (isOperandInFarSpace (IC_LEFT (dic)) || + isOperandInFarSpace (IC_RIGHT (dic)) || + IS_OP_RUONLY (IC_LEFT (ic)) || + IS_OP_RUONLY (IC_RIGHT (ic))) + { + return NULL; + } + /* if pointer set then make sure the pointer + is one byte */ + if (POINTER_SET (dic) && + !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE))) + return NULL; - /* otherwise check that the definition does - not contain any symbols in far space */ - if (isOperandInFarSpace (IC_LEFT (dic)) || - isOperandInFarSpace (IC_RIGHT (dic)) || - IS_OP_RUONLY (IC_LEFT (ic)) || - IS_OP_RUONLY (IC_RIGHT (ic))) - { - return NULL; + if (POINTER_GET (dic) && + !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE))) + return NULL; } - /* if pointer set then make sure the pointer - is one byte */ - if (POINTER_SET (dic) && - !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE))) - return NULL; - - if (POINTER_GET (dic) && - !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE))) - return NULL; + /* Make sure no overlapping liverange is already assigned to DPTR */ + if (OP_SYMBOL(op)->clashes) + { + symbol *sym; + int i; + + for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) + { + if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) + { + sym = hTabItemWithKey(liveRanges,i); + if (sym->ruonly) + return NULL ; + } + } + } sic = dic; - /* also make sure the intervenening instructions - don't have any thing in far space */ + /* also make sure the intervening instructions + don't have anything in far space */ for (dic = dic->next; dic && dic != ic && sic != ic; dic = dic->next) { - /* if there is an intervening function call then no */ if (dic->op == CALL || dic->op == PCALL) - return NULL; + return NULL; /* if pointer set then make sure the pointer is one byte */ if (POINTER_SET (dic) && - !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE))) - return NULL; + !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE))) + return NULL; if (POINTER_GET (dic) && - !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE))) - return NULL; + !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE))) + return NULL; /* if address of & the result is remat the okay */ if (dic->op == ADDRESS_OF && - OP_SYMBOL (IC_RESULT (dic))->remat) - continue; + OP_SYMBOL (IC_RESULT (dic))->remat) + continue; /* if operand has size of three or more & this operation is a '*','/' or '%' then 'b' may cause a problem */ if ((dic->op == '%' || dic->op == '/' || dic->op == '*') && - getSize (operandType (op)) >= 3) - return NULL; + getSize (operandType (op)) >= 3) + return NULL; /* if left or right or result is in far space */ if (isOperandInFarSpace (IC_LEFT (dic)) || - isOperandInFarSpace (IC_RIGHT (dic)) || - isOperandInFarSpace (IC_RESULT (dic)) || - IS_OP_RUONLY (IC_LEFT (dic)) || - IS_OP_RUONLY (IC_RIGHT (dic)) || - IS_OP_RUONLY (IC_RESULT (dic))) - { - return NULL; - } + isOperandInFarSpace (IC_RIGHT (dic)) || + isOperandInFarSpace (IC_RESULT (dic)) || + IS_OP_RUONLY (IC_LEFT (dic)) || + IS_OP_RUONLY (IC_RIGHT (dic)) || + IS_OP_RUONLY (IC_RESULT (dic))) + { + return NULL; + } /* if left or right or result is on stack */ if (isOperandOnStack(IC_LEFT(dic)) || - isOperandOnStack(IC_RIGHT(dic)) || - isOperandOnStack(IC_RESULT(dic))) { - return NULL; + isOperandOnStack(IC_RIGHT(dic)) || + isOperandOnStack(IC_RESULT(dic))) { + return NULL; } } OP_SYMBOL (op)->ruonly = 1; return sic; - } /*-----------------------------------------------------------------*/ @@ -2042,7 +2632,7 @@ isBitwiseOptimizable (iCode * ic) sym_link *rtype = getSpec (operandType (IC_RIGHT (ic))); /* bitwise operations are considered optimizable - under the following conditions (Jean-Louis VERN) + under the following conditions (Jean-Louis VERN) x & lit bit & bit @@ -2061,6 +2651,63 @@ isBitwiseOptimizable (iCode * ic) return FALSE; } +/*-----------------------------------------------------------------*/ +/* isCommutativeOp - tests whether this op cares what order its */ +/* operands are in */ +/*-----------------------------------------------------------------*/ +bool isCommutativeOp(unsigned int op) +{ + if (op == '+' || op == '*' || op == EQ_OP || + op == '^' || op == '|' || op == BITWISEAND) + return TRUE; + else + return FALSE; +} + +/*-----------------------------------------------------------------*/ +/* operandUsesAcc - determines whether the code generated for this */ +/* operand will have to use the accumulator */ +/*-----------------------------------------------------------------*/ +bool operandUsesAcc(operand *op, bool allowBitspace) +{ + if (!op) + return FALSE; + + if (IS_SYMOP(op)) { + symbol *sym = OP_SYMBOL(op); + memmap *symspace; + + if (sym->accuse) + return TRUE; /* duh! */ + + if (IN_STACK(sym->etype) || sym->onStack || + (SPIL_LOC(op) && SPIL_LOC(op)->onStack)) + return TRUE; /* acc is used to calc stack offset */ + + if (IS_ITEMP(op)) + { + if (SPIL_LOC(op)) { + sym = SPIL_LOC(op); /* if spilled, look at spill location */ + } else { + return FALSE; /* more checks? */ + } + } + + symspace = SPEC_OCLS(sym->etype); + + if (sym->iaccess && symspace->paged) + return TRUE; /* must fetch paged indirect sym via accumulator */ + + if (!allowBitspace && IN_BITSPACE(symspace)) + return TRUE; /* fetching bit vars uses the accumulator */ + + if (IN_FARSPACE(symspace) || IN_CODESPACE(symspace)) + return TRUE; /* fetched via accumulator and dptr */ + } + + return FALSE; +} + /*-----------------------------------------------------------------*/ /* packRegsForAccUse - pack registers for acc use */ /*-----------------------------------------------------------------*/ @@ -2074,6 +2721,17 @@ packRegsForAccUse (iCode * ic) return; } + /* if we are calling a reentrant function that has stack parameters */ + if (ic->op == CALL && + IFFUNC_ISREENT(operandType(IC_LEFT(ic))) && + FUNC_HASSTACKPARM(operandType(IC_LEFT(ic)))) + return; + + if (ic->op == PCALL && + IFFUNC_ISREENT(operandType(IC_LEFT(ic))->next) && + FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))->next)) + return; + /* if + or - then it has to be one byte result */ if ((ic->op == '+' || ic->op == '-') && getSize (operandType (IC_RESULT (ic))) > 1) @@ -2094,7 +2752,6 @@ packRegsForAccUse (iCode * ic) getSize (operandType (IC_RESULT (ic))) > 1) return; - /* has only one definition */ if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1) return; @@ -2105,7 +2762,7 @@ packRegsForAccUse (iCode * ic) /* and the usage immediately follows this iCode */ if (!(uic = hTabItemWithKey (iCodehTab, - bitVectFirstBit (OP_USES (IC_RESULT (ic)))))) + bitVectFirstBit (OP_USES (IC_RESULT (ic)))))) return; if (ic->next != uic) @@ -2118,12 +2775,12 @@ packRegsForAccUse (iCode * ic) if (uic->op == JUMPTABLE) return; - /* if the usage is not is an assignment - or an arithmetic / bitwise / shift operation then not */ if (POINTER_SET (uic) && getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1) return; + /* if the usage is not an assignment + or an arithmetic / bitwise / shift operation then not */ if (uic->op != '=' && !IS_ARITHMETIC_OP (uic) && !IS_BITWISE_OP (uic) && @@ -2131,17 +2788,17 @@ packRegsForAccUse (iCode * ic) uic->op != RIGHT_OP) return; - /* if used in ^ operation then make sure right is not a - literl */ + /* if used in ^ operation then make sure right is not a + literal (WIML: Why is this?) */ if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic))) return; /* if shift operation make sure right side is not a literal */ + /* WIML: Why is this? */ if (uic->op == RIGHT_OP && (isOperandLiteral (IC_RIGHT (uic)) || getSize (operandType (IC_RESULT (uic))) > 1)) return; - if (uic->op == LEFT_OP && (isOperandLiteral (IC_RIGHT (uic)) || getSize (operandType (IC_RESULT (uic))) > 1)) @@ -2158,22 +2815,23 @@ packRegsForAccUse (iCode * ic) return; #endif - /* if either one of them in far space then we cannot */ - if ((IS_TRUE_SYMOP (IC_LEFT (uic)) && - isOperandInFarSpace (IC_LEFT (uic))) || - (IS_TRUE_SYMOP (IC_RIGHT (uic)) && - isOperandInFarSpace (IC_RIGHT (uic)))) - return; - /* if the usage has only one operand then we can */ if (IC_LEFT (uic) == NULL || IC_RIGHT (uic) == NULL) goto accuse; - /* make sure this is on the left side if not - a '+' since '+' is commutative */ - if (ic->op != '+' && - IC_LEFT (uic)->key != IC_RESULT (ic)->key) + /* if the other operand uses the accumulator then we cannot */ + if ( (IC_LEFT (uic)->key == IC_RESULT (ic)->key && + operandUsesAcc (IC_RIGHT (uic), IS_BIT (operandType (IC_LEFT (uic))))) || + (IC_RIGHT(uic)->key == IC_RESULT(ic)->key && + operandUsesAcc (IC_LEFT (uic), IS_BIT (operandType (IC_RIGHT (uic))))) ) + return; + + /* make sure this is on the left side if not commutative */ + /* except for '-', which has been written to be able to + handle reversed operands */ + if (!(isCommutativeOp(ic->op) || ic->op == '-') && + IC_LEFT (uic)->key != IC_RESULT (ic)->key) return; #if 0 @@ -2189,35 +2847,20 @@ packRegsForAccUse (iCode * ic) } #endif - /* if the other one is not on stack then we can */ - if (IC_LEFT (uic)->key == IC_RESULT (ic)->key && - (IS_ITEMP (IC_RIGHT (uic)) || - (IS_TRUE_SYMOP (IC_RIGHT (uic)) && - !OP_SYMBOL (IC_RIGHT (uic))->onStack))) - goto accuse; - - if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key && - (IS_ITEMP (IC_LEFT (uic)) || - (IS_TRUE_SYMOP (IC_LEFT (uic)) && - !OP_SYMBOL (IC_LEFT (uic))->onStack))) - goto accuse; - - return; - accuse: OP_SYMBOL (IC_RESULT (ic))->accuse = 1; - } /*-----------------------------------------------------------------*/ -/* packForPush - hueristics to reduce iCode for pushing */ +/* packForPush - heuristics to reduce iCode for pushing */ /*-----------------------------------------------------------------*/ static void -packForPush (iCode * ic, eBBlock * ebp) +packForPush (iCode * ic, eBBlock ** ebpp, int blockno) { iCode *dic, *lic; bitVect *dbv; + struct eBBlock * ebp=ebpp[blockno]; if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic))) return; @@ -2229,38 +2872,52 @@ packForPush (iCode * ic, eBBlock * ebp) /* find the definition */ if (!(dic = hTabItemWithKey (iCodehTab, - bitVectFirstBit (OP_DEFS (IC_LEFT (ic)))))) + bitVectFirstBit (OP_DEFS (IC_LEFT (ic)))))) return; if (dic->op != '=' || POINTER_SET (dic)) return; - /* make sure the right side does not have any definitions - inbetween */ - dbv = OP_DEFS(IC_RIGHT(dic)); - for (lic = ic; lic && lic != dic ; lic = lic->prev) { - if (bitVectBitValue(dbv,lic->key)) - return ; + if (dic->seq < ebp->fSeq) { // Evelyn did this + int i; + for (i=0; iseq >= ebpp[i]->fSeq && dic->seq <= ebpp[i]->lSeq) { + ebp=ebpp[i]; + break; + } + } + wassert (i!=blockno); // no way to recover from here } - /* make sure they have the same type */ - { - sym_link *itype=operandType(IC_LEFT(ic)); - sym_link *ditype=operandType(IC_RIGHT(dic)); - if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) || - SPEC_LONG(itype)!=SPEC_LONG(ditype)) - return; - } - /* extend the live range of replaced operand if needed */ - if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) { - OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq; + if (IS_SYMOP(IC_RIGHT(dic))) { + /* make sure the right side does not have any definitions + inbetween */ + dbv = OP_DEFS(IC_RIGHT(dic)); + for (lic = ic; lic && lic != dic ; lic = lic->prev) { + if (bitVectBitValue(dbv,lic->key)) + return ; + } + /* make sure they have the same type */ + if (IS_SPEC(operandType(IC_LEFT(ic)))) + { + sym_link *itype=operandType(IC_LEFT(ic)); + sym_link *ditype=operandType(IC_RIGHT(dic)); + + if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) || + SPEC_LONG(itype)!=SPEC_LONG(ditype)) + return; + } + /* extend the live range of replaced operand if needed */ + if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) { + OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq; + } + bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); } + /* we now we know that it has one & only one def & use and the that the definition is an assignment */ - IC_LEFT (ic) = IC_RIGHT (dic); - + ReplaceOpWithCheaperOp(&IC_LEFT (ic), IC_RIGHT (dic)); remiCodeFromeBBlock (ebp, dic); - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); } @@ -2269,14 +2926,14 @@ packForPush (iCode * ic, eBBlock * ebp) /* pressure */ /*-----------------------------------------------------------------*/ static void -packRegisters (eBBlock * ebp) +packRegisters (eBBlock ** ebpp, int blockno) { iCode *ic; int change = 0; + eBBlock *ebp=ebpp[blockno]; while (1) { - change = 0; /* look for assignments of the form */ @@ -2284,246 +2941,310 @@ packRegisters (eBBlock * ebp) /* .... */ /* TrueSym := iTempNN:1 */ for (ic = ebp->sch; ic; ic = ic->next) - { - /* find assignment of the form TrueSym := iTempNN:1 */ - if (ic->op == '=' && !POINTER_SET (ic)) - change += packRegsForAssign (ic, ebp); - } + { + /* find assignment of the form TrueSym := iTempNN:1 */ + if (ic->op == '=' && !POINTER_SET (ic)) + change += packRegsForAssign (ic, ebp); + } if (!change) - break; + break; } for (ic = ebp->sch; ic; ic = ic->next) { - /* if this is an itemp & result of an address of a true sym + /* Fix for bug #979599: */ + /* P0 &= ~1; */ + + /* Look for two subsequent iCodes with */ + /* iTemp := _c; */ + /* _c = iTemp & op; */ + /* and replace them by */ + /* iTemp := _c; */ + /* _c = _c & op; */ + if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^') && + ic->prev && + ic->prev->op == '=' && + IS_ITEMP (IC_LEFT (ic)) && + IC_LEFT (ic) == IC_RESULT (ic->prev) && + isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev))) + { + iCode* ic_prev = ic->prev; + symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev)); + + ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic)); + if (IC_RESULT (ic_prev) != IC_RIGHT (ic)) + { + bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key); + if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */ + prev_result_sym->liveTo == ic->seq) + { + prev_result_sym->liveTo = ic_prev->seq; + } + } + bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key); + + bitVectSetBit (ic->rlive, IC_RESULT (ic)->key); + + if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev)))) + { + bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key); + bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key); + remiCodeFromeBBlock (ebp, ic_prev); + hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL); + } + } + + /* if this is an itemp & result of an address of a true sym then mark this as rematerialisable */ if (ic->op == ADDRESS_OF && - IS_ITEMP (IC_RESULT (ic)) && - IS_TRUE_SYMOP (IC_LEFT (ic)) && - bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 && - !OP_SYMBOL (IC_LEFT (ic))->onStack) - { - - OP_SYMBOL (IC_RESULT (ic))->remat = 1; - OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic; - OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL; - - } + IS_ITEMP (IC_RESULT (ic)) && + IS_TRUE_SYMOP (IC_LEFT (ic)) && + bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 && + !OP_SYMBOL (IC_LEFT (ic))->onStack) + { + OP_SYMBOL (IC_RESULT (ic))->remat = 1; + OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic; + OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL; + } /* if straight assignment then carry remat flag if this is the only definition */ if (ic->op == '=' && - !POINTER_SET (ic) && - IS_SYMOP (IC_RIGHT (ic)) && - OP_SYMBOL (IC_RIGHT (ic))->remat && - !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) && - bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1) - { - - OP_SYMBOL (IC_RESULT (ic))->remat = - OP_SYMBOL (IC_RIGHT (ic))->remat; - OP_SYMBOL (IC_RESULT (ic))->rematiCode = - OP_SYMBOL (IC_RIGHT (ic))->rematiCode; - } + !POINTER_SET (ic) && + IS_SYMOP (IC_RIGHT (ic)) && + OP_SYMBOL (IC_RIGHT (ic))->remat && + !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) && + !isOperandGlobal(IC_RESULT(ic)) && /* due to bug 1618050 */ + bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1) + { + OP_SYMBOL (IC_RESULT (ic))->remat = + OP_SYMBOL (IC_RIGHT (ic))->remat; + OP_SYMBOL (IC_RESULT (ic))->rematiCode = + OP_SYMBOL (IC_RIGHT (ic))->rematiCode; + } /* if cast to a generic pointer & the pointer being - cast is remat, then we can remat this cast as well */ - if (ic->op == CAST && - IS_SYMOP(IC_RIGHT(ic)) && - OP_SYMBOL(IC_RIGHT(ic))->remat ) { - sym_link *to_type = operandType(IC_LEFT(ic)); - sym_link *from_type = operandType(IC_RIGHT(ic)); - if (IS_GENPTR(to_type) && IS_PTR(from_type)) { - OP_SYMBOL (IC_RESULT (ic))->remat = 1; - OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic; - OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL; - } - } - - /* if this is a +/- operation with a rematerizable + cast is remat, then we can remat this cast as well */ + if (ic->op == CAST && + IS_SYMOP(IC_RIGHT(ic)) && + OP_SYMBOL(IC_RIGHT(ic))->remat && + bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1) + { + sym_link *to_type = operandType(IC_LEFT(ic)); + sym_link *from_type = operandType(IC_RIGHT(ic)); + if (IS_GENPTR(to_type) && IS_PTR(from_type)) + { + OP_SYMBOL (IC_RESULT (ic))->remat = 1; + OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic; + OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL; + } + } + + /* if this is a +/- operation with a rematerizable then mark this as rematerializable as well */ if ((ic->op == '+' || ic->op == '-') && - (IS_SYMOP (IC_LEFT (ic)) && - IS_ITEMP (IC_RESULT (ic)) && - IS_OP_LITERAL (IC_RIGHT (ic))) && - OP_SYMBOL (IC_LEFT (ic))->remat && - (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) && - bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1) - { - OP_SYMBOL (IC_RESULT (ic))->remat = 1; - OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic; - OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL; - } + (IS_SYMOP (IC_LEFT (ic)) && + IS_ITEMP (IC_RESULT (ic)) && + IS_OP_LITERAL (IC_RIGHT (ic))) && + OP_SYMBOL (IC_LEFT (ic))->remat && + (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) && + bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1) + { + OP_SYMBOL (IC_RESULT (ic))->remat = 1; + OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic; + OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL; + } /* mark the pointer usages */ - if (POINTER_SET (ic)) - OP_SYMBOL (IC_RESULT (ic))->uptr = 1; + if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic))) + OP_SYMBOL (IC_RESULT (ic))->uptr = 1; - if (POINTER_GET (ic)) - OP_SYMBOL (IC_LEFT (ic))->uptr = 1; + if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))) + OP_SYMBOL (IC_LEFT (ic))->uptr = 1; if (!SKIP_IC2 (ic)) - { - /* if we are using a symbol on the stack - then we should say mcs51_ptrRegReq */ - if (ic->op == IFX && IS_SYMOP (IC_COND (ic))) - mcs51_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack || - OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0); - else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic))) - mcs51_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack || - OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0); - else - { - if (IS_SYMOP (IC_LEFT (ic))) - mcs51_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack || - OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0); - if (IS_SYMOP (IC_RIGHT (ic))) - mcs51_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack || - OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0); - if (IS_SYMOP (IC_RESULT (ic))) - mcs51_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack || - OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0); - } - } + { + /* if we are using a symbol on the stack + then we should say mcs51_ptrRegReq */ + if (options.useXstack && ic->parmPush + && (ic->op == IPUSH || ic->op == IPOP)) + mcs51_ptrRegReq++; + if (ic->op == IFX && IS_SYMOP (IC_COND (ic))) + mcs51_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack || + OP_SYMBOL (IC_COND (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_COND (ic))->etype) == idata) ? 1 : 0); + else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic))) + mcs51_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack || + OP_SYMBOL (IC_JTCOND (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_JTCOND (ic))->etype) == idata) ? 1 : 0); + else + { + if (IS_SYMOP (IC_LEFT (ic))) + mcs51_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack || + OP_SYMBOL (IC_LEFT (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata) ? 1 : 0); + if (IS_SYMOP (IC_RIGHT (ic))) + mcs51_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack || + OP_SYMBOL (IC_RIGHT (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata) ? 1 : 0); + if (IS_SYMOP (IC_RESULT (ic))) + mcs51_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack || + OP_SYMBOL (IC_RESULT (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_RESULT (ic))->etype) == idata) ? 1 : 0); + if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic)) + && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE) + mcs51_ptrRegReq ++; + if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic)) + && getSize (OP_SYMBOL (IC_RESULT (ic))->type) <= (unsigned int) PTRSIZE) + mcs51_ptrRegReq ++; + } + } /* if the condition of an if instruction is defined in the previous instruction and - this is the only usage then + this is the only usage then mark the itemp as a conditional */ if ((IS_CONDITIONAL (ic) || - (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) && - ic->next && ic->next->op == IFX && - bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 && - isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) && - OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq) - { - OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND; - continue; - } + (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) && + ic->next && ic->next->op == IFX && + bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 && + isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) && + OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq) + { + OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND; + continue; + } + + /* if the condition of an if instruction + is defined in the previous GET_POINTER instruction and + this is the only usage then + mark the itemp as accumulator use */ + if ((POINTER_GET (ic) && getSize (operandType (IC_RESULT (ic))) <=1) && + ic->next && ic->next->op == IFX && + bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 && + isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) && + OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq) + { + OP_SYMBOL (IC_RESULT (ic))->accuse = 1; + continue; + } /* reduce for support function calls */ if (ic->supportRtn || ic->op == '+' || ic->op == '-') - packRegsForSupport (ic, ebp); + packRegsForSupport (ic, ebp); /* some cases the redundant moves can can be eliminated for return statements */ - if ((ic->op == RETURN || ic->op == SEND) && - !isOperandInFarSpace (IC_LEFT (ic)) && - options.model == MODEL_SMALL) { - if (0 && options.stackAuto) { - /* we should check here if acc will be clobbered for stack - offset calculations */ - } else { - packRegsForOneuse (ic, IC_LEFT (ic), ebp); - } + if ((ic->op == RETURN || (ic->op == SEND && ic->argreg == 1)) && + !isOperandInFarSpace (IC_LEFT (ic)) && + options.model == MODEL_SMALL) { + packRegsForOneuse (ic, IC_LEFT (ic), ebp); } /* if pointer set & left has a size more than one and right is not in far space */ if (POINTER_SET (ic) && - !isOperandInFarSpace (IC_RIGHT (ic)) && - !OP_SYMBOL (IC_RESULT (ic))->remat && - !IS_OP_RUONLY (IC_RIGHT (ic)) && - getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) - - packRegsForOneuse (ic, IC_RESULT (ic), ebp); + IS_SYMOP (IC_RESULT (ic)) && + !isOperandInFarSpace (IC_RIGHT (ic)) && + !OP_SYMBOL (IC_RESULT (ic))->remat && + !IS_OP_RUONLY (IC_RIGHT (ic)) && + getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) + packRegsForOneuse (ic, IC_RESULT (ic), ebp); /* if pointer get */ if (POINTER_GET (ic) && - !isOperandInFarSpace (IC_RESULT (ic)) && - !OP_SYMBOL (IC_LEFT (ic))->remat && - !IS_OP_RUONLY (IC_RESULT (ic)) && - getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) - - packRegsForOneuse (ic, IC_LEFT (ic), ebp); - - - /* if this is cast for intergral promotion then - check if only use of the definition of the + IS_SYMOP (IC_LEFT (ic)) && + !isOperandInFarSpace (IC_RESULT (ic)) && + !OP_SYMBOL (IC_LEFT (ic))->remat && + !IS_OP_RUONLY (IC_RESULT (ic)) && + getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) + packRegsForOneuse (ic, IC_LEFT (ic), ebp); + + /* if this is a cast for intergral promotion then + check if it's the only use of the definition of the operand being casted/ if yes then replace - the result of that arithmetic operation with + the result of that arithmetic operation with this result and get rid of the cast */ if (ic->op == CAST) - { - sym_link *fromType = operandType (IC_RIGHT (ic)); - sym_link *toType = operandType (IC_LEFT (ic)); - - if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) && - getSize (fromType) != getSize (toType) && - SPEC_USIGN (fromType) == SPEC_USIGN (toType)) - { - - iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp); - if (dic) - { - if (IS_ARITHMETIC_OP (dic)) - { - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - IC_RESULT (dic) = IC_RESULT (ic); - remiCodeFromeBBlock (ebp, ic); - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key); - hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); - OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); - ic = ic->prev; - } - else - OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0; - } - } - else - { - - /* if the type from and type to are the same - then if this is the only use then packit */ - if (compareType (operandType (IC_RIGHT (ic)), - operandType (IC_LEFT (ic))) == 1) - { - iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp); - if (dic) - { - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - IC_RESULT (dic) = IC_RESULT (ic); - remiCodeFromeBBlock (ebp, ic); - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key); - hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); - OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); - ic = ic->prev; - } - } - } - } - - /* pack for PUSH + { + sym_link *fromType = operandType (IC_RIGHT (ic)); + sym_link *toType = operandType (IC_LEFT (ic)); + + if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) && + getSize (fromType) != getSize (toType) && + SPEC_USIGN (fromType) == SPEC_USIGN (toType)) + { + + iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp); + if (dic) + { + if (IS_ARITHMETIC_OP (dic)) + { + bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); + ReplaceOpWithCheaperOp(&IC_RESULT (dic), IC_RESULT (ic)); + remiCodeFromeBBlock (ebp, ic); + bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key); + hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); + OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); + ic = ic->prev; + } + else + OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0; + } + } + else + { + /* if the type from and type to are the same + then if this is the only use then packit */ + if (compareType (operandType (IC_RIGHT (ic)), + operandType (IC_LEFT (ic))) == 1) + { + iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp); + if (dic) + { + bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); + ReplaceOpWithCheaperOp(&IC_RESULT (dic), IC_RESULT (ic)); + remiCodeFromeBBlock (ebp, ic); + bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key); + hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL); + OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); + ic = ic->prev; + } + } + } + } + + /* pack for PUSH iTempNN := (some variable in farspace) V1 push iTempNN ; ------------- push V1 */ if (ic->op == IPUSH) - { - packForPush (ic, ebp); - } + { + packForPush (ic, ebpp, blockno); + } /* pack registers for accumulator use, when the result of an arithmetic or bit wise operation has only one use, that use is immediately following - the defintion and the using iCode has only one + the definition and the using iCode has only one operand or has two operands but one is literal & the result of that operation is not on stack then we can leave the result of this operation in acc:b combination */ if ((IS_ARITHMETIC_OP (ic) - || IS_CONDITIONAL(ic) - || IS_BITWISE_OP (ic) - || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL - || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic))) - ) && - IS_ITEMP (IC_RESULT (ic)) && - getSize (operandType (IC_RESULT (ic))) <= 2) - - packRegsForAccUse (ic); + || IS_CONDITIONAL(ic) + || IS_BITWISE_OP (ic) + || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL + || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic))) + ) && + IS_ITEMP (IC_RESULT (ic)) && + getSize (operandType (IC_RESULT (ic))) <= 2) + + packRegsForAccUse (ic); } } @@ -2531,30 +3252,53 @@ packRegisters (eBBlock * ebp) /* assignRegisters - assigns registers to each live range as need */ /*-----------------------------------------------------------------*/ void -mcs51_assignRegisters (eBBlock ** ebbs, int count) +mcs51_assignRegisters (ebbIndex * ebbi) { + eBBlock ** ebbs = ebbi->bbOrder; + int count = ebbi->count; iCode *ic; int i; setToNull ((void *) &_G.funcrUsed); + setToNull ((void *) &_G.regAssigned); + setToNull ((void *) &_G.totRegAssigned); mcs51_ptrRegReq = _G.stackExtend = _G.dataExtend = 0; - mcs51_nRegs = 8; + if ((currFunc && IFFUNC_ISREENT (currFunc->type)) || options.stackAuto) + { + mcs51_nRegs = 16; + } + else + { + mcs51_nRegs = 8; + } + _G.allBitregs = findAllBitregs (); + /* change assignments this will remove some live ranges reducing some register pressure */ + for (i = 0; i < count; i++) - packRegisters (ebbs[i]); + packRegisters (ebbs, i); + + /* liveranges probably changed by register packing + so we compute them again */ + recomputeLiveRanges (ebbs, count); if (options.dump_pack) - dumpEbbsToFileExt (DUMP_PACK, ebbs, count); + dumpEbbsToFileExt (DUMP_PACK, ebbi); - /* first determine for each live range the number of + /* first determine for each live range the number of registers & the type of registers required for each */ regTypeNum (*ebbs); /* and serially allocate registers */ serialRegAssign (ebbs, count); + freeAllRegs (); + //setToNull ((void *) &_G.regAssigned); + //setToNull ((void *) &_G.totRegAssigned); + fillGaps(); + /* if stack was extended then tell the user */ if (_G.stackExtend) { @@ -2575,11 +3319,21 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count) createRegMask (ebbs, count); /* redo that offsets for stacked automatic variables */ - redoStackOffsets (); + if (currFunc) { + redoStackOffsets (); + } + + /* make sure r0 & r1 are flagged as used if they might be used */ + /* as pointers */ + if (currFunc && mcs51_ptrRegReq) + { + currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R0_IDX); + currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R1_IDX); + } if (options.dump_rassgn) { - dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count); + dumpEbbsToFileExt (DUMP_RASSGN, ebbi); dumpLiveRanges (DUMP_LRANGE, liveRanges); } @@ -2594,8 +3348,8 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count) /* free up any _G.stackSpil locations allocated */ applyToSet (_G.stackSpil, deallocStackSpil); _G.slocNum = 0; - setToNull ((void **) &_G.stackSpil); - setToNull ((void **) &_G.spiltSet); + setToNull ((void *) &_G.stackSpil); + setToNull ((void *) &_G.spiltSet); /* mark all registers as free */ freeAllRegs ();