X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fhc08%2Fralloc.c;h=995b78763b3f8a0353d4d2b566ee7da231868015;hb=90bdb43b342189fcb94a398855d43f3f47f96738;hp=ee599f19353b95df7c0a021a1dfa297b7062ab6e;hpb=b59e5e4e1c772b197e15e9f82f42507d18bcb546;p=fw%2Fsdcc diff --git a/src/hc08/ralloc.c b/src/hc08/ralloc.c index ee599f19..995b7876 100644 --- a/src/hc08/ralloc.c +++ b/src/hc08/ralloc.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------ - SDCCralloc.c - source file for register allocation. (8051) specific + SDCCralloc.c - source file for register allocation. 68HC08 specific Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) @@ -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" @@ -61,21 +61,23 @@ int hc08_ptrRegReq; /* one byte pointer register required */ regs regshc08[] = { - {REG_GPR, A_IDX, REG_GPR, "a", "a", "0", 1, NULL, 0, 1}, - {REG_GPR, X_IDX, REG_GPR, "x", "x", "0", 2, NULL, 0, 1}, - {REG_GPR, H_IDX, REG_GPR, "h", "h", "0", 4, NULL, 0, 1}, - {REG_PTR, HX_IDX, REG_PTR, "hx", "hx", "0", 6, NULL, 0, 1}, - {REG_GPR, XA_IDX, REG_GPR, "xa", "xa", "0", 3, NULL, 0, 1}, + {REG_GPR, A_IDX, "a", 1, NULL, 0, 1}, + {REG_GPR, X_IDX, "x", 2, NULL, 0, 1}, + {REG_GPR, H_IDX, "h", 4, NULL, 0, 1}, + {REG_PTR, HX_IDX, "hx", 6, NULL, 0, 1}, + {REG_GPR, XA_IDX, "xa", 3, NULL, 0, 1}, - {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, NULL, 0, 1}, + {REG_CND, CND_IDX, "C", 0, NULL, 0, 1}, + {0, SP_IDX, "sp", 0, NULL, 0, 1}, }; -int hc08_nRegs = 6; +int hc08_nRegs = 7; regs *hc08_reg_a; regs *hc08_reg_x; regs *hc08_reg_h; regs *hc08_reg_hx; regs *hc08_reg_xa; +regs *hc08_reg_sp; static void spillThis (symbol *); static void freeAllRegs (); @@ -87,7 +89,7 @@ static regs * allocReg (short type) { return NULL; - + if ((type==REG_PTR) && (regshc08[HX_IDX].isFree)) { regshc08[HX_IDX].isFree = 0; @@ -130,7 +132,7 @@ hc08_freeReg (regs * reg) } reg->isFree = 1; - + switch (reg->rIdx) { case A_IDX: @@ -283,9 +285,9 @@ 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 */ @@ -389,7 +391,7 @@ liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *), if (!bitVectBitValue (lrs, i)) 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))) { @@ -509,7 +511,7 @@ spillLRWithPtrReg (symbol * forSym) int j; /* if no registers assigned to it or spilt */ - /* if it does not overlap with this then + /* if it does not overlap with this then not need to spill it */ if (lrsym->isspilt || !lrsym->nRegs || @@ -539,7 +541,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)) { @@ -607,7 +609,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; @@ -653,7 +655,7 @@ spillThis (symbol * sym) if (!(sym->remat || sym->usl.spillLoc)) createStackSpil (sym); - /* mark it has spilt & put it in the spilt set */ + /* mark it as spilt & put it in the spilt set */ sym->isspilt = sym->spillA = 1; _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key); @@ -668,7 +670,7 @@ spillThis (symbol * sym) 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 (!hc08_ptrRegReq && isSpiltOnStack (sym)) @@ -736,7 +738,9 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) /* 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))) + if (!_G.blockSpil && + !isiCodeInFunctionCall (ic) && + (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic))) { sym = leastUsedLR (selectS); if (sym != forSym) @@ -823,7 +827,7 @@ 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) { @@ -878,7 +882,7 @@ tryAgain: if (!spilSomething (ic, ebp, sym)) return NULL; - /* this looks like an infinite loop but + /* this looks like an infinite loop but in really selectSpil will abort */ goto tryAgain; } @@ -904,7 +908,7 @@ tryAgain: if (!spilSomething (ic, ebp, sym)) return NULL; - /* this looks like an infinite loop but + /* this looks like an infinite loop but in really selectSpil will abort */ goto tryAgain; } @@ -985,7 +989,7 @@ deassignLRs (iCode * ic, eBBlock * ebp) if (sym->liveTo > ic->seq) 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) { @@ -1001,7 +1005,7 @@ deassignLRs (iCode * ic, eBBlock * ebp) 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 && @@ -1030,6 +1034,7 @@ deassignLRs (iCode * ic, eBBlock * ebp) (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 */ @@ -1101,8 +1106,8 @@ willCauseSpill (int nr, int rt) of te 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; @@ -1179,16 +1184,16 @@ 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, + + werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT, sym->prereqv ? sym->prereqv->name : sym->name); spillThis (sym); } @@ -1260,7 +1265,13 @@ serialRegAssign (eBBlock ** ebbs, int count) int j; int ptrRegSet = 0; - /* if it does not need or is spilt + /* Make sure any spill location is definately 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 || @@ -1277,14 +1288,24 @@ serialRegAssign (eBBlock ** ebbs, int count) continue; } /* if trying to allocate this will cause - a spill and there is nothing to spill + 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))) { + 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; + continue; } /* if it has a spillocation & is used less than @@ -1387,7 +1408,7 @@ serialRegAssign (eBBlock ** ebbs, int count) verifyRegsAssigned (IC_LEFT (ic), ic); verifyRegsAssigned (IC_RIGHT (ic), ic); } - } + } } @@ -1397,12 +1418,12 @@ serialRegAssign (eBBlock ** ebbs, int count) static void fillGaps() { symbol *sym =NULL; - int key =0; - + int key =0; + if (getenv("DISABLE_FILL_GAPS")) return; - - /* look for livernages that was spilt by the allocator */ - for (sym = hTabFirstItem(liveRanges,&key) ; sym ; + + /* look for liveranges that were spilt by the allocator */ + for (sym = hTabFirstItem(liveRanges,&key) ; sym ; sym = hTabNextItem(liveRanges,&key)) { int i; @@ -1422,9 +1443,9 @@ static void fillGaps() clr = hTabItemWithKey(liveRanges,i); assert(clr); - + /* mark these registers as used */ - for (k = 0 ; k < clr->nRegs ; k++ ) + for (k = 0 ; k < clr->nRegs ; k++ ) hc08_useReg(clr->regs[k]); } @@ -1439,12 +1460,12 @@ static void fillGaps() if (sym->regType == REG_PTR) sym->regs[i] = getRegPtrNoSpil (); else - sym->regs[i] = getRegGprNoSpil (); + sym->regs[i] = getRegGprNoSpil (); } /* for all its definitions check if the registers allocated needs positioning NOTE: we can position - only ONCE if more than One positioning required + only ONCE if more than One positioning required then give up */ sym->isspilt = 0; for (i = 0 ; i < sym->defs->size ; i++ ) { @@ -1454,11 +1475,11 @@ static void fillGaps() 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)) && + if (IS_SYMOP(IC_LEFT(ic)) && bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) { pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic))); } - if (IS_SYMOP(IC_RIGHT(ic)) && + if (IS_SYMOP(IC_RIGHT(ic)) && bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) { pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic))); } @@ -1473,7 +1494,7 @@ static void fillGaps() if (!IS_ASSIGN_ICODE(ic)) continue ; /* if result is assigned to registers */ - if (IS_SYMOP(IC_RESULT(ic)) && + if (IS_SYMOP(IC_RESULT(ic)) && bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) { pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic))); } @@ -1489,7 +1510,7 @@ static void fillGaps() } freeAllRegs(); D(printf ("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN")); - continue ; + continue ; } D(printf ("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN")); _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key); @@ -1606,7 +1627,7 @@ createRegMask (eBBlock ** ebbs, int count) ic->rUsed = regsUsedIniCode (ic); _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed); - /* now create the register mask for those + /* now create the register mask for those registers that are in use : this is a super set of ic->rUsed */ ic->rMask = newBitVect (hc08_nRegs + 1); @@ -1653,7 +1674,7 @@ rematStr (symbol * sym) char *s = buffer; iCode *ic = sym->rematiCode; // int offset = 0; - + while (1) { /* if plus or minus print the right hand side */ @@ -1666,7 +1687,7 @@ rematStr (symbol * sym) continue; } -/* +/* if (ic->op == '+') { offset += operandLitValue (IC_RIGHT (ic)); @@ -1724,7 +1745,7 @@ regTypeNum (eBBlock *ebbs) if (sym->regType == REG_CND) continue; - /* if used in return only then we don't + /* if used in return only then we don't need registers */ if (sym->ruonly || sym->accuse) { @@ -1739,34 +1760,13 @@ regTypeNum (eBBlock *ebbs) (ic = hTabItemWithKey (iCodehTab, bitVectFirstBit (sym->defs))) && POINTER_GET (ic) && - !sym->noSpilLoc && - !IS_BITVAR (sym->etype)) + !IS_BITVAR (sym->etype) && + (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) { - - /* and that pointer is remat in data space */ - if (IS_SYMOP (IC_LEFT (ic)) && - OP_SYMBOL (IC_LEFT (ic))->remat && - !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) && - DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER) + if (ptrPseudoSymSafe (sym, ic)) { - /* 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='='; - ReplaceOpWithCheaperOp(&IC_RIGHT(ic), IC_RESULT(ic)); - IC_LEFT(ic)=NULL; -#endif + ptrPseudoSymConvert (sym, ic, rematStr (OP_SYMBOL (IC_LEFT (ic)))); continue; } @@ -1907,7 +1907,7 @@ packRegsForLiteral (iCode * ic) { int k; iCode *uic; - + if (ic->op != '=') return; if (POINTER_SET (ic)) @@ -1922,7 +1922,7 @@ packRegsForLiteral (iCode * ic) { uic = hTabItemWithKey (iCodehTab, k); if (!uic) continue; - + if (uic->op != IFX && uic->op != JUMPTABLE) { if (IC_LEFT (uic) && IC_LEFT (uic)->key == IC_RESULT (ic)->key) @@ -1953,7 +1953,6 @@ packRegsForAssign (iCode * ic, eBBlock * ebp) return 0; } - /* if the true symbol is defined in far space or on stack then we should not since this will increase register pressure */ #if 0 @@ -1962,14 +1961,14 @@ packRegsForAssign (iCode * ic, eBBlock * ebp) } #endif - /* 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 0 /* jwk: This collides with 1.43 but I really see no need for - this anymore. It fixes bug #716790 and substantially improves + this anymore. It fixes bug #716790 and substantially improves redundant register usage around function calls. */ @@ -2028,16 +2027,18 @@ packRegsForAssign (iCode * ic, eBBlock * ebp) 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)) { /* if result is a bit too then it's ok */ - etype = operandType (IC_RESULT (dic)); + etype = operandType (IC_RESULT (ic)); if (!IS_BITFIELD (etype)) - return 0; - } + { + return 0; + } + } } /* if the result is on stack or iaccess then it must be the same atleast one of the operands */ @@ -2070,7 +2071,7 @@ pack: } // TODO: and the otherway around? - /* delete from liverange table also + /* delete from liverange table also delete from all the points inbetween and the new one */ for (sic = dic; sic != ic; sic = sic->next) @@ -2104,7 +2105,7 @@ findAssignToSym (operand * op, iCode * ic) and eliminate the use of iTempAA, freeing up its register for other uses. */ - + for (dic = ic->prev; dic; dic = dic->prev) { @@ -2113,7 +2114,7 @@ findAssignToSym (operand * op, iCode * ic) if (dic->op == '=' && !POINTER_SET (dic) && IC_RESULT (dic)->key == op->key - && IS_TRUE_SYMOP(IC_RIGHT(dic)) + && IS_TRUE_SYMOP(IC_RIGHT(dic)) ) break; /* found where this temp was defined */ @@ -2133,11 +2134,11 @@ findAssignToSym (operand * op, iCode * ic) /* 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 the symbol is volatile then we should not */ if (isOperandVolatile (IC_RIGHT (dic), TRUE)) return NULL; @@ -2148,7 +2149,7 @@ findAssignToSym (operand * op, iCode * ic) /* 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 */ @@ -2156,14 +2157,14 @@ findAssignToSym (operand * op, iCode * ic) if ((ic->op == '+' || ic->op == '-') && OP_SYMBOL (IC_RIGHT (dic))->onStack) { - + 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; } #endif - + /* now make sure that the right side of dic is not defined between ic & dic */ if (dic) @@ -2216,7 +2217,7 @@ reassignAliasedSym (eBBlock *ebp, iCode *assignment, iCode *use, operand *op) bitVectUnSetBit(OP_SYMBOL(IC_RESULT(assignment))->defs, assignment->key); hTabDeleteItem (&iCodehTab, assignment->key, assignment, DELETE_ITEM, NULL); } - + /*-----------------------------------------------------------------*/ /* packRegsForSupport :- reduce some registers for support calls */ @@ -2226,7 +2227,7 @@ packRegsForSupport (iCode * ic, eBBlock * ebp) { iCode *dic; int changes = 0; - + /* for the left & right operand :- look to see if the left was assigned a true symbol in far space in that case replace them */ @@ -2283,19 +2284,19 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) return NULL; return NULL; - + if (ic->op != SEND //RETURN && ic->op != SEND && !POINTER_SET (ic) && !POINTER_GET (ic) ) return NULL; - + if (ic->op == SEND && ic->argreg != 1) return NULL; - /* this routine will mark the a symbol as used in one - instruction use only && if the defintion is local + /* this routine will mark the a symbol as used in one + instruction use only && if the defintion is local (ie. within the basic block) && has only one definition && - that definiion is either a return value from a + that definiion is either a return value from a function or does not contain any variables in far space */ uses = bitVectCopy (OP_USES (op)); @@ -2316,7 +2317,7 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) /* if that only usage is a cast */ if (dic->op == CAST) { /* to a bigger type */ - if (getSize(OP_SYM_TYPE(IC_RESULT(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; @@ -2362,7 +2363,7 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) if (POINTER_GET (dic) && !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE))) return NULL; -#endif +#endif sic = dic; @@ -2432,7 +2433,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 @@ -2497,11 +2498,11 @@ bool operandUsesAcc2(operand *op) // if (sym->iaccess && symspace->paged) // return TRUE; /* must fetch paged indirect sym via accumulator */ - + if (IN_BITSPACE(symspace)) return TRUE; /* fetching bit vars uses the accumulator */ - - if (IN_FARSPACE(symspace) || IN_CODESPACE(symspace)) + + if (IN_FARSPACE(symspace) || IN_CODESPACE(symspace)) return TRUE; /* fetched via accumulator and dptr */ } @@ -2509,168 +2510,165 @@ bool operandUsesAcc2(operand *op) } /*-----------------------------------------------------------------*/ -/* packRegsForAccUse - pack registers for acc use */ +/* canDefAccResult - return 1 if the iCode can generate a result */ +/* in A or XA */ /*-----------------------------------------------------------------*/ -static void -packRegsForAccUse (iCode * ic) +static int +canDefAccResult (iCode * ic) { - iCode *uic; - - /* if this is an aggregate, e.g. a one byte char array */ - if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) { - return; - } + int size; - /* if we are calling a reentrant function that has stack parameters */ - #if 0 - 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; - #endif + if (ic->op == IFX || ic->op == JUMPTABLE) /* these iCodes have no result */ + return 0; - /* if + or - then it has to be one byte result */ - if ((ic->op == '+' || ic->op == '-') - && getSize (operandType (IC_RESULT (ic))) > 1) - return; + if (POINTER_SET (ic)) + return 0; + if (!IC_RESULT (ic)) + return 0; - /* if shift operation make sure right side is a literal */ - if (ic->op == RIGHT_OP && - (!isOperandLiteral (IC_RIGHT (ic)) || - (getSize (operandType (IC_RESULT (ic) )) > 1))) - return; + if (!IS_ITEMP (IC_RESULT (ic))) + return 0; - if (ic->op == LEFT_OP && - (!isOperandLiteral (IC_RIGHT (ic)) || - (getSize (operandType (IC_RESULT (ic) )) > 1))) - return; + /* I don't think an iTemp can be an aggregate, but just in case */ + if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) + return 0; - if (IS_BITWISE_OP (ic) && - getSize (operandType (IC_RESULT (ic))) > 1) - return; + size = getSize (operandType (IC_RESULT (ic))); + if (size == 1) + { + /* All 1 byte operations should safely generate an accumulator result */ + return 1; + } + else if (size == 2) + { + switch (ic->op) + { + case LEFT_OP: + case RIGHT_OP: + return isOperandLiteral (IC_RIGHT (ic)) + && SPEC_USIGN (operandType (IC_RESULT (ic))); + case CALL: + case PCALL: + case '*': + case RECEIVE: + case '=': /* assignment, since POINTER_SET is already ruled out */ + return 1; + + default: + return 0; + } + } - /* has only one definition */ - if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1) - return; + return 0; +} - /* has only one use */ - if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1) - return; +/*-----------------------------------------------------------------*/ +/* canUseAccOperand - return 1 if the iCode can use the operand */ +/* when passed in A or XA */ +/*-----------------------------------------------------------------*/ +static int +canUseAccOperand (iCode * ic, operand * op) +{ + int size; + operand * otherOp; - /* and the usage immediately follows this iCode */ - if (!(uic = hTabItemWithKey (iCodehTab, - bitVectFirstBit (OP_USES (IC_RESULT (ic)))))) - return; + if (ic->op == IFX) + { + if (isOperandEqual (op, IC_COND (ic))) + return 1; + else + return 0; + } - if (ic->next != uic) - return; + if (ic->op == JUMPTABLE) + { + if (isOperandEqual (op, IC_JTCOND (ic))) + return 1; + else + return 0; + } - /* if it is a conditional branch then we definitely can */ - if (uic->op == IFX) - goto accuse; + if (POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic))) + return 1; - if (uic->op == JUMPTABLE) - return; + if (isOperandEqual (op, IC_LEFT (ic))) + otherOp = IC_RIGHT (ic); + else if (isOperandEqual (op, IC_RIGHT (ic))) + otherOp = IC_LEFT (ic); + else + return 0; -#if 0 - if (POINTER_SET (uic) && - getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1) - return; -#endif + /* Generation of SEND is deferred until CALL; not safe */ + /* if there are intermediate iCodes */ + if (ic->op == SEND && ic->next && ic->next->op != CALL) + return 0; - /* if the usage is not is an assignment - or an arithmetic / bitwise / shift operation then not */ - if (uic->op != '=' && - !IS_ARITHMETIC_OP (uic) && - !IS_BITWISE_OP (uic) && - (uic->op != LEFT_OP) && - (uic->op != RIGHT_OP) && - (uic->op != GETHBIT) && - (uic->op != RETURN) && - (uic->op != '~') && - (uic->op != '!')) - return; + size = getSize (operandType (op)); + if (size == 1) + { + /* All 1 byte operations should safely use an accumulator operand */ + return 1; + } + else if (size == 2) + { + switch (ic->op) + { + case LEFT_OP: + case RIGHT_OP: + return isOperandLiteral (IC_RIGHT (ic)); + case SEND: + return 1; + default: + return 0; + } + } -#if 0 - /* if used in ^ operation then make sure right is not a - literal (WIML: Why is this?) */ - if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic))) - return; + return 0; +} - /* 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)) - return; -#endif - /* make sure that the result of this icode is not on the - stack, since acc is used to compute stack offset */ -#if 0 - if (IS_TRUE_SYMOP (IC_RESULT (uic)) && - OP_SYMBOL (IC_RESULT (uic))->onStack) - return; -#else -// if (isOperandOnStack(IC_RESULT(uic))) -// return; -#endif +/*-----------------------------------------------------------------*/ +/* packRegsForAccUse - pack registers for acc use */ +/*-----------------------------------------------------------------*/ +static int +packRegsForAccUse (iCode * ic) +{ + iCode * uic; + operand * op; - /* if the usage has only one operand then we can */ - if (IC_LEFT (uic) == NULL || - IC_RIGHT (uic) == NULL) - goto accuse; + if (!canDefAccResult (ic)) + return 0; -#if 0 - /* if the other operand uses the accumulator then we cannot */ - if ( (IC_LEFT(uic)->key == IC_RESULT(ic)->key && - operandUsesAcc2(IC_RIGHT(uic))) || - (IC_RIGHT(uic)->key == IC_RESULT(ic)->key && - operandUsesAcc2(IC_LEFT(uic))) ) - return; + op = IC_RESULT (ic); - /* 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 (!(isCommutativeOp2(ic->op) || ic->op == '-') && - IC_LEFT (uic)->key != IC_RESULT (ic)->key) - return; -#endif + /* has only one definition */ + if (bitVectnBitsOn (OP_DEFS (op)) > 1) + return 0; -#if 0 - // this is too dangerous and need further restrictions - // see bug #447547 + /* has only one use */ + if (bitVectnBitsOn (OP_USES (op)) > 1) + return 0; - /* if one of them is a literal then we can */ - if ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) || - (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic)))) - { - OP_SYMBOL (IC_RESULT (ic))->accuse = 1; - return; - } -#endif + uic = ic->next; + if (!uic) + return 0; -accuse: + if (!canUseAccOperand (uic, op)) + return 0; + #if 0 if ((POINTER_GET(uic)) || (ic->op == ADDRESS_OF && uic->op == '+' && IS_OP_LITERAL (IC_RIGHT (uic)))) { OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_HX; return; } - + #endif + OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_XA; + return 1; } /*-----------------------------------------------------------------*/ @@ -2715,7 +2713,7 @@ packForPush (iCode * ic, eBBlock ** ebpp, int blockno) inbetween */ dbv = OP_DEFS(IC_RIGHT(dic)); for (lic = ic; lic && lic != dic ; lic = lic->prev) { - if (bitVectBitValue(dbv,lic->key)) + if (bitVectBitValue(dbv,lic->key)) return ; } /* make sure they have the same type */ @@ -2723,7 +2721,7 @@ packForPush (iCode * ic, eBBlock ** ebpp, int blockno) { 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; @@ -2733,7 +2731,7 @@ packForPush (iCode * ic, eBBlock ** ebpp, int blockno) 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 */ @@ -2776,11 +2774,11 @@ packRegisters (eBBlock ** ebpp, int blockno) for (ic = ebp->sch; ic; ic = ic->next) { //packRegsForLiteral (ic); - - /* if this is an itemp & result of an address of a true sym + + /* 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_ITEMP (IC_RESULT (ic)) && IS_TRUE_SYMOP (IC_LEFT (ic)) && bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 && !OP_SYMBOL (IC_LEFT (ic))->onStack ) @@ -2823,20 +2821,20 @@ packRegisters (eBBlock ** ebpp, int blockno) /* if cast to a generic pointer & the pointer being cast is remat, then we can remat this cast as well */ - if (ic->op == CAST && + 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)) { + 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 + /* 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)) && @@ -2900,6 +2898,57 @@ packRegisters (eBBlock ** ebpp, int blockno) continue; } + #if 0 + /* 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; + } + + if (ic->op != IFX && ic->op !=JUMPTABLE && !POINTER_SET (ic) + && IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)) + && getSize (operandType (IC_RESULT (ic))) == 1 + && bitVectnBitsOn (OP_USES (IC_RESULT (ic))) == 1 + && ic->next + && OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq) + { + int accuse = 0; + + if (ic->next->op == IFX) + { + if (isOperandEqual (IC_RESULT (ic), IC_COND (ic->next))) + accuse = 1; + } + else if (ic->next->op == JUMPTABLE) + { + if (isOperandEqual (IC_RESULT (ic), IC_JTCOND (ic->next))) + accuse = 1; + } + else + { + if (isOperandEqual (IC_RESULT (ic), IC_LEFT (ic->next))) + accuse = 1; + if (isOperandEqual (IC_RESULT (ic), IC_RIGHT (ic->next))) + accuse = 1; + } + + if (accuse) + { + OP_SYMBOL (IC_RESULT (ic))->accuse = 1; + continue; + } + + } + #endif + /* reduce for support function calls */ if (ic->supportRtn || (ic->op != IFX && ic->op != JUMPTABLE)) packRegsForSupport (ic, ebp); @@ -2918,7 +2967,7 @@ packRegisters (eBBlock ** ebpp, int blockno) if (POINTER_SET (ic) && /* !isOperandInFarSpace (IC_RIGHT (ic)) && */ !OP_SYMBOL (IC_RESULT (ic))->remat && - !IS_OP_RUONLY (IC_RIGHT (ic)) + !IS_OP_RUONLY (IC_RIGHT (ic)) /* && getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1 */ ) packRegsForOneuse (ic, IC_RESULT (ic), ebp); @@ -2927,15 +2976,15 @@ packRegisters (eBBlock ** ebpp, int blockno) IS_SYMOP (IC_LEFT (ic)) && /* !isOperandInFarSpace (IC_RESULT (ic)) && */ !OP_SYMBOL (IC_LEFT (ic))->remat && - !IS_OP_RUONLY (IC_RESULT (ic)) + !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 + check if 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) { @@ -2951,7 +3000,7 @@ packRegisters (eBBlock ** ebpp, int blockno) 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); @@ -2987,8 +3036,8 @@ packRegisters (eBBlock ** ebpp, int blockno) } } #endif - - /* pack for PUSH + + /* pack for PUSH iTempNN := (some variable in farspace) V1 push iTempNN ; ------------- @@ -2999,32 +3048,7 @@ packRegisters (eBBlock ** ebpp, int blockno) packForPush (ic, ebpp, blockno); } - - #if 1 - /* 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 - 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 x:a - combination */ - if ((IS_ARITHMETIC_OP (ic) - || IS_CONDITIONAL(ic) - || IS_BITWISE_OP (ic) - || ic->op == '=' - || ic->op == '!' - || ic->op == '~' - || ic->op == GETHBIT - || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL - || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic))) - || ic->op == RECEIVE - ) && - IS_ITEMP (IC_RESULT (ic)) && - getSize (operandType (IC_RESULT (ic))) <= 1) - - packRegsForAccUse (ic); - #endif + packRegsForAccUse (ic); } } @@ -3032,8 +3056,10 @@ packRegisters (eBBlock ** ebpp, int blockno) /* assignRegisters - assigns registers to each live range as need */ /*-----------------------------------------------------------------*/ void -hc08_assignRegisters (eBBlock ** ebbs, int count) +hc08_assignRegisters (ebbIndex * ebbi) { + eBBlock ** ebbs = ebbi->bbOrder; + int count = ebbi->count; iCode *ic; int i; @@ -3041,12 +3067,14 @@ hc08_assignRegisters (eBBlock ** ebbs, int count) setToNull ((void *) &_G.regAssigned); setToNull ((void *) &_G.totRegAssigned); hc08_ptrRegReq = _G.stackExtend = _G.dataExtend = 0; - hc08_nRegs = 5; + hc08_nRegs = 7; hc08_reg_a = hc08_regWithIdx(A_IDX); hc08_reg_x = hc08_regWithIdx(X_IDX); hc08_reg_h = hc08_regWithIdx(H_IDX); hc08_reg_hx = hc08_regWithIdx(HX_IDX); hc08_reg_xa = hc08_regWithIdx(XA_IDX); + hc08_reg_sp = hc08_regWithIdx(SP_IDX); + hc08_nRegs = 5; /* change assignments this will remove some live ranges reducing some register pressure */ @@ -3056,11 +3084,11 @@ hc08_assignRegisters (eBBlock ** ebbs, int count) /* 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); @@ -3098,7 +3126,7 @@ hc08_assignRegisters (eBBlock ** ebbs, int count) if (options.dump_rassgn) { - dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count); + dumpEbbsToFileExt (DUMP_RASSGN, ebbi); dumpLiveRanges (DUMP_LRANGE, liveRanges); } @@ -3113,8 +3141,8 @@ hc08_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 ();