*/
#include "z80.h"
+#include "SDCCicode.h"
-enum {
- DISABLE_PACK_ACC = 0,
- DISABLE_PACK_ASSIGN = 0,
- LIMITED_PACK_ACC = 1
-};
-
-#define D_ALLOC 1
-
-#if 0
+/* Flags to turn off optimisations.
+ */
+enum
+ {
+ DISABLE_PACK_ACC = 0,
+ DISABLE_PACK_ASSIGN = 0,
+ DISABLE_PACK_ONE_USE = 0,
+ DISABLE_PACK_HL = 0,
+ DISABLE_PACK_IY = 0
+ };
+
+/* Flags to turn on debugging code.
+ */
+enum
+ {
+ D_ALLOC = 0,
+ D_ALLOC2 = 0,
+ D_ACCUSE2 = 0,
+ D_ACCUSE2_VERBOSE = 0,
+ D_HLUSE = 0,
+ D_HLUSE2 = 0,
+ D_HLUSE2_VERBOSE = 0,
+ D_FILL_GAPS = 0,
+ D_PACK_IY = 0,
+ D_PACK_HLUSE3 = 0
+ };
+
+#if 1
#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 */
-/* targetting other processors. The decision for this will have */
-/* to be made on a routine by routine basis */
-/* routines used to pack registers are most definitely not reusable*/
-/* since the pack the registers depending strictly on the MCU */
-/*-----------------------------------------------------------------*/
+#define DISABLE_PACKREGSFORSUPPORT 1
+#define DISABLE_PACKREGSFORACCUSE 1
-bitVect *spiltSet = NULL ;
-set *stackSpil = NULL;
-bitVect *regAssigned = NULL;
-short blockSpil = 0;
-int slocNum = 0 ;
-extern void genZ80Code(iCode *);
-bitVect *funcrUsed = NULL; /* registers used in a function */
-int stackExtend = 0;
-int dataExtend = 0;
-int _nRegs;
-
-/** Set to help debug register pressure related problems */
-#define DEBUG_FAKE_EXTRA_REGS 0
-
-static regs _gbz80_regs[] = {
- { REG_GPR, C_IDX , "c", 1 },
- { REG_GPR, B_IDX , "b", 1 },
- { REG_CND, CND_IDX, "c", 1}
+extern void genZ80Code (iCode *);
+
+/** Local static variables */
+static struct
+{
+ bitVect *spiltSet;
+ set *stackSpil;
+ bitVect *regAssigned;
+ bitVect *totRegAssigned; /* final set of LRs that got into registers */
+ short blockSpil;
+ int slocNum;
+ /* registers used in a function */
+ bitVect *funcrUsed;
+ int stackExtend;
+ int dataExtend;
+ int nRegs;
+} _G;
+
+static regs _gbz80_regs[] =
+{
+ {REG_GPR, C_IDX, "c", 1},
+ {REG_GPR, B_IDX, "b", 1},
+ {REG_CND, CND_IDX, "c", 1}
};
-static regs _z80_regs[] = {
- { REG_GPR, C_IDX , "c", 1 },
- { REG_GPR, B_IDX , "b", 1 },
- { REG_GPR, E_IDX , "e", 1 },
- { REG_GPR, D_IDX , "d", 1 },
- /* { REG_GPR, L_IDX , "l", 1 },
- { REG_GPR, H_IDX , "h", 1 },*/
-#if DEBUG_FAKE_EXTRA_REGS
- { REG_GPR, M_IDX , "m", 1 },
- { REG_GPR, N_IDX , "n", 1 },
- { REG_GPR, O_IDX , "o", 1 },
- { REG_GPR, P_IDX , "p", 1 },
- { REG_GPR, Q_IDX , "q", 1 },
- { REG_GPR, R_IDX , "r", 1 },
- { REG_GPR, S_IDX , "s", 1 },
- { REG_GPR, T_IDX , "t", 1 },
-#endif
- { REG_CND, CND_IDX, "c", 1}
+static regs _z80_regs[] =
+{
+ {REG_GPR, C_IDX, "c", 1},
+ {REG_GPR, B_IDX, "b", 1},
+ {REG_GPR, E_IDX, "e", 1},
+ {REG_GPR, D_IDX, "d", 1},
+ {REG_CND, CND_IDX, "c", 1}
};
regs *regsZ80;
#define GBZ80_MAX_REGS ((sizeof(_gbz80_regs)/sizeof(_gbz80_regs[0]))-1)
static void spillThis (symbol *);
+static void freeAllRegs ();
/** Allocates register of given type.
'type' is not used on the z80 version. It was used to select
@return Pointer to the newly allocated register.
*/
-static regs *allocReg (short type)
+static regs *
+allocReg (short type)
{
- int i;
-
- for ( i = 0 ; i < _nRegs ; i++ ) {
- /* For now we allocate from any free */
- if (regsZ80[i].isFree ) {
- regsZ80[i].isFree = 0;
- if (currFunc)
- currFunc->regsUsed =
- bitVectSetBit(currFunc->regsUsed,i);
- D(D_ALLOC, ("allocReg: alloced %zr\n", ®sZ80[i]));
- return ®sZ80[i];
+ int i;
+
+ for (i = 0; i < _G.nRegs; i++)
+ {
+ /* For now we allocate from any free */
+ if (regsZ80[i].isFree)
+ {
+ regsZ80[i].isFree = 0;
+ if (currFunc)
+ {
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, i);
+ }
+ D (D_ALLOC, ("allocReg: alloced %p\n", ®sZ80[i]));
+ return ®sZ80[i];
}
}
- D(D_ALLOC, ("allocReg: No free.\n"));
- return NULL;
+ D (D_ALLOC, ("allocReg: No free.\n"));
+ return NULL;
}
/** Returns pointer to register wit index number
*/
-regs *regWithIdx (int idx)
+regs *
+regWithIdx (int idx)
{
- int i;
-
- 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);
+ int i;
+
+ for (i = 0; i < _G.nRegs; i++)
+ {
+ if (regsZ80[i].rIdx == idx)
+ {
+ return ®sZ80[i];
+ }
+ }
+
+ wassertl (0, "regWithIdx not found");
+ exit (1);
}
/** Frees a register.
*/
-static void freeReg (regs *reg)
+static void
+freeReg (regs * reg)
{
- wassert(!reg->isFree);
- reg->isFree = 1;
- D(D_ALLOC, ("freeReg: freed %zr\n", reg));
+ wassert (!reg->isFree);
+ reg->isFree = 1;
+ D (D_ALLOC, ("freeReg: freed %p\n", reg));
}
/** Returns number of free registers.
*/
-static int nFreeRegs (int type)
+static int
+nFreeRegs (int type)
{
- int i;
- int nfr=0;
-
- for (i = 0 ; i < _nRegs; i++ ) {
- /* For now only one reg type */
- if (regsZ80[i].isFree)
- nfr++;
+ int i;
+ int nfr = 0;
+
+ for (i = 0; i < _G.nRegs; i++)
+ {
+ /* For now only one reg type */
+ if (regsZ80[i].isFree)
+ {
+ nfr++;
+ }
}
- return nfr;
+ return nfr;
}
/** Free registers with type.
*/
-static int nfreeRegsType (int type)
+static int
+nfreeRegsType (int type)
{
- int nfr ;
- if (type == REG_PTR) {
- if ((nfr = nFreeRegs(type)) == 0)
- return nFreeRegs(REG_GPR);
- }
-
- return nFreeRegs(type);
+ int nfr;
+ if (type == REG_PTR)
+ {
+ if ((nfr = nFreeRegs (type)) == 0)
+ {
+ return nFreeRegs (REG_GPR);
+ }
+ }
+
+ return nFreeRegs (type);
}
+/*-----------------------------------------------------------------*/
+/* useReg - marks a register as used */
+/*-----------------------------------------------------------------*/
+static void
+useReg (regs * reg)
+{
+ reg->isFree = 0;
+}
#if 0
/*-----------------------------------------------------------------*/
/* allDefsOutOfRange - all definitions are out of a range */
/*-----------------------------------------------------------------*/
-static bool allDefsOutOfRange (bitVect *defs,int fseq, int toseq)
+static bool
+allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
{
- int i ;
+ int i;
+
+ if (!defs)
+ return TRUE;
+
+ for (i = 0; i < defs->size; i++)
+ {
+ iCode *ic;
- if (!defs)
- return TRUE ;
+ if (bitVectBitValue (defs, i) &&
+ (ic = hTabItemWithKey (iCodehTab, i)) &&
+ (ic->seq >= fseq && ic->seq <= toseq))
- for ( i = 0 ;i < defs->size ; i++ ) {
- iCode *ic;
+ return FALSE;
- if (bitVectBitValue(defs,i) &&
- (ic = hTabItemWithKey(iCodehTab,i)) &&
- ( ic->seq >= fseq && ic->seq <= toseq))
-
- return FALSE;
-
}
-
- return TRUE;
+
+ return TRUE;
}
#endif
-
+
/*-----------------------------------------------------------------*/
/* computeSpillable - given a point find the spillable live ranges */
/*-----------------------------------------------------------------*/
-static bitVect *computeSpillable (iCode *ic)
+static bitVect *
+computeSpillable (iCode * ic)
{
- bitVect *spillable ;
-
- /* spillable live ranges are those that are live at this
- point . the following categories need to be subtracted
- from this set.
- a) - those that are already spilt
- b) - if being used by this one
- c) - defined by this one */
-
- spillable = bitVectCopy(ic->rlive);
- spillable =
- bitVectCplAnd(spillable,spiltSet); /* those already spilt */
- spillable =
- bitVectCplAnd(spillable,ic->uses); /* used in this one */
- bitVectUnSetBit(spillable,ic->defKey);
- spillable = bitVectIntersect(spillable,regAssigned);
- return spillable;
-
+ bitVect *spillable;
+
+ /* spillable live ranges are those that are live at this
+ point . the following categories need to be subtracted
+ from this set.
+ a) - those that are already spilt
+ b) - if being used by this one
+ c) - defined by this one */
+
+ spillable = bitVectCopy (ic->rlive);
+ spillable =
+ bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */
+ spillable =
+ bitVectCplAnd (spillable, ic->uses); /* used in this one */
+ bitVectUnSetBit (spillable, ic->defKey);
+ spillable = bitVectIntersect (spillable, _G.regAssigned);
+
+ return spillable;
}
/*-----------------------------------------------------------------*/
/* noSpilLoc - return true if a variable has no spil location */
/*-----------------------------------------------------------------*/
-static int noSpilLoc (symbol *sym, eBBlock *ebp,iCode *ic)
+static int
+noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
{
- return (sym->usl.spillLoc ? 0 : 1);
+ return (sym->usl.spillLoc ? 0 : 1);
}
/*-----------------------------------------------------------------*/
/* hasSpilLoc - will return 1 if the symbol has spil location */
/*-----------------------------------------------------------------*/
-static int hasSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic)
+static int
+hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
{
- return (sym->usl.spillLoc ? 1 : 0);
+ return (sym->usl.spillLoc ? 1 : 0);
}
/** Will return 1 if the remat flag is set.
into registers at creation as it can be re-created at any time -
i.e. it's constant in some way.
*/
-static int rematable (symbol *sym, eBBlock *ebp, iCode *ic)
+static int
+rematable (symbol * sym, eBBlock * ebp, iCode * ic)
{
- return sym->remat;
+ return sym->remat;
}
/*-----------------------------------------------------------------*/
/* allLRs - return true for all */
/*-----------------------------------------------------------------*/
-static int allLRs (symbol *sym, eBBlock *ebp, iCode *ic)
+static int
+allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
{
- return 1;
+ return 1;
}
-/*-----------------------------------------------------------------*/
-/* liveRangesWith - applies function to a given set of live range */
-/*-----------------------------------------------------------------*/
-set *liveRangesWith (bitVect *lrs, int (func)(symbol *,eBBlock *, iCode *),
- eBBlock *ebp, iCode *ic)
+/** liveRangesWith - applies function to a given set of live range
+ */
+static set *
+liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
+ eBBlock * ebp, iCode * ic)
{
- set *rset = NULL;
- int i;
-
- if (!lrs || !lrs->size)
- return NULL;
+ set *rset = NULL;
+ int i;
- for ( i = 1 ; i < lrs->size ; i++ ) {
- symbol *sym;
- if (!bitVectBitValue(lrs,i))
- continue ;
+ if (!lrs || !lrs->size)
+ return NULL;
- /* if we don't find it in the live range
- hash table we are in serious trouble */
- if (!(sym = hTabItemWithKey(liveRanges,i))) {
- werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
- "liveRangesWith could not find liveRange");
- exit(1);
+ for (i = 1; i < lrs->size; i++)
+ {
+ symbol *sym;
+ if (!bitVectBitValue (lrs, i))
+ continue;
+
+ /* if we don't find it in the live range
+ hash table we are in serious trouble */
+ if (!(sym = hTabItemWithKey (liveRanges, i)))
+ {
+ wassertl (0, "liveRangesWith could not find liveRange");
+ exit (1);
}
-
- if (func(sym,ebp,ic) && bitVectBitValue(regAssigned,sym->key))
- addSetHead(&rset,sym);
+
+ if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
+ {
+ addSetHead (&rset, sym);
+ }
}
- return rset;
+ return rset;
}
-/*-----------------------------------------------------------------*/
-/* leastUsedLR - given a set determines which is the least used */
-/*-----------------------------------------------------------------*/
-symbol *leastUsedLR (set *sset)
+/** leastUsedLR - given a set determines which is the least used
+ */
+static symbol *
+leastUsedLR (set * sset)
{
- symbol *sym = NULL, *lsym = NULL ;
-
- sym = lsym = setFirstItem(sset);
+ symbol *sym = NULL, *lsym = NULL;
- if (!lsym)
- return NULL;
+ sym = lsym = setFirstItem (sset);
+
+ if (!lsym)
+ return NULL;
+
+ for (; lsym; lsym = setNextItem (sset))
+ {
+
+ /* if usage is the same then prefer
+ the spill the smaller of the two */
+ if (lsym->used == sym->used)
+ if (getSize (lsym->type) < getSize (sym->type))
+ sym = lsym;
- for (; lsym; lsym = setNextItem(sset)) {
-
- /* if usage is the same then prefer
- the spill the smaller of the two */
- if ( lsym->used == sym->used )
- if (getSize(lsym->type) < getSize(sym->type))
- sym = lsym;
-
- /* if less usage */
- if (lsym->used < sym->used )
- sym = lsym;
-
- }
-
- setToNull((void **)&sset);
- sym->blockSpil = 0;
- return sym;
+ /* if less usage */
+ if (lsym->used < sym->used)
+ sym = lsym;
+
+ }
+
+ setToNull ((void **) &sset);
+ sym->blockSpil = 0;
+ return sym;
}
-/*-----------------------------------------------------------------*/
-/* noOverLap - will iterate through the list looking for over lap */
-/*-----------------------------------------------------------------*/
-static int noOverLap (set *itmpStack, symbol *fsym)
+/** noOverLap - will iterate through the list looking for over lap
+ */
+static int
+noOverLap (set * itmpStack, symbol * fsym)
{
- symbol *sym;
-
- for (sym = setFirstItem(itmpStack); sym;
- sym = setNextItem(itmpStack)) {
- if (sym->liveTo > fsym->liveFrom )
- return 0;
-
- }
- return 1;
+ symbol *sym;
+
+ for (sym = setFirstItem (itmpStack); sym;
+ sym = setNextItem (itmpStack))
+ {
+ if (bitVectBitValue(sym->clashes,fsym->key))
+ return 0;
+#if 0
+ // if sym starts before (or on) our end point
+ // and ends after (or on) our start point,
+ // it is an overlap.
+ if (sym->liveFrom <= fsym->liveTo &&
+ sym->liveTo >= fsym->liveFrom)
+ {
+ return 0;
+ }
+#endif
+ }
+ return 1;
}
/*-----------------------------------------------------------------*/
/* isFree - will return 1 if the a free spil location is found */
/*-----------------------------------------------------------------*/
-DEFSETFUNC(isFree)
+DEFSETFUNC (isFree)
{
- symbol *sym = item;
- V_ARG(symbol **,sloc);
- V_ARG(symbol *,fsym);
+ symbol *sym = item;
+ V_ARG (symbol **, sloc);
+ V_ARG (symbol *, fsym);
- /* if already found */
- if (*sloc)
- return 0;
+ /* if already found */
+ if (*sloc)
+ return 0;
- /* if it is free && and the itmp assigned to
- this does not have any overlapping live ranges
- with the one currently being assigned and
- the size can be accomodated */
- if (sym->isFree &&
- noOverLap(sym->usl.itmpStack,fsym) &&
- getSize(sym->type) >= getSize(fsym->type)) {
- *sloc = sym;
- return 1;
+ /* if it is free && and the itmp assigned to
+ this does not have any overlapping live ranges
+ with the one currently being assigned and
+ the size can be accomodated */
+ if (sym->isFree &&
+ noOverLap (sym->usl.itmpStack, fsym) &&
+ getSize (sym->type) >= getSize (fsym->type))
+ {
+ *sloc = sym;
+ return 1;
}
- return 0;
+ return 0;
}
/*-----------------------------------------------------------------*/
/* createStackSpil - create a location on the stack to spil */
/*-----------------------------------------------------------------*/
-symbol *createStackSpil (symbol *sym)
+static symbol *
+createStackSpil (symbol * sym)
{
- 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)) {
- /* found a free one : just update & return */
- sym->usl.spillLoc = sloc;
- sym->stackSpil= 1;
- sloc->isFree = 0;
- addSetHead(&sloc->usl.itmpStack,sym);
- D(D_ALLOC, ("createStackSpil: found existing\n"));
- return sym;
- }
-
- /* could not then have to create one , this is the hard part
- we need to allocate this on the stack : this is really a
- hack!! but cannot think of anything better at this time */
-
- sprintf(buffer,"sloc%d",slocNum++);
- sloc = newiTemp(buffer);
-
- /* set the type to the spilling symbol */
- sloc->type = copyLinkChain(sym->type);
- sloc->etype = getSpec(sloc->type);
- SPEC_SCLS(sloc->etype) = S_AUTO ;
-
- /* we don't allow it to be allocated`
- onto the external stack since : so we
- temporarily turn it off ; we also
- turn off memory model to prevent
- the spil from going to the external storage
- and turn off overlaying
- */
- allocLocal(sloc);
-
- sloc->isref = 1; /* to prevent compiler warning */
-
- /* if it is on the stack then update the stack */
- if (IN_STACK(sloc->etype)) {
- currFunc->stack += getSize(sloc->type);
- stackExtend += getSize(sloc->type);
- } else
- dataExtend += getSize(sloc->type);
-
- /* add it to the stackSpil set */
- addSetHead(&stackSpil,sloc);
- sym->usl.spillLoc = sloc;
- sym->stackSpil = 1;
-
- /* add it to the set of itempStack set
- of the spill location */
- addSetHead(&sloc->usl.itmpStack,sym);
+ symbol *sloc = NULL;
+
+ D (D_ALLOC, ("createStackSpil: for sym %p\n", sym));
+
+ /* first go try and find a free one that is already
+ existing on the stack */
+ if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
+ {
+ /* found a free one : just update & return */
+ sym->usl.spillLoc = sloc;
+ sym->stackSpil = 1;
+ sloc->isFree = 0;
+ addSetHead (&sloc->usl.itmpStack, sym);
+ D (D_ALLOC, ("createStackSpil: found existing\n"));
+ return sym;
+ }
+
+ /* could not then have to create one , this is the hard part
+ we need to allocate this on the stack : this is really a
+ hack!! but cannot think of anything better at this time */
+
+ sprintf (buffer, "sloc%d", _G.slocNum++);
+ sloc = newiTemp (buffer);
+
+ /* set the type to the spilling symbol */
+ sloc->type = copyLinkChain (sym->type);
+ sloc->etype = getSpec (sloc->type);
+ SPEC_SCLS (sloc->etype) = S_AUTO;
+ SPEC_EXTR (sloc->etype) = 0;
+ SPEC_STAT (sloc->etype) = 0;
+ SPEC_VOLATILE(sloc->etype) = 0;
+
+ allocLocal (sloc);
+
+ sloc->isref = 1; /* to prevent compiler warning */
+
+ /* if it is on the stack then update the stack */
+ if (IN_STACK (sloc->etype))
+ {
+ currFunc->stack += getSize (sloc->type);
+ _G.stackExtend += getSize (sloc->type);
+ }
+ else
+ {
+ _G.dataExtend += getSize (sloc->type);
+ }
- D(D_ALLOC, ("createStackSpil: created new\n"));
- return sym;
+ /* add it to the stackSpil set */
+ addSetHead (&_G.stackSpil, sloc);
+ sym->usl.spillLoc = sloc;
+ sym->stackSpil = 1;
+
+ /* 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;
}
/*-----------------------------------------------------------------*/
-/* isSpiltOnStack - returns true if the spil location is on stack */
+/* spillThis - spils a specific operand */
/*-----------------------------------------------------------------*/
-bool isSpiltOnStack (symbol *sym)
+static void
+spillThis (symbol * sym)
{
- link *etype;
+ int i;
- if (!sym)
- return FALSE ;
-
- if (!sym->isspilt)
- return FALSE ;
+ D (D_ALLOC, ("spillThis: spilling %p\n", sym));
-/* if (sym->stackSpil) */
-/* return TRUE; */
-
- if (!sym->usl.spillLoc)
- return FALSE;
+ /* if this is rematerializable or has a spillLocation
+ we are okay, else we need to create a spillLocation
+ for it */
+ if (!(sym->remat || sym->usl.spillLoc))
+ {
+ createStackSpil (sym);
+ }
- etype = getSpec(sym->usl.spillLoc->type);
- if (IN_STACK(etype))
- return TRUE;
+ /* mark it has spilt & put it in the spilt set */
+ 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->regs[i])
+ {
+ freeReg (sym->regs[i]);
+ sym->regs[i] = NULL;
+ }
+ }
- return FALSE ;
+ if (sym->usl.spillLoc && !sym->remat)
+ {
+ sym->usl.spillLoc->allocreq++;
+ }
+ return;
}
+#if DISABLED
/*-----------------------------------------------------------------*/
-/* spillThis - spils a specific operand */
+/* allDefsOutOfRange - all definitions are out of a range */
/*-----------------------------------------------------------------*/
-static void spillThis (symbol *sym)
+static bool
+allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
{
- 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 */
- if (!(sym->remat || sym->usl.spillLoc))
- createStackSpil (sym);
-
- /* mark it has spilt & put it in the spilt set */
- sym->isspilt = 1;
- spiltSet = bitVectSetBit(spiltSet,sym->key);
-
- bitVectUnSetBit(regAssigned,sym->key);
-
- for (i = 0 ; i < sym->nRegs ; i++) {
- if (sym->regs[i]) {
- freeReg(sym->regs[i]);
- sym->regs[i] = NULL;
- }
+ 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;
+
}
-
- /* if spilt on stack then free up r0 & r1
- if they could have been assigned to some
- LIVE ranges */
- if (sym->usl.spillLoc && !sym->remat)
- sym->usl.spillLoc->allocreq = 1;
- return;
+
+ return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
+/* but is not used as a pointer */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+ 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 */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+ return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
+ allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
}
+#endif
/** Select a iTemp to spil : rather a simple procedure.
*/
-symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym)
+symbol *
+selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
{
- bitVect *lrcs= NULL ;
- set *selectS ;
- symbol *sym;
+ bitVect *lrcs = NULL;
+ set *selectS;
+ symbol *sym;
- D(D_ALLOC, ("selectSpil: finding spill for ic %zi\n", ic));
- /* get the spillable live ranges */
- lrcs = computeSpillable (ic);
+ D (D_ALLOC, ("selectSpil: finding spill for ic %p\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);
+ /* 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);
}
#if 0
- /* get live ranges with spillLocations in direct space */
- if ((selectS = liveRangesWith(lrcs,directSpilLoc,ebp,ic))) {
- sym = leastUsedLR(selectS);
- strcpy(sym->rname,(sym->usl.spillLoc->rname[0] ?
- sym->usl.spillLoc->rname :
- sym->usl.spillLoc->name));
- sym->spildir = 1;
- /* mark it as allocation required */
- sym->usl.spillLoc->allocreq = 1;
- return sym;
- }
-
- /* if the symbol is local to the block then */
- if (forSym->liveTo < ebp->lSeq ) {
-
- /* check if there are any live ranges allocated
- to registers that are not used in this block */
- if (!blockSpil && (selectS = liveRangesWith(lrcs,notUsedInBlock,ebp,ic))) {
- sym = leastUsedLR(selectS);
- /* if this is not rematerializable */
- if (!sym->remat) {
- blockSpil++;
- sym->blockSpil = 1;
+ /* get live ranges with spillLocations in direct space */
+ if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
+ {
+ sym = leastUsedLR (selectS);
+ strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
+ sym->usl.spillLoc->rname :
+ sym->usl.spillLoc->name));
+ sym->spildir = 1;
+ /* mark it as allocation required */
+ sym->usl.spillLoc->allocreq++;
+ return sym;
+ }
+
+ /* if the symbol is local to the block then */
+ if (forSym->liveTo < ebp->lSeq)
+ {
+
+ /* check if there are any live ranges allocated
+ to registers that are not used in this block */
+ if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
+ {
+ sym = leastUsedLR (selectS);
+ /* if this is not rematerializable */
+ if (!sym->remat)
+ {
+ _G.blockSpil++;
+ wassertl (0, "Attempted to do an unsupported block spill");
+ sym->blockSpil = 1;
}
- return sym;
- }
-
- /* check if there are any live ranges that not
- 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++;
+ return sym;
+ }
+
+ /* check if there are any live ranges that not
+ used in the remainder of the block */
+ if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+ {
+ sym = leastUsedLR (selectS);
+ if (sym != forSym)
+ {
+ if (!sym->remat)
+ {
+ wassertl (0, "Attempted to do an unsupported remain spill");
+ sym->remainSpil = 1;
+ _G.blockSpil++;
+ }
+ return sym;
}
- return sym;
}
}
- /* find live ranges with spillocation && not used as pointers */
- if ((selectS = liveRangesWith(lrcs,hasSpilLocnoUptr,ebp,ic))) {
-
- sym = leastUsedLR(selectS);
- /* mark this as allocation required */
- sym->usl.spillLoc->allocreq = 1;
- return sym;
- }
-#endif
-
- /* 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;
- }
-
- /* couldn't find then we need to create a spil
- 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;
- return sym;
+ /* find live ranges with spillocation && not used as pointers */
+ if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
+ {
+
+ sym = leastUsedLR (selectS);
+ /* mark this as allocation required */
+ sym->usl.spillLoc->allocreq++;
+ return sym;
}
-
- /* 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;
-
+#endif
+
+ /* 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++;
+ return sym;
+ }
+
+ /* couldn't find then we need to create a spil
+ 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++;
+ return sym;
+ }
+
+ /* 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;
+
}
/** Spil some variable & mark registers as free.
A spill occurs when an iTemp wont fit into the available registers.
*/
-bool spilSomething (iCode *ic, eBBlock *ebp, symbol *forSym)
+bool
+spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
{
- symbol *ssym;
- int i ;
+ 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);
-
- /* mark it as spilt */
- ssym->isspilt = 1;
- spiltSet = bitVectSetBit(spiltSet,ssym->key);
-
- /* mark it as not register assigned &
- take it away from the set */
- bitVectUnSetBit(regAssigned,ssym->key);
-
- /* mark the registers as free */
- for (i = 0 ; i < ssym->nRegs ;i++ )
- if (ssym->regs[i])
- freeReg(ssym->regs[i]);
+ /* get something we can spil */
+ ssym = selectSpil (ic, ebp, forSym);
+
+ /* mark it as spilt */
+ 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++)
+ if (ssym->regs[i])
+ freeReg (ssym->regs[i]);
+
+ wassertl (ssym->blockSpil == 0, "Encountered a sym with a block spill");
+ wassertl (ssym->remainSpil == 0, "Encountered a sym with a remain spill");
#if 0
- /* if spilt on stack then free up r0 & r1
- if they could have been assigned to as gprs */
- if (!ptrRegReq && isSpiltOnStack(ssym) ) {
- ptrRegReq++ ;
- spillLRWithPtrReg(ssym);
- }
-
- /* if this was a block level spil then insert push & pop
- at the start & end of block respectively */
- if (ssym->blockSpil) {
- iCode *nic = newiCode(IPUSH,operandFromSymbol(ssym),NULL);
- /* add push to the start of the block */
- addiCodeToeBBlock(ebp,nic,( ebp->sch->op == LABEL ?
+ /* if spilt on stack then free up r0 & r1
+ if they could have been assigned to as gprs */
+ if (!ptrRegReq && isSpiltOnStack (ssym))
+ {
+ ptrRegReq++;
+ spillLRWithPtrReg (ssym);
+ }
+
+ /* if this was a block level spil then insert push & pop
+ at the start & end of block respectively */
+ if (ssym->blockSpil)
+ {
+ iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+ /* add push to the start of the block */
+ addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
ebp->sch->next : ebp->sch));
- nic = newiCode(IPOP,operandFromSymbol(ssym),NULL);
- /* add pop to the end of the block */
- addiCodeToeBBlock(ebp,nic,NULL);
- }
-
- /* if spilt because not used in the remainder of the
- block then add a push before this instruction and
- a pop at the end of the block */
- if (ssym->remainSpil) {
-
- iCode *nic = newiCode(IPUSH,operandFromSymbol(ssym),NULL);
- /* add push just before this instruction */
- addiCodeToeBBlock(ebp,nic,ic);
-
- nic = newiCode(IPOP,operandFromSymbol(ssym),NULL);
- /* add pop to the end of the block */
- addiCodeToeBBlock(ebp,nic,NULL);
+ nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+ /* add pop to the end of the block */
+ addiCodeToeBBlock (ebp, nic, NULL);
+ }
+
+ /* if spilt because not used in the remainder of the
+ block then add a push before this instruction and
+ a pop at the end of the block */
+ if (ssym->remainSpil)
+ {
+
+ iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+ /* add push just before this instruction */
+ addiCodeToeBBlock (ebp, nic, ic);
+
+ nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+ /* add pop to the end of the block */
+ addiCodeToeBBlock (ebp, nic, NULL);
}
#endif
- D(D_ALLOC, ("spilSomething: done.\n"));
+ D (D_ALLOC, ("spilSomething: done.\n"));
- if (ssym == forSym )
- return FALSE ;
- else
- return TRUE ;
+ if (ssym == forSym)
+ return FALSE;
+ else
+ return TRUE;
}
/** Will try for GPR if not spil.
*/
-regs *getRegGpr (iCode *ic, eBBlock *ebp,symbol *sym)
+regs *
+getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
{
- regs *reg;
+ regs *reg;
- D(D_ALLOC, ("getRegGpr: on ic %zi\n"));
- tryAgain:
- /* try for gpr type */
- if ((reg = allocReg(REG_GPR))) {
- D(D_ALLOC, ("getRegGpr: got a reg.\n"));
- return reg;
+ D (D_ALLOC, ("getRegGpr: on ic %p\n", ic));
+tryAgain:
+ /* try for gpr type */
+ if ((reg = allocReg (REG_GPR)))
+ {
+ D (D_ALLOC, ("getRegGpr: got a reg.\n"));
+ return reg;
}
- /* we have to spil */
- if (!spilSomething (ic,ebp,sym)) {
- D(D_ALLOC, ("getRegGpr: have to spill.\n"));
- return NULL ;
+ /* we have to spil */
+ 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 */
- goto tryAgain ;
+ /* this looks like an infinite loop but
+ in really selectSpil will abort */
+ goto tryAgain;
+}
+
+static regs *getRegGprNoSpil()
+{
+ regs *reg;
+
+ /* try for gpr type */
+ if ((reg = allocReg (REG_GPR)))
+ {
+ D (D_ALLOC, ("getRegGprNoSpil: got a reg.\n"));
+ return reg;
+ }
+ assert(0);
}
/** Symbol has a given register.
*/
-static bool symHasReg(symbol *sym,regs *reg)
+static bool
+symHasReg (symbol * sym, regs * reg)
{
- int i;
+ int i;
- for ( i = 0 ; i < sym->nRegs ; i++)
- if (sym->regs[i] == reg)
- return TRUE;
-
- return FALSE;
+ for (i = 0; i < sym->nRegs; i++)
+ if (sym->regs[i] == reg)
+ return TRUE;
+
+ return FALSE;
}
/** Check the live to and if they have registers & are not spilt then
free up the registers
*/
-static void deassignLRs (iCode *ic, eBBlock *ebp)
+static void
+deassignLRs (iCode * ic, eBBlock * ebp)
{
- symbol *sym;
- int k;
- symbol *result;
-
- for (sym = hTabFirstItem(liveRanges,&k); sym;
- sym = hTabNextItem(liveRanges,&k)) {
-
- symbol *psym= NULL;
- /* if it does not end here */
- if (sym->liveTo > ic->seq )
- continue ;
+ symbol *sym;
+ int k;
+ symbol *result;
- /* if it was spilt on stack then we can
- mark the stack spil location as free */
- if (sym->isspilt ) {
- if (sym->stackSpil) {
- sym->usl.spillLoc->isFree = 1;
- sym->stackSpil = 0;
+ for (sym = hTabFirstItem (liveRanges, &k); sym;
+ sym = hTabNextItem (liveRanges, &k))
+ {
+
+ symbol *psym = NULL;
+ /* if it does not end here */
+ if (sym->liveTo > ic->seq)
+ continue;
+
+ /* if it was spilt on stack then we can
+ mark the stack spil location as free */
+ if (sym->isspilt)
+ {
+ if (sym->stackSpil)
+ {
+ sym->usl.spillLoc->isFree = 1;
+ sym->stackSpil = 0;
}
- continue ;
+ continue;
}
-
- if (!bitVectBitValue(regAssigned,sym->key))
- continue;
-
- /* special case check if this is an IFX &
- the privious one was a pop and the
- previous one was not spilt then keep track
- of the symbol */
- if (ic->op == IFX && ic->prev &&
- ic->prev->op == IPOP &&
- !ic->prev->parmPush &&
- !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;
-
- bitVectUnSetBit(regAssigned,sym->key);
-
- /* if the result of this one needs registers
- and does not have it then assign it right
- away */
- if (IC_RESULT(ic) &&
- ! (SKIP_IC2(ic) || /* not a special icode */
- ic->op == JUMPTABLE ||
- ic->op == IFX ||
- ic->op == IPUSH ||
- ic->op == IPOP ||
- ic->op == RETURN) &&
- (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->regType == sym->regType && /* same register types */
- result->nRegs && /* which needs registers */
- ! result->isspilt && /* and does not already have them */
- ! result->remat &&
- ! bitVectBitValue(regAssigned,result->key) &&
- /* the number of free regs + number of regs in this LR
- can accomodate the what result Needs */
- ((nfreeRegsType(result->regType) +
- sym->nRegs) >= result->nRegs)
- ) {
- for (i = 0 ; i < max(sym->nRegs,result->nRegs) ; i++) {
- if (i < sym->nRegs )
- result->regs[i] = sym->regs[i] ;
- else
- result->regs[i] = getRegGpr (ic,ebp,result);
-
- /* if the allocation falied which means
- this was spilt then break */
- if (!result->regs[i]) {
- wassert(0);
- assert(0);
- break;
+
+ if (!bitVectBitValue (_G.regAssigned, sym->key))
+ continue;
+
+ /* special case check if this is an IFX &
+ the privious one was a pop and the
+ previous one was not spilt then keep track
+ of the symbol */
+ if (ic->op == IFX && ic->prev &&
+ ic->prev->op == IPOP &&
+ !ic->prev->parmPush &&
+ !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
+ psym = OP_SYMBOL (IC_LEFT (ic->prev));
+
+ D (D_ALLOC, ("deassignLRs: in loop on sym %p nregs %u\n", sym, sym->nRegs));
+
+ if (sym->nRegs)
+ {
+ int i = 0;
+
+ bitVectUnSetBit (_G.regAssigned, sym->key);
+
+ /* if the result of this one needs registers
+ and does not have it then assign it right
+ away */
+ if (IC_RESULT (ic) &&
+ !(SKIP_IC2 (ic) || /* not a special icode */
+ ic->op == JUMPTABLE ||
+ ic->op == IFX ||
+ ic->op == IPUSH ||
+ ic->op == IPOP ||
+ ic->op == RETURN) &&
+ (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->regType == sym->regType && /* same register types */
+ result->nRegs && /* which needs registers */
+ !result->isspilt && /* and does not already have them */
+ !result->remat &&
+ !bitVectBitValue (_G.regAssigned, result->key) &&
+ /* the number of free regs + number of regs in this LR
+ can accomodate the what result Needs */
+ ((nfreeRegsType (result->regType) +
+ sym->nRegs) >= result->nRegs)
+ )
+ {
+ for (i = 0; i < result->nRegs; i++)
+ {
+ if (i < sym->nRegs)
+ result->regs[i] = sym->regs[i];
+ else
+ result->regs[i] = getRegGpr (ic, ebp, result);
+
+ /* if the allocation falied which means
+ this was spilt then break */
+ if (!result->regs[i])
+ {
+ wassert (0);
+ assert (0);
+ break;
}
}
- regAssigned = bitVectSetBit(regAssigned,result->key);
- }
-
- /* free the remaining */
- for (; i < sym->nRegs ; i++) {
- if (psym) {
- if (!symHasReg(psym,sym->regs[i]))
- freeReg(sym->regs[i]);
- } else
- freeReg(sym->regs[i]);
- // sym->regs[i] = NULL;
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+ _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key);
+ }
+
+ /* free the remaining */
+ for (; i < sym->nRegs; i++)
+ {
+ if (psym)
+ {
+ if (!symHasReg (psym, sym->regs[i]))
+ freeReg (sym->regs[i]);
+ }
+ else
+ freeReg (sym->regs[i]);
+ // sym->regs[i] = NULL;
}
}
}
/** Reassign this to registers.
*/
-static void reassignLR (operand *op)
+static void
+reassignLR (operand * op)
{
- symbol *sym = OP_SYMBOL(op);
- int i;
+ 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;
- bitVectUnSetBit(spiltSet,sym->key);
-
- regAssigned = bitVectSetBit(regAssigned,sym->key);
+ /* not spilt any more */
+ 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);
- blockSpil--;
+ _G.blockSpil--;
- for (i=0;i<sym->nRegs;i++)
- sym->regs[i]->isFree = 0;
+ for (i = 0; i < sym->nRegs; i++)
+ sym->regs[i]->isFree = 0;
}
/** Determines if allocating will cause a spill.
*/
-static int willCauseSpill ( int nr, int rt)
+static int
+willCauseSpill (int nr, int rt)
{
- /* first check if there are any avlb registers
- of te type required */
- if (nFreeRegs(0) >= nr)
- return 0;
+ /* first check if there are any avlb registers
+ of te type required */
+ if (nFreeRegs (0) >= nr)
+ return 0;
- /* it will cause a spil */
- return 1;
+ /* it will cause a spil */
+ return 1;
}
/** The allocator can allocate same registers to result 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;
-
- 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;
+ int count = min (result->nRegs, opsym->nRegs);
+ int i, j = 0, shared = 0;
+ int change = 0;
+
+ 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)
+ return 0;
+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;
}
}
}
- xchgPositions:
- if (shared) {
- regs *tmp = result->regs[i];
- result->regs[i] = result->regs[j];
- result->regs[j] = tmp;
- goto again;
+xchgPositions:
+ if (shared)
+ {
+ regs *tmp = result->regs[i];
+ result->regs[i] = result->regs[j];
+ result->regs[j] = tmp;
+ change ++;
+ goto again;
}
+ return change ;
}
/** Try to allocate a pair of registers to the symbol.
*/
-bool tryAllocatingRegPair(symbol *sym)
+bool
+tryAllocatingRegPair (symbol * sym)
{
- int i;
- wassert(sym->nRegs == 2);
- for ( i = 0 ; i < _nRegs ; i+=2 ) {
- if ((regsZ80[i].isFree)&&(regsZ80[i+1].isFree)) {
- regsZ80[i].isFree = 0;
- sym->regs[0] = ®sZ80[i];
- regsZ80[i+1].isFree = 0;
- sym->regs[1] = ®sZ80[i+1];
- if (currFunc) {
- currFunc->regsUsed =
- bitVectSetBit(currFunc->regsUsed,i);
- currFunc->regsUsed =
- bitVectSetBit(currFunc->regsUsed,i+1);
+ int i;
+ wassert (sym->nRegs == 2);
+ for (i = 0; i < _G.nRegs; i += 2)
+ {
+ if ((regsZ80[i].isFree) && (regsZ80[i + 1].isFree))
+ {
+ regsZ80[i].isFree = 0;
+ sym->regs[0] = ®sZ80[i];
+ regsZ80[i + 1].isFree = 0;
+ sym->regs[1] = ®sZ80[i + 1];
+ sym->regType = REG_PAIR;
+
+ if (currFunc)
+ {
+ currFunc->regsUsed =
+ bitVectSetBit (currFunc->regsUsed, i);
+ currFunc->regsUsed =
+ bitVectSetBit (currFunc->regsUsed, i + 1);
}
- D(D_ALLOC, ("tryAllocRegPair: succeded for sym %zs\n", sym));
- return TRUE;
+ D (D_ALLOC, ("tryAllocRegPair: succeded for sym %p\n", sym));
+ return TRUE;
}
}
- D(D_ALLOC, ("tryAllocRegPair: failed on sym %zs\n", sym));
- return FALSE;
+ D (D_ALLOC, ("tryAllocRegPair: failed on sym %p\n", sym));
+ return FALSE;
}
/** Serially allocate registers to the variables.
This is the main register allocation function. It is called after
packing.
*/
-static void serialRegAssign (eBBlock **ebbs, int count)
+static void
+serialRegAssign (eBBlock ** ebbs, int count)
{
- int i;
-
- /* for all blocks */
- for (i = 0; i < count ; i++ ) {
-
- iCode *ic;
-
- if (ebbs[i]->noPath &&
- (ebbs[i]->entryLabel != entryLabel &&
- ebbs[i]->entryLabel != returnLabel ))
- continue ;
+ int i;
- /* 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) {
- wassert(0);
- reassignLR (IC_LEFT(ic));
+ /* for all blocks */
+ for (i = 0; i < count; i++)
+ {
+
+ iCode *ic;
+
+ 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)
+ {
+
+ /* if this is an ipop that means some live
+ range will have to be assigned again */
+ 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 &&
- 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 */
- /* MLH: removed RESULT and POINTER_SET condition */
- if (SKIP_IC2(ic) ||
- ic->op == JUMPTABLE ||
- ic->op == IFX ||
- ic->op == IPUSH ||
- ic->op == IPOP)
- 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;
-
- 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) {
- D(D_ALLOC, ("serialRegAssign: wont live long enough.\n"));
- 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++;
+
+ /* take away registers from live
+ ranges that end at this instruction */
+ deassignLRs (ic, ebbs[i]);
+
+ /* some don't need registers */
+ /* MLH: removed RESULT and POINTER_SET condition */
+ if (SKIP_IC2 (ic) ||
+ ic->op == JUMPTABLE ||
+ ic->op == IFX ||
+ ic->op == IPUSH ||
+ ic->op == IPOP)
+ 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 ;
+ /* 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;
+
+ 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
+ or will not live beyond this instructions */
+ if (!sym->nRegs ||
+ sym->isspilt ||
+ bitVectBitValue (_G.regAssigned, sym->key) ||
+ sym->liveTo <= ic->seq)
+ {
+ D (D_ALLOC, ("serialRegAssign: wont live long enough.\n"));
+ 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) ) ) {
-
- D(D_ALLOC, ("serialRegAssign: \"remat spill\"\n"));
- spillThis (sym) ;
- 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)
+ {
+ D (D_ALLOC, ("serialRegAssign: \"spilling to be safe.\"\n"));
+ 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)))
+ {
+
+ D (D_ALLOC, ("serialRegAssign: \"remat spill\"\n"));
+ 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;
- }
- }
-
- /* else we assign registers to it */
- regAssigned = bitVectSetBit(regAssigned,sym->key);
+ }
- /* 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)) {
+ /* 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;
+ }
+ }
+ }
+ }
+
+ /* else we assign registers to it */
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+ _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
+
+ /* 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 {
- for (j = 0 ; j < sym->nRegs ;j++ ) {
- sym->regs[j] = getRegGpr(ic,ebbs[i],sym);
-
- /* if the allocation falied which means
- this was spilt then break */
- if (!sym->regs[j]) {
+ else
+ {
+ for (j = 0; j < sym->nRegs; j++)
+ {
+ sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+ /* if the allocation falied which means
+ this was spilt then break */
+ if (!sym->regs[j])
+ {
+ D (D_ALLOC, ("Couldnt alloc (spill)\n"))
break;
}
}
}
- /* 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 && ic->op != '=')
- positionRegs(OP_SYMBOL(IC_RESULT(ic)),
- OP_SYMBOL(IC_RIGHT(ic)),ic->lineno);
-
- }
+ /* 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)));
+
+ }
}
}
}
/*-----------------------------------------------------------------*/
-/* rUmaskForOp :- returns register mask for an operand */
+/* fillGaps - Try to fill in the Gaps left by Pass1 */
/*-----------------------------------------------------------------*/
-bitVect *rUmaskForOp (operand *op)
+static void fillGaps()
{
- bitVect *rumask;
- symbol *sym;
- int j;
+ symbol *sym =NULL;
+ int key =0;
- /* only temporaries are assigned registers */
- if (!IS_ITEMP(op))
- return NULL;
-
- sym = OP_SYMBOL(op);
+ if (getenv("DISABLE_FILL_GAPS")) return;
- /* if spilt or no registers assigned to it
- then nothing */
- if (sym->isspilt || !sym->nRegs)
- return NULL;
+ /* look for livernages that was spilt by the allocator */
+ for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
+ sym = hTabNextItem(liveRanges,&key)) {
- rumask = newBitVect(_nRegs);
+ int i;
+ int pdone = 0;
- for (j = 0; j < sym->nRegs; j++) {
- rumask = bitVectSetBit(rumask, sym->regs[j]->rIdx);
- }
+ if (!sym->spillA || !sym->clashes || sym->remat) continue ;
- return rumask;
-}
+ /* 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;
-/** Returns bit vector of registers used in iCode.
- */
-bitVect *regsUsedIniCode (iCode *ic)
-{
- bitVect *rmask = newBitVect(_nRegs);
+ if (bitVectBitValue(sym->clashes,i) == 0 || /* those that clash with this */
+ bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+ continue ;
- /* do the special cases first */
- if (ic->op == IFX ) {
- rmask = bitVectUnion(rmask,
- rUmaskForOp(IC_COND(ic)));
- goto ret;
- }
+ assert (clr = hTabItemWithKey(liveRanges,i));
+
+ /* mark these registers as used */
+ for (k = 0 ; k < clr->nRegs ; k++ )
+ useReg(clr->regs[k]);
+ }
- /* for the jumptable */
- if (ic->op == JUMPTABLE) {
- rmask = bitVectUnion(rmask,
- rUmaskForOp(IC_JTCOND(ic)));
+ if (willCauseSpill(sym->nRegs,sym->regType)) {
+ /* NOPE :( clear all registers & and continue */
+ freeAllRegs();
+ continue ;
+ }
- goto ret;
- }
+ /* THERE IS HOPE !!!! */
+ for (i=0; i < sym->nRegs ; i++ ) {
+ sym->regs[i] = getRegGprNoSpil ();
+ }
- /* of all other cases */
- if (IC_LEFT(ic))
- rmask = bitVectUnion(rmask,
- rUmaskForOp(IC_LEFT(ic)));
-
-
- if (IC_RIGHT(ic))
- rmask = bitVectUnion(rmask,
- rUmaskForOp(IC_RIGHT(ic)));
+ /* 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 (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(D_FILL_GAPS,("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+ continue ;
+ }
+ D(D_FILL_GAPS,("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 */
+/*-----------------------------------------------------------------*/
+bitVect *
+rUmaskForOp (operand * op)
+{
+ bitVect *rumask;
+ symbol *sym;
+ int j;
+
+ /* only temporaries are assigned registers */
+ if (!IS_ITEMP (op))
+ return NULL;
+
+ sym = OP_SYMBOL (op);
+
+ /* if spilt or no registers assigned to it
+ then nothing */
+ if (sym->isspilt || !sym->nRegs)
+ return NULL;
+
+ rumask = newBitVect (_G.nRegs);
+
+ for (j = 0; j < sym->nRegs; j++)
+ {
+ rumask = bitVectSetBit (rumask, sym->regs[j]->rIdx);
+ }
+
+ return rumask;
+}
+
+bitVect *
+z80_rUmaskForOp (operand * op)
+{
+ return rUmaskForOp (op);
+}
+
+/** Returns bit vector of registers used in iCode.
+ */
+bitVect *
+regsUsedIniCode (iCode * ic)
+{
+ bitVect *rmask = newBitVect (_G.nRegs);
+
+ /* do the special cases first */
+ if (ic->op == IFX)
+ {
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_COND (ic)));
+ goto ret;
+ }
+
+ /* for the jumptable */
+ if (ic->op == JUMPTABLE)
+ {
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_JTCOND (ic)));
+
+ goto ret;
+ }
+
+ /* of all other cases */
+ if (IC_LEFT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_LEFT (ic)));
+
+
+ if (IC_RIGHT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_RIGHT (ic)));
- if (IC_RESULT(ic))
- rmask = bitVectUnion(rmask,
- rUmaskForOp(IC_RESULT(ic)));
+ if (IC_RESULT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_RESULT (ic)));
- ret:
- return rmask;
+ret:
+ return rmask;
}
/** For each instruction will determine the regsUsed.
*/
-static void createRegMask (eBBlock **ebbs, int count)
+static void
+createRegMask (eBBlock ** ebbs, int count)
{
- int i;
+ int i;
- /* for all blocks */
- for (i = 0; i < count ; i++ ) {
- iCode *ic ;
+ /* for all blocks */
+ for (i = 0; i < count; i++)
+ {
+ 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;
- /* for all instructions */
- for ( ic = ebbs[i]->sch ; ic ; ic = ic->next ) {
-
- int j;
+ /* for all instructions */
+ for (ic = ebbs[i]->sch; ic; ic = ic->next)
+ {
- if (SKIP_IC2(ic) || !ic->rlive)
- continue ;
-
- /* first mark the registers used in this
- instruction */
- ic->rUsed = regsUsedIniCode(ic);
- funcrUsed = bitVectUnion(funcrUsed,ic->rUsed);
-
- /* now create the register mask for those
- registers that are in use : this is a
- super set of ic->rUsed */
- ic->rMask = newBitVect(_nRegs+1);
-
- /* for all live Ranges alive at this point */
- for (j = 1; j < ic->rlive->size; j++ ) {
- symbol *sym;
- int k;
-
- /* if not alive then continue */
- if (!bitVectBitValue(ic->rlive,j))
- continue ;
-
- /* find the live range we are interested in */
- if (!(sym = hTabItemWithKey(liveRanges,j))) {
- werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
- "createRegMask cannot find live range");
- exit(0);
+ int j;
+
+ if (SKIP_IC2 (ic) || !ic->rlive)
+ continue;
+
+ /* first mark the registers used in this
+ instruction */
+ ic->rUsed = regsUsedIniCode (ic);
+ _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
+
+ /* now create the register mask for those
+ registers that are in use : this is a
+ super set of ic->rUsed */
+ ic->rMask = newBitVect (_G.nRegs + 1);
+
+ /* for all live Ranges alive at this point */
+ for (j = 1; j < ic->rlive->size; j++)
+ {
+ symbol *sym;
+ int k;
+
+ /* if not alive then continue */
+ if (!bitVectBitValue (ic->rlive, j))
+ continue;
+
+ /* find the live range we are interested in */
+ if (!(sym = hTabItemWithKey (liveRanges, j)))
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "createRegMask cannot find live range");
+ exit (0);
}
- /* if no register assigned to it */
- if (!sym->nRegs || sym->isspilt)
- continue ;
+ /* if no register assigned to it */
+ if (!sym->nRegs || sym->isspilt)
+ continue;
- /* for all the registers allocated to it */
- for (k = 0 ; k < sym->nRegs ;k++)
- if (sym->regs[k])
- ic->rMask =
- bitVectSetBit(ic->rMask,sym->regs[k]->rIdx);
+ /* for all the registers allocated to it */
+ for (k = 0; k < sym->nRegs; k++)
+ if (sym->regs[k])
+ ic->rMask =
+ bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
}
}
}
/** Returns the rematerialized string for a remat var.
*/
-char *rematStr (symbol *sym)
+char *
+rematStr (symbol * sym)
{
- char *s = buffer;
- iCode *ic = sym->rematiCode;
-
- while (1) {
-
- /* if plus or minus print the right hand side */
- if (ic->op == '+' || ic->op == '-') {
- sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
- ic->op );
- s += strlen(s);
- ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
- continue ;
- }
- /* we reached the end */
- sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
- break;
+ char *s = buffer;
+ iCode *ic = sym->rematiCode;
+
+ while (1)
+ {
+
+ /* if plus or minus print the right hand side */
+ if (ic->op == '+' || ic->op == '-')
+ {
+ sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
+ ic->op);
+ s += strlen (s);
+ ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+ continue;
+ }
+ /* we reached the end */
+ sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+ break;
}
- return buffer ;
+ return buffer;
}
/*-----------------------------------------------------------------*/
/* regTypeNum - computes the type & number of registers required */
/*-----------------------------------------------------------------*/
-static void regTypeNum (void)
+static void
+regTypeNum (void)
{
- symbol *sym;
- int k;
+ symbol *sym;
+ int k;
- /* for each live range do */
- for ( sym = hTabFirstItem(liveRanges,&k); sym ;
- sym = hTabNextItem(liveRanges,&k)) {
+ /* for each live range do */
+ for (sym = hTabFirstItem (liveRanges, &k); sym;
+ sym = hTabNextItem (liveRanges, &k))
+ {
- /* if used zero times then no registers needed */
- if ((sym->liveTo - sym->liveFrom) == 0)
- continue ;
+ /* if used zero times then no registers needed */
+ 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) {
+ D (D_ALLOC, ("regTypeNum: loop on sym %p\n", sym));
- /* if the type is marked as a conditional */
- if (sym->regType == REG_CND)
- continue ;
+ /* if the live range is a temporary */
+ if (sym->isitmp)
+ {
- /* if used in return only then we don't
- need registers */
- if (sym->ruonly || sym->accuse) {
- if (IS_AGGREGATE(sym->type) || sym->isptr)
- sym->type = aggrToPtr(sym->type,FALSE);
- continue ;
+ /* if the type is marked as a conditional */
+ if (sym->regType == REG_CND)
+ continue;
+
+ /* if used in return only then we don't
+ need registers */
+ if (sym->ruonly || sym->accuse)
+ {
+ if (IS_AGGREGATE (sym->type) || sym->isptr)
+ sym->type = aggrToPtr (sym->type, FALSE);
+ continue;
}
- /* if not then we require registers */
- sym->nRegs = ((IS_AGGREGATE(sym->type) || sym->isptr ) ?
- getSize(sym->type = aggrToPtr(sym->type,FALSE)) :
- getSize(sym->type));
+ /* 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 ");
- printTypeChain(sym->type,stderr);fprintf(stderr,"\n");
- }
-
- /* determine the type of register required */
- /* Always general purpose */
- sym->regType = REG_GPR ;
-
- } else
- /* for the first run we don't provide */
- /* registers for true symbols we will */
- /* see how things go */
- sym->nRegs = 0 ;
+ if (sym->nRegs > 4)
+ {
+ fprintf (stderr, "allocated more than 4 or 0 registers for type ");
+ printTypeChain (sym->type, stderr);
+ fprintf (stderr, "\n");
+ }
+
+ /* determine the type of register required */
+ /* Always general purpose */
+ sym->regType = REG_GPR;
+
+ }
+ else
+ {
+ /* for the first run we don't provide */
+ /* registers for true symbols we will */
+ /* see how things go */
+ D (D_ALLOC, ("regTypeNum: #2 setting num of %p to 0\n", sym));
+ sym->nRegs = 0;
+ }
}
-
+
}
/** Mark all registers as free.
*/
-static void freeAllRegs()
+static void
+freeAllRegs ()
{
- int i;
+ int i;
- D(D_ALLOC, ("freeAllRegs: running.\n"));
+ D (D_ALLOC, ("freeAllRegs: running.\n"));
- for (i=0;i< _nRegs;i++ )
- regsZ80[i].isFree = 1;
+ for (i = 0; i < _G.nRegs; i++)
+ regsZ80[i].isFree = 1;
}
/*-----------------------------------------------------------------*/
/* deallocStackSpil - this will set the stack pointer back */
/*-----------------------------------------------------------------*/
-DEFSETFUNC(deallocStackSpil)
+DEFSETFUNC (deallocStackSpil)
{
- symbol *sym = item;
+ symbol *sym = item;
- deallocLocal(sym);
- return 0;
+ deallocLocal (sym);
+ return 0;
}
/** Register reduction for assignment.
*/
-static int packRegsForAssign (iCode *ic,eBBlock *ebp)
+static int
+packRegsForAssign (iCode * ic, eBBlock * ebp)
{
- iCode *dic, *sic;
+ iCode *dic, *sic;
- D(D_ALLOC, ("packRegsForAssing: running on ic %zi\n", ic));
-
- if (
- /* !IS_TRUE_SYMOP(IC_RESULT(ic)) ||*/
- !IS_ITEMP(IC_RIGHT(ic)) ||
- OP_LIVETO(IC_RIGHT(ic)) > ic->seq ||
- OP_SYMBOL(IC_RIGHT(ic))->isind)
- return 0;
+ D (D_ALLOC, ("packRegsForAssign: running on ic %p\n", ic));
-#if 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 (!IS_ITEMP (IC_RIGHT (ic)) ||
+ OP_SYMBOL (IC_RIGHT (ic))->isind ||
+ OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
+ {
+ return 0;
}
-#endif
- /* 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)) {
- dic = NULL;
- break;
+ /* 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)
+ {
+ /* PENDING: Don't pack across function calls. */
+ if (dic->op == CALL || dic->op == PCALL)
+ {
+ dic = NULL;
+ break;
}
- if (SKIP_IC2(dic))
- continue;
+ if (SKIP_IC2 (dic))
+ continue;
- if (IS_SYMOP(IC_RESULT(dic)) &&
- IC_RESULT(dic)->key == IC_RIGHT(ic)->key) {
- break;
+ if (IS_SYMOP (IC_RESULT (dic)) &&
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ {
+ 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_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 0
- if (POINTER_SET(dic) &&
- IC_RESULT(dic)->key == IC_RESULT(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;
}
-#endif
}
-
- if (!dic)
- return 0 ; /* did not find */
-
- /* if the result is on stack or iaccess then it must be
- the same atleast one of the operands */
- if (OP_SYMBOL(IC_RESULT(ic))->onStack ||
- OP_SYMBOL(IC_RESULT(ic))->iaccess ) {
-
- /* the operation has only one symbol
- operator then we can pack */
- if ((IC_LEFT(dic) && !IS_SYMOP(IC_LEFT(dic))) ||
- (IC_RIGHT(dic) && !IS_SYMOP(IC_RIGHT(dic))))
- goto pack;
-
- if (!((IC_LEFT(dic) &&
- IC_RESULT(ic)->key == IC_LEFT(dic)->key) ||
- (IC_RIGHT(dic) &&
- IC_RESULT(ic)->key == IC_RIGHT(dic)->key)))
- return 0;
+
+ if (!dic)
+ return 0; /* did not find */
+
+ /* if the result is on stack or iaccess then it must be
+ the same atleast one of the operands */
+ if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
+ OP_SYMBOL (IC_RESULT (ic))->iaccess)
+ {
+ /* the operation has only one symbol
+ operator then we can pack */
+ if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
+ (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
+ goto pack;
+
+ if (!((IC_LEFT (dic) &&
+ IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
+ (IC_RIGHT (dic) &&
+ IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
+ return 0;
}
pack:
- /* found the definition */
- /* replace the result with the result of */
- /* this assignment and remove this assignment */
- IC_RESULT(dic) = IC_RESULT(ic) ;
-
- if (IS_ITEMP(IC_RESULT(dic)) && OP_SYMBOL(IC_RESULT(dic))->liveFrom > dic->seq) {
- OP_SYMBOL(IC_RESULT(dic))->liveFrom = dic->seq;
- }
- /* delete from liverange table also
- delete from all the points inbetween and the new
- one */
- for ( sic = dic; sic != ic ; sic = sic->next ) {
- bitVectUnSetBit(sic->rlive,IC_RESULT(ic)->key);
- if (IS_ITEMP(IC_RESULT(dic)))
- bitVectSetBit(sic->rlive,IC_RESULT(dic)->key);
- }
-
- remiCodeFromeBBlock(ebp,ic);
- return 1;
+ /* 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)
+ {
+ OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
+ }
+ /* delete from liverange table also
+ delete from all the points inbetween and the new
+ one */
+ for (sic = dic; sic != ic; sic = sic->next)
+ {
+ bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
+ if (IS_ITEMP (IC_RESULT (dic)))
+ bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+ }
+
+ remiCodeFromeBBlock (ebp, ic);
+ // 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);
+ return 1;
}
/** Scanning backwards looks for first assig found.
*/
-iCode *findAssignToSym (operand *op,iCode *ic)
+iCode *
+findAssignToSym (operand * op, iCode * ic)
{
- iCode *dic;
-
- for (dic = ic->prev ; dic ; dic = dic->prev) {
-
- /* if definition by assignment */
- if (dic->op == '=' &&
- !POINTER_SET(dic) &&
- IC_RESULT(dic)->key == op->key)
- /* && IS_TRUE_SYMOP(IC_RIGHT(dic))*/
- {
-
- /* we are interested only if defined in far space */
- /* or in stack space in case of + & - */
-
- /* if assigned to a non-symbol then return
- true */
- if (!IS_SYMOP(IC_RIGHT(dic)))
- break ;
-
- /* if the symbol is in far space then
- we should not */
- if (isOperandInFarSpace(IC_RIGHT(dic)))
- return NULL ;
-
- /* for + & - operations make sure that
- if it is on the stack it is the same
- as one of the three operands */
- if ((ic->op == '+' || ic->op == '-') &&
- OP_SYMBOL(IC_RIGHT(dic))->onStack) {
-
- if ( IC_RESULT(ic)->key != IC_RIGHT(dic)->key &&
- IC_LEFT(ic)->key != IC_RIGHT(dic)->key &&
- IC_RIGHT(ic)->key != IC_RIGHT(dic)->key)
- return NULL;
- }
-
- break ;
-
- }
+ iCode *dic;
- /* if we find an usage then we cannot delete it */
- if (IC_LEFT(dic) && IC_LEFT(dic)->key == op->key)
- return NULL;
-
- if (IC_RIGHT(dic) && IC_RIGHT(dic)->key == op->key)
- return NULL;
+ for (dic = ic->prev; dic; dic = dic->prev)
+ {
- if (POINTER_SET(dic) && IC_RESULT(dic)->key == op->key)
+ /* if definition by assignment */
+ if (dic->op == '=' &&
+ !POINTER_SET (dic) &&
+ IC_RESULT (dic)->key == op->key)
+ /* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */
+ {
+
+ /* we are interested only if defined in far space */
+ /* or in stack space in case of + & - */
+
+ /* if assigned to a non-symbol then return
+ true */
+ if (!IS_SYMOP (IC_RIGHT (dic)))
+ break;
+
+ /* if the symbol is in far space then
+ we should not */
+ if (isOperandInFarSpace (IC_RIGHT (dic)))
return NULL;
- }
- /* now make sure that the right side of dic
- is not defined between ic & dic */
- if (dic) {
- iCode *sic = dic->next ;
+ /* for + & - operations make sure that
+ if it is on the stack it is the same
+ as one of the three operands */
+ if ((ic->op == '+' || ic->op == '-') &&
+ OP_SYMBOL (IC_RIGHT (dic))->onStack)
+ {
- for (; sic != ic ; sic = sic->next)
- if (IC_RESULT(sic) &&
- IC_RESULT(sic)->key == IC_RIGHT(dic)->key)
+ if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
+ IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
+ IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
return NULL;
+ }
+
+ break;
+
+ }
+
+ /* if we find an usage then we cannot delete it */
+ if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+ return NULL;
+
+ if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+ return NULL;
+
+ if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+ return NULL;
+ }
+
+ /* now make sure that the right side of dic
+ is not defined between ic & dic */
+ if (dic)
+ {
+ iCode *sic = dic->next;
+
+ for (; sic != ic; sic = sic->next)
+ if (IC_RESULT (sic) &&
+ IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+ return NULL;
}
- return dic;
-
-
+ return dic;
+
+
}
+#if !DISABLE_PACKREGSFORSUPPORT
+// PENDING
+
/*-----------------------------------------------------------------*/
/* packRegsForSupport :- reduce some registers for support calls */
/*-----------------------------------------------------------------*/
-static int packRegsForSupport (iCode *ic, eBBlock *ebp)
+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 */
- 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);
- iCode *sic;
-
- if (!dic)
- goto right ;
-
- /* found it we need to remove it from the
- block */
- for ( sic = dic; sic != ic ; sic = sic->next )
- bitVectUnSetBit(sic->rlive,IC_LEFT(ic)->key);
-
- IC_LEFT(ic)->operand.symOperand =
- IC_RIGHT(dic)->operand.symOperand;
- IC_LEFT(ic)->key = IC_RIGHT(dic)->operand.symOperand->key;
- remiCodeFromeBBlock(ebp,dic);
- change++;
+ 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 */
+ D (D_ALLOC, ("packRegsForSupport: running on ic %p\n", ic));
+
+ if (IS_ITEMP (IC_LEFT (ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
+ {
+ iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
+ iCode *sic;
+
+ if (!dic)
+ goto right;
+
+ /* found it we need to remove it from the
+ block */
+ for (sic = dic; sic != ic; sic = sic->next)
+ bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+
+ IC_LEFT (ic)->operand.symOperand =
+ IC_RIGHT (dic)->operand.symOperand;
+ IC_LEFT (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);
+ // PENDING: Check vs mcs51
+ change++;
}
-
- /* do the same for the right operand */
- right:
- if (!change &&
- IS_ITEMP(IC_RIGHT(ic)) &&
- OP_SYMBOL(IC_RIGHT(ic))->liveTo <= ic->seq) {
- iCode *dic = findAssignToSym(IC_RIGHT(ic),ic);
- iCode *sic;
-
- if (!dic)
- return change ;
-
- /* found it we need to remove it from the block */
- for ( sic = dic; sic != ic ; sic = sic->next )
- bitVectUnSetBit(sic->rlive,IC_RIGHT(ic)->key);
-
- IC_RIGHT(ic)->operand.symOperand =
- IC_RIGHT(dic)->operand.symOperand;
- IC_RIGHT(ic)->key = IC_RIGHT(dic)->operand.symOperand->key;
-
- remiCodeFromeBBlock(ebp,dic);
- change ++;
- }
-
- return change ;
+
+ /* do the same for the right operand */
+right:
+ if (!change &&
+ IS_ITEMP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
+ {
+ iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
+ iCode *sic;
+
+ if (!dic)
+ return change;
+
+ /* found it we need to remove it from the block */
+ for (sic = dic; sic != ic; sic = sic->next)
+ bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+
+ IC_RIGHT (ic)->operand.symOperand =
+ IC_RIGHT (dic)->operand.symOperand;
+ 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);
+ // PENDING: vs mcs51
+ change++;
+ }
+
+ return change;
}
+#endif
#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
/** Will reduce some registers for single use.
*/
-static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
+static iCode *
+packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
{
- bitVect *uses ;
- iCode *dic, *sic;
+ bitVect *uses;
+ iCode *dic, *sic;
- D(D_ALLOC, ("packRegsForOneUse: running on ic %zi\n", ic));
+ // PENDING: Disable
+ D (D_ALLOC, ("packRegsForOneUse: running on ic %p\n", ic));
- /* if returning a literal then do nothing */
- if (!IS_SYMOP(op))
- return NULL;
-
- /* only upto 2 bytes since we cannot predict
- the usage of b, & acc */
- if (getSize(operandType(op)) > 2 &&
- ic->op != RETURN &&
- ic->op != SEND)
- return NULL;
+ /* if returning a literal then do nothing */
+ if (!IS_SYMOP (op))
+ return NULL;
- /* this routine will mark the a symbol as used in one
- instruction use only && if the defintion is local
- (ie. within the basic block) && has only one definition &&
- that definiion is either a return value from a
- function or does not contain any variables in
- far space */
- uses = bitVectCopy(OP_USES(op));
- bitVectUnSetBit(uses,ic->key); /* take away this iCode */
- if (!bitVectIsZero(uses)) /* has other uses */
- return NULL ;
-
- /* if it has only one defintion */
- if (bitVectnBitsOn(OP_DEFS(op)) > 1)
- return NULL ; /* has more than one definition */
-
- /* get the that definition */
- if (!(dic =
- hTabItemWithKey(iCodehTab,
- bitVectFirstBit(OP_DEFS(op)))))
- return NULL ;
-
- /* found the definition now check if it is local */
- if (dic->seq < ebp->fSeq ||
- dic->seq > ebp->lSeq)
- return NULL ; /* non-local */
-
- /* 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) {
- OP_SYMBOL(op)->ruonly = 1;
- return dic;
+ /* only upto 2 bytes since we cannot predict
+ the usage of b, & acc */
+ if (getSize (operandType (op)) > 2)
+ return NULL;
+
+ if (ic->op != RETURN &&
+ ic->op != SEND)
+ return NULL;
+
+ /* this routine will mark the a symbol as used in one
+ instruction use only && if the defintion is local
+ (ie. within the basic block) && has only one definition &&
+ that definiion is either a return value from a
+ function or does not contain any variables in
+ far space */
+ uses = bitVectCopy (OP_USES (op));
+ bitVectUnSetBit (uses, ic->key); /* take away this iCode */
+ if (!bitVectIsZero (uses)) /* has other uses */
+ return NULL;
+
+ /* if it has only one defintion */
+ if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+ return NULL; /* has more than one definition */
+
+ /* get the that definition */
+ if (!(dic =
+ hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_DEFS (op)))))
+ return NULL;
+
+ /* found the definition now check if it is local */
+ if (dic->seq < ebp->fSeq ||
+ dic->seq > ebp->lSeq)
+ return NULL; /* non-local */
+
+ /* 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 &&
+ !POINTER_SET(ic) && !POINTER_GET(ic))
+ {
+ OP_SYMBOL (op)->ruonly = 1;
+ return dic;
}
- dic = dic->next ;
- }
-
- /* otherwise check that the definition does
- not contain any symbols in far space */
- if (isOperandInFarSpace(IC_LEFT(dic)) ||
- isOperandInFarSpace(IC_RIGHT(dic)) ||
- IS_OP_RUONLY(IC_LEFT(ic)) ||
- IS_OP_RUONLY(IC_RIGHT(ic)) ) {
- return NULL;
+ dic = dic->next;
}
-
- /* if pointer set then make sure the pointer is one byte */
- if (POINTER_SET(dic))
- return NULL;
- if (POINTER_GET(dic))
+ /* otherwise check that the definition does
+ not contain any symbols in far space */
+ if (isOperandInFarSpace (IC_LEFT (dic)) ||
+ isOperandInFarSpace (IC_RIGHT (dic)) ||
+ IS_OP_RUONLY (IC_LEFT (ic)) ||
+ IS_OP_RUONLY (IC_RIGHT (ic)))
+ {
return NULL;
-
- sic = dic;
+ }
- /* also make sure the intervenening instructions
- don't have any thing in far space */
- for (dic = dic->next ; dic && dic != ic ; dic = dic->next) {
- /* if there is an intervening function call then no */
- if (dic->op == CALL || dic->op == PCALL)
- return NULL;
- /* if pointer set then make sure the pointer
- is one byte */
- if (POINTER_SET(dic))
- return NULL ;
-
- if (POINTER_GET(dic))
- return NULL ;
-
- /* if address of & the result is remat the okay */
- if (dic->op == ADDRESS_OF &&
- OP_SYMBOL(IC_RESULT(dic))->remat)
- continue ;
-
- /* if left or right or result is in far space */
- if (isOperandInFarSpace(IC_LEFT(dic)) ||
- isOperandInFarSpace(IC_RIGHT(dic)) ||
- isOperandInFarSpace(IC_RESULT(dic)) ||
- IS_OP_RUONLY(IC_LEFT(dic)) ||
- IS_OP_RUONLY(IC_RIGHT(dic)) ||
- IS_OP_RUONLY(IC_RESULT(dic)) ) {
- return NULL;
+ /* if pointer set then make sure the pointer is one byte */
+ if (POINTER_SET (dic))
+ return NULL;
+
+ if (POINTER_GET (dic))
+ return NULL;
+
+ sic = dic;
+
+ /* also make sure the intervenening instructions
+ don't have any thing in far space */
+ for (dic = dic->next; dic && dic != ic; dic = dic->next)
+ {
+ /* if there is an intervening function call then no */
+ if (dic->op == CALL || dic->op == PCALL)
+ return NULL;
+ /* if pointer set then make sure the pointer
+ is one byte */
+ if (POINTER_SET (dic))
+ return NULL;
+
+ if (POINTER_GET (dic))
+ return NULL;
+
+ /* if address of & the result is remat the okay */
+ if (dic->op == ADDRESS_OF &&
+ OP_SYMBOL (IC_RESULT (dic))->remat)
+ continue;
+
+ /* if left or right or result is in far space */
+ if (isOperandInFarSpace (IC_LEFT (dic)) ||
+ isOperandInFarSpace (IC_RIGHT (dic)) ||
+ isOperandInFarSpace (IC_RESULT (dic)) ||
+ IS_OP_RUONLY (IC_LEFT (dic)) ||
+ IS_OP_RUONLY (IC_RIGHT (dic)) ||
+ IS_OP_RUONLY (IC_RESULT (dic)))
+ {
+ return NULL;
}
}
-
- OP_SYMBOL(op)->ruonly = 1;
- return sic;
+
+ OP_SYMBOL (op)->ruonly = 1;
+ return sic;
}
/*-----------------------------------------------------------------*/
/* isBitwiseOptimizable - requirements of JEAN LOUIS VERN */
/*-----------------------------------------------------------------*/
-static bool isBitwiseOptimizable (iCode *ic)
+static bool
+isBitwiseOptimizable (iCode * ic)
{
- link *rtype = getSpec(operandType(IC_RIGHT(ic)));
-
- /* bitwise operations are considered optimizable
- under the following conditions (Jean-Louis VERN)
-
- x & lit
- bit & bit
- bit & x
- bit ^ bit
- bit ^ x
- x ^ lit
- x | lit
- bit | bit
- bit | x
- */
- if (IS_LITERAL(rtype))
- return TRUE;
- return FALSE;
+ sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
+
+ /* bitwise operations are considered optimizable
+ under the following conditions (Jean-Louis VERN)
+
+ x & lit
+ bit & bit
+ bit & x
+ bit ^ bit
+ bit ^ x
+ x ^ lit
+ x | lit
+ bit | bit
+ bit | x
+ */
+ if (IS_LITERAL (rtype))
+ return TRUE;
+ return FALSE;
}
/** Optimisations:
ld (iy),(hl)
*/
+#if !DISABLE_PACKREGSFORACCUSE
+// PENDING
+
/** 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.
*/
-static void packRegsForAccUse (iCode *ic)
+static void
+packRegsForAccUse (iCode * ic)
{
- iCode *uic;
-
- /* if + or - then it has to be one byte result */
- if ((ic->op == '+' || ic->op == '-')
- && getSize(operandType(IC_RESULT(ic))) > 1)
- return ;
-
- /* if shift operation make sure right side is not a literal */
- if (ic->op == RIGHT_OP &&
- (isOperandLiteral(IC_RIGHT(ic)) ||
- getSize(operandType(IC_RESULT(ic))) > 1))
- return ;
-
- if (ic->op == LEFT_OP &&
- ( isOperandLiteral(IC_RIGHT(ic)) ||
- getSize(operandType(IC_RESULT(ic))) > 1))
- 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 it is a conditional branch then we definitely can */
- if (uic->op == IFX )
- goto accuse;
+ 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)
+ return;
- if ( uic->op == JUMPTABLE )
- return ;
+ /* if shift operation make sure right side is not a literal */
+ if (ic->op == RIGHT_OP &&
+ (isOperandLiteral (IC_RIGHT (ic)) ||
+ getSize (operandType (IC_RESULT (ic))) > 1))
+ return;
+
+ if (ic->op == LEFT_OP &&
+ (isOperandLiteral (IC_RIGHT (ic)) ||
+ getSize (operandType (IC_RESULT (ic))) > 1))
+ 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 it is a conditional branch then we definitely can */
+ if (uic->op == IFX)
+ goto accuse;
+
+ if (uic->op == JUMPTABLE)
+ return;
#if 0
- /* if the usage is not is an assignment or an
- arithmetic / bitwise / shift operation then not */
- if (POINTER_SET(uic) &&
- getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)) > 1)
- return;
+ /* if the usage is not is an assignment or an
+ arithmetic / bitwise / shift operation then not */
+ if (POINTER_SET (uic) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
+ return;
#endif
- if (uic->op != '=' &&
- !IS_ARITHMETIC_OP(uic) &&
- !IS_BITWISE_OP(uic) &&
- uic->op != LEFT_OP &&
- uic->op != RIGHT_OP )
- return;
-
- /* if used in ^ operation then make sure right is not a
- literl */
- if (uic->op == '^' && isOperandLiteral(IC_RIGHT(uic)))
- return ;
-
- /* if shift operation make sure right side is not a literal */
- if (uic->op == RIGHT_OP &&
- ( isOperandLiteral(IC_RIGHT(uic)) ||
- getSize(operandType(IC_RESULT(uic))) > 1))
- return ;
-
- if (uic->op == LEFT_OP &&
- ( isOperandLiteral(IC_RIGHT(uic)) ||
- getSize(operandType(IC_RESULT(uic))) > 1))
- return ;
-
+ if (uic->op != '=' &&
+ !IS_ARITHMETIC_OP (uic) &&
+ !IS_BITWISE_OP (uic) &&
+ uic->op != LEFT_OP &&
+ uic->op != RIGHT_OP)
+ return;
+
+ /* if used in ^ operation then make sure right is not a
+ literl */
+ if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
+ return;
+
+ /* if shift operation make sure right side is not a literal */
+ if (uic->op == RIGHT_OP &&
+ (isOperandLiteral (IC_RIGHT (uic)) ||
+ getSize (operandType (IC_RESULT (uic))) > 1))
+ return;
+
+ if (uic->op == LEFT_OP &&
+ (isOperandLiteral (IC_RIGHT (uic)) ||
+ getSize (operandType (IC_RESULT (uic))) > 1))
+ return;
+
#if 0
- /* make sure that the result of this icode is not on the
- stack, since acc is used to compute stack offset */
- if (IS_TRUE_SYMOP(IC_RESULT(uic)) &&
- OP_SYMBOL(IC_RESULT(uic))->onStack)
- return ;
+ /* make sure that the result of this icode is not on the
+ stack, since acc is used to compute stack offset */
+ if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
+ OP_SYMBOL (IC_RESULT (uic))->onStack)
+ return;
#endif
#if 0
- /* if either one of them in far space then we cannot */
- if ((IS_TRUE_SYMOP(IC_LEFT(uic)) &&
- isOperandInFarSpace(IC_LEFT(uic))) ||
- (IS_TRUE_SYMOP(IC_RIGHT(uic)) &&
- isOperandInFarSpace(IC_RIGHT(uic))))
- return ;
+ /* if either one of them in far space then we cannot */
+ if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
+ isOperandInFarSpace (IC_LEFT (uic))) ||
+ (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
+ isOperandInFarSpace (IC_RIGHT (uic))))
+ return;
#endif
- /* if the usage has only one operand then we can */
- if (IC_LEFT(uic) == NULL ||
- IC_RIGHT(uic) == NULL)
- goto accuse;
-
- /* make sure this is on the left side if not
- a '+' since '+' is commutative */
- if (ic->op != '+' &&
- IC_LEFT(uic)->key != IC_RESULT(ic)->key)
- 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;
- return ;
- }
-
- /** This is confusing :) Guess for now */
- if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
- (IS_ITEMP(IC_RIGHT(uic)) ||
- (IS_TRUE_SYMOP(IC_RIGHT(uic)))))
- goto accuse;
-
- if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
- (IS_ITEMP(IC_LEFT(uic)) ||
- (IS_TRUE_SYMOP(IC_LEFT(uic)))))
- goto accuse ;
- return ;
- accuse:
- OP_SYMBOL(IC_RESULT(ic))->accuse = ACCUSE_A;
+ /* if the usage has only one operand then we can */
+ if (IC_LEFT (uic) == NULL ||
+ IC_RIGHT (uic) == NULL)
+ goto accuse;
+
+ /* make sure this is on the left side if not
+ a '+' since '+' is commutative */
+ if (ic->op != '+' &&
+ IC_LEFT (uic)->key != IC_RESULT (ic)->key)
+ return;
+
+ // See mcs51 ralloc for reasoning
+#if 0
+ /* 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))))
+ {
+ goto accuse;
+ return;
+ }
+#endif
+
+/** This is confusing :) Guess for now */
+ if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
+ (IS_ITEMP (IC_RIGHT (uic)) ||
+ (IS_TRUE_SYMOP (IC_RIGHT (uic)))))
+ goto accuse;
+
+ if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
+ (IS_ITEMP (IC_LEFT (uic)) ||
+ (IS_TRUE_SYMOP (IC_LEFT (uic)))))
+ goto accuse;
+ return;
+accuse:
+ OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_A;
}
+#endif
-static void packRegsForHLUse (iCode *ic)
+static void
+packRegsForHLUse (iCode * ic)
{
- iCode *uic;
+ iCode *uic;
- if (IS_GB)
- return;
+ /* PENDING: Could do IFX */
+ if (ic->op == IFX)
+ {
+ return;
+ }
- /* has only one definition */
- if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1)
- return ;
+ /* has only one definition */
+ if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+ {
+ D (D_HLUSE, (" + Dropping as has more than one def\n"));
+ return;
+ }
- /* has only one use */
- if (bitVectnBitsOn(OP_USES(IC_RESULT(ic))) > 1)
- return ;
+ /* has only one use */
+ if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
+ {
+ D (D_HLUSE, (" + Dropping as has more than one use\n"));
+ return;
+ }
- /* and the usage immediately follows this iCode */
- if (!(uic = hTabItemWithKey(iCodehTab,
- bitVectFirstBit(OP_USES(IC_RESULT(ic))))))
- return ;
+ /* and the usage immediately follows this iCode */
+ if (!(uic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+ {
+ D (D_HLUSE, (" + Dropping as usage isn't in this block\n"));
+ return;
+ }
- if (ic->next != uic)
- return ;
+ if (ic->next != uic)
+ {
+ D (D_HLUSE, (" + Dropping as usage doesn't follow this\n"));
+ 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:
- printf("Hey, it worked!\n");
- OP_SYMBOL(IC_RESULT(ic))->accuse = ACCUSE_HL;
+ if (uic->op ==IFX)
+ {
+ return;
+ }
+
+ if (getSize (operandType (IC_RESULT (ic))) != 2 ||
+ (IC_LEFT(uic) && getSize (operandType (IC_LEFT (uic))) != 2) ||
+ (IC_RIGHT(uic) && getSize (operandType (IC_RIGHT (uic))) != 2))
+ {
+ D (D_HLUSE, (" + Dropping as the result size is not 2\n"));
+ return;
+ }
+
+ if (IS_Z80)
+ {
+ if (ic->op == CAST && uic->op == IPUSH)
+ goto hluse;
+ if (ic->op == ADDRESS_OF && uic->op == IPUSH)
+ goto hluse;
+ if (ic->op == ADDRESS_OF && POINTER_GET (uic) && IS_ITEMP( IC_RESULT (uic)))
+ goto hluse;
+ if (ic->op == CALL && ic->parmBytes == 0 && (uic->op == '-' || uic->op == '+'))
+ goto hluse;
+ }
+ else if (IS_GB)
+ {
+ /* Case of assign a constant to offset in a static array. */
+ if (ic->op == '+' && IS_VALOP (IC_RIGHT (ic)))
+ {
+ if (uic->op == '=' && POINTER_SET (uic))
+ {
+ goto hluse;
+ }
+ else if (uic->op == IPUSH && getSize (operandType (IC_LEFT (uic))) == 2)
+ {
+ goto hluse;
+ }
+ }
+ }
+
+ D (D_HLUSE, (" + Dropping as it's a bad op\n"));
+ return;
+hluse:
+ OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_SCRATCH;
}
-bool opPreservesA(iCode *ic, iCode *uic)
+static iCode *
+packRegsForHLUse3 (iCode * lic, operand * op, eBBlock * ebp)
{
- /* if it is a conditional branch then we definitely can */
- if (uic->op == IFX )
- return FALSE;
+ int i, key;
+ symbol *sym;
+ iCode *ic, *dic;
+ bool isFirst = TRUE;
- if ( uic->op == JUMPTABLE )
- return FALSE;
+ 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 the usage has only one operand then we can */
- /* PENDING: check */
- if (IC_LEFT(uic) == NULL ||
- IC_RIGHT(uic) == NULL)
- return FALSE;
+ if ( OP_SYMBOL(op)->accuse)
+ {
+ return NULL;
+ }
- /* PENDING: check this rule */
- if (getSize(operandType(IC_RESULT(uic))) > 1) {
- return FALSE;
+ if (OP_SYMBOL(op)->remat)
+ {
+ return NULL;
}
- /*
- Bad:
- !IS_ARITHMETIC_OP(uic) (sub requires A)
- */
- if (
- uic->op != '+' &&
- !IS_BITWISE_OP(uic) &&
- uic->op != '=' &&
- uic->op != EQ_OP &&
- !POINTER_GET(uic) &&
- /*
- uic->op != LEFT_OP &&
- uic->op != RIGHT_OP &&*/
- 1
- ) {
- return FALSE;
+ /* Only defined once */
+ if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+ return NULL;
+
+ if (getSize (operandType (op)) > 2)
+ return NULL;
+
+ /* And this is the definition */
+ if (bitVectFirstBit (OP_DEFS (op)) != lic->key)
+ return NULL;
+
+ /* first check if any overlapping liverange has already been
+ assigned to DPTR */
+ if (OP_SYMBOL(op)->clashes)
+ {
+ for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ )
+ {
+ if (bitVectBitValue(OP_SYMBOL(op)->clashes,i))
+ {
+ sym = hTabItemWithKey(liveRanges,i);
+ if (sym->accuse == ACCUSE_SCRATCH)
+ {
+ return NULL;
+ }
+ }
+ }
}
- /* PENDING */
- if (!IC_LEFT(uic) || !IC_RESULT(ic))
- 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.
+ */
+ dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
- /** This is confusing :) Guess for now */
- if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
- (IS_ITEMP(IC_RIGHT(uic)) ||
- (IS_TRUE_SYMOP(IC_RIGHT(uic)))))
- return TRUE;
-
- if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
- (IS_ITEMP(IC_LEFT(uic)) ||
- (IS_TRUE_SYMOP(IC_LEFT(uic)))))
- return TRUE;
+ for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+ ic = hTabNextItem(iCodeSeqhTab, &key))
+ {
+ 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;
+ if (ic->op == ADDRESS_OF)
+ continue;
+ if (POINTER_GET (ic))
+ continue;
+ if (ic->op == '=' && !POINTER_SET(ic))
+ continue;
+ }
- return FALSE;
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic))
+ && isOperandInDirSpace (IC_RESULT (ic)))
+ return NULL;
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic))
+ && isOperandInDirSpace (IC_LEFT (ic)))
+ return NULL;
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic))
+ && isOperandInDirSpace (IC_RIGHT (ic)))
+ return NULL;
+
+ /* Handle the non left/right/result ones first */
+ if (ic->op == IFX)
+ continue;
+ if (ic->op == JUMPTABLE)
+ return NULL;
+
+ if (SKIP_IC2(ic))
+ continue;
+
+ if (ic->op == CAST)
+ continue;
+
+ if (ic->op == IPUSH && isOperandEqual (op, IC_LEFT (ic)))
+ continue;
+
+ if (ic->op == SEND && isOperandEqual (op, IC_LEFT (ic)))
+ continue;
+
+ 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;
+
+ if (IS_VALOP (IC_RIGHT (ic)) &&
+ (ic->op == EQ_OP ||
+ 0))
+ {
+ continue;
+ }
+
+ /* By default give up */
+ return NULL;
+ }
+
+ D (D_PACK_HLUSE3, ("Succeeded!\n"))
+
+ OP_SYMBOL (op)->accuse = ACCUSE_SCRATCH;
+ return dic;
+}
+
+static iCode *
+packRegsForIYUse (iCode * lic, operand * op, eBBlock * ebp)
+{
+ int i, key;
+ symbol *sym;
+ iCode *ic, *dic;
+ bitVect *uses;
+
+ 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 (OP_SYMBOL(op)->remat)
+ {
+ return NULL;
+ }
+
+ /* Only defined once */
+ if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+ return NULL;
+
+ /* And this is the definition */
+ if (bitVectFirstBit (OP_DEFS (op)) != lic->key)
+ return NULL;
+
+ /* first check if any overlapping liverange has already been
+ assigned to DPTR */
+ if (OP_SYMBOL(op)->clashes)
+ {
+ for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ )
+ {
+ if (bitVectBitValue(OP_SYMBOL(op)->clashes,i))
+ {
+ sym = hTabItemWithKey(liveRanges,i);
+ if (sym->accuse == ACCUSE_IY)
+ {
+ return NULL;
+ }
+ }
+ }
+ }
+
+ /* Only a few instructions can load into IY */
+ if (lic->op != '=')
+ {
+ 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.
+ */
+ dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+ uses = OP_USES(op);
+
+ for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+ ic = hTabNextItem(iCodeSeqhTab,&key))
+ {
+ if (D_PACK_IY)
+ piCode(ic, NULL);
+
+ if (ic->op == PCALL ||
+ ic->op == CALL ||
+ ic->op == JUMPTABLE
+ )
+ return NULL;
+
+ 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 == '=' &&
+ isOperandEqual(IC_RESULT(ic), op))
+ continue;
+
+ if (ic->op == GET_VALUE_AT_ADDRESS &&
+ isOperandEqual(IC_LEFT(ic), op))
+ continue;
+
+ if (isOperandEqual(IC_RESULT(ic), IC_LEFT(ic)) == FALSE)
+ return NULL;
+
+ if (IC_RIGHT (ic) && IS_VALOP (IC_RIGHT (ic)))
+ {
+ if (ic->op == '+' ||
+ ic->op == '-')
+ {
+ /* Only works if the constant is small */
+ if (operandLitValue (IC_RIGHT (ic)) < 4)
+ continue;
+ }
+ }
+
+ return NULL;
+ }
+ else
+ {
+ /* This iCode doesn't use the sym. See if this iCode preserves IY.
+ */
+ continue;
+ }
+
+ /* By default give up */
+ return NULL;
+ }
+
+ D (D_PACK_IY, ("Succeeded IY!\n"));
+
+ OP_SYMBOL (op)->accuse = ACCUSE_IY;
+ return dic;
}
+/** Returns TRUE if this operation can use acc and if it preserves the value.
+ */
+static bool
+opPreservesA (iCode * uic)
+{
+ if (uic->op == IFX)
+ {
+ /* If we've gotten this far then the thing to compare must be
+ small enough and must be in A.
+ */
+ return TRUE;
+ }
+
+ if (uic->op == JUMPTABLE)
+ {
+ D (D_ACCUSE2, (" + Dropping as operation is a Jumptable\n"));
+ return FALSE;
+ }
+
+ /* A pointer assign preserves A if A is the left value. */
+ if (uic->op == '=' && POINTER_SET (uic))
+ {
+ return TRUE;
+ }
+
+ /* if the usage has only one operand then we can */
+ /* PENDING: check */
+ if (IC_LEFT (uic) == NULL ||
+ IC_RIGHT (uic) == NULL)
+ {
+ D (D_ACCUSE2, (" + Dropping as operation has only one operand\n"));
+ return FALSE;
+ }
+
+ /* PENDING: check this rule */
+ if (getSize (operandType (IC_RESULT (uic))) > 1)
+ {
+ D (D_ACCUSE2, (" + Dropping as operation has size is too big\n"));
+ return FALSE;
+ }
+
+
+ /* Disabled all of the old rules as they weren't verified and have
+ caused at least one problem.
+ */
+ return FALSE;
+}
+
+/** Returns true if this operand preserves the value of A.
+ */
+static bool
+opIgnoresA (iCode * ic, iCode * uic)
+{
+ /* A increment of an iTemp by a constant is OK. */
+ if ( uic->op == '+' &&
+ IS_ITEMP (IC_LEFT (uic)) &&
+ IS_ITEMP (IC_RESULT (uic)) &&
+ IS_OP_LITERAL (IC_RIGHT (uic)))
+ {
+ unsigned int icount = (unsigned int) floatFromVal (IC_RIGHT (uic)->operand.valOperand);
+
+ /* Being an ITEMP means that we're already a symbol. */
+ if (icount == 1 &&
+ IC_RESULT (uic)->operand.symOperand->key == IC_LEFT (uic)->operand.symOperand->key
+ )
+ {
+ return TRUE;
+ }
+ }
+ else if (uic->op == '=' && !POINTER_SET (uic))
+ {
+ /* If they are equal and get optimised out then things are OK. */
+ if (isOperandEqual (IC_RESULT (uic), IC_RIGHT (uic)))
+ {
+ /* Straight assign is OK. */
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+/* Some optimisation cases:
+
+ 1. Part of memcpy
+; genPointerGet
+ ld l,-4(ix)
+ ld h,-3(ix)
+ ld c,(hl)
+; genPlus
+ inc -4(ix)
+ jp nz,00108$
+ inc -3(ix)
+00108$:
+; genAssign (pointer)
+ ld a,c
+ ld (de),a
+
+ want to optimise down to:
+ ld hl,-4(ix) ...
+ ld a,(hl)
+ inc -4(ix).w ...
+ ld (de),a
+
+ So genPointer get is OK
+ genPlus where the right is constant, left is iTemp, and result is same as left
+ genAssign (pointer) is OK
+
+ 2. Part of _strcpy
+; genPointerGet
+ ld a,(de)
+ ld c,a
+; genIfx
+ xor a,a
+ or a,c
+ jp z,00103$
+; _strcpy.c 40
+; genAssign (pointer)
+; AOP_STK for _strcpy_to_1_1
+ ld l,-2(ix)
+ ld h,-1(ix)
+ ld (hl),c
+
+ want to optimise down to:
+ ld a,(de)
+ or a,a
+ jp z,00103$
+ ld (bc),a
+
+ So genIfx where IC_COND has size of 1 and is a constant.
+*/
+
/** 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 accumulator.
- Note that the 'A preserving' list is currently emperical :)e
+ Note that the 'A preserving' list is currently emperical :)
*/
-static void packRegsForAccUse2(iCode *ic)
+static void
+packRegsForAccUse2 (iCode * ic)
{
- 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 != '=' &&
- ic->op != EQ_OP &&
- ic->op != CAST &&
- 1)
- return;
-
- /* if + or - then it has to be one byte result.
- MLH: Ok.
- */
- if ((ic->op == '+' || ic->op == '-')
- && getSize(operandType(IC_RESULT(ic))) > 1)
- return ;
-
- /* if shift operation make sure right side is not a literal.
- MLH: depends.
- */
-#if 0
- if (ic->op == RIGHT_OP &&
- (isOperandLiteral(IC_RIGHT(ic)) ||
- getSize(operandType(IC_RESULT(ic))) > 1))
- return ;
-
- if (ic->op == LEFT_OP &&
- ( isOperandLiteral(IC_RIGHT(ic)) ||
- getSize(operandType(IC_RESULT(ic))) > 1))
- return ;
-#endif
-
- /* has only one definition */
- if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1) {
- return;
- }
-
- /* Right. We may be able to propagate it through if:
- For each in the chain of uses the intermediate is OK.
- */
- /* Get next with 'uses result' bit on
- If this->next == next
- Validate use of next
- If OK, increase count
- */
- /* and the usage immediately follows this iCode */
- if (!(uic = hTabItemWithKey(iCodehTab,
- bitVectFirstBit(OP_USES(IC_RESULT(ic)))))) {
- return;
- }
-
- {
- /* Create a copy of the OP_USES bit vect */
- bitVect *uses = bitVectCopy(OP_USES(IC_RESULT(ic)));
- int setBit;
- iCode *scan = ic, *next;
-
- do {
- setBit = bitVectFirstBit(uses);
- next = hTabItemWithKey(iCodehTab, setBit);
- if (scan->next == next) {
- bitVectUnSetBit(uses, setBit);
- /* Still contigous. */
- if (!opPreservesA(ic, next)) {
- return;
- }
- scan = next;
- }
- else {
- return;
- }
- } while (!bitVectIsZero(uses));
- OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
- return;
- }
-
- /* OLD CODE FOLLOWS */
- /* if it is a conditional branch then we definitely can
- MLH: Depends.
- */
-#if 0
- if (uic->op == IFX )
- goto accuse;
-
- /* MLH: Depends. */
- if ( uic->op == JUMPTABLE )
- return ;
-#endif
+ 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 &&
+ ic->op != '<' &&
+ ic->op != '>' &&
+ ic->op != CAST &&
+ ic->op != GETHBIT &&
+ 1)
+ {
+ D (D_ACCUSE2, (" + Dropping as not a 'good' source command\n"));
+ return;
+ }
- /* if the usage is not is an assignment or an
- arithmetic / bitwise / shift operation then not.
- MLH: Pending: Invalid. Our pointer sets are always peechy.
- */
-#if 0
- if (POINTER_SET(uic) &&
- getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)) > 1) {
- printf("e5 %u\n", getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)));
- return;
+ /* if + or - then it has to be one byte result.
+ MLH: Ok.
+ */
+ if ((ic->op == '+' || ic->op == '-')
+ && getSize (operandType (IC_RESULT (ic))) > 1)
+ {
+ D (D_ACCUSE2, (" + Dropping as it's a big + or -\n"));
+ return;
}
-#endif
- printf("1\n");
- if (uic->op != '=' &&
- !IS_ARITHMETIC_OP(uic) &&
- !IS_BITWISE_OP(uic) &&
- uic->op != LEFT_OP &&
- uic->op != RIGHT_OP ) {
- printf("e6\n");
- return;
- }
-
- /* if used in ^ operation then make sure right is not a
- literl */
- if (uic->op == '^' && isOperandLiteral(IC_RIGHT(uic)))
- return ;
-
- /* if shift operation make sure right side is not a literal */
- if (uic->op == RIGHT_OP &&
- ( isOperandLiteral(IC_RIGHT(uic)) ||
- getSize(operandType(IC_RESULT(uic))) > 1))
- return ;
-
- if (uic->op == LEFT_OP &&
- ( isOperandLiteral(IC_RIGHT(uic)) ||
- getSize(operandType(IC_RESULT(uic))) > 1))
- return ;
-
-#if 0
- /* make sure that the result of this icode is not on the
- stack, since acc is used to compute stack offset */
- if (IS_TRUE_SYMOP(IC_RESULT(uic)) &&
- OP_SYMBOL(IC_RESULT(uic))->onStack)
- return ;
-#endif
+ /* has only one definition */
+ if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+ {
+ D (D_ACCUSE2, (" + Dropping as it has more than one definition\n"));
+ return;
+ }
-#if 0
- /* if either one of them in far space then we cannot */
- if ((IS_TRUE_SYMOP(IC_LEFT(uic)) &&
- isOperandInFarSpace(IC_LEFT(uic))) ||
- (IS_TRUE_SYMOP(IC_RIGHT(uic)) &&
- isOperandInFarSpace(IC_RIGHT(uic))))
- return ;
-#endif
+ /* Right. We may be able to propagate it through if:
+ For each in the chain of uses the intermediate is OK.
+ */
+ /* Get next with 'uses result' bit on
+ If this->next == next
+ Validate use of next
+ If OK, increase count
+ */
+ /* and the usage immediately follows this iCode */
+ if (!(uic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+ {
+ D (D_ACCUSE2, (" + Dropping as usage does not follow first\n"));
+ return;
+ }
- /* if the usage has only one operand then we can */
- if (IC_LEFT(uic) == NULL ||
- IC_RIGHT(uic) == NULL)
- goto accuse;
-
- /* make sure this is on the left side if not
- a '+' since '+' is commutative */
- if (ic->op != '+' &&
- IC_LEFT(uic)->key != IC_RESULT(ic)->key)
- 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;
- return ;
- }
-
- /** This is confusing :) Guess for now */
- if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
- (IS_ITEMP(IC_RIGHT(uic)) ||
- (IS_TRUE_SYMOP(IC_RIGHT(uic)))))
- goto accuse;
-
- if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
- (IS_ITEMP(IC_LEFT(uic)) ||
- (IS_TRUE_SYMOP(IC_LEFT(uic)))))
- goto accuse ;
- return ;
- accuse:
- printf("acc ok!\n");
- OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
+ {
+ /* Create a copy of the OP_USES bit vect */
+ bitVect *uses = bitVectCopy (OP_USES (IC_RESULT (ic)));
+ int setBit;
+ iCode *scan = ic, *next;
+
+ do
+ {
+ setBit = bitVectFirstBit (uses);
+ next = hTabItemWithKey (iCodehTab, setBit);
+ if (scan->next == next)
+ {
+ D (D_ACCUSE2_VERBOSE, (" ! Is next in line\n"));
+
+ bitVectUnSetBit (uses, setBit);
+ /* Still contigous. */
+ if (!opPreservesA (next))
+ {
+ D (D_ACCUSE2, (" + Dropping as operation doesn't preserve A\n"));
+ return;
+ }
+ D (D_ACCUSE2_VERBOSE, (" ! Preserves A, so continue scanning\n"));
+ scan = next;
+ }
+ else if (scan->next == NULL && bitVectnBitsOn (uses) == 1 && next != NULL)
+ {
+ if (next->prev == NULL)
+ {
+ if (!opPreservesA (next))
+ {
+ D (D_ACCUSE2, (" + Dropping as operation doesn't preserve A #2\n"));
+ return;
+ }
+ bitVectUnSetBit (uses, setBit);
+ scan = next;
+ }
+ else
+ {
+ D (D_ACCUSE2, (" + Dropping as last in list and next doesn't start a block\n"));
+ return;
+ }
+ }
+ else if (scan->next == NULL)
+ {
+ D (D_ACCUSE2, (" + Dropping as hit the end of the list\n"));
+ D (D_ACCUSE2, (" + Next in htab: %p\n", next));
+ return;
+ }
+ else
+ {
+ if (opIgnoresA (ic, scan->next))
+ {
+ /* Safe for now. */
+ scan = scan->next;
+ D (D_ACCUSE2_VERBOSE, (" ! Op ignores A, so continue scanning\n"));
+ }
+ else
+ {
+ D (D_ACCUSE2, (" + Dropping as parts are not consecuitive and intermediate might use A\n"));
+ return;
+ }
+ }
+ }
+ while (!bitVectIsZero (uses));
+
+ OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_A;
+ return;
+ }
}
/** Does some transformations to reduce register pressure.
*/
-static void packRegisters (eBBlock *ebp)
+static void
+packRegisters (eBBlock * ebp)
{
- iCode *ic ;
- int change = 0 ;
+ iCode *ic;
+ int change = 0;
- D(D_ALLOC, ("packRegisters: entered.\n"));
-
- while (1 && !DISABLE_PACK_ASSIGN) {
- change = 0;
- /* look for assignments of the form */
- /* iTempNN = TRueSym (someoperation) SomeOperand */
- /* .... */
- /* TrueSym := iTempNN:1 */
- for ( ic = ebp->sch ; ic ; ic = ic->next ) {
- /* find assignment of the form TrueSym := iTempNN:1 */
- if (ic->op == '=' && !POINTER_SET(ic))
- change += packRegsForAssign(ic,ebp);
+ D (D_ALLOC, ("packRegisters: entered.\n"));
+
+ while (1 && !DISABLE_PACK_ASSIGN)
+ {
+ change = 0;
+ /* look for assignments of the form */
+ /* iTempNN = TRueSym (someoperation) SomeOperand */
+ /* .... */
+ /* TrueSym := iTempNN:1 */
+ for (ic = ebp->sch; ic; ic = ic->next)
+ {
+ /* find assignment of the form TrueSym := iTempNN:1 */
+ if (ic->op == '=' && !POINTER_SET (ic))
+ change += packRegsForAssign (ic, ebp);
}
- if (!change)
- break;
+ if (!change)
+ break;
}
- for ( ic = ebp->sch ; ic ; ic = ic->next ) {
- /* 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)) &&
- bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) == 1 &&
- !OP_SYMBOL(IC_LEFT(ic))->onStack ) {
-
- OP_SYMBOL(IC_RESULT(ic))->remat = 1;
- OP_SYMBOL(IC_RESULT(ic))->rematiCode = ic;
- OP_SYMBOL(IC_RESULT(ic))->usl.spillLoc = NULL;
+ for (ic = ebp->sch; ic; ic = ic->next)
+ {
+ /* 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 %p\n", ic));
+
+ if (ic->op == ADDRESS_OF &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ IS_TRUE_SYMOP (IC_LEFT (ic)) &&
+ bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+ !OP_SYMBOL (IC_LEFT (ic))->onStack)
+ {
+
+ OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+ OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
}
- /* Safe: just propagates the remat flag */
- /* if straight assignment then carry remat flag if this is the
- only definition */
- if (ic->op == '=' &&
- !POINTER_SET(ic) &&
- IS_SYMOP(IC_RIGHT(ic)) &&
- OP_SYMBOL(IC_RIGHT(ic))->remat &&
- bitVectnBitsOn(OP_SYMBOL(IC_RESULT(ic))->defs) <= 1) {
-
- OP_SYMBOL(IC_RESULT(ic))->remat =
- OP_SYMBOL(IC_RIGHT(ic))->remat;
- OP_SYMBOL(IC_RESULT(ic))->rematiCode =
- OP_SYMBOL(IC_RIGHT(ic))->rematiCode ;
+ /* Safe: just propagates the remat flag */
+ /* if straight assignment then carry remat flag if this is the
+ only definition */
+ if (ic->op == '=' &&
+ !POINTER_SET (ic) &&
+ IS_SYMOP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->remat &&
+ bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
+ {
+
+ OP_SYMBOL (IC_RESULT (ic))->remat =
+ OP_SYMBOL (IC_RIGHT (ic))->remat;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode =
+ OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
}
- /* if the condition of an if instruction is defined in the
- previous instruction then mark the itemp as a conditional */
- if ((IS_CONDITIONAL(ic) ||
- ( ( ic->op == BITWISEAND ||
- ic->op == '|' ||
- ic->op == '^' ) &&
- isBitwiseOptimizable(ic))) &&
- ic->next && ic->next->op == IFX &&
- isOperandEqual(IC_RESULT(ic),IC_COND(ic->next)) &&
- OP_SYMBOL(IC_RESULT(ic))->liveTo <= ic->next->seq) {
-
- OP_SYMBOL(IC_RESULT(ic))->regType = REG_CND;
- continue ;
+ /* if the condition of an if instruction is defined in the
+ previous instruction then mark the itemp as a conditional */
+ if ((IS_CONDITIONAL (ic) ||
+ ((ic->op == BITWISEAND ||
+ ic->op == '|' ||
+ ic->op == '^') &&
+ 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)
+ {
+
+ OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
+ continue;
}
#if 0
- /* reduce for support function calls */
- if (ic->supportRtn || ic->op == '+' || ic->op == '-' )
- packRegsForSupport(ic,ebp);
+ /* reduce for support function calls */
+ if (ic->supportRtn || ic->op == '+' || ic->op == '-')
+ packRegsForSupport (ic, ebp);
#endif
-#if 0
- /* some cases the redundant moves can
- can be eliminated for return statements */
- if ((ic->op == RETURN || ic->op == SEND) &&
- !isOperandInFarSpace(IC_LEFT(ic)) &&
- !options.model)
- packRegsForOneuse (ic,IC_LEFT(ic),ebp);
-#endif
- /* if pointer set & left has a size more than
- one and right is not in far space */
- if (POINTER_SET(ic) &&
- /* MLH: no such thing.
- !isOperandInFarSpace(IC_RIGHT(ic)) && */
- !OP_SYMBOL(IC_RESULT(ic))->remat &&
- !IS_OP_RUONLY(IC_RIGHT(ic)) &&
- getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 )
-
- packRegsForOneuse (ic,IC_RESULT(ic),ebp);
-
- /* if pointer get */
- if (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 )
- 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 (IS_ITEMP(IC_RESULT(ic))) {
- packRegsForHLUse(ic);
+ /* some cases the redundant moves can
+ can be eliminated for return statements */
+ if (ic->op == RETURN || ic->op == SEND)
+ {
+ packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+ }
+
+ /* if pointer set & left has a size more than
+ one and right is not in far space */
+ if (!DISABLE_PACK_ONE_USE &&
+ POINTER_SET (ic) &&
+ /* MLH: no such thing.
+ !isOperandInFarSpace(IC_RIGHT(ic)) && */
+ !OP_SYMBOL (IC_RESULT (ic))->remat &&
+ !IS_OP_RUONLY (IC_RIGHT (ic)) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
+ {
+
+ packRegsForOneuse (ic, IC_RESULT (ic), ebp);
+ }
+
+ /* if pointer get */
+ 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)
+ {
+
+ 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)))
+ {
+ if (IS_GB)
+ packRegsForHLUse (ic);
+ else
+ packRegsForHLUse3 (ic, IC_RESULT (ic), ebp);
+ }
+
+ if (!DISABLE_PACK_IY && IS_ITEMP (IC_RESULT (ic)) && IS_Z80)
+ {
+ packRegsForIYUse (ic, IC_RESULT (ic), ebp);
+ }
+
+ if (!DISABLE_PACK_ACC && IS_ITEMP (IC_RESULT (ic)) &&
+ getSize (operandType (IC_RESULT (ic))) == 1)
+ {
+ packRegsForAccUse2 (ic);
}
-#if 0
- if ((IS_ARITHMETIC_OP(ic)
- || IS_BITWISE_OP(ic)
- || ic->op == LEFT_OP || ic->op == RIGHT_OP
- ) &&
- IS_ITEMP(IC_RESULT(ic)) &&
- getSize(operandType(IC_RESULT(ic))) <= 2)
- packRegsForAccUse (ic);
-#else
- if (!DISABLE_PACK_ACC && IS_ITEMP(IC_RESULT(ic)) &&
- getSize(operandType(IC_RESULT(ic))) == 1)
- packRegsForAccUse2(ic);
-#endif
}
}
-
+
+/** Joins together two byte constant pushes into one word push.
+ */
+static iCode *
+joinPushes (iCode *lic)
+{
+ iCode *ic, *uic;
+
+ for (ic = lic; ic; ic = ic->next)
+ {
+ int first, second;
+ value *val;
+
+ uic = ic->next;
+
+ /* Anything past this? */
+ if (uic == NULL)
+ {
+ continue;
+ }
+ /* This and the next pushes? */
+ if (ic->op != IPUSH || uic->op != IPUSH)
+ {
+ continue;
+ }
+ /* Both literals? */
+ if ( !IS_OP_LITERAL (IC_LEFT (ic)) || !IS_OP_LITERAL (IC_LEFT (uic)))
+ {
+ continue;
+ }
+ /* Both characters? */
+ if ( getSize (operandType (IC_LEFT (ic))) != 1 || getSize (operandType (IC_LEFT (uic))) != 1)
+ {
+ continue;
+ }
+ /* Pull out the values, make a new type, and create the new iCode for it.
+ */
+ first = (int)operandLitValue ( IC_LEFT (ic));
+ second = (int)operandLitValue ( IC_LEFT (uic));
+
+ sprintf (buffer, "%u", ((first << 8) | (second & 0xFF)) & 0xFFFFU);
+ val = constVal (buffer);
+ SPEC_NOUN (val->type) = V_INT;
+ IC_LEFT (ic)->operand.valOperand = val;
+
+ /* Now remove the second one from the list. */
+ ic->next = uic->next;
+ if (uic->next)
+ {
+ /* Patch up the reverse link */
+ uic->next->prev = ic;
+ }
+ }
+
+ return lic;
+}
+
/*-----------------------------------------------------------------*/
/* assignRegisters - assigns registers to each live range as need */
/*-----------------------------------------------------------------*/
-void z80_assignRegisters (eBBlock **ebbs, int count)
+void
+z80_assignRegisters (eBBlock ** ebbs, int count)
{
- iCode *ic;
- int i ;
+ iCode *ic;
+ int i;
- D(D_ALLOC, ("\n-> z80_assignRegisters: entered.\n"));
+ D (D_ALLOC, ("\n-> z80_assignRegisters: entered.\n"));
- setToNull((void *)&funcrUsed);
- stackExtend = dataExtend = 0;
+ setToNull ((void *) &_G.funcrUsed);
+ setToNull ((void *) &_G.totRegAssigned);
+ _G.stackExtend = _G.dataExtend = 0;
- if (IS_GB) {
- /* DE is required for the code gen. */
- _nRegs = GBZ80_MAX_REGS;
- regsZ80 = _gbz80_regs;
+ if (IS_GB)
+ {
+ /* DE is required for the code gen. */
+ _G.nRegs = GBZ80_MAX_REGS;
+ regsZ80 = _gbz80_regs;
}
- else {
- _nRegs = Z80_MAX_REGS;
- regsZ80 = _z80_regs;
+ else
+ {
+ _G.nRegs = Z80_MAX_REGS;
+ regsZ80 = _z80_regs;
}
- /* change assignments this will remove some
- live ranges reducing some register pressure */
- for (i = 0 ; i < count ;i++ )
- packRegisters (ebbs[i]);
+ /* change assignments this will remove some
+ live ranges reducing some register pressure */
+ for (i = 0; i < count; i++)
+ packRegisters (ebbs[i]);
- if (options.dump_pack)
- dumpEbbsToFileExt(".dumppack",ebbs,count);
+ if (options.dump_pack)
+ dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
- /* first determine for each live range the number of
- registers & the type of registers required for each */
- regTypeNum ();
-
- /* and serially allocate registers */
- serialRegAssign(ebbs,count);
+ /* first determine for each live range the number of
+ registers & the type of registers required for each */
+ regTypeNum ();
+
+ /* and serially allocate registers */
+ serialRegAssign (ebbs, count);
+
+ freeAllRegs ();
+ fillGaps();
- /* if stack was extended then tell the user */
- if (stackExtend) {
-/* werror(W_TOOMANY_SPILS,"stack", */
-/* stackExtend,currFunc->name,""); */
- stackExtend = 0 ;
+ /* if stack was extended then tell the user */
+ if (_G.stackExtend)
+ {
+/* werror(W_TOOMANY_SPILS,"stack", */
+/* _G.stackExtend,currFunc->name,""); */
+ _G.stackExtend = 0;
}
- if (dataExtend) {
-/* werror(W_TOOMANY_SPILS,"data space", */
-/* dataExtend,currFunc->name,""); */
- dataExtend = 0 ;
+ if (_G.dataExtend)
+ {
+/* werror(W_TOOMANY_SPILS,"data space", */
+/* _G.dataExtend,currFunc->name,""); */
+ _G.dataExtend = 0;
}
- if (options.dump_rassgn)
- dumpEbbsToFileExt(".dumprassgn",ebbs,count);
+ if (options.dump_rassgn) {
+ dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+ dumpLiveRanges (DUMP_LRANGE, liveRanges);
+ }
+
+ /* after that create the register mask
+ for each of the instruction */
+ createRegMask (ebbs, count);
- /* after that create the register mask
- for each of the instruction */
- createRegMask (ebbs,count);
+ /* now get back the chain */
+ ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
- /* now get back the chain */
- ic = iCodeLabelOptimize(iCodeFromeBBlock (ebbs,count));
+ ic = joinPushes (ic);
- /* redo that offsets for stacked automatic variables */
- redoStackOffsets ();
+ /* redo that offsets for stacked automatic variables */
+ redoStackOffsets ();
- genZ80Code(ic);
+ genZ80Code (ic);
- /* free up any stackSpil locations allocated */
- applyToSet(stackSpil,deallocStackSpil);
- slocNum = 0;
- setToNull((void **)&stackSpil);
- setToNull((void **)&spiltSet);
- /* mark all registers as free */
- freeAllRegs();
+ /* free up any stackSpil locations allocated */
+ applyToSet (_G.stackSpil, deallocStackSpil);
+ _G.slocNum = 0;
+ setToNull ((void **) &_G.stackSpil);
+ setToNull ((void **) &_G.spiltSet);
+ /* mark all registers as free */
+ freeAllRegs ();
- return ;
+ return;
}