/*------------------------------------------------------------------------
- SDCCralloc.c - source file for register allocation. (8051) specific
+ SDCCralloc.c - source file for register allocation. (DS80C390) specific
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
+
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
+ what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
#include "common.h"
/* since the pack the registers depending strictly on the MCU */
/*-----------------------------------------------------------------*/
+#define D(x)
+
/* Global data */
static struct
{
bitVect *totRegAssigned; /* final set of LRs that got into registers */
short blockSpil;
int slocNum;
- bitVect *funcrUsed; /* registers used in a function */
+ bitVect *funcrUsed; /* registers used in a function */
int stackExtend;
int dataExtend;
+ bitVect *allBitregs; /* all bit registers */
}
_G;
/* Shared with gen.c */
-int ds390_ptrRegReq; /* one byte pointer register required */
+int ds390_ptrRegReq; /* one byte pointer register required */
/* 8051 registers */
regs regs390[] =
{REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1, 1},
{REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1, 1},
{REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1, 1},
+ {REG_GPR, DPL_IDX, REG_GPR, "dpl", "dpl", "dpl", 0, 0, 0},
+ {REG_GPR, DPH_IDX, REG_GPR, "dph", "dph", "dph", 0, 0, 0},
+ {REG_GPR, DPX_IDX, REG_GPR, "dpx", "dpx", "dpx", 0, 0, 0},
+ {REG_GPR, B_IDX, REG_GPR, "b", "b", "b", 0, 0, 0},
+ {REG_BIT, B0_IDX, REG_BIT, "b0", "b0", "bits", 0, 1, 0},
+ {REG_BIT, B1_IDX, REG_BIT, "b1", "b1", "bits", 1, 1, 0},
+ {REG_BIT, B2_IDX, REG_BIT, "b2", "b2", "bits", 2, 1, 0},
+ {REG_BIT, B3_IDX, REG_BIT, "b3", "b3", "bits", 3, 1, 0},
+ {REG_BIT, B4_IDX, REG_BIT, "b4", "b4", "bits", 4, 1, 0},
+ {REG_BIT, B5_IDX, REG_BIT, "b5", "b5", "bits", 5, 1, 0},
+ {REG_BIT, B6_IDX, REG_BIT, "b6", "b6", "bits", 6, 1, 0},
+ {REG_BIT, B7_IDX, REG_BIT, "b7", "b7", "bits", 7, 1, 0},
{REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 0, 0},
{REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 0, 0},
{REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 0, 0},
{REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 0, 0},
{REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 0, 0},
- {REG_CND, CND_IDX, REG_GPR, "C", "C", "xreg", 0, 0, 0},
- {REG_GPR, DPL_IDX, REG_GPR, "dpl", "dpl", "dpl", 0, 0, 0},
- {REG_GPR, DPH_IDX, REG_GPR, "dph", "dph", "dph", 0, 0, 0},
- {REG_GPR, DPX_IDX, REG_GPR, "dpx", "dpx", "dpx", 0, 0, 0},
- {REG_GPR, B_IDX, REG_GPR, "b", "b", "b", 0, 0, 0},
+ {REG_CND, CND_IDX, REG_GPR, "C", "psw", "xreg", 0, 0, 0},
+ {0, DPL1_IDX, 0, "dpl1", "dpl1", "dpl1", 0, 0, 0},
+ {0, DPH1_IDX, 0, "dph1", "dph1", "dph1", 0, 0, 0},
+ {0, DPX1_IDX, 0, "dpx1", "dpx1", "dpx1", 0, 0, 0},
+ {0, DPS_IDX, 0, "dps", "dps", "dps", 0, 0, 0},
+ {0, A_IDX, 0, "a", "acc", "acc", 0, 0, 0},
+ {0, AP_IDX, 0, "ap", "ap", "ap", 0, 0, 0},
};
+
int ds390_nRegs = 13;
+int ds390_nBitRegs = 0;
+
static void spillThis (symbol *);
static void freeAllRegs ();
+static iCode * packRegsDPTRuse (operand *);
+static int packRegsDPTRnuse (operand *,unsigned);
/*-----------------------------------------------------------------*/
/* allocReg - allocates register of given type */
/* if type is given as 0 then any
free register will do */
if (!type &&
- regs390[i].isFree)
- {
- regs390[i].isFree = 0;
- if (currFunc)
- currFunc->regsUsed =
- bitVectSetBit (currFunc->regsUsed, i);
- return ®s390[i];
- }
- /* other wise look for specific type
- of register */
+ regs390[i].isFree)
+ {
+ regs390[i].isFree = 0;
+ if (currFunc)
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, i);
+ return ®s390[i];
+ }
+ /* otherwise look for specific type of register */
if (regs390[i].isFree &&
- regs390[i].type == type)
- {
- regs390[i].isFree = 0;
- if (currFunc)
- currFunc->regsUsed =
- bitVectSetBit (currFunc->regsUsed, i);
- return ®s390[i];
- }
+ regs390[i].type == type)
+ {
+ regs390[i].isFree = 0;
+ if (currFunc)
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, i);
+ return ®s390[i];
+ }
}
return NULL;
}
/*-----------------------------------------------------------------*/
-/* ds390_regWithIdx - returns pointer to register wit index number */
+/* ds390_regWithIdx - returns pointer to register with index number*/
/*-----------------------------------------------------------------*/
regs *
ds390_regWithIdx (int idx)
{
int i;
- for (i = 0; i < ds390_nRegs; i++)
+ for (i = 0; i < sizeof(regs390)/sizeof(regs); i++)
if (regs390[i].rIdx == idx)
return ®s390[i];
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "regWithIdx not found");
+ "regWithIdx not found");
exit (1);
}
static void
freeReg (regs * reg)
{
+ if (!reg)
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "freeReg - Freeing NULL register");
+ exit (1);
+ }
+
reg->isFree = 1;
}
reg->isFree = 0;
}
-
/*-----------------------------------------------------------------*/
/* nFreeRegs - returns number of free registers */
/*-----------------------------------------------------------------*/
if (type == REG_PTR)
{
if ((nfr = nFreeRegs (type)) == 0)
- return nFreeRegs (REG_GPR);
+ return nFreeRegs (REG_GPR);
}
return nFreeRegs (type);
}
-
/*-----------------------------------------------------------------*/
-/* allDefsOutOfRange - all definitions are out of a range */
+/* isOperandInReg - returns true if operand is currently in regs */
/*-----------------------------------------------------------------*/
-static bool
-allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
+static int isOperandInReg(operand *op)
{
- int i;
-
- if (!defs)
- return TRUE;
-
- for (i = 0; i < defs->size; i++)
- {
- iCode *ic;
-
- if (bitVectBitValue (defs, i) &&
- (ic = hTabItemWithKey (iCodehTab, i)) &&
- (ic->seq >= fseq && ic->seq <= toseq))
-
- return FALSE;
-
- }
-
- return TRUE;
+ if (!IS_SYMOP(op)) return 0;
+ if (OP_SYMBOL(op)->ruonly) return 1;
+ if (OP_SYMBOL(op)->accuse) return 1;
+ if (OP_SYMBOL(op)->dptr) return 1;
+ return bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(op)->key);
}
/*-----------------------------------------------------------------*/
{
bitVect *spillable;
- /* spillable live ranges are those that are live at this
+ /* spillable live ranges are those that are live at this
point . the following categories need to be subtracted
- from this set.
+ 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 */
+ bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */
spillable =
- bitVectCplAnd (spillable, ic->uses); /* used in this one */
+ bitVectCplAnd (spillable, ic->uses); /* used in this one */
bitVectUnSetBit (spillable, ic->defKey);
spillable = bitVectIntersect (spillable, _G.regAssigned);
return spillable;
}
+/*-----------------------------------------------------------------*/
+/* bitType - will return 1 if the symbol has type REG_BIT */
+/*-----------------------------------------------------------------*/
+static int
+bitType (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+ return (sym->regType == REG_BIT ? 1 : 0);
+}
+
/*-----------------------------------------------------------------*/
/* noSpilLoc - return true if a variable has no spil location */
/*-----------------------------------------------------------------*/
}
/*-----------------------------------------------------------------*/
-/* directSpilLoc - will return 1 if the splilocation is in direct */
+/* directSpilLoc - will return 1 if the spillocation is in direct */
/*-----------------------------------------------------------------*/
static int
directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
return sym->remat;
}
-/*-----------------------------------------------------------------*/
-/* 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 */
/*-----------------------------------------------------------------*/
notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
{
return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
- allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+ allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static set *
liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
- eBBlock * ebp, iCode * ic)
+ eBBlock * ebp, iCode * ic)
{
set *rset = NULL;
int i;
{
symbol *sym;
if (!bitVectBitValue (lrs, i))
- continue;
+ continue;
- /* if we don't find it in the live range
+ /* 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);
- }
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "liveRangesWith could not find liveRange");
+ exit (1);
+ }
if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
- addSetHead (&rset, sym);
+ addSetHead (&rset, sym);
}
return rset;
{
/* if usage is the same then prefer
- the spill the smaller of the two */
+ to spill the smaller of the two */
if (lsym->used == sym->used)
- if (getSize (lsym->type) < getSize (sym->type))
- sym = lsym;
+ if (getSize (lsym->type) < getSize (sym->type))
+ sym = lsym;
/* if less usage */
if (lsym->used < sym->used)
- sym = lsym;
+ sym = lsym;
}
- setToNull ((void **) &sset);
+ setToNull ((void *) &sset);
sym->blockSpil = 0;
return sym;
}
for (sym = setFirstItem (itmpStack); sym;
sym = setNextItem (itmpStack))
{
- if (bitVectBitValue(sym->clashes,fsym->key)) return 0;
+ if (bitVectBitValue(sym->clashes,fsym->key)) return 0;
}
return 1;
}
{
int j;
- /* if no registers assigned to it or
- spilt */
- /* if it does not overlap with this then
- not need to spill it */
+ /* if no registers assigned to it or spilt */
+ /* if it does not overlap this then
+ no need to spill it */
if (lrsym->isspilt || !lrsym->nRegs ||
- (lrsym->liveTo < forSym->liveFrom))
- continue;
+ (lrsym->liveTo < forSym->liveFrom))
+ continue;
/* go thru the registers : if it is either
- r0 or r1 then spil it */
+ r0 or r1 then spill it */
for (j = 0; j < lrsym->nRegs; j++)
- if (lrsym->regs[j] == r0 ||
- lrsym->regs[j] == r1)
- {
- spillThis (lrsym);
- break;
- }
+ if (lrsym->regs[j] == r0 ||
+ lrsym->regs[j] == r1)
+ {
+ spillThis (lrsym);
+ break;
+ }
}
}
char slocBuffer[30];
- /* first go try and find a free one that is already
+ /* 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->usl.spillLoc = sloc;
sym->stackSpil = 1;
sloc->isFree = 0;
addSetHead (&sloc->usl.itmpStack, sym);
we need to allocate this on the stack : this is really a
hack!! but cannot think of anything better at this time */
- if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
+ if (SNPRINTF (slocBuffer, sizeof(slocBuffer),
+ "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
{
fprintf (stderr, "***Internal error: slocBuffer overflowed: %s:%d\n",
- __FILE__, __LINE__);
+ __FILE__, __LINE__);
exit (1);
}
/* set the type to the spilling symbol */
sloc->type = copyLinkChain (sym->type);
sloc->etype = getSpec (sloc->type);
- if (options.model == MODEL_SMALL) {
- SPEC_SCLS (sloc->etype) = S_DATA;
- } else {
- SPEC_SCLS (sloc->etype) = S_XDATA;
- }
+ if (!IS_BIT (sloc->etype))
+ {
+ if (options.model == MODEL_SMALL)
+ {
+ SPEC_SCLS (sloc->etype) = S_DATA;
+ }
+ else
+ {
+ SPEC_SCLS (sloc->etype) = S_XDATA;
+ }
+ }
SPEC_EXTR (sloc->etype) = 0;
SPEC_STAT (sloc->etype) = 0;
+ SPEC_VOLATILE(sloc->etype) = 0;
+ SPEC_ABSA(sloc->etype) = 0;
- /* we don't allow it to be allocated`
+ /* 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
+ and turn off overlaying
*/
useXstack = options.useXstack;
options.useXstack = useXstack;
options.model = model;
options.noOverlay = noOverlay;
- sloc->isref = 1; /* to prevent compiler warning */
+ sloc->isref = 1; /* to prevent compiler warning */
/* if it is on the stack then update the stack */
if (IN_STACK (sloc->etype))
sym->usl.spillLoc = sloc;
sym->stackSpil = 1;
- /* add it to the set of itempStack set
+ /* add it to the set of itempStack set
of the spill location */
addSetHead (&sloc->usl.itmpStack, sym);
return sym;
if (!(sym->remat || sym->usl.spillLoc))
createStackSpil (sym);
-
/* mark it has spilt & put it in the spilt set */
sym->isspilt = sym->spillA = 1;
_G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
if (sym->regs[i])
{
- freeReg (sym->regs[i]);
- sym->regs[i] = NULL;
+ freeReg (sym->regs[i]);
+ sym->regs[i] = NULL;
}
- /* if spilt on stack then free up r0 & r1
+ /* if spilt on stack then free up r0 & r1
if they could have been assigned to some
LIVE ranges */
- if (!ds390_ptrRegReq && isSpiltOnStack (sym))
+ if (!ds390_ptrRegReq && isSpiltOnStack (sym) && !options.stack10bit)
{
- ds390_ptrRegReq += !options.stack10bit;
+ ds390_ptrRegReq ++;
spillLRWithPtrReg (sym);
}
/* get the spillable live ranges */
lrcs = computeSpillable (ic);
- /* get all live ranges that are rematerizable */
- if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+ /* remove incompatible registers */
+ if ((forSym->regType == REG_PTR) || (forSym->regType == REG_GPR))
{
+ selectS = liveRangesWith (lrcs, bitType, ebp, ic);
+
+ for (sym = setFirstItem (selectS); sym; sym = setNextItem (selectS))
+ {
+ bitVectUnSetBit (lrcs, sym->key);
+ }
+ }
+ /* get all live ranges that are rematerializable */
+ if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+ {
/* return the least used of these */
return leastUsedLR (selectS);
}
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));
+ strncpyz (sym->rname,
+ sym->usl.spillLoc->rname[0] ?
+ sym->usl.spillLoc->rname : sym->usl.spillLoc->name,
+ sizeof(sym->rname));
sym->spildir = 1;
/* mark it as allocation required */
sym->usl.spillLoc->allocreq++;
/* 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++;
- sym->blockSpil = 1;
- }
- return sym;
- }
+ {
+ sym = leastUsedLR (selectS);
+ /* if this is not rematerializable */
+ if (!sym->remat)
+ {
+ _G.blockSpil++;
+ sym->blockSpil = 1;
+ }
+ 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)
- {
- sym->remainSpil = 1;
- _G.blockSpil++;
- }
- return sym;
- }
- }
+ if (!_G.blockSpil &&
+ !isiCodeInFunctionCall (ic) &&
+ (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+ {
+ sym = leastUsedLR (selectS);
+ if (sym != forSym)
+ {
+ if (!sym->remat)
+ {
+ sym->remainSpil = 1;
+ _G.blockSpil++;
+ }
+ 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++;
/* find live ranges with spillocation */
if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
{
-
sym = leastUsedLR (selectS);
sym->usl.spillLoc->allocreq++;
return sym;
used ofcourse */
if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
{
-
/* return a created spil location */
sym = createStackSpil (leastUsedLR (selectS));
sym->usl.spillLoc->allocreq++;
if (ssym->regs[i])
freeReg (ssym->regs[i]);
- /* if spilt on stack then free up r0 & r1
+ /* if spilt on stack then free up r0 & r1
if they could have been assigned to as gprs */
if (!ds390_ptrRegReq && isSpiltOnStack (ssym) && !options.stack10bit)
{
- ds390_ptrRegReq++;
+ ds390_ptrRegReq++;
spillLRWithPtrReg (ssym);
}
- /* if this was a block level spil then insert push & pop
+ /* 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));
+ ebp->sch->next : ebp->sch));
nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
/* add pop to the end of the block */
addiCodeToeBBlock (ebp, nic, NULL);
getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
{
regs *reg;
+ int j;
tryAgain:
/* try for a ptr type */
if (!spilSomething (ic, ebp, sym))
return NULL;
- /* this looks like an infinite loop but
+ /* make sure partially assigned registers aren't reused */
+ for (j=0; j<=sym->nRegs; j++)
+ if (sym->regs[j])
+ sym->regs[j]->isFree = 0;
+
+ /* this looks like an infinite loop but
in really selectSpil will abort */
goto tryAgain;
}
getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
{
regs *reg;
+ int j;
tryAgain:
/* try for gpr type */
if (!spilSomething (ic, ebp, sym))
return NULL;
- /* this looks like an infinite loop but
+ /* make sure partially assigned registers aren't reused */
+ for (j=0; j<=sym->nRegs; j++)
+ if (sym->regs[j])
+ sym->regs[j]->isFree = 0;
+
+ /* this looks like an infinite loop but
in really selectSpil will abort */
goto tryAgain;
}
/*-----------------------------------------------------------------*/
-/* getRegPtrNoSpil - get it cannot split */
+/* getRegBit - will try for Bit if not spill this */
+/*-----------------------------------------------------------------*/
+static regs *getRegBit (symbol * sym)
+{
+ regs *reg;
+
+ /* try for a bit type */
+ if ((reg = allocReg (REG_BIT)))
+ return reg;
+
+ spillThis (sym);
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegPtrNoSpil - get it cannot be spilt */
/*-----------------------------------------------------------------*/
static regs *getRegPtrNoSpil()
{
return reg;
assert(0);
+
+ /* just to make the compiler happy */
+ return 0;
}
/*-----------------------------------------------------------------*/
-/* getRegGprNoSpil - get it cannot split */
+/* getRegGprNoSpil - get it cannot be spilt */
/*-----------------------------------------------------------------*/
static regs *getRegGprNoSpil()
{
return reg;
assert(0);
+
+ /* just to make the compiler happy */
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegBitNoSpil - get it cannot be spilt */
+/*-----------------------------------------------------------------*/
+static regs *getRegBitNoSpil()
+{
+ regs *reg;
+
+ /* try for a bit type */
+ if ((reg = allocReg (REG_BIT)))
+ return reg;
+
+ /* try for gpr type */
+ if ((reg = allocReg (REG_GPR)))
+ return reg;
+
+ assert(0);
+
+ /* just to make the compiler happy */
+ return 0;
}
/*-----------------------------------------------------------------*/
return FALSE;
}
+/*-----------------------------------------------------------------*/
+/* updateRegUsage - update the registers in use at the start of */
+/* this icode */
+/*-----------------------------------------------------------------*/
+static void
+updateRegUsage (iCode * ic)
+{
+ int reg;
+
+ for (reg=0; reg<ds390_nRegs; reg++)
+ {
+ if (regs390[reg].isFree)
+ {
+ ic->riu &= ~(1<<regs390[reg].offset);
+ }
+ else
+ {
+ ic->riu |= (1<<regs390[reg].offset);
+ BitBankUsed |= (reg >= B0_IDX);
+ }
+ }
+}
+
/*-----------------------------------------------------------------*/
/* deassignLRs - check the live to and if they have registers & are */
/* not spilt then free up the registers */
symbol *psym = NULL;
/* if it does not end here */
if (sym->liveTo > ic->seq)
- continue;
+ continue;
- /* if it was spilt on stack then we can
+ /* 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;
- }
+ {
+ if (sym->stackSpil)
+ {
+ sym->usl.spillLoc->isFree = 1;
+ sym->stackSpil = 0;
+ }
+ continue;
+ }
if (!bitVectBitValue (_G.regAssigned, sym->key))
- continue;
+ continue;
/* special case check if this is an IFX &
- the privious one was a pop and the
+ 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));
+ ic->prev->op == IPOP &&
+ !ic->prev->parmPush &&
+ !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
+ psym = OP_SYMBOL (IC_LEFT (ic->prev));
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 ||
- POINTER_SET (ic)) &&
- (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);
-
- _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]);
- }
- }
+ {
+ 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 ||
+ POINTER_SET (ic)) &&
+ (result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */
+ result->liveTo > ic->seq && /* and will live beyond this */
+ result->liveTo <= ebp->lSeq && /* does not go beyond this block */
+ result->liveFrom == ic->seq && /* does not start before here */
+ result->regType == sym->regType && /* same register types */
+ result->nRegs && /* which needs registers */
+ !result->isspilt && /* and does not already have them */
+ !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);
+
+ _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]);
+ }
+ }
}
}
static int
willCauseSpill (int nr, int rt)
{
- /* first check if there are any avlb registers
- of te type required */
+ /* first check if there are any available registers
+ of the type required */
if (rt == REG_PTR)
{
- /* special case for pointer type
- if pointer type not avlb then
+ /* special case for pointer type
+ if pointer type not avlb then
check for type gpr */
if (nFreeRegs (rt) >= nr)
- return 0;
+ return 0;
if (nFreeRegs (REG_GPR) >= nr)
- return 0;
+ return 0;
+ }
+ else if (rt == REG_BIT)
+ {
+ if (nFreeRegs (rt) >= nr)
+ return 0;
}
else
{
if (ds390_ptrRegReq)
- {
- if (nFreeRegs (rt) >= nr)
- return 0;
- }
+ {
+ if (nFreeRegs (rt) >= nr)
+ return 0;
+ }
else
- {
- if (nFreeRegs (REG_PTR) +
- nFreeRegs (REG_GPR) >= nr)
- return 0;
- }
+ {
+ if (nFreeRegs (REG_PTR) +
+ nFreeRegs (REG_GPR) >= nr)
+ return 0;
+ }
}
/* it will cause a spil */
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;
- }
- }
+ {
+ if (result->regs[i] == opsym->regs[j] && i != j)
+ {
+ shared = 1;
+ goto xchgPositions;
+ }
+ }
}
xchgPositions:
if (shared)
change ++;
goto again;
}
- return change ;
+ return change;
+}
+
+/*-----------------------------------------------------------------*/
+/* unusedLRS - returns a bitVector of liveranges not used in 'ebp' */
+/*-----------------------------------------------------------------*/
+bitVect *unusedLRs (eBBlock *ebp)
+{
+ bitVect *ret = NULL;
+ symbol *sym;
+ int key;
+
+ if (!ebp) return NULL;
+ for (sym = hTabFirstItem(liveRanges,&key); sym ;
+ sym = hTabNextItem(liveRanges,&key)) {
+
+ if (notUsedInBlock(sym,ebp,NULL)) {
+ ret = bitVectSetBit(ret,sym->key);
+ }
+ }
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------*/
+/* deassignUnsedLRs - if this baisc block ends in a return then */
+/* deassign symbols not used in this block */
+/*-----------------------------------------------------------------*/
+bitVect *deassignUnsedLRs(eBBlock *ebp)
+{
+ bitVect *unused = NULL;
+ int i;
+
+ switch (returnAtEnd(ebp)) {
+ case 2: /* successor block ends in a return */
+ unused = unusedLRs((eBBlock *) setFirstItem(ebp->succList));
+ /* fall thru */
+ case 1: /* this block ends in a return */
+ unused = bitVectIntersect(unused,unusedLRs(ebp));
+ break;
+ }
+
+ if (unused) {
+ for (i = 0 ; i < unused->size ; i++ ) {
+
+ /* if unused */
+ if (bitVectBitValue(unused,i)) {
+
+ /* if assigned to registers */
+ if (bitVectBitValue(_G.regAssigned,i)) {
+ symbol *sym;
+ int j;
+
+ sym = hTabItemWithKey(liveRanges,i);
+ /* remove it from regassigned & mark the
+ register free */
+ bitVectUnSetBit(_G.regAssigned,i);
+ for (j = 0 ; j < sym->nRegs; j++)
+ freeReg(sym->regs[j]);
+ } else {
+ /* not assigned to registers : remove from set*/
+ bitVectUnSetBit(unused,i);
+ }
+ }
+ }
+ }
+ return unused;
+}
+
+/*-----------------------------------------------------------------*/
+/* reassignUnusedLRs - put registers to unused Live ranges */
+/*-----------------------------------------------------------------*/
+void reassignUnusedLRs (bitVect *unused)
+{
+ int i;
+ if (!unused) return ;
+
+ for (i = 0 ; i < unused->size ; i++ ) {
+ /* if unused : means it was assigned to registers before */
+ if (bitVectBitValue(unused,i)) {
+ symbol *sym;
+ int j;
+
+ /* put it back into reg set*/
+ bitVectSetBit(_G.regAssigned,i) ;
+
+ sym = hTabItemWithKey(liveRanges,i);
+ /* make registers busy */
+ for (j = 0 ; j < sym->nRegs; j++)
+ sym->regs[j]->isFree = 0;
+ }
+ }
+}
+
+/*------------------------------------------------------------------*/
+/* verifyRegsAssigned - make sure an iTemp is properly initialized; */
+/* it should either have registers or have beed spilled. Otherwise, */
+/* there was an uninitialized variable, so just spill this to get */
+/* the operand in a valid state. */
+/*------------------------------------------------------------------*/
+static void
+verifyRegsAssigned (operand *op, iCode * ic)
+{
+ symbol * sym;
+
+ if (!op) return;
+ if (!IS_ITEMP (op)) return;
+
+ sym = OP_SYMBOL (op);
+ if (sym->isspilt) return;
+ if (!sym->nRegs) return;
+ if (sym->regs[0]) return;
+
+ werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
+ sym->prereqv ? sym->prereqv->name : sym->name);
+ spillThis (sym);
}
+
/*-----------------------------------------------------------------*/
/* serialRegAssign - serially allocate registers to the variables */
/*-----------------------------------------------------------------*/
/* for all blocks */
for (i = 0; i < count; i++)
- {
+ { /* ebbs */
iCode *ic;
+ bitVect *unusedLRs = NULL;
if (ebbs[i]->noPath &&
- (ebbs[i]->entryLabel != entryLabel &&
- ebbs[i]->entryLabel != returnLabel))
- continue;
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
- /* of all instructions do */
+ unusedLRs = deassignUnsedLRs(ebbs[i]);
+
+ /* for 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)
- 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++;
-
- /* take away registers from live
- ranges that end at this instruction */
- deassignLRs (ic, ebbs[i]);
-
- /* some don't need registers */
- if (SKIP_IC2 (ic) ||
- ic->op == JUMPTABLE ||
- ic->op == IFX ||
- ic->op == IPUSH ||
- ic->op == IPOP ||
- (IC_RESULT (ic) && POINTER_SET (ic)))
- 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;
- int ptrRegSet = 0;
-
- /* 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)
- 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)
- {
- 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)))
- {
-
- spillThis (sym);
- continue;
-
- }
-
- /* 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;
- }
- }
- }
- }
-
- /* if we need ptr regs for the right side
- then mark it */
- if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
- && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
- <= (unsigned) PTRSIZE)
- {
- ds390_ptrRegReq++;
- ptrRegSet = 1;
- }
- /* else we assign registers to it */
- _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
- _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
-
- for (j = 0; j < sym->nRegs; j++)
- {
- if (sym->regType == REG_PTR)
- sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
- else
- sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
-
- /* if the allocation falied which means
- this was spilt then break */
- if (!sym->regs[j])
- 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)));
- /* 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)));
-
- if (ptrRegSet)
- {
- ds390_ptrRegReq--;
- ptrRegSet = 0;
- }
-
- }
- }
+ {
+ updateRegUsage(ic);
+
+ /* if this is an ipop that means some live
+ range will have to be assigned again */
+ if (ic->op == IPOP)
+ 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++;
+
+ /* take away registers from live
+ ranges that end at this instruction */
+ deassignLRs (ic, ebbs[i]);
+
+ /* some don't need registers */
+ if (SKIP_IC2 (ic) ||
+ ic->op == JUMPTABLE ||
+ ic->op == IFX ||
+ ic->op == IPUSH ||
+ ic->op == IPOP ||
+ (IC_RESULT (ic) && POINTER_SET (ic)))
+ 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;
+ int ptrRegSet = 0;
+
+ /* Make sure any spill location is definitely allocated */
+ if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
+ !sym->usl.spillLoc->allocreq)
+ {
+ sym->usl.spillLoc->allocreq++;
+ }
+
+ /* 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)
+ 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)
+ {
+ spillThis (sym);
+ continue;
+ }
+
+ willCS = willCauseSpill (sym->nRegs, sym->regType);
+ /* if this is a bit variable then don't use precious registers
+ along with expensive bit-to-char conversions but just spill
+ it */
+ if (willCS && SPEC_NOUN(sym->etype) == V_BIT)
+ {
+ 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 */
+ spillable = computeSpillable (ic);
+ if (sym->remat || (willCS && bitVectIsZero (spillable)))
+ {
+ spillThis (sym);
+ continue;
+ }
+
+ /* If the live range preceeds the point of definition
+ then ideally we must take into account registers that
+ have been allocated after sym->liveFrom but freed
+ before ic->seq. This is complicated, so spill this
+ symbol instead and let fillGaps handle the allocation. */
+ if (sym->liveFrom < ic->seq)
+ {
+ spillThis (sym);
+ continue;
+ }
+
+ /* if it has a spillocation & is used less than
+ all other live ranges then spill this */
+ if (willCS) {
+ 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;
+ }
+ }
+ }
+ }
+
+ /* if we need ptr regs for the right side
+ then mark it */
+ if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
+ && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned) PTRSIZE)
+ {
+ ds390_ptrRegReq++;
+ ptrRegSet = 1;
+ }
+ /* else we assign registers to it */
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+ _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
+
+ for (j = 0; j < sym->nRegs; j++)
+ {
+ sym->regs[j] = NULL;
+ if (sym->regType == REG_PTR)
+ sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+ else if (sym->regType == REG_BIT)
+ sym->regs[j] = getRegBit (sym);
+ else
+ sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+ /* if the allocation failed which means
+ this was spilt then break */
+ if (!sym->regs[j])
+ break;
+ }
+
+ /* if it shares registers with operands make sure
+ that they are in the same position */
+ if (!POINTER_SET(ic) && !POINTER_GET(ic))
+ {
+ if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->nRegs)
+ {
+ 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)));
+ }
+ }
+
+ if (ptrRegSet)
+ {
+ ds390_ptrRegReq--;
+ ptrRegSet = 0;
+ }
+
+ }
+ }
+ reassignUnusedLRs(unusedLRs);
}
+
+ /* Check for and fix any problems with uninitialized operands */
+ for (i = 0; i < count; i++)
+ {
+ iCode *ic;
+
+ if (ebbs[i]->noPath &&
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
+
+ for (ic = ebbs[i]->sch; ic; ic = ic->next)
+ {
+ if (SKIP_IC2 (ic))
+ continue;
+
+ if (ic->op == IFX)
+ {
+ verifyRegsAssigned (IC_COND (ic), ic);
+ continue;
+ }
+
+ if (ic->op == JUMPTABLE)
+ {
+ verifyRegsAssigned (IC_JTCOND (ic), ic);
+ continue;
+ }
+
+ verifyRegsAssigned (IC_RESULT (ic), ic);
+ verifyRegsAssigned (IC_LEFT (ic), ic);
+ verifyRegsAssigned (IC_RIGHT (ic), ic);
+ }
+ }
}
/*-----------------------------------------------------------------*/
static void fillGaps()
{
symbol *sym =NULL;
- int key =0;
-
+ int key =0;
+ int loop = 0, change;
+ int pass;
+
if (getenv("DISABLE_FILL_GAPS")) return;
- /* look for livernages that was spilt by the allocator */
- for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
- sym = hTabNextItem(liveRanges,&key)) {
-
- int i;
- int pdone = 0;
-
- if (!sym->spillA || !sym->clashes || sym->remat) continue ;
-
- /* find the liveRanges this one clashes with, that are
- still assigned to registers & mark the registers as used*/
- for ( i = 0 ; i < sym->clashes->size ; i ++) {
- int k;
- symbol *clr;
-
- if (bitVectBitValue(sym->clashes,i) == 0 || /* those that clash with this */
- bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
- continue ;
-
- assert (clr = hTabItemWithKey(liveRanges,i));
-
- /* mark these registers as used */
- for (k = 0 ; k < clr->nRegs ; k++ )
- useReg(clr->regs[k]);
- }
-
- if (willCauseSpill(sym->nRegs,sym->regType)) {
- /* NOPE :( clear all registers & and continue */
- freeAllRegs();
- continue ;
- }
-
- /* THERE IS HOPE !!!! */
- for (i=0; i < sym->nRegs ; i++ ) {
- if (sym->regType == REG_PTR)
- sym->regs[i] = getRegPtrNoSpil ();
- else
- sym->regs[i] = getRegGprNoSpil ();
- }
-
- /* 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;
- }
- }
- /* had to position more than once GIVE UP */
- if (pdone > 1) {
- /* UNDO all the changes we made to try this */
- sym->isspilt = 0;
- for (i=0; i < sym->nRegs ; i++ ) {
- sym->regs[i] = NULL;
- }
- freeAllRegs();
- printf("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN");
- continue ;
- }
- printf("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();
+
+ /* First try to do DPTRuse once more since now we know what got into
+ registers */
+
+ while (loop++ < 10) {
+ change = 0;
+
+ for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
+ sym = hTabNextItem(liveRanges,&key)) {
+ int size = getSize(sym->type);
+
+ if (sym->liveFrom == sym->liveTo) continue;
+
+ if (sym->uptr && sym->dptr==0 && !sym->ruonly &&
+ size < 4 && size > 1) {
+
+ if (packRegsDPTRuse(operandFromSymbol(sym))) {
+
+ /* if this was assigned to registers then */
+ if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
+ /* take it out of the register assigned set */
+ bitVectUnSetBit(_G.totRegAssigned,sym->key);
+ } else if (sym->usl.spillLoc) {
+ sym->usl.spillLoc->allocreq--;
+ sym->usl.spillLoc = NULL;
+ }
+
+ sym->nRegs = 0;
+ sym->isspilt = sym->spillA = 0;
+ continue ;
+ }
+
+ /* try assigning other dptrs */
+ if (sym->dptr == 0 && packRegsDPTRnuse(operandFromSymbol(sym),1) && !getenv("DPTRnDISABLE")) {
+ /* if this was ssigned to registers then */
+ if (bitVectBitValue(_G.totRegAssigned,sym->key)) {
+ /* take it out of the register assigned set */
+ bitVectUnSetBit(_G.totRegAssigned,sym->key);
+ } else if (sym->usl.spillLoc) {
+ sym->usl.spillLoc->allocreq--;
+ sym->usl.spillLoc = NULL;
+ }
+ sym->nRegs = 0;
+ sym->isspilt = sym->spillA = 0;
+ }
+ }
+ }
+
+ /* look for liveranges that were spilt by the allocator */
+ for (sym = hTabFirstItem(liveRanges,&key) ; sym ;
+ sym = hTabNextItem(liveRanges,&key)) {
+
+ int i;
+ int pdone = 0;
+
+ if (!sym->spillA || !sym->clashes || sym->remat) continue ;
+ if (!sym->uses || !sym->defs) continue ;
+ /* find the liveRanges this one clashes with, that are
+ still assigned to registers & mark the registers as used*/
+ for ( i = 0 ; i < sym->clashes->size ; i ++) {
+ int k;
+ symbol *clr;
+
+ if (bitVectBitValue(sym->clashes,i) == 0 || /* those that clash with this */
+ bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+ continue ;
+
+ clr = hTabItemWithKey(liveRanges,i);
+ assert(clr);
+
+ /* mark these registers as used */
+ for (k = 0 ; k < clr->nRegs ; k++ )
+ useReg(clr->regs[k]);
+ }
+
+ if (willCauseSpill(sym->nRegs,sym->regType)) {
+ /* NOPE :( clear all registers & and continue */
+ freeAllRegs();
+ continue ;
+ }
+
+ /* THERE IS HOPE !!!! */
+ for (i=0; i < sym->nRegs ; i++ ) {
+ if (sym->regType == REG_PTR)
+ sym->regs[i] = getRegPtrNoSpil ();
+ else if (sym->regType == REG_BIT)
+ sym->regs[i] = getRegBitNoSpil ();
+ else
+ sym->regs[i] = getRegGprNoSpil ();
+ }
+
+ /* 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.
+ We may need to perform the checks twice; once to
+ position the registers as needed, the second to
+ verify any register repositioning is still
+ compatible.
+ */
+ sym->isspilt = 0;
+ for (pass=0; pass<2; pass++) {
+ 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)))>0);
+ }
+ if (IS_SYMOP(IC_RIGHT(ic)) &&
+ bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
+ pdone += (positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)))>0);
+ }
+ 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 (POINTER_SET(ic) || POINTER_GET(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)))>0);
+ }
+ if (pdone > 1) break;
+ }
+ }
+ if (pdone == 0) break; /* second pass only if regs repositioned */
+ 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 (fprintf (stderr, "Fill Gap gave up due to positioning for "
+ "%s in function %s\n",
+ sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+ continue ;
+ }
+ D (fprintf (stderr, "FILLED GAP for %s in function %s\n",
+ sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+ _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
+ sym->isspilt = sym->spillA = 0 ;
+ sym->usl.spillLoc->allocreq--;
+ sym->usl.spillLoc = NULL;
+ freeAllRegs();
+ change ++;
+ }
+ if (!change) break;
}
}
/*-----------------------------------------------------------------*/
-/* rUmaskForOp :- returns register mask for an operand */
+/* findAllBitregs :- returns bit vector of all bit registers */
/*-----------------------------------------------------------------*/
static bitVect *
-rUmaskForOp (operand * op)
+findAllBitregs (void)
+{
+ bitVect *rmask = newBitVect (ds390_nRegs);
+ int j;
+
+ for (j = 0; j < ds390_nRegs; j++)
+ {
+ if (regs390[j].type == REG_BIT)
+ rmask = bitVectSetBit (rmask, regs390[j].rIdx);
+ }
+
+ return rmask;
+}
+
+/*-----------------------------------------------------------------*/
+/* ds390_allBitregs :- returns bit vector of all bit registers */
+/*-----------------------------------------------------------------*/
+bitVect *
+ds390_allBitregs (void)
+{
+ return _G.allBitregs;
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand */
+/*-----------------------------------------------------------------*/
+bitVect *
+ds390_rUmaskForOp (operand * op)
{
bitVect *rumask;
symbol *sym;
for (j = 0; j < sym->nRegs; j++)
{
rumask = bitVectSetBit (rumask,
- sym->regs[j]->rIdx);
+ sym->regs[j]->rIdx);
}
return rumask;
if (ic->op == IFX)
{
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_COND (ic)));
+ ds390_rUmaskForOp (IC_COND (ic)));
goto ret;
}
if (ic->op == JUMPTABLE)
{
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_JTCOND (ic)));
+ ds390_rUmaskForOp (IC_JTCOND (ic)));
goto ret;
}
/* of all other cases */
if (IC_LEFT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_LEFT (ic)));
+ ds390_rUmaskForOp (IC_LEFT (ic)));
if (IC_RIGHT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_RIGHT (ic)));
+ ds390_rUmaskForOp (IC_RIGHT (ic)));
if (IC_RESULT (ic))
rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_RESULT (ic)));
+ ds390_rUmaskForOp (IC_RESULT (ic)));
ret:
return rmask;
iCode *ic;
if (ebbs[i]->noPath &&
- (ebbs[i]->entryLabel != entryLabel &&
- ebbs[i]->entryLabel != returnLabel))
- continue;
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
/* for all instructions */
for (ic = ebbs[i]->sch; ic; ic = ic->next)
- {
-
- 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 (ds390_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);
- }
-
- /* special case for ruonly */
- if (sym->ruonly && sym->liveFrom != sym->liveTo) {
- int size = getSize(sym->type);
- int j = DPL_IDX;
- for (k = 0 ; k < size; k++ )
- ic->rMask = bitVectSetBit (ic->rMask, j++);
- 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);
- }
- }
+ {
+
+ 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 (ds390_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");
+ fprintf(stderr, "\tmissing live range: key=%d\n", j);
+ exit (0);
+ }
+#if 0
+ /* special case for ruonly */
+ if (sym->ruonly && sym->liveFrom != sym->liveTo) {
+ int size = getSize(sym->type);
+ int j = DPL_IDX;
+ for (k = 0 ; k < size; k++ )
+ ic->rMask = bitVectSetBit (ic->rMask, j++);
+ continue ;
+ }
+#endif
+ /* 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);
+ }
+ }
}
}
static char *
rematStr (symbol * sym)
{
- char *s = buffer;
iCode *ic = sym->rematiCode;
+ int offset = 0;
while (1)
{
+ /* if plus adjust offset to right hand side */
+ if (ic->op == '+')
+ {
+ offset += (int) operandLitValue (IC_RIGHT (ic));
+ ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+ continue;
+ }
+
+ /* if minus adjust offset to right hand side */
+ if (ic->op == '-')
+ {
+ offset -= (int) operandLitValue (IC_RIGHT (ic));
+ ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+ continue;
+ }
- /* 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;
- }
/* cast then continue */
if (IS_CAST_ICODE(ic)) {
- ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
- continue;
+ ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+ continue;
}
/* we reached the end */
- sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
break;
}
+ if (offset)
+ {
+ SNPRINTF (buffer, sizeof(buffer),
+ "(%s %c 0x%04x)",
+ OP_SYMBOL (IC_LEFT (ic))->rname,
+ offset >= 0 ? '+' : '-',
+ abs (offset) & 0xffff);
+ }
+ else
+ {
+ strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
+ }
return buffer;
}
/* if used zero times then no registers needed */
if ((sym->liveTo - sym->liveFrom) == 0)
- continue;
+ continue;
/* if the live range is a temporary */
if (sym->isitmp)
- {
-
- /* 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 the symbol has only one definition &
- that definition is a get_pointer and the
- pointer we are getting is rematerializable and
- in "data" space */
-
- if (bitVectnBitsOn (sym->defs) == 1 &&
- (ic = hTabItemWithKey (iCodehTab,
- bitVectFirstBit (sym->defs))) &&
- POINTER_GET (ic) &&
- !sym->noSpilLoc &&
- !IS_BITVAR (sym->etype))
- {
-
-
- /* if remat in data space */
- if (OP_SYMBOL (IC_LEFT (ic))->remat &&
- !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
- DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER)
- {
-
- /* create a psuedo symbol & force a spil */
- symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
- psym->type = sym->type;
- psym->etype = sym->etype;
- strcpy (psym->rname, psym->name);
- sym->isspilt = 1;
- sym->usl.spillLoc = psym;
- continue;
- }
-
- /* if in data space or idata space then try to
- allocate pointer register */
-
- }
-
- /* 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 (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 */
- if (sym->nRegs == 1 &&
- IS_PTR (sym->type) &&
- sym->uptr)
- sym->regType = REG_PTR;
- else
- sym->regType = REG_GPR;
-
- }
+ {
+
+ /* 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 the symbol has only one definition &
+ that definition is a get_pointer */
+ if (bitVectnBitsOn (sym->defs) == 1 &&
+ (ic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (sym->defs))) &&
+ POINTER_GET (ic) &&
+ !IS_BITVAR (sym->etype) &&
+ (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER))
+ {
+
+ if (ptrPseudoSymSafe (sym, ic))
+ {
+ ptrPseudoSymConvert (sym, ic, rematStr (OP_SYMBOL (IC_LEFT (ic))));
+ continue;
+ }
+
+ /* if in data space or idata space then try to
+ allocate pointer register */
+
+ }
+
+ /* 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 (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 */
+ if (sym->nRegs == 1 && IS_PTR (sym->type) && sym->uptr)
+ sym->regType = REG_PTR;
+ else if (IS_BIT(sym->type))
+ sym->regType = REG_BIT;
+ else
+ 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;
+ /* for the first run we don't provide */
+ /* registers for true symbols we will */
+ /* see how things go */
+ sym->nRegs = 0;
}
}
for (i = 0; i < ds390_nRegs; i++)
regs390[i].isFree = 1;
+
+ for (i = B0_IDX; i < ds390_nBitRegs; i++)
+ regs390[i].isFree = 1;
}
/*-----------------------------------------------------------------*/
symbol on the right */
for (dic = ic->prev; dic; dic = dic->prev)
{
-
/* if the definition is a call then no */
if ((dic->op == CALL || dic->op == PCALL) &&
- IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
- {
- return NULL;
- }
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ {
+ return NULL;
+ }
/* if shift by unknown amount then not */
if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
- IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
- return NULL;
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ return NULL;
/* if pointer get and size > 1 */
if (POINTER_GET (dic) &&
- getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
- return NULL;
+ getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
+ return NULL;
if (POINTER_SET (dic) &&
- getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
- return NULL;
+ getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
+ return NULL;
- /* if any three is a true symbol in far space */
+ /* if any tree is a true symbol in far space */
if (IC_RESULT (dic) &&
- IS_TRUE_SYMOP (IC_RESULT (dic)) &&
- isOperandInFarSpace (IC_RESULT (dic)))
- return NULL;
+ IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+ isOperandInFarSpace (IC_RESULT (dic)))
+ return NULL;
if (IC_RIGHT (dic) &&
- IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
- isOperandInFarSpace (IC_RIGHT (dic)) &&
- !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
- return NULL;
+ IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
+ isOperandInFarSpace (IC_RIGHT (dic)) &&
+ !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
+ return NULL;
if (IC_LEFT (dic) &&
- IS_TRUE_SYMOP (IC_LEFT (dic)) &&
- isOperandInFarSpace (IC_LEFT (dic)) &&
- !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
- return NULL;
+ IS_TRUE_SYMOP (IC_LEFT (dic)) &&
+ isOperandInFarSpace (IC_LEFT (dic)) &&
+ !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
+ return NULL;
if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
- {
- if ((dic->op == LEFT_OP ||
- dic->op == RIGHT_OP ||
- dic->op == '-') &&
- IS_OP_LITERAL (IC_RIGHT (dic)))
- return NULL;
- else
- return dic;
- }
+ {
+ if ((dic->op == LEFT_OP ||
+ dic->op == RIGHT_OP ||
+ dic->op == '-') &&
+ IS_OP_LITERAL (IC_RIGHT (dic)))
+ return NULL;
+ else
+ return dic;
+ }
}
return NULL;
if (isOperandInFarSpace (IC_RESULT (ic)))
{
if ((dic = farSpacePackable (ic)))
- goto pack;
+ goto pack;
else
- return 0;
+ return 0;
}
#else
if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic)) {
}
#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
+ /* 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 then don't pack it */
if ((dic->op == CALL || dic->op == PCALL))
- {
- dic = NULL;
- break;
- }
+ {
+ dic = NULL;
+ break;
+ }
if (SKIP_IC2 (dic))
- continue;
+ continue;
if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
- IS_OP_VOLATILE (IC_RESULT (dic)))
- {
- dic = NULL;
- break;
- }
+ IS_OP_VOLATILE (IC_RESULT (dic)))
+ {
+ dic = NULL;
+ break;
+ }
if (IS_SYMOP (IC_RESULT (dic)) &&
- IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
- {
- if (POINTER_SET (dic))
- dic = NULL;
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ {
+ if (POINTER_SET (dic))
+ dic = NULL;
- break;
- }
+ break;
+ }
if (IS_SYMOP (IC_RIGHT (dic)) &&
- (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
- IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
- {
- dic = NULL;
- break;
- }
+ (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;
- }
+ (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+ IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+ {
+ dic = NULL;
+ break;
+ }
if (POINTER_SET (dic) &&
- IC_RESULT (dic)->key == IC_RESULT (ic)->key)
- {
- dic = NULL;
- break;
- }
+ IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+ {
+ dic = NULL;
+ break;
+ }
}
if (!dic)
- return 0; /* did not find */
+ return 0; /* did not find */
+ /* if assignment then check that right is not a bit */
+ if (ASSIGNMENT (ic) && !POINTER_SET (ic))
+ {
+ sym_link *etype = operandType (IC_RESULT (dic));
+ if (IS_BITFIELD (etype))
+ {
+ /* if result is a bit too then it's ok */
+ etype = operandType (IC_RESULT (ic));
+ if (!IS_BITFIELD (etype))
+ {
+ return 0;
+ }
+ }
+ }
/* 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 ||
/* 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;
+ (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;
+ 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 */
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 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);
+ bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
}
remiCodeFromeBBlock (ebp, ic);
bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
- OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
return 1;
-
}
-/*-----------------------------------------------------------------*/
+/*------------------------------------------------------------------*/
/* findAssignToSym : scanning backwards looks for first assig found */
-/*-----------------------------------------------------------------*/
+/*------------------------------------------------------------------*/
static iCode *
findAssignToSym (operand * op, iCode * ic)
{
iCode *dic;
+ /* This routine is used to find sequences like
+ iTempAA = FOO;
+ ...; (intervening ops don't use iTempAA or modify FOO)
+ blah = blah + iTempAA;
+
+ and eliminate the use of iTempAA, freeing up its register for
+ other uses.
+ */
+
for (dic = ic->prev; dic; dic = dic->prev)
{
/* if definition by assignment */
if (dic->op == '=' &&
- !POINTER_SET (dic) &&
- IC_RESULT (dic)->key == op->key
+ !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 + & - */
+ /* we are interested only if defined in far space */
+ /* or in stack space in case of + & - */
- /* if assigned to a non-symbol then return
- FALSE */
- if (!IS_SYMOP (IC_RIGHT (dic)))
- return NULL;
+ /* if assigned to a non-symbol then return
+ FALSE */
+ if (!IS_SYMOP (IC_RIGHT (dic)))
+ return NULL;
- /* if the symbol is in far space then
- we should not */
- if (isOperandInFarSpace (IC_RIGHT (dic)))
- return NULL;
+ /* 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)
- {
+ /* 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;
- }
+ 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;
+ break;
- }
+ }
/* if we find an usage then we cannot delete it */
if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
- return NULL;
+ return NULL;
if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
- return NULL;
+ return NULL;
if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
- return NULL;
+ return NULL;
}
/* now make sure that the right side of 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;
+ if (IC_RESULT (sic) &&
+ IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+ return NULL;
}
return dic;
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 */
iCode *sic;
if (!dic)
- goto right;
+ 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);
+ for (sic = dic; sic != ic; sic = sic->next) {
+ bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+ sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key);
+ }
+ wassert(IS_SYMOP(IC_LEFT (ic)));
+ wassert(IS_SYMOP(IC_RIGHT (dic)));
IC_LEFT (ic)->operand.symOperand =
- IC_RIGHT (dic)->operand.symOperand;
+ IC_RIGHT (dic)->operand.symOperand;
+ OP_SYMBOL(IC_LEFT(ic))->liveTo = ic->seq;
IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
remiCodeFromeBBlock (ebp, dic);
iCode *sic;
if (!dic)
- return change;
+ return change;
/* if this is a subtraction & the result
is a true symbol in far space then don't pack */
if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
- {
- sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
- if (IN_FARSPACE (SPEC_OCLS (etype)))
- return change;
- }
+ {
+ sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
+ if (IN_FARSPACE (SPEC_OCLS (etype)))
+ 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);
+ for (sic = dic; sic != ic; sic = sic->next) {
+ bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+ sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key);
+ }
+ wassert(IS_SYMOP(IC_RIGHT (ic)));
+ wassert(IS_SYMOP(IC_RIGHT (dic)));
IC_RIGHT (ic)->operand.symOperand =
- IC_RIGHT (dic)->operand.symOperand;
+ IC_RIGHT (dic)->operand.symOperand;
IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
-
+ OP_SYMBOL(IC_RIGHT(ic))->liveTo = ic->seq;
remiCodeFromeBBlock (ebp, dic);
bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
return change;
}
-#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
+/*-----------------------------------------------------------------*/
+/* packRegsDPTRnuse - color live ranges that can go into extra DPTRS */
+/*-----------------------------------------------------------------*/
+static int packRegsDPTRnuse( operand *op , unsigned dptr)
+{
+ int i,key;
+ iCode *ic;
+
+ if (!IS_SYMOP(op) || !IS_ITEMP(op)) return 0;
+ if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly || OP_SYMBOL(op)->dptr)
+ return 0;
+
+ /* first check if any overlapping liverange has already been
+ assigned to this DPTR */
+ if (OP_SYMBOL(op)->clashes) {
+ for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) {
+ symbol *sym;
+ if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) {
+ sym = hTabItemWithKey(liveRanges,i);
+ if (sym->dptr == dptr) return 0;
+ }
+ }
+ }
+
+ /* future for more dptrs */
+ if (dptr > 1) {
+ OP_SYMBOL(op)->dptr = dptr;
+ return 1;
+ }
+
+ /* DPTR1 is special since it is also used as a scratch by the backend .
+ so we walk thru the entire live range of this operand and make sure
+ DPTR1 will not be used by the backed . The logic here is to find out if
+ more than one operand in an icode is in far space then we give up : we
+ don't keep it live across functions for now
+ */
+
+ ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
+ for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
+ ic = hTabNextItem(iCodeSeqhTab,&key)) {
+ int nfs =0;
+
+ if (ic->op == CALL || ic->op == PCALL) return 0;
+
+ /* single operand icode are ok */
+ if (ic->op == IFX || ic->op == IPUSH)
+ continue ;
+
+ if (ic->op == SEND ) {
+ if (ic->argreg != 1 ) return 0;
+ else continue ;
+ }
+ /* two special cases first */
+ if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op) && /* pointer get */
+ !OP_SYMBOL(IC_LEFT(ic))->ruonly && /* with result in far space */
+ (isOperandInFarSpace(IC_RESULT(ic)) &&
+ !isOperandInReg(IC_RESULT(ic)))) {
+ return 0;
+ }
+
+ if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) && /* pointer set */
+ !OP_SYMBOL(IC_RESULT(ic))->ruonly && /* with right in far space */
+ (isOperandInFarSpace(IC_RIGHT(ic)) &&
+ !isOperandInReg(IC_RIGHT(ic)))) {
+ return 0;
+ }
+
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) && /* if symbol operand */
+ !isOperandEqual(IC_RESULT(ic),op) && /* not the same as this */
+ ((isOperandInFarSpace(IC_RESULT(ic)) || /* in farspace or */
+ OP_SYMBOL(IC_RESULT(ic))->onStack) && /* on the stack */
+ !isOperandInReg(IC_RESULT(ic)))) { /* and not in register */
+ nfs++;
+ }
+ /* same for left */
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) && /* if symbol operand */
+ !isOperandEqual(IC_LEFT(ic),op) && /* not the same as this */
+ ((isOperandInFarSpace(IC_LEFT(ic)) || /* in farspace or */
+ OP_SYMBOL(IC_LEFT(ic))->onStack) && /* on the stack */
+ !isOperandInReg(IC_LEFT(ic)))) { /* and not in register */
+ nfs++;
+ }
+ /* same for right */
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) && /* if symbol operand */
+ !isOperandEqual(IC_RIGHT(ic),op) && /* not the same as this */
+ ((isOperandInFarSpace(IC_RIGHT(ic)) || /* in farspace or */
+ OP_SYMBOL(IC_RIGHT(ic))->onStack) && /* on the stack */
+ !isOperandInReg(IC_RIGHT(ic)))) { /* and not in register */
+ nfs++;
+ }
+
+ // Check that no other ops in this range have been assigned to dptr1.
+ // I don't understand why this is not caught by the first check, above.
+ // But it isn't always, see bug 769624.
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ (OP_SYMBOL(IC_RESULT(ic))->dptr == 1))
+ {
+ //fprintf(stderr, "dptr1 already in use in live range #1\n");
+ return 0;
+ }
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+ (OP_SYMBOL(IC_LEFT(ic))->dptr == 1))
+ {
+ //fprintf(stderr, "dptr1 already in use in live range # 2\n");
+ return 0;
+ }
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+ (OP_SYMBOL(IC_RIGHT(ic))->dptr == 1))
+ {
+ //fprintf(stderr, "dptr1 already in use in live range # 3\n");
+ return 0;
+ }
+
+ if (nfs && IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ OP_SYMBOL(IC_RESULT(ic))->ruonly) return 0;
+
+ if (nfs > 1) return 0;
+ }
+ OP_SYMBOL(op)->dptr = dptr;
+ return 1;
+}
/*-----------------------------------------------------------------*/
/* packRegsDPTRuse : - will reduce some registers for single Use */
/*-----------------------------------------------------------------*/
static iCode *
-packRegsDPTRuse (iCode * lic, operand * op, eBBlock * ebp)
+packRegsDPTRuse (operand * op)
{
/* go thru entire liveRange of this variable & check for
other possible usage of DPTR , if we don't find it the
symbol *sym;
iCode *ic, *dic;
sym_link *type, *etype;
-
+
if (!IS_SYMOP(op) || !IS_ITEMP(op)) return NULL;
- if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly) return NULL;
+ if (OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly) 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->ruonly) return NULL ;
- }
- }
+ for (i = 0 ; i < OP_SYMBOL(op)->clashes->size ; i++ ) {
+ if (bitVectBitValue(OP_SYMBOL(op)->clashes,i)) {
+ sym = hTabItemWithKey(liveRanges,i);
+ if (sym->ruonly) return NULL ;
+ }
+ }
}
/* no then go thru this guys live range */
dic = ic = hTabFirstItemWK(iCodeSeqhTab,OP_SYMBOL(op)->liveFrom);
for (; ic && ic->seq <= OP_SYMBOL(op)->liveTo;
- ic = hTabNextItem(iCodeSeqhTab,&key)) {
-
- if (SKIP_IC3(ic)) continue;
-
- /* if PCALL cannot be sure give up */
- if (ic->op == PCALL) return NULL;
-
- /* if CALL then make sure it is VOID || return value not used */
- if (ic->op == CALL) {
- if (OP_SYMBOL(IC_RESULT(ic))->liveTo ==
- OP_SYMBOL(IC_RESULT(ic))->liveFrom) continue ;
- etype = getSpec(type = operandType(IC_RESULT(ic)));
- if (getSize(type) == 0) continue ;
- return NULL ;
- }
-
- /* special case of add with a [remat] */
- if (ic->op == '+' &&
- OP_SYMBOL(IC_LEFT(ic))->remat &&
- !isOperandInFarSpace(IC_RIGHT(ic))) continue ;
-
- /* special case */
- /* pointerGet */
- if (POINTER_GET(ic) && isOperandEqual(IC_RESULT(ic),op) &&
- getSize(operandType(IC_LEFT(ic))) > 1) return NULL ;
-
- if (POINTER_SET(ic) && isOperandEqual(IC_RIGHT(ic),op) &&
- getSize(operandType(IC_RESULT(ic))) > 1) return NULL;
-
- /* general case */
- if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
- !isOperandEqual(IC_RESULT(ic),op) &&
- (isOperandInFarSpace(IC_RESULT(ic)) ||
- OP_SYMBOL(IC_RESULT(ic))->ruonly ||
- OP_SYMBOL(IC_RESULT(ic))->onStack)) return NULL;
-
- if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
- !isOperandEqual(IC_RIGHT(ic),op) &&
- (OP_SYMBOL(IC_RIGHT(ic))->liveTo > ic->seq ||
- IS_TRUE_SYMOP(IC_RIGHT(ic)) ||
- OP_SYMBOL(IC_RIGHT(ic))->ruonly) &&
- (isOperandInFarSpace(IC_RIGHT(ic)) ||
- OP_SYMBOL(IC_RIGHT(ic))->onStack)) return NULL;
-
- if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
- !isOperandEqual(IC_LEFT(ic),op) &&
- (OP_SYMBOL(IC_LEFT(ic))->liveTo > ic->seq ||
- IS_TRUE_SYMOP(IC_LEFT(ic)) ||
- OP_SYMBOL(IC_LEFT(ic))->ruonly) &&
- (isOperandInFarSpace(IC_LEFT(ic)) ||
- OP_SYMBOL(IC_LEFT(ic))->onStack)) return NULL;
-
- if (IC_LEFT(ic) && IC_RIGHT(ic) &&
- IS_ITEMP(IC_LEFT(ic)) && IS_ITEMP(IC_RIGHT(ic)) &&
- isOperandInFarSpace(IC_LEFT(ic)) && isOperandInFarSpace(IC_RIGHT(ic)))
- return NULL;
+ ic = hTabNextItem(iCodeSeqhTab,&key)) {
+
+ if (SKIP_IC3(ic)) continue;
+
+ /* if PCALL cannot be sure give up */
+ if (ic->op == PCALL) return NULL;
+
+ /* if SEND & not the first parameter then giveup */
+ if (ic->op == SEND && ic->argreg != 1 &&
+ ((isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic))) ||
+ isOperandEqual(op,IC_LEFT(ic)))) return NULL;
+
+ /* if CALL then make sure it is VOID || return value not used
+ or the return value is assigned to this one */
+ if (ic->op == CALL) {
+ if (OP_SYMBOL(IC_RESULT(ic))->liveTo ==
+ OP_SYMBOL(IC_RESULT(ic))->liveFrom) continue ;
+ etype = getSpec(type = operandType(IC_RESULT(ic)));
+ if (getSize(type) == 0 || isOperandEqual(op,IC_RESULT(ic)))
+ continue ;
+ return NULL ;
+ }
+
+ /* special case of add with a [remat] */
+ if (ic->op == '+' &&
+ OP_SYMBOL(IC_LEFT(ic))->remat &&
+ (isOperandInFarSpace(IC_RIGHT(ic)) &&
+ !isOperandInReg(IC_RIGHT(ic)))) return NULL ;
+
+ /* special cases */
+ /* pointerGet */
+ if (POINTER_GET(ic) && !isOperandEqual(IC_LEFT(ic),op) &&
+ getSize(operandType(IC_LEFT(ic))) > 1 ) return NULL ;
+
+ /* pointerSet */
+ if (POINTER_SET(ic) && !isOperandEqual(IC_RESULT(ic),op) &&
+ getSize(operandType(IC_RESULT(ic))) > 1 ) return NULL;
+
+ /* conditionals can destroy 'b' - make sure B wont
+ be used in this one*/
+ if ((IS_CONDITIONAL(ic) || ic->op == '*' || ic->op == '/' ||
+ ic->op == LEFT_OP || ic->op == RIGHT_OP ) &&
+ getSize(operandType(op)) > 3) return NULL;
+
+ /* if this is a cast to a bigger type */
+ if (ic->op==CAST) {
+ if (!IS_PTR(OP_SYM_TYPE(IC_RESULT(ic))) &&
+ getSize(OP_SYM_TYPE(IC_RESULT(ic))) >
+ getSize(OP_SYM_TYPE(IC_RIGHT(ic)))) {
+ return 0;
+ }
+ }
+
+ /* general case */
+ if (IC_RESULT(ic) && IS_SYMOP(IC_RESULT(ic)) &&
+ !isOperandEqual(IC_RESULT(ic),op) &&
+ ( ( ( isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->onStack) &&
+ !isOperandInReg(IC_RESULT(ic))) ||
+ OP_SYMBOL(IC_RESULT(ic))->ruonly)) return NULL;
+
+ if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+ !isOperandEqual(IC_RIGHT(ic),op) &&
+ (OP_SYMBOL(IC_RIGHT(ic))->liveTo >= ic->seq ||
+ IS_TRUE_SYMOP(IC_RIGHT(ic)) ||
+ OP_SYMBOL(IC_RIGHT(ic))->ruonly) &&
+ ( ( isOperandInFarSpace(IC_RIGHT(ic)) || OP_SYMBOL(IC_RIGHT(ic))->onStack) &&
+ !isOperandInReg(IC_RIGHT(ic))) ) return NULL;
+
+ if (IC_LEFT(ic) && IS_SYMOP(IC_LEFT(ic)) &&
+ !isOperandEqual(IC_LEFT(ic),op) &&
+ (OP_SYMBOL(IC_LEFT(ic))->liveTo >= ic->seq ||
+ IS_TRUE_SYMOP(IC_LEFT(ic)) ||
+ OP_SYMBOL(IC_LEFT(ic))->ruonly) &&
+ ( ( isOperandInFarSpace(IC_LEFT(ic)) || OP_SYMBOL(IC_LEFT(ic))->onStack) &&
+ !isOperandInReg(IC_LEFT(ic))) ) return NULL;
+
+ if (IC_LEFT(ic) && IC_RIGHT(ic) &&
+ IS_ITEMP(IC_LEFT(ic)) && IS_ITEMP(IC_RIGHT(ic)) &&
+ (isOperandInFarSpace(IC_LEFT(ic)) && !isOperandInReg(IC_LEFT(ic))) &&
+ (isOperandInFarSpace(IC_RIGHT(ic)) && !isOperandInReg(IC_RIGHT(ic))))
+ return NULL;
}
OP_SYMBOL(op)->ruonly = 1;
+ if (OP_SYMBOL(op)->usl.spillLoc) {
+ if (OP_SYMBOL(op)->spillA)
+ OP_SYMBOL(op)->usl.spillLoc->allocreq--;
+ OP_SYMBOL(op)->usl.spillLoc = NULL;
+ }
return dic;
}
sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
/* bitwise operations are considered optimizable
- under the following conditions (Jean-Louis VERN)
+ under the following conditions (Jean-Louis VERN)
x & lit
bit & bit
bit | bit
bit | x
*/
- if ( IS_LITERAL (rtype) ||
+ if (IS_LITERAL (rtype) ||
(IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
return TRUE;
else
return;
}
+ /* if we are calling a reentrant function that has stack parameters */
+ if (ic->op == CALL &&
+ IFFUNC_ISREENT(operandType(IC_LEFT(ic))) &&
+ FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))))
+ return;
+
+ if (ic->op == PCALL &&
+ IFFUNC_ISREENT(operandType(IC_LEFT(ic))->next) &&
+ FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))->next))
+ return;
+
/* if + or - then it has to be one byte result */
if ((ic->op == '+' || ic->op == '-')
&& getSize (operandType (IC_RESULT (ic))) > 1)
/* and the usage immediately follows this iCode */
if (!(uic = hTabItemWithKey (iCodehTab,
- bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+ bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
return;
if (ic->next != uic)
uic->op != RIGHT_OP)
return;
- /* if used in ^ operation then make sure right is not a
- literl */
+ /* if used in ^ operation then make sure right is not a
+ literal */
if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
return;
/* make sure that the result of this icode is not on the
stack, since acc is used to compute stack offset */
-#if 0
- if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
- OP_SYMBOL (IC_RESULT (uic))->onStack)
+ if (isOperandOnStack(IC_RESULT(uic)))
return;
-#else
- ifSymbolOnStack(IC_RESULT(uic))
- return;
-#endif
/* if either one of them in far space then we cannot */
if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
IC_LEFT (uic)->key != IC_RESULT (ic)->key)
return;
-#if 0
- // this is too dangerous and need further restrictions
- // see bug #447547
-
- /* 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;
- }
-#endif
-
/* if the other one is not on stack then we can */
if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
(IS_ITEMP (IC_RIGHT (uic)) ||
(IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
- !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
+ !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
goto accuse;
if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
(IS_ITEMP (IC_LEFT (uic)) ||
(IS_TRUE_SYMOP (IC_LEFT (uic)) &&
- !OP_SYMBOL (IC_LEFT (uic))->onStack)))
+ !OP_SYMBOL (IC_LEFT (uic))->onStack)))
goto accuse;
return;
accuse:
OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
-
}
/*-----------------------------------------------------------------*/
-/* packForPush - hueristics to reduce iCode for pushing */
+/* packForPush - heuristics to reduce iCode for pushing */
/*-----------------------------------------------------------------*/
static void
-packForPush (iCode * ic, eBBlock * ebp)
+packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
{
iCode *dic, *lic;
bitVect *dbv;
+ struct eBBlock * ebp = ebpp[blockno];
- if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
+ if ((ic->op != IPUSH && ic->op != SEND) || !IS_ITEMP (IC_LEFT (ic)))
return;
/* must have only definition & one usage */
/* find the definition */
if (!(dic = hTabItemWithKey (iCodehTab,
- bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
+ bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
return;
if (dic->op != '=' || POINTER_SET (dic))
return;
+ if (dic->eBBlockNum != ic->eBBlockNum) return ;
+
/* make sure the right side does not have any definitions
inbetween */
dbv = OP_DEFS(IC_RIGHT(dic));
for (lic = ic; lic && lic != dic ; lic = lic->prev) {
- if (bitVectBitValue(dbv,lic->key)) return ;
+ if (bitVectBitValue (dbv, lic->key))
+ return;
}
/* make sure they have the same type */
+ if (IS_SPEC(operandType(IC_LEFT(ic))))
{
sym_link *itype=operandType(IC_LEFT(ic));
sym_link *ditype=operandType(IC_RIGHT(dic));
if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
- SPEC_LONG(itype)!=SPEC_LONG(ditype))
+ SPEC_LONG(itype)!=SPEC_LONG(ditype))
return;
}
/* extend the live range of replaced operand if needed */
- if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
- OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
+ if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < OP_SYMBOL(IC_LEFT(ic))->liveTo) {
+ OP_SYMBOL(IC_RIGHT(dic))->liveTo = OP_SYMBOL(IC_LEFT(ic))->liveTo;
+ OP_SYMBOL(IC_RIGHT(dic))->clashes =
+ bitVectUnion(OP_SYMBOL(IC_RIGHT(dic))->clashes,
+ OP_SYMBOL(IC_LEFT(ic))->clashes);
}
+ for (lic = ic; lic && lic != dic; lic = lic->prev)
+ {
+ bitVectUnSetBit (lic->rlive, IC_LEFT (ic)->key);
+ if (IS_ITEMP (IC_RIGHT (dic)))
+ bitVectSetBit (lic->rlive, IC_RIGHT (dic)->key);
+ }
/* we now we know that it has one & only one def & use
and the that the definition is an assignment */
IC_LEFT (ic) = IC_RIGHT (dic);
/* pressure */
/*-----------------------------------------------------------------*/
static void
-packRegisters (eBBlock * ebp)
+packRegisters (eBBlock ** ebpp, int blockno)
{
iCode *ic;
int change = 0;
+ eBBlock *ebp = ebpp[blockno];
while (1)
{
-
change = 0;
/* look for assignments of the form */
/* .... */
/* 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);
- }
+ {
+ /* find assignment of the form TrueSym := iTempNN:1 */
+ if (ic->op == '=' && !POINTER_SET (ic))
+ change += packRegsForAssign (ic, ebp);
+ }
if (!change)
- break;
+ break;
}
for (ic = ebp->sch; ic; ic = ic->next)
{
-
- /* if this is an itemp & result of a address of a true sym
+ /* Fix for bug #979599: */
+ /* P0 &= ~1; */
+
+ /* Look for two subsequent iCodes with */
+ /* iTemp := _c; */
+ /* _c = iTemp & op; */
+ /* and replace them by */
+ /* iTemp := _c; */
+ /* _c = _c & op; */
+ if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^') &&
+ ic->prev &&
+ ic->prev->op == '=' &&
+ IS_ITEMP (IC_LEFT (ic)) &&
+ IC_LEFT (ic) == IC_RESULT (ic->prev) &&
+ isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev)))
+ {
+ iCode* ic_prev = ic->prev;
+ symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev));
+
+ ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic));
+ if (IC_RESULT (ic_prev) != IC_RIGHT (ic))
+ {
+ bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key);
+ if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */
+ prev_result_sym->liveTo == ic->seq)
+ {
+ prev_result_sym->liveTo = ic_prev->seq;
+ }
+ }
+ bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
+
+ bitVectSetBit (ic->rlive, IC_RESULT (ic)->key);
+
+ if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev))))
+ {
+ bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key);
+ bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key);
+ remiCodeFromeBBlock (ebp, ic_prev);
+ hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL);
+ }
+ }
+
+ /* if this is an itemp & result of an address of a true sym
then mark this as rematerialisable */
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;
-
- }
+ 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;
+
+ }
+
+ /* if this is an itemp & used as a pointer
+ & assigned to a literal then remat */
+ if (IS_ASSIGN_ICODE(ic) &&
+ IS_ITEMP(IC_RESULT(ic)) &&
+ bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+ isOperandLiteral(IC_RIGHT(ic)))
+ {
+ OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+ OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+ }
/* 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 &&
- !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
- 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;
- }
-
+ !POINTER_SET (ic) &&
+ IS_SYMOP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->remat &&
+ !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
+ !isOperandGlobal(IC_RESULT(ic)) && /* due to bug 1618050 */
+ 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 cast to a generic pointer & the pointer being
- cast is remat, then we can remat this cast as well */
- if (ic->op == CAST &&
- IS_SYMOP(IC_RIGHT(ic)) &&
- OP_SYMBOL(IC_RIGHT(ic))->remat ) {
- sym_link *to_type = operandType(IC_LEFT(ic));
- sym_link *from_type = operandType(IC_RIGHT(ic));
- if (IS_GENPTR(to_type) && IS_PTR(from_type)) {
- OP_SYMBOL (IC_RESULT (ic))->remat = 1;
- OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
- OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
- }
+ cast is remat, then we can remat this cast as well */
+ if (ic->op == CAST &&
+ IS_SYMOP(IC_RIGHT(ic)) &&
+ !OP_SYMBOL(IC_RESULT(ic))->isreqv &&
+ OP_SYMBOL(IC_RIGHT(ic))->remat )
+ {
+ sym_link *to_type = operandType(IC_LEFT(ic));
+ sym_link *from_type = operandType(IC_RIGHT(ic));
+ if (IS_GENPTR(to_type) && IS_PTR(from_type))
+ {
+ OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+ OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+ }
}
- /* if this is a +/- operation with a rematerizable
+ /* if this is a +/- operation with a rematerizable
then mark this as rematerializable as well */
if ((ic->op == '+' || ic->op == '-') &&
- (IS_SYMOP (IC_LEFT (ic)) &&
- IS_ITEMP (IC_RESULT (ic)) &&
- OP_SYMBOL (IC_LEFT (ic))->remat &&
- (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
- bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
- IS_OP_LITERAL (IC_RIGHT (ic))))
- {
-
- //int i = operandLitValue(IC_RIGHT(ic));
- OP_SYMBOL (IC_RESULT (ic))->remat = 1;
- OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
- OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
- }
+ (IS_SYMOP (IC_LEFT (ic)) &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->remat &&
+ (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
+ bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+ IS_OP_LITERAL (IC_RIGHT (ic))))
+ {
+
+ //int i = operandLitValue(IC_RIGHT(ic));
+ OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+ OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+ }
/* mark the pointer usages */
- if (POINTER_SET (ic))
- OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
+ if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic)))
+ OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
+
+ if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic)))
+ OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+
+ if (ic->op == RETURN && IS_SYMOP (IC_LEFT(ic)))
+ OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+
+ if (ic->op == RECEIVE && ic->argreg == 1 &&
+ IS_SYMOP (IC_RESULT (ic)) &&
+ getSize (operandType(IC_RESULT(ic))) <= 3)
+ OP_SYMBOL (IC_RESULT(ic))->uptr = 1;
- if (POINTER_GET (ic))
- OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+ if (ic->op == SEND && ic->argreg == 1 &&
+ IS_SYMOP(IC_LEFT(ic)) &&
+ getSize (aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) <= 3)
+ OP_SYMBOL (IC_LEFT(ic))->uptr = 1;
if (!SKIP_IC2 (ic))
- {
- /* if we are using a symbol on the stack
- then we should say ds390_ptrRegReq */
- if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
- ds390_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ? !options.stack10bit : 0) +
- OP_SYMBOL (IC_COND (ic))->iaccess);
- else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
- ds390_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ? !options.stack10bit : 0) +
- OP_SYMBOL (IC_JTCOND (ic))->iaccess);
- else
- {
- if (IS_SYMOP (IC_LEFT (ic)))
- ds390_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ? !options.stack10bit : 0) +
- OP_SYMBOL (IC_LEFT (ic))->iaccess);
- if (IS_SYMOP (IC_RIGHT (ic)))
- ds390_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ? !options.stack10bit : 0) +
- OP_SYMBOL (IC_RIGHT (ic))->iaccess);
- if (IS_SYMOP (IC_RESULT (ic)))
- ds390_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ? !options.stack10bit : 0) +
- OP_SYMBOL (IC_RESULT (ic))->iaccess);
- }
- }
+ {
+ /* if we are using a symbol on the stack
+ then we should say ds390_ptrRegReq */
+ if (options.useXstack && ic->parmPush
+ && (ic->op == IPUSH || ic->op == IPOP))
+ ds390_ptrRegReq++;
+ if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
+ ds390_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ? !options.stack10bit : 0) +
+ OP_SYMBOL (IC_COND (ic))->iaccess +
+ (SPEC_OCLS(OP_SYMBOL (IC_COND (ic))->etype) == idata));
+ else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
+ ds390_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ? !options.stack10bit : 0) +
+ OP_SYMBOL (IC_JTCOND (ic))->iaccess +
+ (SPEC_OCLS(OP_SYMBOL (IC_JTCOND (ic))->etype) == idata));
+ else
+ {
+ if (IS_SYMOP (IC_LEFT (ic)))
+ ds390_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ? !options.stack10bit : 0) +
+ OP_SYMBOL (IC_LEFT (ic))->iaccess +
+ (SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata));
+ if (IS_SYMOP (IC_RIGHT (ic)))
+ ds390_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ? !options.stack10bit : 0) +
+ OP_SYMBOL (IC_RIGHT (ic))->iaccess +
+ (SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata));
+ if (IS_SYMOP (IC_RESULT (ic)))
+ ds390_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ? !options.stack10bit : 0) +
+ OP_SYMBOL (IC_RESULT (ic))->iaccess +
+ (SPEC_OCLS(OP_SYMBOL (IC_RESULT (ic))->etype) == idata));
+ }
+ }
-#if 0
- /* if the condition of an if instruction
- is defined in the previous instruction then
- mark the itemp as a conditional */
- if ((IS_CONDITIONAL (ic) ||
- (IS_BITWISE_OP(ic) && 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;
- }
-#else
/* if the condition of an if instruction
is defined in the previous instruction and
- this is the only usage then
+ this is the only usage then
mark the itemp as a conditional */
if ((IS_CONDITIONAL (ic) ||
- (IS_BITWISE_OP(ic) && 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;
- }
-#endif
-
+ (IS_BITWISE_OP(ic) && 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 1
/* reduce for support function calls */
if (ic->supportRtn || ic->op == '+' || ic->op == '-')
- packRegsForSupport (ic, ebp);
-
+ packRegsForSupport (ic, ebp);
+#endif
/* 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) {
-
- packRegsDPTRuse (ic, IC_LEFT (ic), ebp);
+ can be eliminated for return statements . Can be elminated for the first SEND */
+ if ((ic->op == RETURN ||
+ ((ic->op == SEND || ic->op == RECEIVE)&& ic->argreg == 1)) &&
+ !isOperandInFarSpace (IC_LEFT (ic)) &&
+ !options.model) {
+
+ packRegsDPTRuse (IC_LEFT (ic));
}
- if ((ic->op == CALL && getSize(operandType(IC_RESULT(ic))) <= 4)) {
- packRegsDPTRuse (ic, IC_RESULT (ic), ebp);
+ if (ic->op == CALL) {
+ sym_link *ftype = operandType(IC_LEFT(ic));
+ if (getSize(operandType(IC_RESULT(ic))) <= 4 &&
+ !IFFUNC_ISBUILTIN(ftype)) {
+ packRegsDPTRuse (IC_RESULT (ic));
+ }
}
/* if pointer set & left has a size more than
one and right is not in far space */
if (POINTER_SET (ic) &&
- !isOperandInFarSpace (IC_RIGHT (ic)) &&
- !OP_SYMBOL (IC_RESULT (ic))->remat &&
- !IS_OP_RUONLY (IC_RIGHT (ic)) &&
- getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) {
-
- packRegsDPTRuse (ic, IC_RESULT (ic), ebp);
+ !isOperandInFarSpace (IC_RIGHT (ic)) &&
+ IS_SYMOP (IC_RESULT (ic)) &&
+ !OP_SYMBOL (IC_RESULT (ic))->remat &&
+ !IS_OP_RUONLY (IC_RIGHT (ic)) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) {
+
+ packRegsDPTRuse (IC_RESULT (ic));
}
/* if pointer get */
if (POINTER_GET (ic) &&
- !isOperandInFarSpace (IC_RESULT (ic)) &&
- !OP_SYMBOL (IC_LEFT (ic))->remat &&
- !IS_OP_RUONLY (IC_RESULT (ic)) &&
- getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) {
+ !isOperandInFarSpace (IC_RESULT (ic)) &&
+ IS_SYMOP (IC_LEFT (ic)) &&
+ !OP_SYMBOL (IC_LEFT (ic))->remat &&
+ !IS_OP_RUONLY (IC_RESULT (ic)) &&
+ getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1) {
- packRegsDPTRuse (ic, IC_LEFT (ic), ebp);
+ packRegsDPTRuse (IC_LEFT (ic));
}
- /* if this is cast for intergral promotion then
- check if only use of the definition of the
+ /* if this is a cast for intergral promotion then
+ check if it's the only use of the definition of the
operand being casted/ if yes then replace
- the result of that arithmetic operation with
+ the result of that arithmetic operation with
this result and get rid of the cast */
if (ic->op == CAST)
- {
- sym_link *fromType = operandType (IC_RIGHT (ic));
- sym_link *toType = operandType (IC_LEFT (ic));
-
- if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
- getSize (fromType) != getSize (toType) &&
- SPEC_USIGN (fromType) == SPEC_USIGN (toType))
- {
-
- iCode *dic = packRegsDPTRuse (ic, IC_RIGHT (ic), ebp);
- if (dic)
- {
- if (IS_ARITHMETIC_OP (dic))
- {
- bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
- IC_RESULT (dic) = IC_RESULT (ic);
- remiCodeFromeBBlock (ebp, ic);
- bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
- hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
- OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
- ic = ic->prev;
- }
- else
- OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
- }
- }
- else
- {
-
- /* if the type from and type to are the same
- then if this is the only use then packit */
- if (compareType (operandType (IC_RIGHT (ic)),
- operandType (IC_LEFT (ic))) == 1)
- {
- iCode *dic = packRegsDPTRuse (ic, IC_RIGHT (ic), ebp);
- if (dic)
- {
- bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
- IC_RESULT (dic) = IC_RESULT (ic);
- remiCodeFromeBBlock (ebp, ic);
- bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
- hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
- OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
- ic = ic->prev;
- }
- }
- }
- }
-
- /* pack for PUSH
+ {
+ sym_link *fromType = operandType (IC_RIGHT (ic));
+ sym_link *toType = operandType (IC_LEFT (ic));
+
+ if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
+ getSize (fromType) != getSize (toType) &&
+ SPEC_USIGN (fromType) == SPEC_USIGN (toType))
+ {
+
+ iCode *dic = packRegsDPTRuse (IC_RIGHT (ic));
+ if (dic)
+ {
+ if (IS_ARITHMETIC_OP (dic))
+ {
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ IC_RESULT (dic) = IC_RESULT (ic);
+ remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+ OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ ic = ic->prev;
+ }
+ else
+ OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
+ }
+ }
+ else
+ {
+
+ /* if the type from and type to are the same
+ then if this is the only use then packit */
+ if (compareType (operandType (IC_RIGHT (ic)),
+ operandType (IC_LEFT (ic))) == 1)
+ {
+ iCode *dic = packRegsDPTRuse (IC_RIGHT (ic));
+ if (dic)
+ {
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ IC_RESULT (dic) = IC_RESULT (ic);
+ remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+ OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ ic = ic->prev;
+ }
+ }
+ }
+ }
+
+ /* pack for PUSH
iTempNN := (some variable in farspace) V1
push iTempNN ;
-------------
push V1
*/
- if (ic->op == IPUSH)
- {
- packForPush (ic, ebp);
- }
+ if (ic->op == IPUSH || ic->op == SEND)
+ {
+ packForPush (ic, ebpp, blockno);
+ }
/* pack registers for accumulator use, when the
we can leave the result of this operation in acc:b
combination */
if ((IS_ARITHMETIC_OP (ic)
- || IS_CONDITIONAL(ic)
- || IS_BITWISE_OP (ic)
- || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL
- || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic)))
- ) &&
- IS_ITEMP (IC_RESULT (ic)) &&
- getSize (operandType (IC_RESULT (ic))) <= 2)
-
- packRegsForAccUse (ic);
-
+ || IS_CONDITIONAL(ic)
+ || IS_BITWISE_OP (ic)
+ || ic->op == LEFT_OP || ic->op == RIGHT_OP
+ || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic)))
+ ) &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ getSize (operandType (IC_RESULT (ic))) <= 2)
+
+ packRegsForAccUse (ic);
}
}
/* assignRegisters - assigns registers to each live range as need */
/*-----------------------------------------------------------------*/
void
-ds390_assignRegisters (eBBlock ** ebbs, int count)
+ds390_assignRegisters (ebbIndex * ebbi)
{
+ eBBlock ** ebbs = ebbi->bbOrder;
+ int count = ebbi->count;
iCode *ic;
int i;
- setToNull ((void *) &_G.funcrUsed);
- setToNull ((void *) &_G.regAssigned);
- setToNull ((void *) &_G.totRegAssigned);
- setToNull ((void *) &_G.funcrUsed);
+ setToNull ((void *) &_G.funcrUsed);
+ setToNull ((void *) &_G.regAssigned);
+ setToNull ((void *) &_G.totRegAssigned);
+ setToNull ((void *) &_G.funcrUsed);
ds390_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
- ds390_nRegs = 18;
- if (options.model != MODEL_FLAT24) options.stack10bit = 0;
+ if ((currFunc && IFFUNC_ISREENT (currFunc->type)) || options.stackAuto)
+ {
+ ds390_nBitRegs = 8;
+ }
+ else
+ {
+ ds390_nBitRegs = 0;
+ }
+ ds390_nRegs = 12 + ds390_nBitRegs;
+ _G.allBitregs = findAllBitregs ();
+
+ if (options.model != MODEL_FLAT24)
+ options.stack10bit = 0;
/* change assignments this will remove some
live ranges reducing some register pressure */
for (i = 0; i < count; i++)
- packRegisters (ebbs[i]);
+ packRegisters (ebbs, i);
+
+ /* liveranges probably changed by register packing
+ so we compute them again */
+ recomputeLiveRanges (ebbs, count);
if (options.dump_pack)
- dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
+ dumpEbbsToFileExt (DUMP_PACK, ebbi);
- /* first determine for each live range the number of
+ /* first determine for each live range the number of
registers & the type of registers required for each */
regTypeNum ();
ds390_nRegs = 8;
freeAllRegs ();
fillGaps();
- ds390_nRegs = 18;
+ ds390_nRegs = 12 + ds390_nBitRegs;
/* if stack was extended then tell the user */
if (_G.stackExtend)
createRegMask (ebbs, count);
/* redo that offsets for stacked automatic variables */
- redoStackOffsets ();
+ if (currFunc)
+ redoStackOffsets ();
+
+ /* make sure r0 & r1 are flagged as used if they might be used */
+ /* as pointers */
+ if (currFunc && ds390_ptrRegReq)
+ {
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R0_IDX);
+ currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R1_IDX);
+ }
- if (options.dump_rassgn) {
- dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+ if (options.dump_rassgn)
+ {
+ dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
dumpLiveRanges (DUMP_LRANGE, liveRanges);
}
/* now get back the chain */
ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
-
gen390Code (ic);
/* free up any _G.stackSpil locations allocated */
applyToSet (_G.stackSpil, deallocStackSpil);
_G.slocNum = 0;
- setToNull ((void **) &_G.stackSpil);
- setToNull ((void **) &_G.spiltSet);
+ setToNull ((void *) &_G.stackSpil);
+ setToNull ((void *) &_G.spiltSet);
/* mark all registers as free */
ds390_nRegs = 8;
freeAllRegs ();