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.
LIMITED_PACK_ACC = 1
};
+#define D_ALLOC 1
+
+#if 0
+#define D(_a, _s) if (_a) { printf _s; fflush(stdout); }
+#else
+#define D(_a, _s)
+#endif
+
/*-----------------------------------------------------------------*/
/* At this point we start getting processor specific although */
/* some routines are non-processor specific & can be reused when */
if (currFunc)
currFunc->regsUsed =
bitVectSetBit(currFunc->regsUsed,i);
+ D(D_ALLOC, ("allocReg: alloced %zr\n", ®sZ80[i]));
return ®sZ80[i];
}
}
+ D(D_ALLOC, ("allocReg: No free.\n"));
return NULL;
}
for (i=0;i < _nRegs;i++)
if (regsZ80[i].rIdx == idx)
return ®sZ80[i];
-
+
werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
"regWithIdx not found");
exit(1);
{
wassert(!reg->isFree);
reg->isFree = 1;
+ D(D_ALLOC, ("freeReg: freed %zr\n", reg));
}
{
symbol *sym;
-
for (sym = setFirstItem(itmpStack); sym;
sym = setNextItem(itmpStack)) {
if (sym->liveTo > fsym->liveFrom )
return 0;
}
-
return 1;
}
{
symbol *sloc= NULL;
+ D(D_ALLOC, ("createStackSpil: for sym %zs\n", sym));
+
/* first go try and find a free one that is already
existing on the stack */
if (applyToSet(stackSpil,isFree,&sloc, sym)) {
sym->stackSpil= 1;
sloc->isFree = 0;
addSetHead(&sloc->usl.itmpStack,sym);
+ D(D_ALLOC, ("createStackSpil: found existing\n"));
return sym;
}
/* add it to the set of itempStack set
of the spill location */
addSetHead(&sloc->usl.itmpStack,sym);
+
+ D(D_ALLOC, ("createStackSpil: created new\n"));
return sym;
}
static void spillThis (symbol *sym)
{
int i;
+
+ D(D_ALLOC, ("spillThis: spilling %zs\n", sym));
+
/* if this is rematerializable or has a spillLocation
we are okay, else we need to create a spillLocation
for it */
set *selectS ;
symbol *sym;
+ D(D_ALLOC, ("selectSpil: finding spill for ic %zi\n", ic));
/* get the spillable live ranges */
lrcs = computeSpillable (ic);
/* get all live ranges that are rematerizable */
if ((selectS = liveRangesWith(lrcs,rematable,ebp,ic))) {
-
+ D(D_ALLOC, ("selectSpil: using remat.\n"));
/* return the least used of these */
return leastUsedLR(selectS);
}
/* find live ranges with spillocation */
if ((selectS = liveRangesWith(lrcs,hasSpilLoc,ebp,ic))) {
-
+ D(D_ALLOC, ("selectSpil: using with spill.\n"));
sym = leastUsedLR(selectS);
sym->usl.spillLoc->allocreq = 1;
return sym;
location on the stack , for which one? the least
used ofcourse */
if ((selectS = liveRangesWith(lrcs,noSpilLoc,ebp,ic))) {
+ D(D_ALLOC, ("selectSpil: creating new spill.\n"));
/* return a created spil location */
sym = createStackSpil(leastUsedLR(selectS));
sym->usl.spillLoc->allocreq = 1;
/* this is an extreme situation we will spill
this one : happens very rarely but it does happen */
+ D(D_ALLOC, ("selectSpil: using spillThis.\n"));
spillThis ( forSym );
return forSym;
symbol *ssym;
int i ;
+ D(D_ALLOC, ("spilSomething: spilling on ic %zi\n", ic));
+
/* get something we can spil */
ssym = selectSpil(ic,ebp,forSym);
}
#endif
+ D(D_ALLOC, ("spilSomething: done.\n"));
+
if (ssym == forSym )
return FALSE ;
else
{
regs *reg;
+ D(D_ALLOC, ("getRegGpr: on ic %zi\n"));
tryAgain:
/* try for gpr type */
- if ((reg = allocReg(REG_GPR)))
+ if ((reg = allocReg(REG_GPR))) {
+ D(D_ALLOC, ("getRegGpr: got a reg.\n"));
return reg;
+ }
/* we have to spil */
- if (!spilSomething (ic,ebp,sym))
+ if (!spilSomething (ic,ebp,sym)) {
+ D(D_ALLOC, ("getRegGpr: have to spill.\n"));
return NULL ;
+ }
/* this looks like an infinite loop but
in really selectSpil will abort */
!OP_SYMBOL(IC_LEFT(ic->prev))->isspilt)
psym = OP_SYMBOL(IC_LEFT(ic->prev));
+ D(D_ALLOC, ("deassignLRs: in loop on sym %zs", sym));
+
if (sym->nRegs) {
int i = 0;
symbol *sym = OP_SYMBOL(op);
int i;
+ D(D_ALLOC, ("reassingLR: on sym %zs\n", sym));
+
/* not spilt any more */
sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
bitVectUnSetBit(spiltSet,sym->key);
*/
static void positionRegs (symbol *result, symbol *opsym, int lineno)
{
- int count = min(result->nRegs,opsym->nRegs);
- int i , j = 0, shared = 0;
+ int count = min(result->nRegs,opsym->nRegs);
+ int i , j = 0, shared = 0;
- /* if the result has been spilt then cannot share */
- if (opsym->isspilt)
- return ;
+ D(D_ALLOC, ("positionRegs: on result %zs opsum %zs line %u\n", result, opsym, lineno));
+
+ /* if the result has been spilt then cannot share */
+ if (opsym->isspilt)
+ return ;
again:
- shared = 0;
- /* first make sure that they actually share */
- for ( i = 0 ; i < count; i++ ) {
- for (j = 0 ; j < count ; j++ ) {
- if (result->regs[i] == opsym->regs[j] && i !=j) {
- shared = 1;
- goto xchgPositions;
- }
- }
+ shared = 0;
+ /* first make sure that they actually share */
+ for ( i = 0 ; i < count; i++ ) {
+ for (j = 0 ; j < count ; j++ ) {
+ if (result->regs[i] == opsym->regs[j] && i !=j) {
+ shared = 1;
+ goto xchgPositions;
+ }
}
+ }
xchgPositions:
- if (shared) {
- regs *tmp = result->regs[i];
- result->regs[i] = result->regs[j];
- result->regs[j] = tmp;
- goto again;
- }
+ if (shared) {
+ regs *tmp = result->regs[i];
+ result->regs[i] = result->regs[j];
+ result->regs[j] = tmp;
+ goto again;
+ }
}
/** Try to allocate a pair of registers to the symbol.
currFunc->regsUsed =
bitVectSetBit(currFunc->regsUsed,i+1);
}
+ D(D_ALLOC, ("tryAllocRegPair: succeded for sym %zs\n", sym));
return TRUE;
}
}
+ D(D_ALLOC, ("tryAllocRegPair: failed on sym %zs\n", sym));
return FALSE;
}
/* if this is an ipop that means some live
range will have to be assigned again */
- if (ic->op == IPOP)
+ if (ic->op == IPOP) {
+ wassert(0);
reassignLR (IC_LEFT(ic));
+ }
/* if result is present && is a true symbol */
if (IC_RESULT(ic) && ic->op != IFX &&
int willCS ;
int j;
+ D(D_ALLOC, ("serialRegAssign: in loop on result %zs\n", sym));
+
/* 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(regAssigned,sym->key) ||
- sym->liveTo <= ic->seq)
+ sym->liveTo <= ic->seq) {
+ D(D_ALLOC, ("serialRegAssign: wont live long enough.\n"));
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 (blockSpil && sym->liveTo > ebbs[i]->lSeq) {
+ D(D_ALLOC, ("serialRegAssign: \"spilling to be safe.\"\n"));
spillThis (sym);
continue ;
}
if ( sym->remat ||
(willCS && bitVectIsZero(spillable) ) ) {
+ D(D_ALLOC, ("serialRegAssign: \"remat spill\"\n"));
spillThis (sym) ;
continue ;
/* Special case: Try to fit into a reg pair if
available */
+ D(D_ALLOC, ("serialRegAssign: actually allocing regs!\n"));
if ((sym->nRegs == 2)&&tryAllocatingRegPair(sym)) {
}
else {
rumask = newBitVect(_nRegs);
for (j = 0; j < sym->nRegs; j++) {
- rumask = bitVectSetBit(rumask,
- sym->regs[j]->rIdx);
+ rumask = bitVectSetBit(rumask, sym->regs[j]->rIdx);
}
return rumask;
/*-----------------------------------------------------------------*/
/* regTypeNum - computes the type & number of registers required */
/*-----------------------------------------------------------------*/
-static void regTypeNum ()
+static void regTypeNum (void)
{
symbol *sym;
int k;
if ((sym->liveTo - sym->liveFrom) == 0)
continue ;
+ D(D_ALLOC, ("regTypeNum: loop on sym %zs\n", sym));
+
/* if the live range is a temporary */
if (sym->isitmp) {
getSize(sym->type = aggrToPtr(sym->type,FALSE)) :
getSize(sym->type));
+ D(D_ALLOC, ("regTypeNum: setup to assign regs sym %zs\n", sym));
+
if (sym->nRegs > 4) {
fprintf(stderr,"allocated more than 4 or 0 registers for type ");
printTypeChain(sym->type,stderr);fprintf(stderr,"\n");
{
int i;
+ D(D_ALLOC, ("freeAllRegs: running.\n"));
+
for (i=0;i< _nRegs;i++ )
regsZ80[i].isFree = 1;
}
static int packRegsForAssign (iCode *ic,eBBlock *ebp)
{
iCode *dic, *sic;
+
+ D(D_ALLOC, ("packRegsForAssing: running on ic %zi\n", ic));
if (
/* !IS_TRUE_SYMOP(IC_RESULT(ic)) ||*/
/* 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));
+
if (IS_ITEMP(IC_LEFT(ic)) &&
OP_SYMBOL(IC_LEFT(ic))->liveTo <= ic->seq) {
iCode *dic = findAssignToSym(IC_LEFT(ic),ic);
bitVect *uses ;
iCode *dic, *sic;
+ D(D_ALLOC, ("packRegsForOneUse: running on ic %zi\n", ic));
+
/* if returning a literal then do nothing */
if (!IS_SYMOP(op))
return NULL;
!IS_BITWISE_OP(uic) &&
uic->op != '=' &&
uic->op != EQ_OP &&
+ !POINTER_GET(uic) &&
/*
uic->op != LEFT_OP &&
- !POINTER_GET(uic) &&
uic->op != RIGHT_OP &&*/
1
) {
{
iCode *uic;
+ D(D_ALLOC, ("packRegsForAccUse2: running on ic %zi\n", ic));
+
/* Filter out all but those 'good' commands */
if (
+ !POINTER_GET(ic) &&
ic->op != '+' &&
!IS_BITWISE_OP(ic) &&
ic->op != '=' &&
{
iCode *ic ;
int change = 0 ;
+
+ D(D_ALLOC, ("packRegisters: entered.\n"));
while (1 && !DISABLE_PACK_ASSIGN) {
change = 0;
/* 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));
+
if (ic->op == ADDRESS_OF &&
IS_ITEMP(IC_RESULT(ic)) &&
IS_TRUE_SYMOP(IC_LEFT(ic)) &&
iCode *ic;
int i ;
+ D(D_ALLOC, ("\n-> z80_assignRegisters: entered.\n"));
+
setToNull((void *)&funcrUsed);
stackExtend = dataExtend = 0;