X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fralloc.c;h=a426dbab114c3bcbf733cfba3217ef890ee7c3ae;hb=420728259e942035b513094f2fc820fbc08fa8ee;hp=c4b0bd9d373e43bbc9cd693ef94b503e877b7a1e;hpb=d347a4fb785c3a716e27a87c95cf2f8c4ff59027;p=fw%2Fsdcc diff --git a/src/mcs51/ralloc.c b/src/mcs51/ralloc.c index c4b0bd9d..a426dbab 100644 --- a/src/mcs51/ralloc.c +++ b/src/mcs51/ralloc.c @@ -37,6 +37,7 @@ /*-----------------------------------------------------------------*/ extern void gen51Code (iCode *); +#define D(x) /* Global data */ static struct @@ -44,6 +45,7 @@ static struct bitVect *spiltSet; set *stackSpil; bitVect *regAssigned; + bitVect *totRegAssigned; /* final set of LRs that got into registers */ short blockSpil; int slocNum; bitVect *funcrUsed; /* registers used in a function */ @@ -76,6 +78,7 @@ regs regs8051[] = }; int mcs51_nRegs = 13; static void spillThis (symbol *); +static void freeAllRegs (); /*-----------------------------------------------------------------*/ /* allocReg - allocates register of given type */ @@ -179,31 +182,13 @@ nfreeRegsType (int type) return nFreeRegs (type); } - /*-----------------------------------------------------------------*/ -/* allDefsOutOfRange - all definitions are out of a range */ +/* useReg - marks a register as used */ /*-----------------------------------------------------------------*/ -static bool -allDefsOutOfRange (bitVect * defs, int fseq, int toseq) +static void +useReg (regs * reg) { - 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; + reg->isFree = 0; } /*-----------------------------------------------------------------*/ @@ -282,17 +267,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 */ /*-----------------------------------------------------------------*/ @@ -513,6 +487,9 @@ createStackSpil (symbol * sym) sloc->etype = getSpec (sloc->type); SPEC_SCLS (sloc->etype) = S_DATA; 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` onto the external stack since : so we @@ -596,10 +573,11 @@ spillThis (symbol * sym) /* mark it has spilt & put it in the spilt set */ - sym->isspilt = 1; + sym->isspilt = sym->spillA = 1; _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key); bitVectUnSetBit (_G.regAssigned, sym->key); + bitVectUnSetBit (_G.totRegAssigned, sym->key); for (i = 0; i < sym->nRegs; i++) @@ -619,7 +597,7 @@ spillThis (symbol * sym) } if (sym->usl.spillLoc && !sym->remat) - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return; } @@ -653,7 +631,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) sym->usl.spillLoc->name)); sym->spildir = 1; /* mark it as allocation required */ - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } @@ -698,7 +676,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) sym = leastUsedLR (selectS); /* mark this as allocation required */ - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } @@ -707,7 +685,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) { sym = leastUsedLR (selectS); - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } @@ -719,7 +697,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) /* return a created spil location */ sym = createStackSpil (leastUsedLR (selectS)); - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } @@ -743,12 +721,13 @@ spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym) ssym = selectSpil (ic, ebp, forSym); /* mark it as spilt */ - ssym->isspilt = 1; + ssym->isspilt = ssym->spillA = 1; _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key); /* mark it as not register assigned & take it away from the set */ bitVectUnSetBit (_G.regAssigned, ssym->key); + bitVectUnSetBit (_G.totRegAssigned, ssym->key); /* mark the registers as free */ for (i = 0; i < ssym->nRegs; i++) @@ -849,6 +828,47 @@ tryAgain: goto tryAgain; } +/*-----------------------------------------------------------------*/ +/* getRegPtrNoSpil - get it cannot split */ +/*-----------------------------------------------------------------*/ +static regs *getRegPtrNoSpil() +{ + regs *reg; + + /* try for a ptr type */ + if ((reg = allocReg (REG_PTR))) + return reg; + + /* try for gpr type */ + if ((reg = allocReg (REG_GPR))) + return reg; + + assert(0); + + /* just to make the compiler happy */ + return 0; +} + +/*-----------------------------------------------------------------*/ +/* getRegGprNoSpil - get it cannot split */ +/*-----------------------------------------------------------------*/ +static regs *getRegGprNoSpil() +{ + + regs *reg; + if ((reg = allocReg (REG_GPR))) + return reg; + + if (!mcs51_ptrRegReq) + if ((reg = allocReg (REG_PTR))) + return reg; + + assert(0); + + /* just to make the compiler happy */ + return 0; +} + /*-----------------------------------------------------------------*/ /* symHasReg - symbol has a given register */ /*-----------------------------------------------------------------*/ @@ -948,6 +968,7 @@ deassignLRs (iCode * ic, eBBlock * ebp) result->regs[i] = getRegGpr (ic, ebp, result); _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key); + _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key); } @@ -977,10 +998,11 @@ reassignLR (operand * op) int i; /* not spilt any more */ - sym->isspilt = sym->blockSpil = sym->remainSpil = 0; + sym->isspilt = sym->spillA = sym->blockSpil = sym->remainSpil = 0; bitVectUnSetBit (_G.spiltSet, sym->key); _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key); + _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key); _G.blockSpil--; @@ -1030,15 +1052,16 @@ willCauseSpill (int nr, int rt) /* ult and operand, if this happens make sure they are in the same */ /* position as the operand otherwise chaos results */ /*-----------------------------------------------------------------*/ -static void -positionRegs (symbol * result, symbol * opsym, int lineno) +static int +positionRegs (symbol * result, symbol * opsym) { int count = min (result->nRegs, opsym->nRegs); int i, j = 0, shared = 0; + int change = 0; /* if the result has been spilt then cannot share */ if (opsym->isspilt) - return; + return 0; again: shared = 0; /* first make sure that they actually share */ @@ -1059,8 +1082,10 @@ xchgPositions: regs *tmp = result->regs[i]; result->regs[i] = result->regs[j]; result->regs[j] = tmp; + change ++; goto again; } + return change; } /*-----------------------------------------------------------------*/ @@ -1092,7 +1117,7 @@ serialRegAssign (eBBlock ** ebbs, int count) /* if result is present && is a true symbol */ if (IC_RESULT (ic) && ic->op != IFX && IS_TRUE_SYMOP (IC_RESULT (ic))) - OP_SYMBOL (IC_RESULT (ic))->allocreq = 1; + OP_SYMBOL (IC_RESULT (ic))->allocreq++; /* take away registers from live ranges that end at this instruction */ @@ -1157,8 +1182,11 @@ serialRegAssign (eBBlock ** ebbs, int count) /* 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)) { - spillThis (sym); - continue; + /* 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; + } } } } @@ -1171,6 +1199,7 @@ serialRegAssign (eBBlock ** ebbs, int count) } /* 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) @@ -1181,10 +1210,6 @@ serialRegAssign (eBBlock ** ebbs, int count) /* 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__); - } break; } } @@ -1194,13 +1219,13 @@ serialRegAssign (eBBlock ** ebbs, int count) if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) && OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') { positionRegs (OP_SYMBOL (IC_RESULT (ic)), - OP_SYMBOL (IC_LEFT (ic)), ic->lineno); + 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)), ic->lineno); + OP_SYMBOL (IC_RIGHT (ic))); } if (ptrRegSet) { @@ -1213,6 +1238,114 @@ serialRegAssign (eBBlock ** ebbs, int count) } } +/*-----------------------------------------------------------------*/ +/* fillGaps - Try to fill in the Gaps left by Pass1 */ +/*-----------------------------------------------------------------*/ +static void fillGaps() +{ + symbol *sym =NULL; + int key =0; + + 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 ; + + 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 + 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; + } + } + for (i = 0 ; i < sym->uses->size ; i++ ) { + if (bitVectBitValue(sym->uses,i)) { + iCode *ic; + if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; + if (SKIP_IC(ic)) continue; + if (!IS_ASSIGN_ICODE(ic)) continue ; + + /* if result is assigned to registers */ + if (IS_SYMOP(IC_RESULT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) { + pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic))); + } + if (pdone > 1) break; + } + } + /* had to position more than once GIVE UP */ + if (pdone > 1) { + /* UNDO all the changes we made to try this */ + sym->isspilt = 1; + for (i=0; i < sym->nRegs ; i++ ) { + sym->regs[i] = NULL; + } + freeAllRegs(); + D(printf ("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN")); + 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--; + freeAllRegs(); + } +} + /*-----------------------------------------------------------------*/ /* rUmaskForOp :- returns register mask for an operand */ /*-----------------------------------------------------------------*/ @@ -1340,6 +1473,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); } @@ -1396,7 +1530,7 @@ rematStr (symbol * sym) /* regTypeNum - computes the type & number of registers required */ /*-----------------------------------------------------------------*/ static void -regTypeNum () +regTypeNum (eBBlock *ebbs) { symbol *sym; int k; @@ -1430,10 +1564,7 @@ regTypeNum () } /* 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))) && @@ -1443,12 +1574,11 @@ regTypeNum () { - /* if remat in data space */ + /* and that pointer is 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) + DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER) { - /* create a psuedo symbol & force a spil */ symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1); psym->type = sym->type; @@ -1456,6 +1586,16 @@ regTypeNum () 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 continue; } @@ -1694,6 +1834,7 @@ 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) @@ -1711,20 +1852,31 @@ 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_SET ((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) { @@ -1734,37 +1886,7 @@ findAssignToSym (operand * op, iCode * ic) IC_RESULT (dic)->key == op->key /* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */ ) - { - - /* we are interested only if defined in far space */ - /* or in stack space in case of + & - */ - - /* if assigned to a non-symbol then return - 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; - - /* 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; - - } + break; /* found where this temp was defined */ /* if we find an usage then we cannot delete it */ if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key) @@ -1777,6 +1899,40 @@ findAssignToSym (operand * op, iCode * ic) return NULL; } + if (!dic) + return NULL; /* didn't find any assignment to op */ + + /* 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 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) @@ -1790,9 +1946,46 @@ 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; + + /* 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 */ @@ -1800,9 +1993,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 */ @@ -1812,56 +2004,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); - - OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic)); - IC_LEFT (ic)->key = OP_SYMBOL(IC_RIGHT (dic))->key; - remiCodeFromeBBlock (ebp, dic); - 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); - - IC_RIGHT (ic)->operand.symOperand = - IC_RIGHT (dic)->operand.symOperand; - IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key; - - remiCodeFromeBBlock (ebp, dic); - 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) @@ -1891,6 +2066,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 && @@ -1931,7 +2108,8 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) a function call */ if (dic->op == CALL || dic->op == PCALL) { - if (ic->op != SEND && ic->op != RETURN) + if (ic->op != SEND && ic->op != RETURN && + !POINTER_SET(ic) && !POINTER_GET(ic)) { OP_SYMBOL (op)->ruonly = 1; return dic; @@ -2044,6 +2222,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 */ /*-----------------------------------------------------------------*/ @@ -2052,6 +2287,22 @@ packRegsForAccUse (iCode * ic) { iCode *uic; + /* if this is an aggregate, e.g. a one byte char array */ + if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) { + 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) @@ -2096,12 +2347,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) && @@ -2110,16 +2361,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)) @@ -2127,26 +2378,32 @@ packRegsForAccUse (iCode * ic) /* 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) return; - - /* if either one of them in far space then we cannot */ - if ((IS_TRUE_SYMOP (IC_LEFT (uic)) && - isOperandInFarSpace (IC_LEFT (uic))) || - (IS_TRUE_SYMOP (IC_RIGHT (uic)) && - isOperandInFarSpace (IC_RIGHT (uic)))) +#else + if (isOperandOnStack(IC_RESULT(uic))) return; +#endif /* if the usage has only one operand then we can */ if (IC_LEFT (uic) == NULL || IC_RIGHT (uic) == NULL) goto accuse; - /* make sure this is on the left side if not - a '+' since '+' is commutative */ - if (ic->op != '+' && - IC_LEFT (uic)->key != IC_RESULT (ic)->key) + /* 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 @@ -2162,35 +2419,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; @@ -2208,30 +2450,44 @@ 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 */ + { + 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); - remiCodeFromeBBlock (ebp, dic); hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); } @@ -2241,10 +2497,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) { @@ -2380,7 +2637,7 @@ 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) { @@ -2431,10 +2688,12 @@ packRegisters (eBBlock * ebp) { 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); + OP_DEFS_SET ((IC_RESULT (dic)), bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key)); ic = ic->prev; } else @@ -2452,10 +2711,12 @@ packRegisters (eBBlock * ebp) iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp); if (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); + OP_DEFS_SET ((IC_RESULT (dic)), bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key)); ic = ic->prev; } } @@ -2470,7 +2731,7 @@ packRegisters (eBBlock * ebp) */ if (ic->op == IPUSH) { - packForPush (ic, ebp); + packForPush (ic, ebpp, blockno); } @@ -2485,7 +2746,7 @@ packRegisters (eBBlock * ebp) if ((IS_ARITHMETIC_OP (ic) || IS_CONDITIONAL(ic) || IS_BITWISE_OP (ic) - || ic->op == LEFT_OP || ic->op == RIGHT_OP + || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic))) ) && IS_ITEMP (IC_RESULT (ic)) && @@ -2505,24 +2766,28 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count) int i; setToNull ((void *) &_G.funcrUsed); + 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); if (options.dump_pack) dumpEbbsToFileExt (DUMP_PACK, ebbs, count); /* first determine for each live range the number of registers & the type of registers required for each */ - regTypeNum (); + regTypeNum (*ebbs); /* and serially allocate registers */ serialRegAssign (ebbs, count); + freeAllRegs (); + fillGaps(); + /* if stack was extended then tell the user */ if (_G.stackExtend) {