X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fralloc.c;h=ec01a64642e23b935a55a847a41fa9527828b4a5;hb=0892d3692ded8c67ab4df6b26f603bb8d243e39d;hp=18eb37a993e4b6b088634eae6c4ce0485c92eb92;hpb=3c14fa0febe494de4e6b32d931cd2d58db841b12;p=fw%2Fsdcc diff --git a/src/mcs51/ralloc.c b/src/mcs51/ralloc.c index 18eb37a9..ec01a646 100644 --- a/src/mcs51/ralloc.c +++ b/src/mcs51/ralloc.c @@ -74,9 +74,13 @@ regs regs8051[] = {REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 1}, {REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 1}, {REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 1}, - {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, 1}, + {REG_CND, CND_IDX, REG_CND, "C", "psw", "0xd0", 0, 1}, + {0, DPL_IDX, 0, "dpl", "dpl", "0x82", 0, 0}, + {0, DPH_IDX, 0, "dph", "dph", "0x83", 0, 0}, + {0, B_IDX, 0, "b", "b", "0xf0", 0, 0}, + {0, A_IDX, 0, "a", "acc", "0xe0", 0, 0}, }; -int mcs51_nRegs = 13; +int mcs51_nRegs = 17; static void spillThis (symbol *); static void freeAllRegs (); @@ -117,6 +121,23 @@ allocReg (short type) return NULL; } +/*-----------------------------------------------------------------*/ +/* allocThisReg - allocates a particular register (if free) */ +/*-----------------------------------------------------------------*/ +static regs * +allocThisReg (regs * reg) +{ + if (!reg->isFree) + return NULL; + + reg->isFree = 0; + if (currFunc) + currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, reg->rIdx); + + return reg; +} + + /*-----------------------------------------------------------------*/ /* mcs51_regWithIdx - returns pointer to register wit index number */ /*-----------------------------------------------------------------*/ @@ -125,7 +146,7 @@ mcs51_regWithIdx (int idx) { int i; - for (i = 0; i < mcs51_nRegs; i++) + for (i = 0; i < sizeof(regs8051)/sizeof(regs); i++) if (regs8051[i].rIdx == idx) return ®s8051[i]; @@ -191,32 +212,6 @@ useReg (regs * reg) reg->isFree = 0; } -/*-----------------------------------------------------------------*/ -/* allDefsOutOfRange - all definitions are out of a range */ -/*-----------------------------------------------------------------*/ -static bool -allDefsOutOfRange (bitVect * defs, int fseq, int toseq) -{ - 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; -} - /*-----------------------------------------------------------------*/ /* computeSpillable - given a point find the spillable live ranges */ /*-----------------------------------------------------------------*/ @@ -293,17 +288,6 @@ rematable (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 */ /*-----------------------------------------------------------------*/ @@ -387,7 +371,7 @@ leastUsedLR (set * sset) } - setToNull ((void **) &sset); + setToNull ((void *) &sset); sym->blockSpil = 0; return sym; } @@ -608,7 +592,6 @@ spillThis (symbol * 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); @@ -820,6 +803,7 @@ static regs * getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym) { regs *reg; + int j; tryAgain: /* try for a ptr type */ @@ -834,6 +818,11 @@ tryAgain: if (!spilSomething (ic, ebp, sym)) return NULL; + /* 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; @@ -846,7 +835,8 @@ static regs * getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym) { regs *reg; - + int j; + tryAgain: /* try for gpr type */ if ((reg = allocReg (REG_GPR))) @@ -860,6 +850,11 @@ tryAgain: if (!spilSomething (ic, ebp, sym)) return NULL; + /* 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; @@ -881,6 +876,9 @@ static regs *getRegPtrNoSpil() return reg; assert(0); + + /* just to make the compiler happy */ + return 0; } /*-----------------------------------------------------------------*/ @@ -898,6 +896,9 @@ static regs *getRegGprNoSpil() return reg; assert(0); + + /* just to make the compiler happy */ + return 0; } /*-----------------------------------------------------------------*/ @@ -980,6 +981,7 @@ deassignLRs (iCode * ic, eBBlock * ebp) (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 */ @@ -1119,6 +1121,33 @@ xchgPositions: return change; } + +/*------------------------------------------------------------------*/ +/* 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 */ /*-----------------------------------------------------------------*/ @@ -1139,7 +1168,18 @@ serialRegAssign (eBBlock ** ebbs, int count) /* of all instructions do */ for (ic = ebbs[i]->sch; ic; ic = ic->next) { - +#if 1 + int reg; + + // update the registers in use at the start of this icode + for (reg=0; regriu &= ~(1<riu |= (1<op == IPOP) @@ -1198,6 +1238,16 @@ serialRegAssign (eBBlock ** ebbs, int count) 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 */ @@ -1228,40 +1278,63 @@ serialRegAssign (eBBlock ** ebbs, int count) mcs51_ptrRegReq++; ptrRegSet = 1; } + if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) + && SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata) { + mcs51_ptrRegReq++; + ptrRegSet = 1; + } + if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) + && SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata) { + mcs51_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 - sym->regs[j] = getRegGpr (ic, ebbs[i], sym); + { + if (ic->op == CAST && IS_SYMOP (IC_RIGHT (ic))) + { + symbol * right = OP_SYMBOL (IC_RIGHT (ic)); + + if (right->regs[j]) + sym->regs[j] = allocThisReg (right->regs[j]); + } + if (!sym->regs[j]) + sym->regs[j] = getRegGpr (ic, ebbs[i], sym); + } /* if the allocation failed which means this was spilt then break */ - if (!sym->regs[j]) { - if (j) { - fprintf (stderr, "%d reg(s) lost in %s:%d\n", - j, __FILE__,__LINE__); + if (!sym->regs[j]) + { + for (i=0; i < sym->nRegs ; i++ ) + sym->regs[i] = NULL; + break; } - 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 (!POINTER_SET(ic) && !POINTER_GET(ic)) { + /* 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) { + 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) { mcs51_ptrRegReq--; @@ -1271,6 +1344,39 @@ serialRegAssign (eBBlock ** ebbs, int count) } } } + + /* 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); + } + } } /*-----------------------------------------------------------------*/ @@ -1279,7 +1385,9 @@ serialRegAssign (eBBlock ** ebbs, int count) static void fillGaps() { symbol *sym =NULL; - int key =0; + int key =0; + int pass; + iCode *ic = NULL; if (getenv("DISABLE_FILL_GAPS")) return; @@ -1302,8 +1410,9 @@ static void fillGaps() bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */ continue ; - assert (clr = hTabItemWithKey(liveRanges,i)); - + clr = hTabItemWithKey(liveRanges,i); + assert(clr); + /* mark these registers as used */ for (k = 0 ; k < clr->nRegs ; k++ ) useReg(clr->regs[k]); @@ -1315,52 +1424,111 @@ static void fillGaps() continue ; } + ic = NULL; + for (i = 0 ; i < sym->defs->size ; i++ ) + { + if (bitVectBitValue(sym->defs,i)) + { + if (!(ic = hTabItemWithKey(iCodehTab,i))) + continue; + if (ic->op == CAST) + break; + } + } + + D(printf("Atemping fillGaps on %s: [",sym->name)); /* THERE IS HOPE !!!! */ for (i=0; i < sym->nRegs ; i++ ) { if (sym->regType == REG_PTR) sym->regs[i] = getRegPtrNoSpil (); else - sym->regs[i] = getRegGprNoSpil (); + { + sym->regs[i] = NULL; + if (ic && ic->op == CAST && IS_SYMOP (IC_RIGHT (ic))) + { + symbol * right = OP_SYMBOL (IC_RIGHT (ic)); + + if (right->regs[i]) + sym->regs[i] = allocThisReg (right->regs[i]); + } + if (!sym->regs[i]) + sym->regs[i] = getRegGprNoSpil (); + } + D(printf("%s ", sym->regs[i]->name)); } + D(printf("]\n")); - /* for all its definitions check if the registers + /* 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 */ + 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 (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))); + for (pass=0; pass<2; pass++) { + D(printf(" checking definitions\n")); + for (i = 0 ; i < sym->defs->size ; i++ ) { + if (bitVectBitValue(sym->defs,i)) { + if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; + D(printf(" ic->seq = %d\n", ic->seq)); + 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))) + { + D(printf(" left = ")); + D(printOperand(IC_LEFT(ic),NULL)); + } + 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))) + { + D(printf(" right = ")); + D(printOperand(IC_RIGHT(ic),NULL)); + } + if (IS_SYMOP(IC_RIGHT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) { + pdone += (positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)))>0); + } + D(printf(" pdone = %d\n", pdone)); + if (pdone > 1) break; } - if (pdone > 1) break; } - } - for (i = 0 ; i < sym->uses->size ; i++ ) { - if (bitVectBitValue(sym->uses,i)) { - iCode *ic; - if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; - if (SKIP_IC(ic)) continue; - if (!IS_ASSIGN_ICODE(ic)) continue ; - - /* if result is assigned to registers */ - if (IS_SYMOP(IC_RESULT(ic)) && - bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) { - pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic))); + D(printf(" checking uses\n")); + for (i = 0 ; i < sym->uses->size ; i++ ) { + if (bitVectBitValue(sym->uses,i)) { + iCode *ic; + if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; + D(printf(" ic->seq = %d\n", ic->seq)); + 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))) + { + D(printf(" result = ")); + D(printOperand(IC_RESULT(ic),NULL)); + } + if (IS_SYMOP(IC_RESULT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) { + pdone += (positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)))>0); + } + D(printf(" pdone = %d\n", pdone)); + if (pdone > 1) break; } - if (pdone > 1) break; } - } + if (pdone == 0) break; /* second pass only if regs repositioned */ + if (pdone > 1) break; + } + D(printf(" sym->regs = [")); + for (i=0; i < sym->nRegs ; i++ ) + D(printf("%s ", sym->regs[i]->name)); + D(printf("]\n")); /* had to position more than once GIVE UP */ if (pdone > 1) { /* UNDO all the changes we made to try this */ @@ -1373,6 +1541,7 @@ static void fillGaps() continue ; } D(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--; @@ -1405,6 +1574,7 @@ mcs51_rUmaskForOp (operand * op) for (j = 0; j < sym->nRegs; j++) { + if (sym->regs[j]) /* EEP - debug */ rumask = bitVectSetBit (rumask, sym->regs[j]->rIdx); } @@ -1507,6 +1677,7 @@ createRegMask (eBBlock ** ebbs, int count) { werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "createRegMask cannot find live range"); + fprintf(stderr, "\tmissing live range: key=%d\n", j); exit (0); } @@ -1592,46 +1763,23 @@ regTypeNum (eBBlock *ebbs) if (sym->ruonly || sym->accuse) { if (IS_AGGREGATE (sym->type) || sym->isptr) - sym->type = aggrToPtr (sym->type, FALSE); + 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 */ - + that definition is a get_pointer */ if (bitVectnBitsOn (sym->defs) == 1 && (ic = hTabItemWithKey (iCodehTab, bitVectFirstBit (sym->defs))) && POINTER_GET (ic) && - !sym->noSpilLoc && - !IS_BITVAR (sym->etype)) + !IS_BITVAR (sym->etype) && + (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) { - - /* 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) + if (ptrPseudoSymSafe (sym, ic)) { - /* 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; -#if 0 // an alternative fix for bug #480076 - /* now this is a useless assignment to itself */ - remiCodeFromeBBlock (ebbs, ic); -#else - /* now this really is an assignment to itself, make it so; - it will be optimized out later */ - ic->op='='; - IC_RIGHT(ic)=IC_RESULT(ic); - IC_LEFT(ic)=NULL; -#endif + ptrPseudoSymConvert (sym, ic, rematStr (OP_SYMBOL (IC_LEFT (ic)))); continue; } @@ -1666,7 +1814,7 @@ regTypeNum (eBBlock *ebbs) /* registers for true symbols we will */ /* see how things go */ sym->nRegs = 0; - } + } } @@ -1727,23 +1875,40 @@ farSpacePackable (iCode * ic) getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1) return NULL; - /* if any three is a true symbol in far space */ - if (IC_RESULT (dic) && - IS_TRUE_SYMOP (IC_RESULT (dic)) && - isOperandInFarSpace (IC_RESULT (dic))) - return NULL; + if (dic->op == IFX) + { + if (IC_COND (dic) && + IS_TRUE_SYMOP (IC_COND (dic)) && + isOperandInFarSpace (IC_COND (dic))) + return NULL; + } + else if (dic->op == JUMPTABLE) + { + if (IC_JTCOND (dic) && + IS_TRUE_SYMOP (IC_JTCOND (dic)) && + isOperandInFarSpace (IC_JTCOND (dic))) + return NULL; + } + else + { + /* if any three is a true symbol in far space */ + if (IC_RESULT (dic) && + 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; + if (IC_RIGHT (dic) && + 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; + if (IC_LEFT (dic) && + 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))) { @@ -1767,12 +1932,10 @@ static int packRegsForAssign (iCode * ic, eBBlock * ebp) { iCode *dic, *sic; - //sym_link *etype = operandType (IC_RIGHT (ic)); if (!IS_ITEMP (IC_RIGHT (ic)) || OP_SYMBOL (IC_RIGHT (ic))->isind || - OP_LIVETO (IC_RIGHT (ic)) > ic->seq - /* why? || IS_BITFIELD (etype) */ ) + OP_LIVETO (IC_RIGHT (ic)) > ic->seq) { return 0; } @@ -1788,66 +1951,114 @@ packRegsForAssign (iCode * ic, eBBlock * ebp) we cannot */ for (dic = ic->prev; dic; dic = dic->prev) { - /* if there is a function call then don't pack it */ + int crossedCall = 0; + + /* We can pack across a function call only if it's a local */ + /* variable or our parameter. Never pack global variables */ + /* or parameters to a function we call. */ if ((dic->op == CALL || dic->op == PCALL)) { - dic = NULL; - break; + if (!OP_SYMBOL (IC_RESULT (ic))->ismyparm + && !OP_SYMBOL (IC_RESULT (ic))->islocal) + { + crossedCall = 1; + } } if (SKIP_IC2 (dic)) continue; - if (IS_TRUE_SYMOP (IC_RESULT (dic)) && - IS_OP_VOLATILE (IC_RESULT (dic))) - { - dic = NULL; - break; - } + if (dic->op == IFX) + { + if (IS_SYMOP (IC_COND (dic)) && + (IC_COND (dic)->key == IC_RESULT (ic)->key || + IC_COND (dic)->key == IC_RIGHT (ic)->key)) + { + dic = NULL; + break; + } + } + else + { + if (IS_TRUE_SYMOP (IC_RESULT (dic)) && + 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; + if (IS_SYMOP (IC_RESULT (dic)) && + 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; - } + if (IS_SYMOP (IC_RIGHT (dic)) && + (IC_RIGHT (dic)->key == IC_RESULT (ic)->key || + IC_RIGHT (dic)->key == IC_RIGHT (ic)->key)) + { + dic = NULL; + break; + } - if (IS_SYMOP (IC_LEFT (dic)) && - (IC_LEFT (dic)->key == IC_RESULT (ic)->key || - IC_LEFT (dic)->key == IC_RIGHT (ic)->key)) - { - dic = NULL; - break; - } + if (IS_SYMOP (IC_LEFT (dic)) && + (IC_LEFT (dic)->key == IC_RESULT (ic)->key || + IC_LEFT (dic)->key == IC_RIGHT (ic)->key)) + { + dic = NULL; + break; + } - if (POINTER_SET (dic) && - IC_RESULT (dic)->key == IC_RESULT (ic)->key) - { - dic = NULL; - break; + if (IS_SYMOP (IC_RESULT (dic)) && + IC_RESULT (dic)->key == IC_RESULT (ic)->key) + { + dic = NULL; + break; + } + + if (crossedCall) + { + dic = NULL; + break; + } + } } if (!dic) 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 0 /* if assignment then check that right is not a bit */ if (ASSIGNMENT (dic) && !POINTER_SET (dic)) { sym_link *etype = operandType (IC_RIGHT (dic)); if (IS_BITFIELD (etype)) - return 0; + { + /* if result is a bit too then it's ok */ + etype = operandType (IC_RESULT (dic)); + if (!IS_BITFIELD (etype)) + return 0; + } } +#endif /* 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 || @@ -1871,12 +2082,14 @@ pack: /* 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); + ReplaceOpWithCheaperOp(&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; } + // TODO: and the otherway around? + /* delete from liverange table also delete from all the points inbetween and the new one */ @@ -1890,19 +2103,27 @@ pack: 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) { @@ -1912,49 +2133,67 @@ findAssignToSym (operand * op, iCode * ic) IC_RESULT (dic)->key == op->key /* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */ ) - { + break; /* found where this temp was defined */ - /* 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))) + /* if we find an usage then we cannot delete it */ + + if (dic->op == IFX) + { + if (IC_COND (dic) && IC_COND (dic)->key == op->key) + return NULL; + } + else if (dic->op == JUMPTABLE) + { + if (IC_JTCOND (dic) && IC_JTCOND (dic)->key == op->key) + return NULL; + } + else + { + if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key) return NULL; - /* if the symbol is in far space then - we should not */ - if (isOperandInFarSpace (IC_RIGHT (dic))) + if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key) return NULL; - /* for + & - operations make sure that - if it is on the stack it is the same - as one of the three operands */ - if ((ic->op == '+' || ic->op == '-') && - OP_SYMBOL (IC_RIGHT (dic))->onStack) - { - - if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key && - IC_LEFT (ic)->key != IC_RIGHT (dic)->key && - IC_RIGHT (ic)->key != IC_RIGHT (dic)->key) - return NULL; - } - - break; - + if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key) + return NULL; } + } - /* if we find an usage then we cannot delete it */ - if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key) - return NULL; + if (!dic) + return NULL; /* didn't find any assignment to op */ - if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key) - return NULL; + /* we are interested only if defined in far space */ + /* or in stack space in case of + & - */ + + /* if assigned to a non-symbol then don't repack regs */ + if (!IS_SYMOP (IC_RIGHT (dic))) + return NULL; + + /* if the symbol is volatile then we should not */ + if (isOperandVolatile (IC_RIGHT (dic), TRUE)) + return NULL; + /* XXX TODO --- should we be passing FALSE to isOperandVolatile()? + What does it mean for an iTemp to be volatile, anyway? Passing + TRUE is more cautious but may prevent possible optimizations */ - if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key) + /* if the symbol is in far space then we should not */ + if (isOperandInFarSpace (IC_RIGHT (dic))) + return NULL; + + /* for + & - operations make sure that + if it is on the stack it is the same + as one of the three operands */ + if ((ic->op == '+' || ic->op == '-') && + OP_SYMBOL (IC_RIGHT (dic))->onStack) + { + + if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key && + IC_LEFT (ic)->key != IC_RIGHT (dic)->key && + IC_RIGHT (ic)->key != IC_RIGHT (dic)->key) return NULL; } - + /* now make sure that the right side of dic is not defined between ic & dic */ if (dic) @@ -1968,9 +2207,47 @@ findAssignToSym (operand * op, iCode * ic) } return dic; +} + +/*-----------------------------------------------------------------*/ +/* reassignAliasedSym - used by packRegsForSupport to replace */ +/* redundant iTemp with equivalent symbol */ +/*-----------------------------------------------------------------*/ +static void +reassignAliasedSym (eBBlock *ebp, iCode *assignment, iCode *use, operand *op) +{ + iCode *ic; + unsigned oldSymKey, newSymKey; + + oldSymKey = op->key; + newSymKey = IC_RIGHT(assignment)->key; + /* only track live ranges of compiler-generated temporaries */ + if (!IS_ITEMP(IC_RIGHT(assignment))) + newSymKey = 0; + /* update the live-value bitmaps */ + for (ic = assignment; ic != use; ic = ic->next) { + bitVectUnSetBit (ic->rlive, oldSymKey); + if (newSymKey != 0) + ic->rlive = bitVectSetBit (ic->rlive, newSymKey); + } + + /* update the sym of the used operand */ + OP_SYMBOL(op) = OP_SYMBOL(IC_RIGHT(assignment)); + op->key = OP_SYMBOL(op)->key; + OP_SYMBOL(op)->accuse = 0; + + /* update the sym's liverange */ + if ( OP_LIVETO(op) < ic->seq ) + setToRange(op, ic->seq, FALSE); + + /* remove the assignment iCode now that its result is unused */ + remiCodeFromeBBlock (ebp, assignment); + bitVectUnSetBit(OP_SYMBOL(IC_RESULT(assignment))->defs, assignment->key); + hTabDeleteItem (&iCodehTab, assignment->key, assignment, DELETE_ITEM, NULL); } + /*-----------------------------------------------------------------*/ /* packRegsForSupport :- reduce some registers for support calls */ @@ -1978,9 +2255,8 @@ findAssignToSym (operand * op, iCode * ic) static int packRegsForSupport (iCode * ic, eBBlock * ebp) { - int change = 0; - iCode *dic, *sic; - + iCode *dic; + /* for the left & right operand :- look to see if the left was assigned a true symbol in far space in that case replace them */ @@ -1990,64 +2266,39 @@ packRegsForSupport (iCode * ic, eBBlock * ebp) { dic = findAssignToSym (IC_LEFT (ic), ic); - if (!dic) - goto right; - - /* found it we need to remove it from the - block */ - for (sic = dic; sic != ic; sic = sic->next) { - bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key); - sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key); - } - - OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic)); - OP_SYMBOL(IC_LEFT(ic))->liveTo = ic->seq; - IC_LEFT (ic)->key = OP_SYMBOL(IC_RIGHT (dic))->key; - remiCodeFromeBBlock (ebp, dic); - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); - change++; + if (dic) + { + /* found it we need to remove it from the block */ + reassignAliasedSym (ebp, dic, ic, IC_LEFT(ic)); + return 1; + } } /* do the same for the right operand */ - right: - if (!change && - IS_ITEMP (IC_RIGHT (ic)) && + if (IS_ITEMP (IC_RIGHT (ic)) && OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq) { iCode *dic = findAssignToSym (IC_RIGHT (ic), ic); - iCode *sic; - if (!dic) - return change; - - /* 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))) + if (dic) { - sym_link *etype = getSpec (operandType (IC_RESULT (dic))); - if (IN_FARSPACE (SPEC_OCLS (etype))) - 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 0; + } + /* found it we need to remove it from the + block */ + reassignAliasedSym (ebp, dic, ic, IC_RIGHT(ic)); + + return 1; } - /* 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); - sic->rlive = bitVectSetBit (sic->rlive, IC_RIGHT (dic)->key); - } - - IC_RIGHT (ic)->operand.symOperand = - IC_RIGHT (dic)->operand.symOperand; - OP_SYMBOL(IC_RIGHT(ic))->liveTo = ic->seq; - IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key; - - remiCodeFromeBBlock (ebp, dic); - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); - change++; } - return change; + return 0; } #define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly) @@ -2077,6 +2328,8 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) !POINTER_GET (ic)) return NULL; + if (ic->op == SEND && ic->argreg != 1) return NULL; + /* this routine will mark the a symbol as used in one instruction use only && if the defintion is local (ie. within the basic block) && has only one definition && @@ -2199,7 +2452,6 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) OP_SYMBOL (op)->ruonly = 1; return sic; - } /*-----------------------------------------------------------------*/ @@ -2231,6 +2483,63 @@ isBitwiseOptimizable (iCode * ic) return FALSE; } +/*-----------------------------------------------------------------*/ +/* isCommutativeOp - tests whether this op cares what order its */ +/* operands are in */ +/*-----------------------------------------------------------------*/ +bool isCommutativeOp(unsigned int op) +{ + if (op == '+' || op == '*' || op == EQ_OP || + op == '^' || op == '|' || op == BITWISEAND) + return TRUE; + else + return FALSE; +} + +/*-----------------------------------------------------------------*/ +/* operandUsesAcc - determines whether the code generated for this */ +/* operand will have to use the accumulator */ +/*-----------------------------------------------------------------*/ +bool operandUsesAcc(operand *op) +{ + if (!op) + return FALSE; + + if (IS_SYMOP(op)) { + symbol *sym = OP_SYMBOL(op); + memmap *symspace; + + if (sym->accuse) + return TRUE; /* duh! */ + + if (IN_STACK(sym->etype) || sym->onStack || + (SPIL_LOC(op) && SPIL_LOC(op)->onStack)) + return TRUE; /* acc is used to calc stack offset */ + + if (IS_ITEMP(op)) + { + if (SPIL_LOC(op)) { + sym = SPIL_LOC(op); /* if spilled, look at spill location */ + } else { + return FALSE; /* more checks? */ + } + } + + symspace = SPEC_OCLS(sym->etype); + + if (sym->iaccess && symspace->paged) + return TRUE; /* must fetch paged indirect sym via accumulator */ + + if (IN_BITSPACE(symspace)) + return TRUE; /* fetching bit vars uses the accumulator */ + + if (IN_FARSPACE(symspace) || IN_CODESPACE(symspace)) + return TRUE; /* fetched via accumulator and dptr */ + } + + return FALSE; +} + /*-----------------------------------------------------------------*/ /* packRegsForAccUse - pack registers for acc use */ /*-----------------------------------------------------------------*/ @@ -2299,12 +2608,12 @@ packRegsForAccUse (iCode * ic) if (uic->op == JUMPTABLE) return; - /* if the usage is not is an assignment - or an arithmetic / bitwise / shift operation then not */ if (POINTER_SET (uic) && getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1) return; + /* if the usage is not is an assignment + or an arithmetic / bitwise / shift operation then not */ if (uic->op != '=' && !IS_ARITHMETIC_OP (uic) && !IS_BITWISE_OP (uic) && @@ -2313,16 +2622,16 @@ packRegsForAccUse (iCode * ic) return; /* if used in ^ operation then make sure right is not a - literl */ + literal (WIML: Why is this?) */ if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic))) return; /* if shift operation make sure right side is not a literal */ + /* WIML: Why is this? */ if (uic->op == RIGHT_OP && (isOperandLiteral (IC_RIGHT (uic)) || getSize (operandType (IC_RESULT (uic))) > 1)) return; - if (uic->op == LEFT_OP && (isOperandLiteral (IC_RIGHT (uic)) || getSize (operandType (IC_RESULT (uic))) > 1)) @@ -2339,22 +2648,23 @@ packRegsForAccUse (iCode * ic) return; #endif - /* if either one of them in far space then we cannot */ - if ((IS_TRUE_SYMOP (IC_LEFT (uic)) && - isOperandInFarSpace (IC_LEFT (uic))) || - (IS_TRUE_SYMOP (IC_RIGHT (uic)) && - isOperandInFarSpace (IC_RIGHT (uic)))) - return; - /* if the usage has only one operand then we can */ if (IC_LEFT (uic) == NULL || IC_RIGHT (uic) == NULL) goto accuse; - /* make sure this is on the left side if not - a '+' since '+' is commutative */ - if (ic->op != '+' && - IC_LEFT (uic)->key != IC_RESULT (ic)->key) + /* if the other operand uses the accumulator then we cannot */ + if ( (IC_LEFT(uic)->key == IC_RESULT(ic)->key && + operandUsesAcc(IC_RIGHT(uic))) || + (IC_RIGHT(uic)->key == IC_RESULT(ic)->key && + operandUsesAcc(IC_LEFT(uic))) ) + return; + + /* make sure this is on the left side if not commutative */ + /* except for '-', which has been written to be able to + handle reversed operands */ + if (!(isCommutativeOp(ic->op) || ic->op == '-') && + IC_LEFT (uic)->key != IC_RESULT (ic)->key) return; #if 0 @@ -2370,35 +2680,20 @@ packRegsForAccUse (iCode * ic) } #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))) - 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))) - goto accuse; - - return; - accuse: OP_SYMBOL (IC_RESULT (ic))->accuse = 1; - } /*-----------------------------------------------------------------*/ /* packForPush - hueristics 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))) return; @@ -2416,32 +2711,46 @@ packForPush (iCode * ic, eBBlock * ebp) if (dic->op != '=' || POINTER_SET (dic)) 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 (dic->seq < ebp->fSeq) { // Evelyn did this + int i; + for (i=0; iseq >= ebpp[i]->fSeq && dic->seq <= ebpp[i]->lSeq) { + ebp=ebpp[i]; + break; + } + } + wassert (i!=blockno); // no way to recover from here } - /* make sure they have the same type */ - { - 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)) - 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 (IS_SYMOP(IC_RIGHT(dic))) { + /* 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 ; + } + /* 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)) + 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; + } + bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,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); - + ReplaceOpWithCheaperOp(&IC_LEFT (ic), IC_RIGHT (dic)); remiCodeFromeBBlock (ebp, dic); - bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); } @@ -2450,10 +2759,11 @@ packForPush (iCode * ic, eBBlock * ebp) /* pressure */ /*-----------------------------------------------------------------*/ static void -packRegisters (eBBlock * ebp) +packRegisters (eBBlock ** ebpp, int blockno) { iCode *ic; int change = 0; + eBBlock *ebp=ebpp[blockno]; while (1) { @@ -2512,7 +2822,8 @@ packRegisters (eBBlock * ebp) 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 ) { + OP_SYMBOL(IC_RIGHT(ic))->remat && + bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1) { 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)) { @@ -2541,30 +2852,45 @@ packRegisters (eBBlock * ebp) if (POINTER_SET (ic)) OP_SYMBOL (IC_RESULT (ic))->uptr = 1; - if (POINTER_GET (ic)) + if (POINTER_GET (ic) && + IS_SYMOP(IC_LEFT (ic))) OP_SYMBOL (IC_LEFT (ic))->uptr = 1; if (!SKIP_IC2 (ic)) { /* if we are using a symbol on the stack then we should say mcs51_ptrRegReq */ + if (options.useXstack && ic->parmPush + && (ic->op == IPUSH || ic->op == IPOP)) + mcs51_ptrRegReq++; if (ic->op == IFX && IS_SYMOP (IC_COND (ic))) mcs51_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack || - OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0); + OP_SYMBOL (IC_COND (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_COND (ic))->etype) == idata) ? 1 : 0); else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic))) mcs51_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack || - OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0); + OP_SYMBOL (IC_JTCOND (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_JTCOND (ic))->etype) == idata) ? 1 : 0); else { if (IS_SYMOP (IC_LEFT (ic))) mcs51_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack || - OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0); + OP_SYMBOL (IC_LEFT (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_LEFT (ic))->etype) == idata) ? 1 : 0); if (IS_SYMOP (IC_RIGHT (ic))) mcs51_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack || - OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0); + OP_SYMBOL (IC_RIGHT (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_RIGHT (ic))->etype) == idata) ? 1 : 0); if (IS_SYMOP (IC_RESULT (ic))) mcs51_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack || - OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0); + OP_SYMBOL (IC_RESULT (ic))->iaccess || + SPEC_OCLS(OP_SYMBOL (IC_RESULT (ic))->etype) == idata) ? 1 : 0); + if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic)) + && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE) + mcs51_ptrRegReq ++; + if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic)) + && getSize (OP_SYMBOL (IC_RESULT (ic))->type) <= (unsigned int) PTRSIZE) + mcs51_ptrRegReq ++; } } @@ -2589,15 +2915,10 @@ packRegisters (eBBlock * ebp) /* some cases the redundant moves can can be eliminated for return statements */ - if ((ic->op == RETURN || ic->op == SEND) && + if ((ic->op == RETURN || (ic->op == SEND && ic->argreg == 1)) && !isOperandInFarSpace (IC_LEFT (ic)) && options.model == MODEL_SMALL) { - if (0 && options.stackAuto) { - /* we should check here if acc will be clobbered for stack - offset calculations */ - } else { - packRegsForOneuse (ic, IC_LEFT (ic), ebp); - } + packRegsForOneuse (ic, IC_LEFT (ic), ebp); } /* if pointer set & left has a size more than @@ -2607,16 +2928,15 @@ packRegisters (eBBlock * ebp) !OP_SYMBOL (IC_RESULT (ic))->remat && !IS_OP_RUONLY (IC_RIGHT (ic)) && getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1) - packRegsForOneuse (ic, IC_RESULT (ic), ebp); /* if pointer get */ if (POINTER_GET (ic) && + IS_SYMOP (IC_LEFT (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) - packRegsForOneuse (ic, IC_LEFT (ic), ebp); @@ -2641,11 +2961,11 @@ packRegisters (eBBlock * ebp) if (IS_ARITHMETIC_OP (dic)) { bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - IC_RESULT (dic) = IC_RESULT (ic); + ReplaceOpWithCheaperOp(&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); + OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); ic = ic->prev; } else @@ -2664,11 +2984,11 @@ packRegisters (eBBlock * ebp) if (dic) { bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key); - IC_RESULT (dic) = IC_RESULT (ic); + ReplaceOpWithCheaperOp(&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); + OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key); ic = ic->prev; } } @@ -2683,7 +3003,7 @@ packRegisters (eBBlock * ebp) */ if (ic->op == IPUSH) { - packForPush (ic, ebp); + packForPush (ic, ebpp, blockno); } @@ -2718,14 +3038,20 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count) int i; setToNull ((void *) &_G.funcrUsed); + setToNull ((void *) &_G.regAssigned); setToNull ((void *) &_G.totRegAssigned); mcs51_ptrRegReq = _G.stackExtend = _G.dataExtend = 0; mcs51_nRegs = 8; /* 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); @@ -2738,6 +3064,8 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count) serialRegAssign (ebbs, count); freeAllRegs (); + //setToNull ((void *) &_G.regAssigned); + //setToNull ((void *) &_G.totRegAssigned); fillGaps(); /* if stack was extended then tell the user */ @@ -2760,7 +3088,17 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count) 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 && mcs51_ptrRegReq) + { + currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R0_IDX); + currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, R1_IDX); + } if (options.dump_rassgn) { @@ -2779,8 +3117,8 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count) /* 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 */ freeAllRegs ();