X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fralloc.c;h=0ecbb87dd5daa51fa6a9084b83b98c5d1b821d7a;hb=fa8d45893981eefc2c18777fbd079939dad4f908;hp=0eb8a3b81a8d3c0e95e3ee1b87ec60eee050ef85;hpb=2b7de736e0cf8462af6677b920d673a3f1bbbf08;p=fw%2Fsdcc diff --git a/src/mcs51/ralloc.c b/src/mcs51/ralloc.c index 0eb8a3b8..0ecbb87d 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 */ /*-----------------------------------------------------------------*/ @@ -514,6 +488,8 @@ createStackSpil (symbol * sym) 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 @@ -597,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++) @@ -620,7 +597,7 @@ spillThis (symbol * sym) } if (sym->usl.spillLoc && !sym->remat) - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return; } @@ -654,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; } @@ -699,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; } @@ -708,7 +685,7 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) { sym = leastUsedLR (selectS); - sym->usl.spillLoc->allocreq = 1; + sym->usl.spillLoc->allocreq++; return sym; } @@ -720,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; } @@ -744,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++) @@ -850,6 +828,41 @@ 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); +} + +/*-----------------------------------------------------------------*/ +/* 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); +} + /*-----------------------------------------------------------------*/ /* symHasReg - symbol has a given register */ /*-----------------------------------------------------------------*/ @@ -949,6 +962,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); } @@ -978,10 +992,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--; @@ -1031,15 +1046,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 */ @@ -1060,8 +1076,10 @@ xchgPositions: regs *tmp = result->regs[i]; result->regs[i] = result->regs[j]; result->regs[j] = tmp; + change ++; goto again; } + return change; } /*-----------------------------------------------------------------*/ @@ -1093,7 +1111,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 */ @@ -1175,6 +1193,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) @@ -1185,10 +1204,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; } } @@ -1198,13 +1213,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) { @@ -1217,6 +1232,113 @@ 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 ; + + assert (clr = hTabItemWithKey(liveRanges,i)); + + /* mark these registers as used */ + for (k = 0 ; k < clr->nRegs ; k++ ) + useReg(clr->regs[k]); + } + + if (willCauseSpill(sym->nRegs,sym->regType)) { + /* NOPE :( clear all registers & and continue */ + freeAllRegs(); + continue ; + } + + /* THERE IS HOPE !!!! */ + for (i=0; i < sym->nRegs ; i++ ) { + if (sym->regType == REG_PTR) + sym->regs[i] = getRegPtrNoSpil (); + else + sym->regs[i] = getRegGprNoSpil (); + } + + /* for all its definitions check if the registers + allocated needs positioning NOTE: we can position + only ONCE if more than One positioning required + then give up */ + sym->isspilt = 0; + for (i = 0 ; i < sym->defs->size ; i++ ) { + if (bitVectBitValue(sym->defs,i)) { + iCode *ic; + if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ; + if (SKIP_IC(ic)) continue; + assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */ + /* if left is assigned to registers */ + if (IS_SYMOP(IC_LEFT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) { + pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic))); + } + if (IS_SYMOP(IC_RIGHT(ic)) && + bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) { + pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic))); + } + if (pdone > 1) break; + } + } + 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 */ /*-----------------------------------------------------------------*/ @@ -1434,10 +1556,7 @@ regTypeNum (eBBlock *ebbs) } /* 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))) && @@ -1447,10 +1566,10 @@ regTypeNum (eBBlock *ebbs) { - /* 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); @@ -1707,6 +1826,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) @@ -1724,6 +1844,7 @@ 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); return 1; @@ -1830,12 +1951,16 @@ packRegsForSupport (iCode * ic, eBBlock * ebp) /* found it we need to remove it from the block */ - for (sic = dic; sic != ic; sic = sic->next) + 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++; } @@ -1862,14 +1987,18 @@ packRegsForSupport (iCode * ic, eBBlock * ebp) } /* found it we need to remove it from the block */ - for (sic = dic; sic != ic; sic = sic->next) + 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++; } @@ -1904,6 +2033,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 && @@ -1944,7 +2075,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; @@ -2070,6 +2202,17 @@ packRegsForAccUse (iCode * 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) @@ -2145,9 +2288,14 @@ 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; +#else + if (isOperandOnStack(IC_RESULT(uic))) + return; +#endif /* if either one of them in far space then we cannot */ if ((IS_TRUE_SYMOP (IC_LEFT (uic)) && @@ -2251,6 +2399,7 @@ packForPush (iCode * ic, eBBlock * ebp) 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); } @@ -2398,7 +2547,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) { @@ -2449,8 +2598,10 @@ 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); ic = ic->prev; @@ -2470,8 +2621,10 @@ 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); ic = ic->prev; @@ -2523,6 +2676,7 @@ 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; @@ -2541,6 +2695,9 @@ mcs51_assignRegisters (eBBlock ** ebbs, int count) /* and serially allocate registers */ serialRegAssign (ebbs, count); + freeAllRegs (); + fillGaps(); + /* if stack was extended then tell the user */ if (_G.stackExtend) {