#define STRCASECMP strcasecmp
#endif
+#ifndef debugf
+#define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest)
+#endif
+void _debugf(char *f, int l, char *frm, ...);
+
+#define NEWREG_DEBUG 0
//#define USE_ONSTACK
* are used to pass and return parameters */
-
+int _inRegAllocator=0; /* flag that marks whther allocReg happens while
+ * inside the register allocator function */
+
static void spillThis (symbol *);
int pic16_ralloc_debug = 0;
vsprintf (buffer, fmt, ap);
fprintf (debugF, "%s", buffer);
+ //fprintf (stderr, "%s", buffer);
/*
- while (isspace(*bufferP)) bufferP++;
+ while (isspace((unsigned char)*bufferP)) bufferP++;
if (bufferP && *bufferP)
lineCurr = (lineCurr ?
static void
debugNewLine (void)
{
- if(!pic16_ralloc_debug)return;
-
- if (debugF)
- fputc ('\n', debugF);
+ if(!pic16_ralloc_debug)return;
+
+ if (debugF)
+ fputc ('\n', debugF);
}
/*-----------------------------------------------------------------*/
/* debugLogClose - closes the debug log file (if opened) */
static void
debugLogClose (void)
{
- if (debugF) {
- fclose (debugF);
- debugF = NULL;
- }
+ if (debugF) {
+ fclose (debugF);
+ debugF = NULL;
+ }
}
#define AOP(op) op->aop
return NULL;
}
-static char *
-decodeOp (unsigned int op)
+char *
+pic16_decodeOp (unsigned int op)
{
if (op < 128 && op > ' ') {
buffer[0] = (op & 0xff);
case IPUSH: return "IPUSH";
case IPOP: return "IPOP";
case PCALL: return "PCALL";
+ case FUNCTION: return "FUNCTION";
case ENDFUNCTION: return "ENDFUNCTION";
case JUMPTABLE: return "JUMPTABLE";
case RRC: return "RRC";
case LABEL: return "LABEL";
case RECEIVE: return "RECEIVE";
case SEND: return "SEND";
+ case DUMMY_READ_VOLATILE: return "DUMMY_READ_VOLATILE";
}
sprintf (buffer, "unkown op %d %c", op, op & 0xff);
return buffer;
}
+
+#if 0
+static char *decodeRegType(short type)
+{
+ switch(type) {
+ case REG_GPR: return "REG_GPR";
+ case REG_PTR: return "REG_PTR";
+ case REG_CND: return "REG_CNT";
+
+ default:
+ return "<unknown>";
+ }
+}
+#endif
+
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static char *
/*-----------------------------------------------------------------*/
/* newReg - allocate and init memory for a new register */
/*-----------------------------------------------------------------*/
-regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop)
+regs* newReg(int type, short pc_type, int rIdx, char *name, unsigned size, int alias, operand *refop)
{
regs *dReg;
if(name)
dReg->name = Safe_strdup(name);
else {
- sprintf(buffer,"r0x%02X", dReg->rIdx);
- if(type == REG_STK)
- *buffer = 's';
- dReg->name = Safe_strdup(buffer);
+ if(xinst && pc_type == PO_GPR_TEMP) {
+ sprintf(buffer,"0x%02x", dReg->rIdx);
+ } else {
+ sprintf(buffer,"r0x%02x", dReg->rIdx);
+ }
+
+ if(type == REG_STK) {
+ *buffer = 's';
+ }
+ dReg->name = Safe_strdup(buffer);
}
dReg->accessBank = 0;
}
-// fprintf(stderr,"newReg: %s, rIdx = 0x%02x\taccess= %d\tregop= %p\n",dReg->name,rIdx, dReg->accessBank, refop);
-
+#if NEWREG_DEBUG
+ fprintf(stderr,"newReg @ %p: %s, rIdx = 0x%02x\taccess= %d\tregop= %p\n",dReg, dReg->name,rIdx, dReg->accessBank, refop);
+#endif
dReg->size = size;
dReg->alias = alias;
dReg->reg_alias = NULL;
dReg->regop = refop;
if(!(type == REG_SFR && alias == 0x80))
- hTabAddItem(&dynDirectRegNames, regname2key(name), dReg);
+ hTabAddItem(&dynDirectRegNames, regname2key(dReg->name), dReg);
return dReg;
}
{
regs *dReg;
+//#define D(text) text
+#define D(text)
+
for (dReg = setFirstItem(dRegs) ; dReg ;
dReg = setNextItem(dRegs)) {
+ D(fprintf(stderr, "%s:%d testing reg w/rIdx = %d (%d f:%d)\t", __FUNCTION__, __LINE__, dReg->rIdx, idx, fixed));
if(idx == dReg->rIdx && (fixed == dReg->isFixed)) {
+ D(fprintf(stderr, "found!\n"));
return dReg;
- }
+ } else
+ D(fprintf(stderr, "not found!\n"));
}
return NULL;
// __FILE__, __LINE__, dReg->name, dReg, dReg->rIdx, dReg->isFree);
if(dReg->isFree) {
+// fprintf(stderr, "%s:%d free register found, rIdx = %d\n", __FILE__, __LINE__, dReg->rIdx);
+
return dReg;
}
}
return NULL;
}
+
+static regs *
+regFindFreeNext(set *dRegs, regs *creg)
+{
+ regs *dReg;
+
+ if(creg) {
+ /* position at current register */
+ for(dReg = setFirstItem(dRegs); dReg != creg; dReg = setNextItem(dRegs));
+ }
+
+ for(dReg = setNextItem(dRegs); dReg; dReg = setNextItem(dRegs)) {
+ if(dReg->isFree) {
+ return dReg;
+ }
+ }
+
+ return NULL;
+}
+
/*-----------------------------------------------------------------*/
/* pic16_initStack - allocate registers for a pseudo stack */
/*-----------------------------------------------------------------*/
return NULL;
}
+
+
/*-----------------------------------------------------------------*/
/* allocReg - allocates register of given type */
/*-----------------------------------------------------------------*/
{
regs * reg=NULL;
+#define MAX_P16_NREGS 16
+
+
#if 0
if(dynrIdx > pic16_nRegs)
+ werror(W_POSSBUG2, __FILE__, __LINE__);
return NULL;
#endif
reg = regFindFree( pic16_dynAllocRegs );
if(reg) {
-// fprintf(stderr, "%s: found FREE register %s\n", __FILE__, reg->name);
+// fprintf(stderr, "%s: [%s][cf:%p] found FREE register %s, rIdx: %d\n", __FILE__, (_inRegAllocator)?"ralloc":"", currFunc, reg->name, reg->rIdx);
}
if(!reg) {
reg = newReg(REG_GPR, PO_GPR_TEMP, dynrIdx++, NULL, 1, 0, NULL);
-// addSet(&pic16_dynAllocRegs, reg);
- }
-
- addSet(&pic16_dynAllocRegs, reg);
- hTabAddItem(&dynAllocRegNames, regname2key(reg->name), reg);
-
- reg->isFree=0;
+// fprintf(stderr, "%s [%s][cf:%p] allocating NEW register %s, rIdx: %d\n", __FILE__,
+// (_inRegAllocator)?"ralloc":"", currFunc, reg->name, reg->rIdx);
+#if 1
+ if(_inRegAllocator && (dynrIdx > MAX_P16_NREGS)) {
+ // debugf("allocating more registers than available\n", 0);
+ // return (NULL);
+ }
+
+ addSet(&pic16_dynAllocRegs, reg);
+ hTabAddItem(&dynAllocRegNames, regname2key(reg->name), reg);
+// fprintf(stderr, "%s:%d added reg to pic16_dynAllocRegs = %p\n", __FUNCTION__, __LINE__, pic16_dynAllocRegs);
+#endif
+ }
+
debugLog ("%s of type %s for register rIdx: %d (0x%x)\n", __FUNCTION__, debugLogRegType (type), dynrIdx-1, dynrIdx-1);
-// fprintf(stderr,"%s:%d: %s\t%s addr= 0x%x\trIdx= 0x%02x isFree: %d\n",
-// __FILE__, __LINE__, __FUNCTION__, reg->name, reg->address, reg->rIdx, reg->isFree);
-
+#if 0
+ fprintf(stderr,"%s:%d: %s\t%s addr= 0x%x\trIdx= 0x%02x isFree: %d\n",
+ __FILE__, __LINE__, __FUNCTION__, reg->name, reg->address, reg->rIdx, reg->isFree);
+#endif
if(reg) {
+ reg->isFree=0;
reg->accessBank = 1; /* this is a temporary register alloc in accessBank */
reg->isLocal = 1; /* this is a local frame register */
// reg->wasUsed = 1;
while(reg) {
if(STRCASECMP(reg->name, name) == 0) {
-// fprintf(stderr, "%s:%d: FOUND name = %s\thash = %d\n", __FUNCTION__, __LINE__, reg->name, hkey);
+// fprintf(stderr, "%s:%d: FOUND name = %s\thash = %d\n", __FUNCTION__, __LINE__, reg->name, hkey);
return(reg);
}
hkey = regname2key(name);
-// fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
+ //fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
reg = hTabFirstItemWK(dynAllocRegNames, hkey);
if(!SPEC_OCLS( OP_SYM_ETYPE(op))) {
-#if 1
+#if 0
if(pic16_debug_verbose)
{
fprintf(stderr, "%s:%d symbol %s(r:%s) is not assigned to a memmap\n", __FILE__, __LINE__,
if(IS_ITEMP(op))return NULL;
+// if(IS_STATIC(OP_SYM_ETYPE(op)))return NULL;
+
+ if(IN_STACK(OP_SYM_ETYPE(op)))return NULL;
+
debugLog ("%s:%d symbol name %s\n", __FUNCTION__, __LINE__, name);
-// fprintf(stderr, "%s symbol name %s\n", __FUNCTION__,name);
+// fprintf(stderr, "%s symbol name %s\tSTATIC:%d\n", __FUNCTION__,name, IS_STATIC(OP_SYM_ETYPE(op)));
{
if(SPEC_CONST ( OP_SYM_ETYPE(op)) && (IS_CHAR ( OP_SYM_ETYPE(op)) )) {
// fprintf(stderr, "%s:%d adding %s in direct registers\n", __FILE__, __LINE__, reg->name);
// addSet(&pic16_dynDirectRegs, reg);
- checkAddReg(&pic16_dynDirectRegs, reg);
+#if 1
+ if(!(IS_STATIC(OP_SYM_ETYPE(op))
+ && OP_SYMBOL(op)->ival
+ ))
+#endif
+ checkAddReg(&pic16_dynDirectRegs, reg);
}
} else {
reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
/* work around for user defined registers in access bank */
- if((reg->address>= 0x00 && reg->address < 0x80)
- || (reg->address >= 0xf80 && reg->address <= 0xfff))
+ if((reg->address>= 0x00 && reg->address < pic16->acsSplitOfs)
+ || (reg->address >= (0xf00 + pic16->acsSplitOfs) && reg->address <= 0xfff))
reg->accessBank = 1;
debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address);
* a new one and put it in the hash table AND in the
* dynDirectRegNames set */
- fprintf (stderr,"%s:%d symbol name %s\tregop= %p\n", __FUNCTION__, __LINE__, name, op);
+ //fprintf (stderr,"%s:%d symbol name %s\tregop= %p\n", __FUNCTION__, __LINE__, name, op);
reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0, op);
regs *dReg;
debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
-// fprintf(stderr, "%s - requesting index = 0x%x\n", __FUNCTION__, idx);
+// fprintf(stderr, "%s - requesting index = 0x%x (type = %d [%s])\n", __FUNCTION__, idx, type, decodeRegType(type));
switch (type) {
return dReg;
}
+ if( (dReg = regWithIdx ( pic16_dynInternalRegs, idx, fixed)) != NULL ) {
+ debugLog ("Found an Internal Register!\n");
+ return dReg;
+ }
+
break;
case REG_STK:
if( (dReg = regWithIdx ( pic16_dynStackRegs, idx, fixed)) != NULL ) {
pic16_allocWithIdx (int idx)
{
- regs *dReg;
+ regs *dReg=NULL;
debugLog ("%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
// fprintf(stderr, "%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
debugLog ("Dynamic Register not found\n");
+#if 1
+ dReg = newReg(REG_GPR, PO_GPR_TEMP, idx, NULL, 1, 0, NULL);
+ addSet(&pic16_dynAllocRegs, dReg);
+ hTabAddItem(&dynAllocRegNames, regname2key(dReg->name), dReg);
+#endif
+ if(!dReg) {
+// return (NULL);
//fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "regWithIdx not found");
- exit (1);
-
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "allocWithIdx not found");
+ exit (1);
+ }
}
dReg->wasUsed = 1;
case REG_GPR:
if((dReg = regFindFree(pic16_dynAllocRegs)) != NULL)
return dReg;
- return allocReg( REG_GPR ); //addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL));
+// return (addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL)));
+ return allocReg( REG_GPR );
case REG_STK:
return NULL;
}
}
+
+regs *
+pic16_findFreeRegNext(short type, regs *creg)
+{
+ // int i;
+ regs* dReg;
+
+ switch (type) {
+ case REG_GPR:
+ if((dReg = regFindFreeNext(pic16_dynAllocRegs, creg)) != NULL)
+ return dReg;
+// return (addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL)));
+ return (allocReg( REG_GPR ) );
+
+ case REG_STK:
+
+ if((dReg = regFindFreeNext(pic16_dynStackRegs, creg)) != NULL)
+ return dReg;
+
+ return NULL;
+
+ case REG_PTR:
+ case REG_CND:
+ case REG_SFR:
+ default:
+ return NULL;
+ }
+}
/*-----------------------------------------------------------------*/
/* freeReg - frees a register */
/*-----------------------------------------------------------------*/
void pic16_writeUsedRegs(FILE *of)
{
- packBits(pic16_dynDirectBitRegs);
-
-// fprintf(stderr, "%s: pic16_dynAllocRegs\n", __FUNCTION__);
- pic16_groupRegistersInSection(pic16_dynAllocRegs);
-
-// fprintf(stderr, "%s: pic16_dynInternalRegs\n", __FUNCTION__);
- pic16_groupRegistersInSection(pic16_dynInternalRegs);
-
-// fprintf(stderr, "%s: pic16_dynStackRegs\n", __FUNCTION__);
- pic16_groupRegistersInSection(pic16_dynStackRegs);
-
-// fprintf(stderr, "%s: pic16_dynDirectRegs\n", __FUNCTION__);
- pic16_groupRegistersInSection(pic16_dynDirectRegs);
-
-// fprintf(stderr, "%s: pic16_dynDirectBitsRegs\n", __FUNCTION__);
- pic16_groupRegistersInSection(pic16_dynDirectBitRegs);
-
-// fprintf(stderr, "%s: pic16_dynProcessorRegs\n", __FUNCTION__);
- pic16_groupRegistersInSection(pic16_dynProcessorRegs);
+ packBits(pic16_dynDirectBitRegs);
+
+ pic16_groupRegistersInSection(pic16_dynAllocRegs);
+ pic16_groupRegistersInSection(pic16_dynInternalRegs);
+ pic16_groupRegistersInSection(pic16_dynStackRegs);
+ pic16_groupRegistersInSection(pic16_dynDirectRegs);
+ pic16_groupRegistersInSection(pic16_dynDirectBitRegs);
+ pic16_groupRegistersInSection(pic16_dynProcessorRegs);
+ pic16_groupRegistersInSection(pic16_dynAccessRegs);
-// fprintf(stderr, "%s: pic16_dynAccessRegs\n", __FUNCTION__);
- pic16_groupRegistersInSection(pic16_dynAccessRegs);
-
- /* dump equates */
- pic16_dump_equates(of, pic16_equ_data);
+ /* dump equates */
+ pic16_dump_equates(of, pic16_equ_data);
// pic16_dump_esection(of, pic16_rel_eedata, 0);
// pic16_dump_esection(of, pic16_fix_eedata, 0);
- /* dump access bank symbols */
- pic16_dump_access(of, pic16_acs_udata);
+ /* dump access bank symbols */
+ pic16_dump_access(of, pic16_acs_udata);
- /* dump initialised data */
- pic16_dump_isection(of, rel_idataSymSet, 0);
- pic16_dump_isection(of, fix_idataSymSet, 1);
+ /* dump initialised data */
+ pic16_dump_isection(of, rel_idataSymSet, 0);
+ pic16_dump_isection(of, fix_idataSymSet, 1);
- /* dump internal registers */
- pic16_dump_int_registers(of, pic16_int_regs);
+ if(!xinst) {
+ /* dump internal registers */
+ pic16_dump_int_registers(of, pic16_int_regs);
+ }
- /* dump generic section variables */
- pic16_dump_gsection(of, sectNames);
+ /* dump generic section variables */
+ pic16_dump_gsection(of, sectNames);
- /* dump other variables */
- pic16_dump_usection(of, pic16_rel_udata, 0);
- pic16_dump_usection(of, pic16_fix_udata, 1);
-
+ /* dump other variables */
+ pic16_dump_usection(of, pic16_rel_udata, 0);
+ pic16_dump_usection(of, pic16_fix_udata, 1);
}
sym->nRegs) >= result->nRegs)
)
{
+
- for (i = 0; i < max (sym->nRegs, result->nRegs); i++)
+// for (i = 0; i < max (sym->nRegs, result->nRegs); i++)
+ /* the above does not free the unsued registers in sym,
+ * leaving them marked as used, and increasing register usage
+ * until the end of the function - VR 23/11/05 */
+
+ 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);
-
}
/* free the remaining */
serialRegAssign (eBBlock ** ebbs, int count)
{
int i;
-
+ iCode *ic;
+
debugLog ("%s\n", __FUNCTION__);
/* for all blocks */
for (i = 0; i < count; i++)
{
-
- iCode *ic;
-
if (ebbs[i]->noPath &&
(ebbs[i]->entryLabel != entryLabel &&
ebbs[i]->entryLabel != returnLabel))
for (ic = ebbs[i]->sch; ic; ic = ic->next)
{
- debugLog (" op: %s\n", decodeOp (ic->op));
+ debugLog (" op: %s\n", pic16_decodeOp (ic->op));
if(IC_RESULT(ic) && !IS_ITEMP( IC_RESULT(ic)))
pic16_allocDirReg(IC_RESULT(ic));
int j;
int ptrRegSet = 0;
+ /* Make sure any spill location is definately 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 */
or this one is rematerializable then
spill this one */
willCS = willCauseSpill (sym->nRegs, sym->regType);
+
+ /* explicit turn off register spilling */
+ willCS = 0;
+
spillable = computeSpillable (ic);
if (sym->remat ||
(willCS && bitVectIsZero (spillable)))
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 0
if (sym->liveFrom < ic->seq)
{
spillThis (sym);
continue;
}
-
+#endif
/* if it has a spillocation & is used less than
all other live ranges then spill this */
if (willCS) {
if (ic->op == RECEIVE)
debugLog ("When I get clever, I'll optimize the receive logic\n");
+ if(POINTER_GET(ic) && IS_BITFIELD(getSpec(operandType(IC_RESULT(ic))))
+ && (SPEC_BLEN(getSpec(operandType(IC_RESULT(ic))))==1)
+ && (ic->next->op == IFX)
+ && (OP_LIVETO(IC_RESULT(ic)) == ic->next->seq)) {
+
+ /* skip register allocation since none will be used */
+ for(j=0;j<sym->nRegs;j++)
+ sym->regs[j] = newReg(REG_TMP, PO_GPR_TEMP, 0, "bad", 1, 0, NULL);
+// OP_SYMBOL(IC_RESULT(ic))->nRegs = 0;
+
+ continue;
+ }
+
/* if we need ptr regs for the right side
then mark it */
- if (POINTER_GET (ic) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
+ if (POINTER_GET (ic) && IS_SYMOP( IC_LEFT(ic) ) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
<= (unsigned) PTRSIZE)
{
pic16_ptrRegReq++;
/* else we assign registers to it */
_G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
- debugLog (" %d - nRegs: %d\n", __LINE__, sym->nRegs);
if(debugF)
bitVectDebugOn(_G.regAssigned, debugF);
if (IS_AGGREGATE (sym->type) || sym->isptr)
sym->type = aggrToPtr (sym->type, FALSE);
debugLog (" %d - no reg needed - used as a return\n", __LINE__);
-
continue;
}
!IS_BITVAR (sym->etype) &&
(aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
+// continue; /* FIXME -- VR */
if (ptrPseudoSymSafe (sym, ic)) {
symbol *psym;
/* registers for true symbols we will */
/* see how things go */
sym->nRegs = 0;
+
}
}
static DEFSETFUNC (markRegFree)
{
((regs *)item)->isFree = 1;
+// ((regs *)item)->wasUsed = 0;
return 0;
}
return NULL;
}
+#if 0
+static int packRegsForPointerGet(iCode *ic, eBBlock *ebp)
+{
+ iCode *dic, *sic;
+
+ debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
+ debugLog ("ic->op = %s\n", pic16_decodeOp( ic->op ) );
+ debugAopGet (" result:", IC_RESULT (ic));
+ debugAopGet (" left:", IC_LEFT (ic));
+ debugAopGet (" right:", IC_RIGHT (ic));
+
+ dic = ic->prev;
+ if((dic->op == '=')
+ && (
+}
+#endif
+
+
+void replaceOperandWithOperand(eBBlock *ebp, iCode *ic, operand *src, iCode *dic, operand *dst);
+
/*-----------------------------------------------------------------*/
/* packRegsForAssign - register reduction for assignment */
/*-----------------------------------------------------------------*/
static int
packRegsForAssign (iCode * ic, eBBlock * ebp)
{
-
iCode *dic, *sic;
debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
- debugLog ("ic->op = %s\n", decodeOp( ic->op ) );
+ debugLog ("ic->op = %s\n", pic16_decodeOp( ic->op ) );
debugAopGet (" result:", IC_RESULT (ic));
debugAopGet (" left:", IC_LEFT (ic));
debugAopGet (" right:", IC_RIGHT (ic));
debugLog (" %d - result is not temp\n", __LINE__);
}
+// if(IS_VALOP(IC_RIGHT(ic)))return 0;
/* See BUGLOG0001 - VR */
#if 1
- if (!IS_ITEMP (IC_RIGHT (ic))) {
+ if (!IS_ITEMP (IC_RIGHT (ic)) /*&& (!IS_PARM(IC_RESULT(ic)))*/) {
debugLog (" %d - not packing - right is not temp\n", __LINE__);
pic16_allocDirReg(IC_RIGHT (ic));
return 0;
* if it fits for pic16, but I leave it here just in case */
/* if assignment then check that right is not a bit */
- if (ASSIGNMENT (dic) && !POINTER_SET (dic)) {
- sym_link *etype = operandType (IC_RIGHT (dic));
+ 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 (dic));
+ etype = operandType (IC_RESULT (ic));
if (!IS_BITFIELD (etype)) {
debugLog(" %d bitfields\n");
return 0;
/* found the definition */
/* replace the result with the result of */
/* this assignment and remove this assignment */
- bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
- IC_RESULT (dic) = IC_RESULT (ic);
- if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
- {
- OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
- }
- /* delete from liverange table also
- delete from all the points inbetween and the new
- one */
- for (sic = dic; sic != ic; sic = sic->next)
- {
- bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
- if (IS_ITEMP (IC_RESULT (dic)))
- bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
- }
-
- remiCodeFromeBBlock (ebp, ic);
- bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ IC_RESULT (dic) = IC_RESULT (ic);
- debugLog(" %d\n", __LINE__ );
- hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
- OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
- return 1;
+ if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
+ {
+ OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
+ }
+ /* delete from liverange table also
+ delete from all the points inbetween and the new
+ one */
+ for (sic = dic; sic != ic; sic = sic->next)
+ {
+ bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
+ if (IS_ITEMP (IC_RESULT (dic)))
+ bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+ }
+ remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ debugLog(" %d\n", __LINE__ );
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+ OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ return 1;
}
+
#if 1
#define NO_packRegsForAccUse
bitVect *uses;
iCode *dic, *sic;
+ return NULL;
+
debugLog ("%s\n", __FUNCTION__);
/* if returning a literal then do nothing */
if (!IS_SYMOP (op))
return NULL;
+ if(OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly)
+ return NULL;
+
/* only upto 2 bytes since we cannot predict
the usage of b, & acc */
- if (getSize (operandType (op)) > (pic16_fReturnSizePic - 3) && /* was 2, changed to 3 -- VR */
- ic->op != RETURN &&
- ic->op != SEND)
+ if (getSize (operandType (op)) > (pic16_fReturnSizePic - 1)
+ && ic->op != RETURN
+ && ic->op != SEND
+ && !POINTER_SET(ic)
+ && !POINTER_GET(ic)
+ )
return NULL;
/* this routine will mark the a symbol as used in one
that definition is either a return value from a
function or does not contain any variables in
far space */
+
+#if 0
uses = bitVectCopy (OP_USES (op));
bitVectUnSetBit (uses, ic->key); /* take away this iCode */
if (!bitVectIsZero (uses)) /* has other uses */
return NULL;
+#endif
+
+#if 1
+ if (bitVectnBitsOn (OP_USES (op)) > 1)
+ return NULL;
+#endif
/* if it has only one defintion */
if (bitVectnBitsOn (OP_DEFS (op)) > 1)
}
dic = dic->next;
}
+ else
+ {
/* otherwise check that the definition does
if (POINTER_GET (dic) &&
!IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
return NULL;
+ }
sic = dic;
operation is a '*','/' or '%' then 'b' may
cause a problem */
if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
- getSize (operandType (op)) >= 3)
+ getSize (operandType (op)) >= 2)
return NULL;
/* if left or right or result is in far space */
for (dic = ic->next; dic; dic = dic->next)
{
-
-
-
if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
- debugLog (" used on left\n");
+ debugLog (" used on left\n");
if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
- debugLog (" used on right\n");
+ debugLog (" used on right\n");
if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
- debugLog (" used on result\n");
+ debugLog (" used on result\n");
if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
- (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
+ (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
return;
-
}
debugLog (" hey we can remove this unnecessary assign\n");
packForPush (iCode * ic, eBBlock * ebp)
{
iCode *dic;
-
+
debugLog ("%s\n", __FUNCTION__);
if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
return;
+#if 0
+ {
+ int n1, n2;
+
+ n1 = bitVectnBitsOn( OP_DEFS(IC_LEFT(ic)));
+ n2 = bitVectnBitsOn( OP_USES(IC_LEFT(ic)));
+ debugf3("defs: %d\tuses: %d\t%s\n", n1, n2, printILine(ic));
+ debugf2("IC_LEFT(ic): from %d to %d\n", OP_LIVEFROM(IC_LEFT(ic)), OP_LIVETO(IC_LEFT(ic)));
+ }
+#endif
+
/* must have only definition & one usage */
if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
return;
+ /* if definition is not assignment,
+ * or is not pointer (because pointer might have changed) */
if (dic->op != '=' || POINTER_SET (dic))
return;
+ /* we must ensure that we can use the delete the assignment,
+ * because the source might have been modified in between.
+ * Until I know how to fix this, I'll use the adhoc fix
+ * to check the liveranges */
+ if((OP_LIVEFROM(IC_RIGHT(dic))==0) || (OP_LIVETO(IC_RIGHT(dic))==0))
+ return;
+// debugf2("IC_RIGHT(dic): from %d to %d\n", OP_LIVEFROM(IC_RIGHT(dic)), OP_LIVETO(IC_RIGHT(dic)));
+
+
+
/* 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);
+
+ debugf("remiCodeFromeBBlock: %s\n", printILine(dic));
remiCodeFromeBBlock (ebp, dic);
bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
{
FILE *of = stderr;
- if(!pic16_ralloc_debug)return;
-
- if(!sl)return;
-
- if(debugF)
- of = debugF;
-
- for ( ; sl; sl=sl->next) {
- if(!IS_DECL(sl) ) {
- switch (SPEC_SCLS(sl)) {
- case S_DATA: fprintf (of, "data "); break;
- case S_XDATA: fprintf (of, "xdata "); break;
- case S_SFR: fprintf (of, "sfr "); break;
- case S_SBIT: fprintf (of, "sbit "); break;
- case S_CODE: fprintf (of, "code "); break;
- case S_IDATA: fprintf (of, "idata "); break;
- case S_PDATA: fprintf (of, "pdata "); break;
- case S_LITERAL: fprintf (of, "literal "); break;
- case S_STACK: fprintf (of, "stack "); break;
- case S_XSTACK: fprintf (of, "xstack "); break;
- case S_BIT: fprintf (of, "bit "); break;
- case S_EEPROM: fprintf (of, "eeprom "); break;
- default: break;
- }
-
- }
- }
+ if(!pic16_ralloc_debug)return;
+
+ if(!sl)return;
+
+ if(debugF)
+ of = debugF;
+
+ for ( ; sl; sl=sl->next) {
+ if(!IS_DECL(sl) ) {
+ switch (SPEC_SCLS(sl)) {
+ case S_DATA: fprintf (of, "data "); break;
+ case S_XDATA: fprintf (of, "xdata "); break;
+ case S_SFR: fprintf (of, "sfr "); break;
+ case S_SBIT: fprintf (of, "sbit "); break;
+ case S_CODE: fprintf (of, "code "); break;
+ case S_IDATA: fprintf (of, "idata "); break;
+ case S_PDATA: fprintf (of, "pdata "); break;
+ case S_LITERAL: fprintf (of, "literal "); break;
+ case S_STACK: fprintf (of, "stack "); break;
+ case S_XSTACK: fprintf (of, "xstack "); break;
+ case S_BIT: fprintf (of, "bit "); break;
+ case S_EEPROM: fprintf (of, "eeprom "); break;
+ default: break;
+ }
+ }
+ }
}
{
// debugLog("%d\n", __LINE__);
/* find assignment of the form TrueSym := iTempNN:1 */
- /* see BUGLOG0001 for workaround with the CAST - VR */
-// if ( (ic->op == '=' || ic->op == CAST) && !POINTER_SET (ic) ) // patch 11
if ( (ic->op == '=') && !POINTER_SET (ic) ) // patch 11
change += packRegsForAssign (ic, ebp);
/* debug stuff */
if (POINTER_SET (ic))
- debugLog (" %d - Pointer set\n", __LINE__);
-
+ debugLog (" %d - Pointer set\n", __LINE__);
+
+ /* 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 a address of a true sym
then mark this as rematerialisable */
if (ic->op == ADDRESS_OF &&
OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
}
+
+#if 0
+ /* try to optimize FSR0 usage when reading data memory pointers */
+
+ if(getenv("OPTIMIZE_NEAR_POINTER_GET")) {
+ static int fsr0usage=0;
+ static iCode *usic;
+
+ if(POINTER_GET(ic) /* this is a memory read */
+ && ic->loop /* this is in a loop */
+ ) {
+ fprintf(stderr, "might optimize FSR0 usage\n");
+ }
+ }
+#endif
+
/* mark the pointer usages */
if (POINTER_SET (ic))
{
OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
debugLog (" marking as a pointer (set) =>");
debugAopGet (" result:", IC_RESULT (ic));
+
}
+
if (POINTER_GET (ic))
{
- OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
- debugLog (" marking as a pointer (get) =>");
- debugAopGet (" left:", IC_LEFT (ic));
+ if(IS_SYMOP(IC_LEFT(ic))) {
+ OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+ debugLog (" marking as a pointer (get) =>");
+ debugAopGet (" left:", IC_LEFT (ic));
+ }
+
+ if(getenv("OPTIMIZE_BITFIELD_POINTER_GET")) {
+ if(IS_ITEMP(IC_LEFT(ic)) && IS_BITFIELD(OP_SYM_ETYPE(IC_LEFT(ic)))) {
+ iCode *dic = ic->prev;
+
+ fprintf(stderr, "%s:%d might give opt POINTER_GET && IS_BITFIELD(IC_LEFT)\n", __FILE__, __LINE__);
+
+ if(dic && dic->op == '='
+ && isOperandEqual(IC_RESULT(dic), IC_LEFT(ic))) {
+
+ fprintf(stderr, "%s:%d && prev is '=' && prev->result == ic->left\n", __FILE__, __LINE__);
+
+
+ /* replace prev->left with ic->left */
+ IC_LEFT(ic) = IC_RIGHT(dic);
+ IC_RIGHT(ic->prev) = NULL;
+
+ /* remove ic->prev iCode (assignment) */
+ remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,ic->key);
+
+
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+ }
+ }
+ }
}
//debugLog(" %d %s\n", __LINE__, __FUNCTION__);
}
}
#endif
+
+#if 1
+ /* there are some problems with packing variables
+ * it seems that the live range estimator doesn't
+ * estimate correctly the liveranges of some symbols */
+
/* pack for PUSH
iTempNN := (some variable in farspace) V1
push iTempNN ;
{
packForPush (ic, ebp);
}
-
+#endif
#ifndef NO_packRegsForAccUse
/* pack registers for accumulator use, when the
printiCChain (ebbs[i]->sch, debugF);
}
}
+
+void dbg_dumpregusage(void);
+
/*-----------------------------------------------------------------*/
/* pic16_assignRegisters - assigns registers to each live range as need */
/*-----------------------------------------------------------------*/
void
-pic16_assignRegisters (eBBlock ** ebbs, int count)
+pic16_assignRegisters (ebbIndex * ebbi)
{
+ eBBlock ** ebbs = ebbi->bbOrder;
+ int count = ebbi->count;
iCode *ic;
int i;
debugLog ("\nebbs before optimizing:\n");
dumpEbbsToDebug (ebbs, count);
+ _inRegAllocator = 1;
+
+ pic16_freeAllRegs();
+#if 0
+ dbg_dumpregusage();
+ /* clear whats left over from peephole parser */
+ pic16_dynAllocRegs= newSet(); //NULL;
+// pic16_dynStackRegs= newSet(); //NULL;
+// pic16_dynProcessorRegs=newSet(); //NULL;
+// pic16_dynDirectRegs=newSet(); //NULL;
+// pic16_dynDirectBitRegs=newSet(); //NULL;
+// pic16_dynInternalRegs=newSet(); //NULL;
+// pic16_dynAccessRegs=newSet(); //NULL;
+
+// dynDirectRegNames=NULL;
+ dynAllocRegNames=NULL;
+// dynProcRegNames=NULL;
+// dynAccessRegNames=NULL;
+#endif
+
setToNull ((void *) &_G.funcrUsed);
pic16_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
for (i = 0; i < count; i++)
pic16_packRegisters (ebbs[i]);
+
{
regs *reg;
int hkey;
- int i=0;
debugLog("dir registers allocated so far:\n");
reg = hTabFirstItem(dynDirectRegNames, &hkey);
+#if 0
while(reg) {
debugLog(" -- #%d reg = %s key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
// fprintf(stderr, " -- #%d reg = %s key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
reg = hTabNextItem(dynDirectRegNames, &hkey);
}
+#endif
}
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
registers & the type of registers required for each */
regTypeNum ();
+ /* start counting function temporary registers from zero */
+ /* XXX: Resetting dynrIdx breaks register allocation,
+ * see #1489055, #1483693 (?), and #1445850! */
+ //dynrIdx = 0;
+
/* and serially allocate registers */
serialRegAssign (ebbs, count);
redoStackOffsets ();
if (options.dump_rassgn)
- dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+ dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
+
+// dumpLR(ebbs, count);
/* now get back the chain */
ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
dumpEbbsToDebug (ebbs, count);
+ _inRegAllocator = 0;
+
genpic16Code (ic);
/* free up any _G.stackSpil locations allocated */
/* mark all registers as free */
pic16_freeAllRegs ();
+
debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
debugLogClose ();
return;