/*-----------------------------------------------------------------*/
extern void gen51Code (iCode *);
+#define D(x)
/* Global data */
static struct
bitVect *spiltSet;
set *stackSpil;
bitVect *regAssigned;
+ bitVect *totRegAssigned; /* final set of LRs that got into registers */
short blockSpil;
int slocNum;
bitVect *funcrUsed; /* registers used in a function */
};
int mcs51_nRegs = 13;
static void spillThis (symbol *);
+static void freeAllRegs ();
/*-----------------------------------------------------------------*/
/* allocReg - allocates register of given type */
return nFreeRegs (type);
}
+/*-----------------------------------------------------------------*/
+/* useReg - marks a register as used */
+/*-----------------------------------------------------------------*/
+static void
+useReg (regs * reg)
+{
+ reg->isFree = 0;
+}
/*-----------------------------------------------------------------*/
/* allDefsOutOfRange - all definitions are out of a range */
for (sym = setFirstItem (itmpStack); sym;
sym = setNextItem (itmpStack))
{
- if (sym->liveTo > fsym->liveFrom)
- return 0;
-
+ if (bitVectBitValue(sym->clashes,fsym->key)) return 0;
}
return 1;
{
int j;
- /* if no registers assigned to it or
- spilt */
+ /* if no registers assigned to it or spilt */
/* if it does not overlap with this then
not need to spill it */
sloc->etype = getSpec (sloc->type);
SPEC_SCLS (sloc->etype) = S_DATA;
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
/* mark it has spilt & put it in the spilt set */
- sym->isspilt = 1;
+ sym->isspilt = sym->spillA = 1;
_G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
bitVectUnSetBit (_G.regAssigned, sym->key);
+ bitVectUnSetBit (_G.totRegAssigned, sym->key);
for (i = 0; i < sym->nRegs; i++)
}
if (sym->usl.spillLoc && !sym->remat)
- sym->usl.spillLoc->allocreq = 1;
+ sym->usl.spillLoc->allocreq++;
return;
}
sym->usl.spillLoc->name));
sym->spildir = 1;
/* mark it as allocation required */
- sym->usl.spillLoc->allocreq = 1;
+ sym->usl.spillLoc->allocreq++;
return sym;
}
sym = leastUsedLR (selectS);
/* mark this as allocation required */
- sym->usl.spillLoc->allocreq = 1;
+ sym->usl.spillLoc->allocreq++;
return sym;
}
{
sym = leastUsedLR (selectS);
- sym->usl.spillLoc->allocreq = 1;
+ sym->usl.spillLoc->allocreq++;
return sym;
}
/* return a created spil location */
sym = createStackSpil (leastUsedLR (selectS));
- sym->usl.spillLoc->allocreq = 1;
+ sym->usl.spillLoc->allocreq++;
return sym;
}
ssym = selectSpil (ic, ebp, forSym);
/* mark it as spilt */
- ssym->isspilt = 1;
+ ssym->isspilt = ssym->spillA = 1;
_G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
/* mark it as not register assigned &
take it away from the set */
bitVectUnSetBit (_G.regAssigned, ssym->key);
+ bitVectUnSetBit (_G.totRegAssigned, ssym->key);
/* mark the registers as free */
for (i = 0; i < ssym->nRegs; i++)
goto tryAgain;
}
+/*-----------------------------------------------------------------*/
+/* getRegPtrNoSpil - get it cannot split */
+/*-----------------------------------------------------------------*/
+static regs *getRegPtrNoSpil()
+{
+ regs *reg;
+
+ /* try for a ptr type */
+ if ((reg = allocReg (REG_PTR)))
+ return reg;
+
+ /* try for gpr type */
+ if ((reg = allocReg (REG_GPR)))
+ return reg;
+
+ assert(0);
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegGprNoSpil - get it cannot split */
+/*-----------------------------------------------------------------*/
+static regs *getRegGprNoSpil()
+{
+
+ regs *reg;
+ if ((reg = allocReg (REG_GPR)))
+ return reg;
+
+ if (!mcs51_ptrRegReq)
+ if ((reg = allocReg (REG_PTR)))
+ return reg;
+
+ assert(0);
+}
+
/*-----------------------------------------------------------------*/
/* symHasReg - symbol has a given register */
/*-----------------------------------------------------------------*/
result->regs[i] = getRegGpr (ic, ebp, result);
_G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+ _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key);
}
int i;
/* not spilt any more */
- sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
+ sym->isspilt = sym->spillA = sym->blockSpil = sym->remainSpil = 0;
bitVectUnSetBit (_G.spiltSet, sym->key);
_G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+ _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
_G.blockSpil--;
/* ult and operand, if this happens make sure they are in the same */
/* position as the operand otherwise chaos results */
/*-----------------------------------------------------------------*/
-static void
-positionRegs (symbol * result, symbol * opsym, int lineno)
+static int
+positionRegs (symbol * result, symbol * opsym)
{
int count = min (result->nRegs, opsym->nRegs);
int i, j = 0, shared = 0;
+ int change = 0;
/* if the result has been spilt then cannot share */
if (opsym->isspilt)
- return;
+ return 0;
again:
shared = 0;
/* first make sure that they actually share */
regs *tmp = result->regs[i];
result->regs[i] = result->regs[j];
result->regs[j] = tmp;
+ change ++;
goto again;
}
+ return change;
}
/*-----------------------------------------------------------------*/
static void
serialRegAssign (eBBlock ** ebbs, int count)
{
- int i;
+ int i;
- /* for all blocks */
- for (i = 0; i < count; i++)
- {
+ /* for all blocks */
+ for (i = 0; i < count; i++) {
- iCode *ic;
+ iCode *ic;
- if (ebbs[i]->noPath &&
- (ebbs[i]->entryLabel != entryLabel &&
- ebbs[i]->entryLabel != returnLabel))
- continue;
+ if (ebbs[i]->noPath &&
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
- /* of all instructions do */
- for (ic = ebbs[i]->sch; ic; ic = ic->next)
- {
+ /* of all instructions do */
+ for (ic = ebbs[i]->sch; ic; ic = ic->next) {
- /* if this is an ipop that means some live
- range will have to be assigned again */
- if (ic->op == IPOP)
- reassignLR (IC_LEFT (ic));
-
- /* if result is present && is a true symbol */
- if (IC_RESULT (ic) && ic->op != IFX &&
- IS_TRUE_SYMOP (IC_RESULT (ic)))
- OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
-
- /* take away registers from live
- ranges that end at this instruction */
- deassignLRs (ic, ebbs[i]);
-
- /* some don't need registers */
- if (SKIP_IC2 (ic) ||
- ic->op == JUMPTABLE ||
- ic->op == IFX ||
- ic->op == IPUSH ||
- ic->op == IPOP ||
- (IC_RESULT (ic) && POINTER_SET (ic)))
- continue;
+ /* if this is an ipop that means some live
+ range will have to be assigned again */
+ if (ic->op == IPOP)
+ reassignLR (IC_LEFT (ic));
- /* now we need to allocate registers
- only for the result */
- if (IC_RESULT (ic))
- {
- symbol *sym = OP_SYMBOL (IC_RESULT (ic));
- bitVect *spillable;
- int willCS;
- int j;
- int ptrRegSet = 0;
-
- /* if it does not need or is spilt
- or is already assigned to registers
- or will not live beyond this instructions */
- if (!sym->nRegs ||
- sym->isspilt ||
- bitVectBitValue (_G.regAssigned, sym->key) ||
- sym->liveTo <= ic->seq)
- continue;
+ /* if result is present && is a true symbol */
+ if (IC_RESULT (ic) && ic->op != IFX &&
+ IS_TRUE_SYMOP (IC_RESULT (ic)))
+ OP_SYMBOL (IC_RESULT (ic))->allocreq++;
- /* if some liverange has been spilt at the block level
- and this one live beyond this block then spil this
- to be safe */
- if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
- {
- spillThis (sym);
- continue;
- }
- /* if trying to allocate this will cause
- a spill and there is nothing to spill
- or this one is rematerializable then
- spill this one */
- willCS = willCauseSpill (sym->nRegs, sym->regType);
- spillable = computeSpillable (ic);
- if (sym->remat ||
- (willCS && bitVectIsZero (spillable)))
- {
+ /* take away registers from live
+ ranges that end at this instruction */
+ deassignLRs (ic, ebbs[i]);
- spillThis (sym);
- continue;
+ /* some don't need registers */
+ if (SKIP_IC2 (ic) ||
+ ic->op == JUMPTABLE ||
+ ic->op == IFX ||
+ ic->op == IPUSH ||
+ ic->op == IPOP ||
+ (IC_RESULT (ic) && POINTER_SET (ic)))
+ continue;
+ /* now we need to allocate registers
+ only for the result */
+ if (IC_RESULT (ic)) {
+ symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+ bitVect *spillable;
+ int willCS;
+ int j;
+ int ptrRegSet = 0;
+
+ /* if it does not need or is spilt
+ or is already assigned to registers
+ or will not live beyond this instructions */
+ if (!sym->nRegs ||
+ sym->isspilt ||
+ bitVectBitValue (_G.regAssigned, sym->key) ||
+ sym->liveTo <= ic->seq)
+ continue;
+
+ /* if some liverange has been spilt at the block level
+ and this one live beyond this block then spil this
+ to be safe */
+ if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) {
+ spillThis (sym);
+ continue;
+ }
+ /* if trying to allocate this will cause
+ a spill and there is nothing to spill
+ or this one is rematerializable then
+ spill this one */
+ willCS = willCauseSpill (sym->nRegs, sym->regType);
+ spillable = computeSpillable (ic);
+ if (sym->remat || (willCS && bitVectIsZero (spillable))) {
+ spillThis (sym);
+ continue;
}
- /* if it has a spillocation & is used less than
- all other live ranges then spill this */
- if (willCS && sym->usl.spillLoc)
- {
-
- symbol *leastUsed =
- leastUsedLR (liveRangesWith (spillable,
- allLRs,
- ebbs[i],
- ic));
- if (leastUsed &&
- leastUsed->used > sym->used)
- {
- spillThis (sym);
- continue;
+ /* if it has a spillocation & is used less than
+ all other live ranges then spill this */
+ if (willCS) {
+ if (sym->usl.spillLoc) {
+ symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+ allLRs, ebbs[i], ic));
+ if (leastUsed && leastUsed->used > sym->used) {
+ spillThis (sym);
+ continue;
+ }
+ } else {
+ /* if none of the liveRanges have a spillLocation then better
+ to spill this one than anything else already assigned to registers */
+ if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
+ /* if this is local to this block then we might find a block spil */
+ if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+ spillThis (sym);
+ continue;
+ }
+ }
+ }
+ }
+ /* if we need ptr regs for the right side
+ then mark it */
+ if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
+ && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE) {
+ mcs51_ptrRegReq++;
+ ptrRegSet = 1;
+ }
+ /* else we assign registers to it */
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+ _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
+
+ for (j = 0; j < sym->nRegs; j++) {
+ if (sym->regType == REG_PTR)
+ sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+ else
+ sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+ /* if the allocation failed which means
+ this was spilt then break */
+ if (!sym->regs[j]) {
+ if (j) {
+ fprintf (stderr, "%d reg(s) lost in %s:%d\n",
+ j, __FILE__,__LINE__);
+ }
+ break;
}
}
- /* if we need ptr regs for the right side
- then mark it */
- if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
- && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
- <= PTRSIZE)
- {
- mcs51_ptrRegReq++;
- ptrRegSet = 1;
+ /* if it shares registers with operands make sure
+ that they are in the same position */
+ if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') {
+ positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+ OP_SYMBOL (IC_LEFT (ic)));
+ }
+ /* do the same for the right operand */
+ if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->nRegs) {
+ positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+ OP_SYMBOL (IC_RIGHT (ic)));
}
- /* else we assign registers to it */
- _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
- for (j = 0; j < sym->nRegs; j++)
- {
- if (sym->regType == REG_PTR)
- sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
- else
- sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+ if (ptrRegSet) {
+ mcs51_ptrRegReq--;
+ ptrRegSet = 0;
+ }
+
+ }
+ }
+ }
+}
- /* if the allocation falied which means
- this was spilt then break */
- if (!sym->regs[j])
- break;
+/*-----------------------------------------------------------------*/
+/* fillGaps - Try to fill in the Gaps left by Pass1 */
+/*-----------------------------------------------------------------*/
+static void fillGaps()
+{
+ symbol *sym =NULL;
+ int key =0;
+
+ if (getenv("DISABLE_FILL_GAPS")) return;
+
+ /* look for livernages that was spilt by the allocator */
+ for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
+ sym = hTabNextItem(liveRanges,&key)) {
+
+ int i;
+ int pdone = 0;
+
+ if (!sym->spillA || !sym->clashes || sym->remat) continue ;
+
+ /* find the liveRanges this one clashes with, that are
+ still assigned to registers & mark the registers as used*/
+ for ( i = 0 ; i < sym->clashes->size ; i ++) {
+ int k;
+ symbol *clr;
+
+ if (bitVectBitValue(sym->clashes,i) == 0 || /* those that clash with this */
+ bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+ continue ;
+
+ assert (clr = hTabItemWithKey(liveRanges,i));
+
+ /* mark these registers as used */
+ for (k = 0 ; k < clr->nRegs ; k++ )
+ useReg(clr->regs[k]);
+ }
+
+ if (willCauseSpill(sym->nRegs,sym->regType)) {
+ /* NOPE :( clear all registers & and continue */
+ freeAllRegs();
+ continue ;
+ }
+
+ /* THERE IS HOPE !!!! */
+ for (i=0; i < sym->nRegs ; i++ ) {
+ if (sym->regType == REG_PTR)
+ sym->regs[i] = getRegPtrNoSpil ();
+ else
+ 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
+ then give up */
+ sym->isspilt = 0;
+ for (i = 0 ; i < sym->defs->size ; i++ ) {
+ if (bitVectBitValue(sym->defs,i)) {
+ iCode *ic;
+ if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+ 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)) &&
+ bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) {
+ pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)));
}
- /* if it shares registers with operands make sure
- that they are in the same position */
- if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
- OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
- positionRegs (OP_SYMBOL (IC_RESULT (ic)),
- OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
- /* do the same for the right operand */
- if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
- OP_SYMBOL (IC_RIGHT (ic))->nRegs)
- positionRegs (OP_SYMBOL (IC_RESULT (ic)),
- OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
-
- if (ptrRegSet)
- {
- mcs51_ptrRegReq--;
- ptrRegSet = 0;
+ if (IS_SYMOP(IC_RIGHT(ic)) &&
+ bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
+ pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)));
}
-
+ if (pdone > 1) break;
+ }
+ }
+ for (i = 0 ; i < sym->uses->size ; i++ ) {
+ if (bitVectBitValue(sym->uses,i)) {
+ iCode *ic;
+ if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+ if (SKIP_IC(ic)) continue;
+ if (!IS_ASSIGN_ICODE(ic)) continue ;
+
+ /* if result is assigned to registers */
+ if (IS_SYMOP(IC_RESULT(ic)) &&
+ bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
+ pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
+ }
+ if (pdone > 1) break;
+ }
+ }
+ /* had to position more than once GIVE UP */
+ if (pdone > 1) {
+ /* UNDO all the changes we made to try this */
+ sym->isspilt = 1;
+ for (i=0; i < sym->nRegs ; i++ ) {
+ sym->regs[i] = NULL;
}
+ freeAllRegs();
+ D(printf ("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+ continue ;
}
+ D(printf ("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+ _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
+ sym->isspilt = sym->spillA = 0 ;
+ sym->usl.spillLoc->allocreq--;
+ freeAllRegs();
}
}
/*-----------------------------------------------------------------*/
/* rUmaskForOp :- returns register mask for an operand */
/*-----------------------------------------------------------------*/
-static bitVect *
-rUmaskForOp (operand * op)
+bitVect *
+mcs51_rUmaskForOp (operand * op)
{
bitVect *rumask;
symbol *sym;
if (ic->op == IFX)
{
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_COND (ic)));
+ mcs51_rUmaskForOp (IC_COND (ic)));
goto ret;
}
if (ic->op == JUMPTABLE)
{
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_JTCOND (ic)));
+ mcs51_rUmaskForOp (IC_JTCOND (ic)));
goto ret;
}
/* of all other cases */
if (IC_LEFT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_LEFT (ic)));
+ mcs51_rUmaskForOp (IC_LEFT (ic)));
if (IC_RIGHT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_RIGHT (ic)));
+ mcs51_rUmaskForOp (IC_RIGHT (ic)));
if (IC_RESULT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_RESULT (ic)));
+ mcs51_rUmaskForOp (IC_RESULT (ic)));
ret:
return rmask;
continue;
}
+ /* cast then continue */
+ if (IS_CAST_ICODE(ic)) {
+ ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+ continue;
+ }
/* we reached the end */
sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
break;
/* regTypeNum - computes the type & number of registers required */
/*-----------------------------------------------------------------*/
static void
-regTypeNum ()
+regTypeNum (eBBlock *ebbs)
{
symbol *sym;
int k;
}
/* 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 */
-
+ that definition is a get_pointer */
if (bitVectnBitsOn (sym->defs) == 1 &&
(ic = hTabItemWithKey (iCodehTab,
bitVectFirstBit (sym->defs))) &&
POINTER_GET (ic) &&
+ !sym->noSpilLoc &&
!IS_BITVAR (sym->etype))
{
- /* if remat in data space */
+ /* and that pointer is remat in data space */
if (OP_SYMBOL (IC_LEFT (ic))->remat &&
- DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER)
+ !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
+ 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);
psym->type = sym->type;
strcpy (psym->rname, psym->name);
sym->isspilt = 1;
sym->usl.spillLoc = psym;
+#if 0 // an alternative fix for bug #480076
+ /* now this is a useless assignment to itself */
+ remiCodeFromeBBlock (ebbs, ic);
+#else
+ /* now this really is an assignment to itself, make it so;
+ it will be optimized out later */
+ ic->op='=';
+ IC_RIGHT(ic)=IC_RESULT(ic);
+ IC_LEFT(ic)=NULL;
+#endif
continue;
}
symbol on the right */
for (dic = ic->prev; dic; dic = dic->prev)
{
-
/* if the definition is a call then no */
if ((dic->op == CALL || dic->op == PCALL) &&
IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
packRegsForAssign (iCode * ic, eBBlock * ebp)
{
iCode *dic, *sic;
- sym_link *etype = operandType (IC_RIGHT (ic));
+ //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 ||
- IS_BITFIELD (etype))
+ OP_LIVETO (IC_RIGHT (ic)) > ic->seq
+ /* why? || IS_BITFIELD (etype) */ )
{
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)))
- {
- if ((dic = farSpacePackable (ic)))
- goto pack;
- else
- return 0;
+ if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic)) {
+ return 0;
+ }
- }
/* find the definition of iTempNN scanning backwards if we find a
a use of the true symbol in before we find the definition then
we cannot */
for (dic = ic->prev; dic; dic = dic->prev)
{
-
- /* if there is a function call and this is
- a parameter & not my parameter then don't pack it */
- if ((dic->op == CALL || dic->op == PCALL) &&
- (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
- !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
+ /* if there is a function call then don't pack it */
+ if ((dic->op == CALL || dic->op == PCALL))
{
dic = NULL;
break;
/* found the definition */
/* replace the result with the result of */
/* this assignment and remove this assignment */
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
IC_RESULT (dic) = IC_RESULT (ic);
if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
}
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);
return 1;
/* or in stack space in case of + & - */
/* if assigned to a non-symbol then return
- true */
+ FALSE */
if (!IS_SYMOP (IC_RIGHT (dic)))
- break;
+ return NULL;
/* if the symbol is in far space then
we should not */
packRegsForSupport (iCode * ic, eBBlock * ebp)
{
int change = 0;
+ iCode *dic, *sic;
+
/* for the left & right operand :- look to see if the
left was assigned a true symbol in far space in that
case replace them */
+
if (IS_ITEMP (IC_LEFT (ic)) &&
OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
{
- iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
- iCode *sic;
+ 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)
+ for (sic = dic; sic != ic; sic = sic->next) {
bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+ sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key);
+ }
- IC_LEFT (ic)->operand.symOperand =
- IC_RIGHT (dic)->operand.symOperand;
- IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+ OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic));
+ OP_SYMBOL(IC_LEFT(ic))->liveTo = ic->seq;
+ 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++;
}
/* do the same for the right operand */
-right:
+ right:
if (!change &&
IS_ITEMP (IC_RIGHT (ic)) &&
OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
}
/* found it we need to remove it from the
block */
- for (sic = dic; sic != ic; sic = sic->next)
+ for (sic = dic; sic != ic; sic = sic->next) {
bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+ sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key);
+ }
IC_RIGHT (ic)->operand.symOperand =
IC_RIGHT (dic)->operand.symOperand;
+ OP_SYMBOL(IC_RIGHT(ic))->liveTo = ic->seq;
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++;
}
/* only upto 2 bytes since we cannot predict
the usage of b, & acc */
- if (getSize (operandType (op)) > (fReturnSizeMCS51 - 2) &&
- ic->op != RETURN &&
+ if (getSize (operandType (op)) > (fReturnSizeMCS51 - 2))
+ return NULL;
+
+ if (ic->op != 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
if (bitVectnBitsOn (OP_DEFS (op)) > 1)
return NULL; /* has more than one definition */
- /* get the that definition */
+ /* get that definition */
if (!(dic =
hTabItemWithKey (iCodehTab,
bitVectFirstBit (OP_DEFS (op)))))
return NULL;
+ /* if that only usage is a cast */
+ if (dic->op == CAST) {
+ /* to a bigger type */
+ if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) >
+ getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
+ /* than we can not, since we cannot predict the usage of b & acc */
+ return NULL;
+ }
+ }
+
/* found the definition now check if it is local */
if (dic->seq < ebp->fSeq ||
dic->seq > ebp->lSeq)
a function call */
if (dic->op == CALL || dic->op == PCALL)
{
- if (ic->op != SEND && ic->op != RETURN)
+ if (ic->op != SEND && ic->op != RETURN &&
+ !POINTER_SET(ic) && !POINTER_GET(ic))
{
OP_SYMBOL (op)->ruonly = 1;
return dic;
{
return NULL;
}
+ /* if left or right or result is on stack */
+ if (isOperandOnStack(IC_LEFT(dic)) ||
+ isOperandOnStack(IC_RIGHT(dic)) ||
+ isOperandOnStack(IC_RESULT(dic))) {
+ return NULL;
+ }
}
OP_SYMBOL (op)->ruonly = 1;
/* bitwise operations are considered optimizable
under the following conditions (Jean-Louis VERN)
- x & lit <== jwk: should be x && lit
+ x & lit
bit & bit
bit & x
bit ^ bit
bit ^ x
- x ^ lit <== jwk: should be x ^^ lit
- x | lit <== jwk: should be x || lit
+ x ^ lit
+ x | lit
bit | bit
bit | x
- */
- if ( /* jwk IS_LITERAL (rtype) || */
+ */
+ if (IS_LITERAL(rtype) ||
(IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
return TRUE;
else
{
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 (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)
/* 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
/* if either one of them in far space then we cannot */
if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
IC_LEFT (uic)->key != IC_RESULT (ic)->key)
return;
+#if 0
+ // this is too dangerous and need further restrictions
+ // see bug #447547
+
/* 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
/* if the other one is not on stack then we can */
if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
/* make sure the right side does not have any definitions
inbetween */
dbv = OP_DEFS(IC_RIGHT(dic));
- for (lic = ic; lic != dic ; lic = lic->prev) {
- if (bitVectBitValue(dbv,lic->key)) return ;
+ 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;
}
/* 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);
-
+
remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
}
for (ic = ebp->sch; ic; ic = ic->next)
{
-
- /* if this is an itemp & result of a 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)) &&
!POINTER_SET (ic) &&
IS_SYMOP (IC_RIGHT (ic)) &&
OP_SYMBOL (IC_RIGHT (ic))->remat &&
+ !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
{
OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
}
+ /* if cast to a generic pointer & the pointer being
+ cast is remat, then we can remat this cast as well */
+ if (ic->op == CAST &&
+ IS_SYMOP(IC_RIGHT(ic)) &&
+ OP_SYMBOL(IC_RIGHT(ic))->remat ) {
+ sym_link *to_type = operandType(IC_LEFT(ic));
+ sym_link *from_type = operandType(IC_RIGHT(ic));
+ if (IS_GENPTR(to_type) && IS_PTR(from_type)) {
+ OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+ OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+ }
+ }
+
/* if this is a +/- operation with a rematerizable
then mark this as rematerializable as well */
if ((ic->op == '+' || ic->op == '-') &&
(IS_SYMOP (IC_LEFT (ic)) &&
IS_ITEMP (IC_RESULT (ic)) &&
+ IS_OP_LITERAL (IC_RIGHT (ic))) &&
OP_SYMBOL (IC_LEFT (ic))->remat &&
- bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
- IS_OP_LITERAL (IC_RIGHT (ic))))
+ (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
+ bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
{
-
- //int i = operandLitValue (IC_RIGHT (ic));
OP_SYMBOL (IC_RESULT (ic))->remat = 1;
OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
}
/* if the condition of an if instruction
- is defined in the previous instruction then
+ is defined in the previous instruction and
+ this is the only usage then
mark the itemp as a conditional */
if ((IS_CONDITIONAL (ic) ||
(IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
ic->next && ic->next->op == IFX &&
+ bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
{
/* 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)
- packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+ options.model == MODEL_SMALL) {
+ if (0 && options.stackAuto) {
+ /* we should check here if acc will be clobbered for stack
+ offset calculations */
+ } else {
+ packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+ }
+ }
/* if pointer set & left has a size more than
one and right is not in far space */
if (dic)
{
if (IS_ARITHMETIC_OP (dic))
- {
+ {
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
IC_RESULT (dic) = IC_RESULT (ic);
remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
ic = ic->prev;
/* if the type from and type to are the same
then if this is the only use then packit */
- if (checkType (operandType (IC_RIGHT (ic)),
+ if (compareType (operandType (IC_RIGHT (ic)),
operandType (IC_LEFT (ic))) == 1)
{
iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
if (dic)
{
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
IC_RESULT (dic) = IC_RESULT (ic);
remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
ic = ic->prev;
we can leave the result of this operation in acc:b
combination */
if ((IS_ARITHMETIC_OP (ic)
+ || IS_CONDITIONAL(ic)
|| IS_BITWISE_OP (ic)
- || ic->op == LEFT_OP || ic->op == RIGHT_OP
+ || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL
|| (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic)))
) &&
IS_ITEMP (IC_RESULT (ic)) &&
getSize (operandType (IC_RESULT (ic))) <= 2)
packRegsForAccUse (ic);
-
}
}
int i;
setToNull ((void *) &_G.funcrUsed);
+ setToNull ((void *) &_G.totRegAssigned);
mcs51_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
- /* if not register extentions then reduce number
- of registers */
- if (options.regExtend)
- mcs51_nRegs = 13;
- else
- mcs51_nRegs = 8;
+ mcs51_nRegs = 8;
/* change assignments this will remove some
live ranges reducing some register pressure */
packRegisters (ebbs[i]);
if (options.dump_pack)
- dumpEbbsToFileExt (".dumppack", ebbs, count);
+ dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
/* first determine for each live range the number of
registers & the type of registers required for each */
- regTypeNum ();
+ regTypeNum (*ebbs);
/* and serially allocate registers */
serialRegAssign (ebbs, count);
+ freeAllRegs ();
+ fillGaps();
+
/* if stack was extended then tell the user */
if (_G.stackExtend)
{
if (options.dump_rassgn)
{
- dumpEbbsToFileExt (".dumprassgn", ebbs, count);
- dumpLiveRanges (".dumplrange", liveRanges);
+ dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+ dumpLiveRanges (DUMP_LRANGE, liveRanges);
}
/* do the overlaysegment stuff SDCCmem.c */
/* now get back the chain */
ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
-
gen51Code (ic);
/* free up any _G.stackSpil locations allocated */