/* since the pack the registers depending strictly on the MCU */
/*-----------------------------------------------------------------*/
+#define D(x)
+
/* Global data */
static struct
{
{REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1, 1},
{REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1, 1},
{REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1, 1},
+ {REG_GPR, DPL_IDX, REG_GPR, "dpl", "dpl", "dpl", 0, 0, 0},
+ {REG_GPR, DPH_IDX, REG_GPR, "dph", "dph", "dph", 0, 0, 0},
+ {REG_GPR, DPX_IDX, REG_GPR, "dpx", "dpx", "dpx", 0, 0, 0},
+ {REG_GPR, B_IDX, REG_GPR, "b", "b", "b", 0, 0, 0},
{REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 0, 0},
{REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 0, 0},
{REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 0, 0},
{REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 0, 0},
{REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 0, 0},
{REG_CND, CND_IDX, REG_GPR, "C", "C", "xreg", 0, 0, 0},
- {REG_GPR, DPL_IDX, REG_GPR, "dpl", "dpl", "dpl", 0, 0, 0},
- {REG_GPR, DPH_IDX, REG_GPR, "dph", "dph", "dph", 0, 0, 0},
- {REG_GPR, DPX_IDX, REG_GPR, "dpx", "dpx", "dpx", 0, 0, 0},
- {REG_GPR, B_IDX, REG_GPR, "b", "b", "b", 0, 0, 0},
};
int ds390_nRegs = 13;
static void spillThis (symbol *);
static void freeAllRegs ();
+static iCode * packRegsDPTRuse (operand *);
/*-----------------------------------------------------------------*/
/* allocReg - allocates register of given type */
return TRUE;
}
+/*-----------------------------------------------------------------*/
+/* isOperandInReg - returns true if operand is currently in regs */
+/*-----------------------------------------------------------------*/
+static int isOperandInReg(operand *op)
+{
+ if (!IS_SYMOP(op)) return 0;
+
+ return bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(op)->key);
+}
+
/*-----------------------------------------------------------------*/
/* computeSpillable - given a point find the spillable live ranges */
/*-----------------------------------------------------------------*/
}
SPEC_EXTR (sloc->etype) = 0;
SPEC_STAT (sloc->etype) = 0;
+ SPEC_VOLATILE(sloc->etype) = 0;
/* we don't allow it to be allocated`
onto the external stack since : so we
int key =0;
if (getenv("DISABLE_FILL_GAPS")) return;
+
+ /* First try to do DPTRuse once more since now we know what got into
+ registers */
+
+ for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
+ sym = hTabNextItem(liveRanges,&key)) {
+
+ if (sym->uptr && !sym->ruonly && getSize(sym->type) < 4) {
+ if (packRegsDPTRuse(operandFromSymbol(sym))) {
+
+ D (fprintf (stderr, "FILL GAPS: found more DPTR use for "
+ "%s in func %s\n",
+ sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+ /* if this was ssigned to registers then */
+ if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
+
+ /* take it out of the register assigned set */
+ bitVectUnSetBit(_G.totRegAssigned,sym->key);
+ sym->nRegs = 0;
+ } else if (sym->usl.spillLoc) sym->usl.spillLoc->allocreq--;
+
+ sym->isspilt = sym->spillA = 0;
+ }
+ }
+ }
+
/* look for livernages that was spilt by the allocator */
for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
sym = hTabNextItem(liveRanges,&key)) {
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 ++) {
sym->regs[i] = getRegGprNoSpil ();
}
- /* for all its definitions check if the registers
+ /* for all its definitions & uses check if the registers
allocated needs positioning NOTE: we can position
only ONCE if more than One positioning required
then give up */
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;
}
freeAllRegs();
- printf("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN");
+ D (fprintf (stderr, "Fill Gap gave up due to positioning for "
+ "%s in function %s\n",
+ sym->name, currFunc ? currFunc->name : "UNKNOWN"));
continue ;
}
- printf("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN");
+ D (fprintf (stderr, "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--;
/*-----------------------------------------------------------------*/
/* rUmaskForOp :- returns register mask for an operand */
/*-----------------------------------------------------------------*/
-static bitVect *
-rUmaskForOp (operand * op)
+bitVect *
+ds390_rUmaskForOp (operand * op)
{
bitVect *rumask;
symbol *sym;
if (ic->op == IFX)
{
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_COND (ic)));
+ ds390_rUmaskForOp (IC_COND (ic)));
goto ret;
}
if (ic->op == JUMPTABLE)
{
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_JTCOND (ic)));
+ ds390_rUmaskForOp (IC_JTCOND (ic)));
goto ret;
}
/* of all other cases */
if (IC_LEFT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_LEFT (ic)));
+ ds390_rUmaskForOp (IC_LEFT (ic)));
if (IC_RIGHT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_RIGHT (ic)));
+ ds390_rUmaskForOp (IC_RIGHT (ic)));
if (IC_RESULT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_RESULT (ic)));
+ ds390_rUmaskForOp (IC_RESULT (ic)));
ret:
return rmask;
/* 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;
/*-----------------------------------------------------------------*/
static int
packRegsForSupport (iCode * ic, eBBlock * ebp)
-{
+{
int change = 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 */
IC_LEFT (ic)->operand.symOperand =
IC_RIGHT (dic)->operand.symOperand;
IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
remiCodeFromeBBlock (ebp, dic);
hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
change++;
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++;
}
/* packRegsDPTRuse : - will reduce some registers for single Use */
/*-----------------------------------------------------------------*/
static iCode *
-packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
+packRegsDPTRuse (operand * op)
{
/* go thru entire liveRange of this variable & check for
other possible usage of DPTR , if we don't find it the
for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
ic = hTabNextItem(iCodeSeqhTab,&key)) {
+ if (SKIP_IC3(ic)) continue;
+
/* if PCALL cannot be sure give up */
if (ic->op == PCALL) return NULL;
- /* if CALL then make sure it is VOID || return value not used */
+ /* if CALL then make sure it is VOID || return value not used
+ or the return value is assigned to this one */
if (ic->op == CALL) {
if (OP_SYMBOL(IC_RESULT(ic))->liveTo ==
OP_SYMBOL(IC_RESULT(ic))->liveFrom) continue ;
etype = getSpec(type = operandType(IC_RESULT(ic)));
- if (getSize(type) == 0) continue ;
+#if 0
+ if (getSize(type) == 0 || isOperandEqual(op,IC_RESULT(ic)))
+#endif
+ if (getSize(type) == 0)
+ continue ;
return NULL ;
}
/* special case of add with a [remat] */
if (ic->op == '+' &&
OP_SYMBOL(IC_LEFT(ic))->remat &&
- !isOperandInFarSpace(IC_RIGHT(ic))) continue ;
+ (isOperandInFarSpace(IC_RIGHT(ic)) &&
+ !isOperandInReg(IC_RIGHT(ic)))) return NULL ;
- /* special case */
+ /* special cases */
/* pointerGet */
- if (POINTER_GET(ic) && isOperandEqual(IC_RESULT(ic),op) &&
- getSize(operandType(IC_LEFT(ic))) > 1) return NULL ;
+ if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op) &&
+ getSize(operandType(IC_LEFT(ic))) > 1 ) return NULL ;
- if (POINTER_SET(ic) && isOperandEqual(IC_RIGHT(ic),op) &&
- getSize(operandType(IC_RESULT(ic))) > 1) return NULL;
+ /* pointerSet */
+ if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) &&
+ getSize(operandType(IC_RESULT(ic))) > 1 ) return NULL;
+
+ /* conditionals can destroy 'b' - make sure B wont be used in this one*/
+ if ((IS_CONDITIONAL(ic) || ic->op == '*' || ic->op == '/' ) &&
+ getSize(operandType(op)) > 3) return NULL;
/* general case */
if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
!isOperandEqual(IC_RESULT(ic),op) &&
- (isOperandInFarSpace(IC_RESULT(ic)) ||
+ ((isOperandInFarSpace(IC_RESULT(ic)) && !isOperandInReg(IC_RESULT(ic))) ||
OP_SYMBOL(IC_RESULT(ic))->ruonly ||
OP_SYMBOL(IC_RESULT(ic))->onStack)) return NULL;
(OP_SYMBOL(IC_RIGHT(ic))->liveTo > ic->seq ||
IS_TRUE_SYMOP(IC_RIGHT(ic)) ||
OP_SYMBOL(IC_RIGHT(ic))->ruonly) &&
- (isOperandInFarSpace(IC_RIGHT(ic)) ||
+ ((isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic)))||
OP_SYMBOL(IC_RIGHT(ic))->onStack)) return NULL;
if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
(OP_SYMBOL(IC_LEFT(ic))->liveTo > ic->seq ||
IS_TRUE_SYMOP(IC_LEFT(ic)) ||
OP_SYMBOL(IC_LEFT(ic))->ruonly) &&
- (isOperandInFarSpace(IC_LEFT(ic)) ||
+ ((isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic)))||
OP_SYMBOL(IC_LEFT(ic))->onStack)) return NULL;
if (IC_LEFT(ic) && IC_RIGHT(ic) &&
IS_ITEMP(IC_LEFT(ic)) && IS_ITEMP(IC_RIGHT(ic)) &&
- isOperandInFarSpace(IC_LEFT(ic)) && isOperandInFarSpace(IC_RIGHT(ic)))
+ (isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic))) &&
+ (isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic))))
return NULL;
}
OP_SYMBOL(op)->ruonly = 1;
{
iCode *uic;
+ /* if this is an aggregate, e.g. a one byte char array */
+ if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
+ 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 (ic) = IC_RIGHT (dic);
remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
}
if (POINTER_GET (ic))
OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+ if (ic->op == RETURN && IS_SYMOP (IC_LEFT(ic)))
+ OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+
if (!SKIP_IC2 (ic))
{
/* if we are using a symbol on the stack
}
#endif
+#if 0 /* unsafe */
/* reduce for support function calls */
if (ic->supportRtn || ic->op == '+' || ic->op == '-')
packRegsForSupport (ic, ebp);
+#endif
/* some cases the redundant moves can
can be eliminated for return statements */
!isOperandInFarSpace (IC_LEFT (ic)) &&
!options.model) {
- packRegsDPTRuse (ic, IC_LEFT (ic), ebp);
+ packRegsDPTRuse (IC_LEFT (ic));
}
- if ((ic->op == CALL && getSize(operandType(IC_RESULT(ic))) <= 4)) {
- packRegsDPTRuse (ic, IC_RESULT (ic), ebp);
+ if (ic->op == CALL) {
+ sym_link *ftype = operandType(IC_LEFT(ic));
+ if (getSize(operandType(IC_RESULT(ic))) <= 4 &&
+ !IFFUNC_ISBUILTIN(ftype)) {
+ packRegsDPTRuse (IC_RESULT (ic));
+ }
}
/* if pointer set & left has a size more than
!IS_OP_RUONLY (IC_RIGHT (ic)) &&
getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) {
- packRegsDPTRuse (ic, IC_RESULT (ic), ebp);
+ packRegsDPTRuse (IC_RESULT (ic));
}
/* if pointer get */
!IS_OP_RUONLY (IC_RESULT (ic)) &&
getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) {
- packRegsDPTRuse (ic, IC_LEFT (ic), ebp);
+ packRegsDPTRuse (IC_LEFT (ic));
}
/* if this is cast for intergral promotion then
SPEC_USIGN (fromType) == SPEC_USIGN (toType))
{
- iCode *dic = packRegsDPTRuse (ic, IC_RIGHT (ic), ebp);
+ iCode *dic = packRegsDPTRuse (IC_RIGHT (ic));
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 (compareType (operandType (IC_RIGHT (ic)),
operandType (IC_LEFT (ic))) == 1)
{
- iCode *dic = packRegsDPTRuse (ic, IC_RIGHT (ic), ebp);
+ iCode *dic = packRegsDPTRuse (IC_RIGHT (ic));
if (dic)
{
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->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;
setToNull ((void *) &_G.totRegAssigned);
setToNull ((void *) &_G.funcrUsed);
ds390_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
- ds390_nRegs = 18;
+ ds390_nRegs = 12;
if (options.model != MODEL_FLAT24) options.stack10bit = 0;
/* change assignments this will remove some
live ranges reducing some register pressure */
ds390_nRegs = 8;
freeAllRegs ();
fillGaps();
- ds390_nRegs = 18;
+ ds390_nRegs = 12;
/* if stack was extended then tell the user */
if (_G.stackExtend)