/*------------------------------------------------------------------------
- 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)
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"
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 ();
allocReg (short type)
{
return NULL;
-
+
if ((type==REG_PTR) && (regshc08[HX_IDX].isFree))
{
regshc08[HX_IDX].isFree = 0;
}
reg->isFree = 1;
-
+
switch (reg->rIdx)
{
case A_IDX:
{
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 */
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)))
{
}
- setToNull ((void **) &sset);
+ setToNull ((void *) &sset);
sym->blockSpil = 0;
return sym;
}
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 ||
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))
{
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;
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);
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))
/* 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)
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)
{
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;
}
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;
}
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)
{
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 &&
(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 */
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;
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 */
/*-----------------------------------------------------------------*/
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 ||
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
}
}
}
+
+ /* 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);
+ }
+ }
+
}
/*-----------------------------------------------------------------*/
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;
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]);
}
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++ ) {
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)));
}
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)));
}
}
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);
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);
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 == '-')
{
ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
continue;
}
-/*
+
+/*
if (ic->op == '+')
{
offset += operandLitValue (IC_RIGHT (ic));
continue;
}
/* we reached the end */
- sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+ if (ic->op == ADDRESS_OF)
+ sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+ else if (ic->op == '=')
+ sprintf (s, "0x%04x", (int) operandLitValue (IC_RIGHT (ic)) );
break;
}
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)
{
(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;
}
}
#endif
+#if 0
+static void
+packRegsForLiteral (iCode * ic)
+{
+ int k;
+ iCode *uic;
+
+ if (ic->op != '=')
+ return;
+ if (POINTER_SET (ic))
+ return;
+ if (!IS_LITERAL (getSpec (operandType (IC_RIGHT (ic)))))
+ return;
+ if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+ return;
+
+ for (k=0; k< OP_USES (IC_RESULT (ic))->size; k++)
+ if (bitVectBitValue (OP_USES (IC_RESULT (ic)), k))
+ {
+ 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)
+ ReplaceOpWithCheaperOp(&IC_LEFT(uic), IC_RIGHT(ic));
+ if (IC_RIGHT (uic) && IC_RIGHT (uic)->key == IC_RESULT (ic)->key)
+ ReplaceOpWithCheaperOp(&IC_RIGHT(uic), IC_RIGHT(ic));
+ if (IC_RESULT (uic) && IC_RESULT (uic)->key == IC_RESULT (ic)->key)
+ ReplaceOpWithCheaperOp(&IC_RESULT(uic), IC_RIGHT(ic));
+ }
+ }
+
+}
+#endif
+
+
/*-----------------------------------------------------------------*/
/* packRegsForAssign - register reduction for assignment */
/*-----------------------------------------------------------------*/
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
}
#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.
*/
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 */
}
// 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)
and eliminate the use of iTempAA, freeing up its register for
other uses.
*/
-
+
for (dic = ic->prev; dic; dic = dic->prev)
{
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 */
/* 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;
/* 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 (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)
bitVectUnSetBit(OP_SYMBOL(IC_RESULT(assignment))->defs, assignment->key);
hTabDeleteItem (&iCodehTab, assignment->key, assignment, DELETE_ITEM, NULL);
}
-
+
/*-----------------------------------------------------------------*/
/* packRegsForSupport :- reduce some registers for support calls */
{
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 */
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));
/* 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;
if (POINTER_GET (dic) &&
!IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
return NULL;
-#endif
+#endif
sic = dic;
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
// 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 */
}
}
/*-----------------------------------------------------------------*/
-/* 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;
- }
-
- /* 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;
+ int size;
- 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;
}
/*-----------------------------------------------------------------*/
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 */
{
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;
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 */
for (ic = ebp->sch; ic; ic = ic->next)
{
- /* if this is an itemp & result of an address of a true sym
+ //packRegsForLiteral (ic);
+
+ /* 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)) &&
OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
}
+#if 1
+ if (ic->op == '=' &&
+ !POINTER_SET (ic) &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ IS_VALOP (IC_RIGHT (ic)) &&
+ 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;
+
+ }
+#endif
/* if straight assignment then carry remat flag if
this is the only definition */
if (ic->op == '=' &&
/* 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)) &&
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);
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);
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)
{
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);
}
}
#endif
-
- /* pack for PUSH
+
+ /* pack for PUSH
iTempNN := (some variable in farspace) V1
push iTempNN ;
-------------
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)))
- ) &&
- IS_ITEMP (IC_RESULT (ic)) &&
- getSize (operandType (IC_RESULT (ic))) <= 1)
-
- packRegsForAccUse (ic);
- #endif
+ packRegsForAccUse (ic);
}
}
/* 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;
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 */
for (i = 0; i < count; 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);
if (options.dump_rassgn)
{
- dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+ dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
dumpLiveRanges (DUMP_LRANGE, liveRanges);
}