+//#define LIVERANGEHUNT
+#ifdef LIVERANGEHUNT
+ #define LRH(x) x
+#else
+ #define LRH(x)
+#endif
/*------------------------------------------------------------------------
SDCCralloc.c - source file for register allocation. (8051) specific
reg->isFree = 0;
}
-/*-----------------------------------------------------------------*/
-/* allDefsOutOfRange - all definitions are out of a range */
-/*-----------------------------------------------------------------*/
-static bool
-allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
-{
- 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;
-}
-
/*-----------------------------------------------------------------*/
/* computeSpillable - given a point find the spillable live ranges */
/*-----------------------------------------------------------------*/
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 */
/*-----------------------------------------------------------------*/
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`
onto the external stack since : so we
if (!(sym->remat || sym->usl.spillLoc))
createStackSpil (sym);
-
+ LRH(printf("spillThis: %s\n", sym->name));
/* mark it has spilt & put it in the spilt set */
sym->isspilt = sym->spillA = 1;
_G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
/* get something we can spil */
ssym = selectSpil (ic, ebp, forSym);
+ LRH(printf("spilSomething: spilled %s for %s\n", ssym->name, forSym->name));
/* mark it as spilt */
ssym->isspilt = ssym->spillA = 1;
return reg;
assert(0);
+
+ /* just to make the compiler happy */
+ return 0;
}
/*-----------------------------------------------------------------*/
return reg;
assert(0);
+
+ /* just to make the compiler happy */
+ return 0;
}
/*-----------------------------------------------------------------*/
/* 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;
}
}
bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
continue ;
- assert (clr = hTabItemWithKey(liveRanges,i));
+ clr = hTabItemWithKey(liveRanges,i);
+ assert(clr);
/* mark these registers as used */
for (k = 0 ; k < clr->nRegs ; k++ )
{
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"createRegMask cannot find live range");
+ fprintf(stderr, "\tmissing live range: key=%d\n", j);
exit (0);
}
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 */
+#ifdef RANGEHUNT
+ /* if this symbol has only one usage and that is an assignment
+ to a ruonly, we don't need registers */
+ // if this symbol has only one def
+ if (bitVectnBitsOn (sym->defs)==1) {
+ printf ("sym: %s has only one usage", sym->name);
+ // find that usage
+ if ((ic = hTabItemWithKey (iCodehTab, bitVectFirstBit (sym->defs)))) {
+ if (ic->op==CALL) {
+ printf (" for a call ");
+ // if this is only assigned to a ruonly
+ if ((ic = hTabItemWithKey (iCodehTab, bitVectFirstBit (sym->defs)))) {
+ if (ic->op=='=') {
+ if (OP_SYMBOL(IC_RESULT(ic))->ruonly) {
+ printf("regTypeNum: %s assigned to %s\n", \
+ sym->name, OP_SYMBOL(IC_RESULT(ic))->name);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+ /* if the symbol has only one definition &
+ that definition is a get_pointer */
if (bitVectnBitsOn (sym->defs) == 1 &&
(ic = hTabItemWithKey (iCodehTab,
bitVectFirstBit (sym->defs))) &&
{
- /* if remat in data space */
+ /* and that pointer is 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)
+ DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER)
{
/* create a psuedo symbol & force a spil */
symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
/* 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);
+ ReplaceOpWithCheaperOp(&IC_RIGHT(ic), IC_RESULT(ic));
IC_LEFT(ic)=NULL;
#endif
continue;
/* registers for true symbols we will */
/* see how things go */
sym->nRegs = 0;
- }
+ }
}
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;
}
+
/* if the true symbol is defined in far space or on stack
then we should not since this will increase register pressure */
if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic)) {
/* 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;
}
+ // jwk: and the otherway around?
+
/* delete from liverange table also
delete from all the points inbetween and the new
one */
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_SET ((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)
{
IC_RESULT (dic)->key == op->key
/* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */
)
- {
-
- /* we are interested only if defined in far space */
- /* or in stack space in case of + & - */
-
- /* if assigned to a non-symbol then return
- FALSE */
- if (!IS_SYMOP (IC_RIGHT (dic)))
- 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;
- }
-
- break;
-
- }
+ break; /* found where this temp was defined */
/* if we find an usage then we cannot delete it */
if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
return NULL;
}
+ if (!dic)
+ return NULL; /* didn't find any assignment to op */
+
+ LRH(printf ("findAssignToSym: %s\n", OP_SYMBOL(IC_RESULT(dic))->name));
+ /* 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;
+ /* 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 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;
+ }
+
/* now make sure that the right side of dic
is not defined between ic & dic */
if (dic)
}
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;
+ /* 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
case replace them */
{
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)))
+ if (dic)
{
- sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
- if (IN_FARSPACE (SPEC_OCLS (etype)))
- 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 0;
+ }
+ /* found it we need to remove it from the
+ block */
+ reassignAliasedSym (ebp, dic, ic, IC_RIGHT(ic));
+
+ return 1;
}
- /* 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++;
}
- return change;
+ return 0;
}
#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
!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
(ie. within the basic block) && has only one definition &&
bitVectFirstBit (OP_DEFS (op)))))
return NULL;
+ LRH(printf ("packRegsForOneUse: %s\n", OP_SYMBOL(op)->name));
/* if that only usage is a cast */
if (dic->op == CAST) {
/* to a bigger type */
OP_SYMBOL (op)->ruonly = 1;
return sic;
-
}
/*-----------------------------------------------------------------*/
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)
+{
+ 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 (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 */
/*-----------------------------------------------------------------*/
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)
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 is an assignment
+ or an arithmetic / bitwise / shift operation then not */
if (uic->op != '=' &&
!IS_ARITHMETIC_OP (uic) &&
!IS_BITWISE_OP (uic) &&
return;
/* if used in ^ operation then make sure right is not a
- literl */
+ 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))
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))) ||
+ (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
+ operandUsesAcc(IC_LEFT(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
}
#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 */
/*-----------------------------------------------------------------*/
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;
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; i<blockno; i++) {
+ if (dic->seq >= 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 */
+ {
+ 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);
}
/* pressure */
/*-----------------------------------------------------------------*/
static void
-packRegisters (eBBlock * ebp)
+packRegisters (eBBlock ** ebpp, int blockno)
{
iCode *ic;
int change = 0;
+ eBBlock *ebp=ebpp[blockno];
while (1)
{
/* some cases the redundant moves can
can be eliminated for return statements */
- if ((ic->op == RETURN || ic->op == SEND) &&
+ if ((ic->op == RETURN || (ic->op == SEND && ic->argreg == 1)) &&
!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);
- }
+ packRegsForOneuse (ic, IC_LEFT (ic), ebp);
}
/* if pointer set & left has a size more than
!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 */
!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 (IS_ARITHMETIC_OP (dic))
{
bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
- IC_RESULT (dic) = IC_RESULT (ic);
+ 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);
+ OP_DEFS_SET ((IC_RESULT (dic)), bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key));
ic = ic->prev;
}
else
if (dic)
{
bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
- IC_RESULT (dic) = IC_RESULT (ic);
+ 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);
+ OP_DEFS_SET ((IC_RESULT (dic)), bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key));
ic = ic->prev;
}
}
*/
if (ic->op == IPUSH)
{
- packForPush (ic, ebp);
+ packForPush (ic, ebpp, blockno);
}
/* change assignments this will remove some
live ranges reducing some register pressure */
for (i = 0; i < count; i++)
- packRegisters (ebbs[i]);
+ packRegisters (ebbs, i);
if (options.dump_pack)
dumpEbbsToFileExt (DUMP_PACK, ebbs, count);