DISABLE_PACK_ACC = 0,
DISABLE_PACK_ASSIGN = 0,
DISABLE_PACK_ONE_USE = 0,
- DISABLE_PACK_HL = 0,
+ DISABLE_PACK_HL = 1,
+ DISABLE_PACK_IY = 0
};
/* Flags to turn on debugging code.
D_HLUSE = 0,
D_HLUSE2 = 0,
D_HLUSE2_VERBOSE = 0,
- D_FILL_GAPS = 0
+ D_FILL_GAPS = 0,
+ D_PACK_IY = 0,
+ D_PACK_HLUSE3 = 0
};
#if 1
reg->isFree = 0;
}
-#if 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;
-}
-#endif
-
/*-----------------------------------------------------------------*/
/* computeSpillable - given a point find the spillable live ranges */
/*-----------------------------------------------------------------*/
}
- setToNull ((void **) &sset);
+ setToNull ((void *) &sset);
sym->blockSpil = 0;
return sym;
}
return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
}
-/*-----------------------------------------------------------------*/
-/* 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 */
/*-----------------------------------------------------------------*/
getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
{
regs *reg;
+ int j;
D (D_ALLOC, ("getRegGpr: on ic %p\n", ic));
tryAgain:
D (D_ALLOC, ("getRegGpr: have to spill.\n"));
return NULL;
}
+
+ /* make sure partially assigned registers aren't reused */
+ for (j=0; j<=sym->nRegs; j++)
+ if (sym->regs[j])
+ sym->regs[j]->isFree = 0;
/* this looks like an infinite loop but
in really selectSpil will abort */
return reg;
}
assert(0);
+
+ /* just to make the compiler happy */
+ return 0;
}
/** Symbol has a given register.
(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 */
return FALSE;
}
+/*------------------------------------------------------------------*/
+/* 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);
+}
+
+
/** Serially allocate registers to the variables.
This is the main register allocation function. It is called after
packing.
}
+ /* If the live range preceeds the point of definition
+ then ideally we must take into account registers that
+ have been allocated after sym->liveFrom but freed
+ before ic->seq. This is complicated, so spill this
+ symbol instead and let fillGaps handle the allocation. */
+ if (sym->liveFrom < ic->seq)
+ {
+ spillThis (sym);
+ continue;
+ }
+
/* if it has a spillocation & is used less than
all other live ranges then spill this */
if (willCS) {
}
}
}
+
+ /* 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);
+ }
+ }
+
}
/*-----------------------------------------------------------------*/
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++ )
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 = 0;
+ sym->isspilt = 1;
for (i=0; i < sym->nRegs ; i++ ) {
sym->regs[i] = NULL;
}
if (SKIP_IC2 (dic))
continue;
- if (IS_SYMOP (IC_RESULT (dic)) &&
- IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
- {
- break;
- }
+ if (dic->op == IFX)
+ {
+ if (IS_SYMOP (IC_COND (dic)) &&
+ (IC_COND (dic)->key == IC_RESULT (ic)->key ||
+ IC_COND (dic)->key == IC_RIGHT (ic)->key))
+ {
+ dic = NULL;
+ break;
+ }
+ }
+ else
+ {
+ if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+ IS_OP_VOLATILE (IC_RESULT (dic)))
+ {
+ dic = NULL;
+ break;
+ }
- if (IS_SYMOP (IC_RIGHT (dic)) &&
- (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
- IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
- {
- dic = NULL;
- break;
- }
+ if (IS_SYMOP (IC_RESULT (dic)) &&
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ {
+ if (POINTER_SET (dic))
+ dic = NULL;
- if (IS_SYMOP (IC_LEFT (dic)) &&
- (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
- IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
- {
- dic = NULL;
- break;
+ break;
+ }
+
+ if (IS_SYMOP (IC_RIGHT (dic)) &&
+ (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
+ IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+ {
+ dic = NULL;
+ break;
+ }
+
+ if (IS_SYMOP (IC_LEFT (dic)) &&
+ (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+ IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+ {
+ dic = NULL;
+ break;
+ }
+
+ if (IS_SYMOP (IC_RESULT (dic)) &&
+ IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+ {
+ dic = NULL;
+ break;
+ }
+
}
}
// PENDING: Check vs mcs51
bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
- OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
return 1;
}
/* now check if it is the return from a function call */
if (dic->op == CALL || dic->op == PCALL)
{
- if (ic->op != SEND && ic->op != RETURN)
+ if (ic->op != SEND && ic->op != RETURN &&
+ !POINTER_SET(ic) && !POINTER_GET(ic))
{
OP_SYMBOL (op)->ruonly = 1;
return dic;
iCode *ic, *dic;
bool isFirst = TRUE;
-#if 0
- printf("Checking:\n");
- piCode(lic, NULL);
-#endif
+ D (D_PACK_HLUSE3, ("Checking HL on %p lic key %u first def %u line %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)), lic->lineno));
+ if (D_PACK_HLUSE3)
+ piCode(lic, NULL);
if ( OP_SYMBOL(op)->accuse)
{
dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
- ic = hTabNextItem(iCodeSeqhTab,&key))
+ ic = hTabNextItem(iCodeSeqhTab, &key))
{
-#if 0
- piCode(ic, NULL);
- printf("(op: %u)\n", ic->op);
-#endif
+ if (D_PACK_HLUSE3)
+ piCode(ic, NULL);
+ D (D_PACK_HLUSE3, ("(On %p: op: %u next: %p)\n", ic, ic->op, ic->next));
+
if (isFirst)
{
isFirst = FALSE;
continue;
if (POINTER_GET (ic))
continue;
+ if (ic->op == '=' && !POINTER_SET(ic))
+ continue;
}
if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic))
if (ic->op == CALL && isOperandEqual (op, IC_RESULT (ic)))
continue;
+ if (ic->op == LEFT_OP && isOperandLiteral (IC_RIGHT (ic)))
+ continue;
+
if ((ic->op == '=' && !POINTER_SET(ic)) ||
ic->op == UNARYMINUS ||
ic->op == '+' ||
ic->op == '-' ||
+ ic->op == '>' ||
+ ic->op == '<' ||
+ ic->op == EQ_OP ||
0)
continue;
+ if (ic->op == '*' && isOperandEqual (op, IC_LEFT (ic)))
+ continue;
+
+ if (POINTER_SET (ic) && isOperandEqual (op, IC_RESULT (ic)))
+ continue;
+
if (POINTER_GET (ic) && isOperandEqual (op, IC_LEFT (ic)))
continue;
return NULL;
}
-#if 0
- printf("Succeeded!\n");
-#endif
- OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
+ D (D_PACK_HLUSE3, ("Succeeded!\n"))
+ OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
return dic;
}
iCode *ic, *dic;
bitVect *uses;
-#if 0
- printf("Checking IY on %p lic key %u first def %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)));
- piCode(lic, NULL);
-#endif
+ D (D_PACK_IY, ("Checking IY on %p lic key %u first def %u line %u:\n", OP_SYMBOL(op), lic->key, bitVectFirstBit(OP_DEFS(op)), lic->lineno));
+ if (D_PACK_IY)
+ piCode(lic, NULL);
if ( OP_SYMBOL(op)->accuse)
{
return NULL;
}
+ if (getSize (operandType (op)) != 2)
+ {
+ D (D_ACCUSE2, (" + Dropping as operation has size is too big\n"));
+ return FALSE;
+ }
+
/* Nothing else that clashes with this is using the scratch
register. Scan through all of the intermediate instructions and
see if any of them could nuke HL.
for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
ic = hTabNextItem(iCodeSeqhTab,&key))
{
-#if 0
- piCode(ic, NULL);
- printf("(op: %u uses %u)\n", ic->op, bitVectBitValue(uses, ic->key));
-#endif
+ if (D_PACK_IY)
+ piCode(ic, NULL);
if (ic->op == PCALL ||
ic->op == CALL ||
if (SKIP_IC2(ic))
continue;
+ /* Be pessamistic. */
+ if (ic->op == IFX)
+ return NULL;
+
+ D (D_PACK_IY, (" op: %u uses %u result: %d left: %d right: %d\n", ic->op, bitVectBitValue(uses, ic->key),
+ IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) ? isOperandInDirSpace(IC_RESULT(ic)) : -1,
+ IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) ? isOperandInDirSpace(IC_LEFT(ic)) : -1,
+ IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) ? isOperandInDirSpace(IC_RIGHT(ic)) : -1
+ ));
+
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ isOperandInDirSpace(IC_RESULT(ic)))
+ return NULL;
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+ isOperandInDirSpace(IC_RIGHT(ic)))
+ return NULL;
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+ isOperandInDirSpace(IC_LEFT(ic)))
+ return NULL;
+
/* Only certain rules will work against IY. Check if this iCode uses
this symbol. */
if (bitVectBitValue(uses, ic->key) != 0)
{
- if (ic->op == IFX)
- return NULL;
-
if (ic->op == '=' &&
isOperandEqual(IC_RESULT(ic), op))
continue;
}
else
{
- if (ic->op == IFX)
- continue;
-
/* This iCode doesn't use the sym. See if this iCode preserves IY.
*/
- if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
- isOperandInDirSpace(IC_RESULT(ic)))
- return NULL;
-
- if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
- isOperandInFarSpace(IC_RIGHT(ic)))
- return NULL;
-
- if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
- isOperandInFarSpace(IC_LEFT(ic)))
- return NULL;
-
continue;
}
return NULL;
}
-#if 0
- printf("Succeeded IY!\n");
-#endif
- OP_SYMBOL (op)->accuse = ACCUSE_IY;
+ D (D_PACK_IY, ("Succeeded IY!\n"));
+ OP_SYMBOL (op)->accuse = ACCUSE_IY;
return dic;
}
iCode *uic;
D (D_ACCUSE2, ("packRegsForAccUse2: running on ic %p line %u\n", ic, ic->lineno));
+ if (D_ACCUSE2)
+ piCode (ic, NULL);
/* Filter out all but those 'good' commands */
if (
!POINTER_GET (ic) &&
ic->op != '+' &&
+ ic->op != '-' &&
!IS_BITWISE_OP (ic) &&
ic->op != '=' &&
ic->op != EQ_OP &&
/* if pointer get */
if (!DISABLE_PACK_ONE_USE &&
POINTER_GET (ic) &&
+ IS_SYMOP (IC_LEFT (ic)) &&
/* MLH: dont have far space
!isOperandInFarSpace(IC_RESULT(ic))&& */
!OP_SYMBOL (IC_LEFT (ic))->remat &&
if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)))
{
+ /* PENDING */
if (IS_GB)
- packRegsForHLUse (ic);
+ {
+ if (0)
+ packRegsForHLUse (ic);
+ }
else
- packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+ {
+ packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+ }
}
- if (!DISABLE_PACK_HL && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
+ if (!DISABLE_PACK_IY && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
{
packRegsForIYUse (ic, IC_RESULT (ic), ebp);
}
first = (int)operandLitValue ( IC_LEFT (ic));
second = (int)operandLitValue ( IC_LEFT (uic));
- sprintf (buffer, "%u", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
+ sprintf (buffer, "%uu", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
val = constVal (buffer);
SPEC_NOUN (val->type) = V_INT;
+ IC_LEFT (ic) = operandFromOperand (IC_LEFT (ic));
IC_LEFT (ic)->operand.valOperand = val;
/* Now remove the second one from the list. */
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);
/* free up any 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 ();