hardware. It allocates based on usage and how long the varible
lives into registers or temporary memory on the stack.
- On the Z80 hl, ix, iy, and a are reserved for the code generator,
- leaving bc and de for allocation. The extra register pressure
+ On the Z80 hl and ix and a are reserved for the code generator,
+ leaving bc and de for allocation. iy is unusable due to currently
+ as it's only adressable as a pair. The extra register pressure
from reserving hl is made up for by how much easier the sub
operations become. You could swap hl for iy if the undocumented
iyl/iyh instructions are available.
enum {
DISABLE_PACK_ACC = 0,
DISABLE_PACK_ASSIGN = 0,
- LIMITED_PACK_ACC = 1
+ DISABLE_PACK_ONE_USE = 0,
+ DISABLE_PACK_HL = 0,
+ LIMITED_PACK_ACC = 1,
};
-#define D_ALLOC 1
+enum {
+ D_ALLOC = 0,
+ D_ALLOC2 = 0
+};
-#if 0
+#if 1
#define D(_a, _s) if (_a) { printf _s; fflush(stdout); }
#else
#define D(_a, _s)
if (currFunc)
currFunc->regsUsed =
bitVectSetBit(currFunc->regsUsed,i);
- D(D_ALLOC, ("allocReg: alloced %zr\n", ®sZ80[i]));
+ D(D_ALLOC, ("allocReg: alloced %p\n", ®sZ80[i]));
return ®sZ80[i];
}
}
{
wassert(!reg->isFree);
reg->isFree = 1;
- D(D_ALLOC, ("freeReg: freed %zr\n", reg));
+ D(D_ALLOC, ("freeReg: freed %p\n", reg));
}
{
symbol *sloc= NULL;
- D(D_ALLOC, ("createStackSpil: for sym %zs\n", sym));
+ D(D_ALLOC, ("createStackSpil: for sym %p\n", sym));
/* first go try and find a free one that is already
existing on the stack */
{
int i;
- D(D_ALLOC, ("spillThis: spilling %zs\n", sym));
+ D(D_ALLOC, ("spillThis: spilling %p\n", sym));
/* if this is rematerializable or has a spillLocation
we are okay, else we need to create a spillLocation
set *selectS ;
symbol *sym;
- D(D_ALLOC, ("selectSpil: finding spill for ic %zi\n", ic));
+ D(D_ALLOC, ("selectSpil: finding spill for ic %p\n", ic));
/* get the spillable live ranges */
lrcs = computeSpillable (ic);
used in the remainder of the block */
if (!blockSpil && (selectS = liveRangesWith(lrcs,notUsedInRemaining,ebp,ic))) {
sym = leastUsedLR (selectS);
- if (!sym->remat) {
- sym->remainSpil = 1;
- blockSpil++;
+ if (sym != ForSym) {
+ if (!sym->remat) {
+ sym->remainSpil = 1;
+ blockSpil++;
+ }
+ return sym;
}
- return sym;
}
}
/* find live ranges with spillocation && not used as pointers */
symbol *ssym;
int i ;
- D(D_ALLOC, ("spilSomething: spilling on ic %zi\n", ic));
+ D(D_ALLOC, ("spilSomething: spilling on ic %p\n", ic));
/* get something we can spil */
ssym = selectSpil(ic,ebp,forSym);
{
regs *reg;
- D(D_ALLOC, ("getRegGpr: on ic %zi\n"));
+ D(D_ALLOC, ("getRegGpr: on ic %p\n", ic));
tryAgain:
/* try for gpr type */
if ((reg = allocReg(REG_GPR))) {
!OP_SYMBOL(IC_LEFT(ic->prev))->isspilt)
psym = OP_SYMBOL(IC_LEFT(ic->prev));
- D(D_ALLOC, ("deassignLRs: in loop on sym %zs", sym));
+ D(D_ALLOC, ("deassignLRs: in loop on sym %p nregs %u\n", sym, sym->nRegs));
if (sym->nRegs) {
int i = 0;
((nfreeRegsType(result->regType) +
sym->nRegs) >= result->nRegs)
) {
- for (i = 0 ; i < max(sym->nRegs,result->nRegs) ; i++) {
+ for (i = 0 ; i < result->nRegs ; i++) {
if (i < sym->nRegs )
result->regs[i] = sym->regs[i] ;
else
symbol *sym = OP_SYMBOL(op);
int i;
- D(D_ALLOC, ("reassingLR: on sym %zs\n", sym));
+ D(D_ALLOC, ("reassingLR: on sym %p\n", sym));
/* not spilt any more */
sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
int count = min(result->nRegs,opsym->nRegs);
int i , j = 0, shared = 0;
- D(D_ALLOC, ("positionRegs: on result %zs opsum %zs line %u\n", result, opsym, lineno));
+ D(D_ALLOC, ("positionRegs: on result %p opsum %p line %u\n", result, opsym, lineno));
/* if the result has been spilt then cannot share */
if (opsym->isspilt)
currFunc->regsUsed =
bitVectSetBit(currFunc->regsUsed,i+1);
}
- D(D_ALLOC, ("tryAllocRegPair: succeded for sym %zs\n", sym));
+ D(D_ALLOC, ("tryAllocRegPair: succeded for sym %p\n", sym));
return TRUE;
}
}
- D(D_ALLOC, ("tryAllocRegPair: failed on sym %zs\n", sym));
+ D(D_ALLOC, ("tryAllocRegPair: failed on sym %p\n", sym));
return FALSE;
}
int willCS ;
int j;
- D(D_ALLOC, ("serialRegAssign: in loop on result %zs\n", sym));
+ D(D_ALLOC, ("serialRegAssign: in loop on result %p\n", sym));
/* if it does not need or is spilt
or is already assigned to registers
/* if the allocation falied which means
this was spilt then break */
if (!sym->regs[j]) {
+ D(D_ALLOC, ("Couldnt alloc (spill)\n"))
break;
}
}
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 && ic->op != '=')
+ OP_SYMBOL(IC_RIGHT(ic))->nRegs)
positionRegs(OP_SYMBOL(IC_RESULT(ic)),
OP_SYMBOL(IC_RIGHT(ic)),ic->lineno);
if ((sym->liveTo - sym->liveFrom) == 0)
continue ;
- D(D_ALLOC, ("regTypeNum: loop on sym %zs\n", sym));
+ D(D_ALLOC, ("regTypeNum: loop on sym %p\n", sym));
/* if the live range is a temporary */
if (sym->isitmp) {
}
/* if not then we require registers */
+ D(D_ALLOC, ("regTypeNum: isagg %u nRegs %u type %p\n", IS_AGGREGATE(sym->type) || sym->isptr, sym->nRegs, sym->type));
sym->nRegs = ((IS_AGGREGATE(sym->type) || sym->isptr ) ?
getSize(sym->type = aggrToPtr(sym->type,FALSE)) :
getSize(sym->type));
+ D(D_ALLOC, ("regTypeNum: setting nRegs of %s (%p) to %u\n", sym->name, sym, sym->nRegs));
- D(D_ALLOC, ("regTypeNum: setup to assign regs sym %zs\n", sym));
+ D(D_ALLOC, ("regTypeNum: setup to assign regs sym %p\n", sym));
if (sym->nRegs > 4) {
fprintf(stderr,"allocated more than 4 or 0 registers for type ");
/* Always general purpose */
sym->regType = REG_GPR ;
- } else
+ } else {
/* for the first run we don't provide */
/* registers for true symbols we will */
/* see how things go */
- sym->nRegs = 0 ;
+ D(D_ALLOC, ("regTypeNum: #2 setting num of %p to 0\n", sym));
+ sym->nRegs = 0;
+ }
}
}
{
iCode *dic, *sic;
- D(D_ALLOC, ("packRegsForAssing: running on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegsForAssing: running on ic %p\n", ic));
if (
/* !IS_TRUE_SYMOP(IC_RESULT(ic)) ||*/
remiCodeFromeBBlock(ebp,ic);
return 1;
-
}
/** Scanning backwards looks for first assig found.
/* for the left & right operand :- look to see if the
left was assigned a true symbol in far space in that
case replace them */
- D(D_ALLOC, ("packRegsForSupport: running on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegsForSupport: running on ic %p\n", ic));
if (IS_ITEMP(IC_LEFT(ic)) &&
OP_SYMBOL(IC_LEFT(ic))->liveTo <= ic->seq) {
bitVect *uses ;
iCode *dic, *sic;
- D(D_ALLOC, ("packRegsForOneUse: running on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegsForOneUse: running on ic %p\n", ic));
/* if returning a literal then do nothing */
if (!IS_SYMOP(op))
/* 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;
+ goto accuse;
return ;
}
goto accuse ;
return ;
accuse:
- OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
+ OP_SYMBOL(IC_RESULT(ic))->accuse = ACCUSE_A;
+}
+
+static void packRegsForHLUse (iCode *ic)
+{
+ iCode *uic;
+
+ if (IS_GB)
+ return;
+
+ /* has only one definition */
+ if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1)
+ return ;
+
+ /* has only one use */
+ if (bitVectnBitsOn(OP_USES(IC_RESULT(ic))) > 1)
+ return ;
+
+ /* and the usage immediately follows this iCode */
+ if (!(uic = hTabItemWithKey(iCodehTab,
+ bitVectFirstBit(OP_USES(IC_RESULT(ic))))))
+ return ;
+
+ if (ic->next != uic)
+ return ;
+
+ if (ic->op == ADDRESS_OF && uic->op == IPUSH)
+ goto hluse;
+ if (ic->op == CALL && IC_LEFT(ic)->parmBytes == 0 && (uic->op == '-' || uic->op == '+'))
+ goto hluse;
+ return;
+ hluse:
+ OP_SYMBOL(IC_RESULT(ic))->accuse = ACCUSE_HL;
}
bool opPreservesA(iCode *ic, iCode *uic)
return FALSE;
}
+static void joinPushes(iCode *ic)
+{
+#if 0
+ if (ic->op == IPUSH &&
+ isOperandLiteral(IC_LEFT(ic)) &&
+ getSize(operandType(IC_LEFT(ic))) == 1 &&
+ ic->next->op == IPUSH &&
+ isOperandLiteral(IC_LEFT(ic->next)) &&
+ getSize(operandType(IC_LEFT(ic->next))) == 1) {
+ /* This is a bit tricky as michaelh doesnt know what he's doing.
+ */
+ /* First upgrade the size of (first) to int */
+ SPEC_NOUN(operandType(IC_LEFT(ic))) = V_INT;
+ SPEC_SHORT(operandType(IC_LEFT(ic))) = 0;
+
+ floatFromVal(AOP
+ /* Now get and join the values */
+ value * val = aop->aopu.aop_lit;
+ /* if it is a float then it gets tricky */
+ /* otherwise it is fairly simple */
+ if (!IS_FLOAT(val->type)) {
+ unsigned long v = floatFromVal(val);
+
+ floatFrom
+ printf("Size %u\n", getSize(operandType(IC_LEFT(ic))));
+ ic->next = ic->next->next;
+ }
+#endif
+}
+
/** Pack registers for acc use.
When the result of this operation is small and short lived it may
- be able to be stored in the accumelator.
+ be able to be stored in the accumulator.
Note that the 'A preserving' list is currently emperical :)e
*/
{
iCode *uic;
- D(D_ALLOC, ("packRegsForAccUse2: running on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegsForAccUse2: running on ic %p\n", ic));
/* Filter out all but those 'good' commands */
if (
return;
}
} while (!bitVectIsZero(uses));
- OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
+ OP_SYMBOL(IC_RESULT(ic))->accuse = ACCUSE_A;
return;
}
/* 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;
+ goto accuse;
return ;
}
return ;
accuse:
printf("acc ok!\n");
- OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
+ OP_SYMBOL(IC_RESULT(ic))->accuse = ACCUSE_A;
}
/** Does some transformations to reduce register pressure.
/* Safe: address of a true sym is always constant. */
/* if this is an itemp & result of a address of a true sym
then mark this as rematerialisable */
-
- D(D_ALLOC, ("packRegisters: looping on ic %zi\n", ic));
+ D(D_ALLOC, ("packRegisters: looping on ic %p\n", ic));
if (ic->op == ADDRESS_OF &&
IS_ITEMP(IC_RESULT(ic)) &&
!isOperandInFarSpace(IC_RIGHT(ic)) && */
!OP_SYMBOL(IC_RESULT(ic))->remat &&
!IS_OP_RUONLY(IC_RIGHT(ic)) &&
- getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 )
+ getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 ) {
packRegsForOneuse (ic,IC_RESULT(ic),ebp);
+ }
/* if pointer get */
- if (POINTER_GET(ic) &&
+ if (!DISABLE_PACK_ONE_USE &&
+ POINTER_GET(ic) &&
/* MLH: dont have far space
!isOperandInFarSpace(IC_RESULT(ic))&& */
!OP_SYMBOL(IC_LEFT(ic))->remat &&
!IS_OP_RUONLY(IC_RESULT(ic)) &&
- getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 )
+ getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 ) {
+
packRegsForOneuse (ic,IC_LEFT(ic),ebp);
+ }
/* 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 acc:b combination */
+
+ if (!DISABLE_PACK_HL && IS_ITEMP(IC_RESULT(ic))) {
+ packRegsForHLUse(ic);
+ }
#if 0
if ((IS_ARITHMETIC_OP(ic)
|| IS_BITWISE_OP(ic)
packRegsForAccUse (ic);
#else
if (!DISABLE_PACK_ACC && IS_ITEMP(IC_RESULT(ic)) &&
- getSize(operandType(IC_RESULT(ic))) == 1)
+ getSize(operandType(IC_RESULT(ic))) == 1) {
packRegsForAccUse2(ic);
+ }
#endif
+ joinPushes(ic);
}
}