X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Favr%2Fralloc.c;h=512edc4fdf7f068101e6c1677cfac87a316ef301;hb=6cb515b98c5977589446a39a6271958383d0a3da;hp=9d93111cd5127c6f732fb71e6e81ba02658fed09;hpb=b01d97125ec089bca855fd4ae9ee395b5a52e96b;p=fw%2Fsdcc diff --git a/src/avr/ralloc.c b/src/avr/ralloc.c index 9d93111c..512edc4f 100644 --- a/src/avr/ralloc.c +++ b/src/avr/ralloc.c @@ -56,37 +56,37 @@ int avr_ptrRegReq; /* pointer register required */ /* AVR registers */ regs regsAVR[] = { {REG_GPR|REG_PAIR, R0_IDX, REG_GPR|REG_PAIR, "r0", "r0", "", 0, 0, 0}, /* scratch */ - {REG_GPR, R1_IDX, REG_GPR , "r1", "r1", "", 0, 0, 0}, /* scratch */ + {REG_GPR, R1_IDX, REG_GPR , "r1", "r1", "", 0, 0, 0}, /* scratch */ {REG_GPR|REG_PAIR, R2_IDX, REG_GPR|REG_PAIR, "r2", "r2", "", 0, 1, 1}, /* gpr */ - {REG_GPR, R3_IDX, REG_GPR , "r3", "r3", "", 0, 1, 1}, /* gpr */ + {REG_GPR, R3_IDX, REG_GPR , "r3", "r3", "", 0, 1, 1}, /* gpr */ {REG_GPR|REG_PAIR, R4_IDX, REG_GPR|REG_PAIR, "r4", "r4", "", 0, 1, 1}, /* gpr */ - {REG_GPR, R5_IDX, REG_GPR , "r5", "r5", "", 0, 1, 1}, /* gpr */ + {REG_GPR, R5_IDX, REG_GPR , "r5", "r5", "", 0, 1, 1}, /* gpr */ {REG_GPR|REG_PAIR, R6_IDX, REG_GPR|REG_PAIR, "r6", "r6", "", 0, 1, 1}, /* gpr */ - {REG_GPR, R7_IDX, REG_GPR , "r7", "r7", "", 0, 1, 1}, /* gpr */ + {REG_GPR, R7_IDX, REG_GPR , "r7", "r7", "", 0, 1, 1}, /* gpr */ {REG_GPR|REG_PAIR, R8_IDX, REG_GPR|REG_PAIR, "r8", "r8", "", 0, 1, 1}, /* gpr */ - {REG_GPR, R9_IDX, REG_GPR , "r9", "r9", "", 0, 1, 1}, /* gpr */ + {REG_GPR, R9_IDX, REG_GPR , "r9", "r9", "", 0, 1, 1}, /* gpr */ {REG_GPR|REG_PAIR, R10_IDX,REG_GPR|REG_PAIR, "r10", "r10","",0, 1, 1}, /* gpr */ - {REG_GPR, R11_IDX,REG_GPR , "r11", "r11","",0, 1, 1}, /* gpr */ + {REG_GPR, R11_IDX,REG_GPR , "r11", "r11","",0, 1, 1}, /* gpr */ {REG_GPR|REG_PAIR, R12_IDX,REG_GPR|REG_PAIR, "r12", "r12","",0, 1, 1}, /* gpr */ - {REG_GPR, R13_IDX,REG_GPR , "r13", "r13","",0, 1, 1}, /* gpr */ + {REG_GPR, R13_IDX,REG_GPR , "r13", "r13","",0, 1, 1}, /* gpr */ {REG_GPR|REG_PAIR, R14_IDX,REG_GPR|REG_PAIR, "r14", "r14","",0, 1, 1}, /* gpr */ - {REG_GPR, R15_IDX,REG_GPR , "r15", "r15","",0, 1, 1}, /* gpr */ + {REG_GPR, R15_IDX,REG_GPR , "r15", "r15","",0, 1, 1}, /* gpr */ {REG_GPR|REG_PAIR, R16_IDX,REG_GPR|REG_PAIR, "r16", "r16","",0, 1, 0}, /* parm/gpr */ - {REG_GPR, R17_IDX,REG_GPR , "r17", "r17","",0, 1, 0}, /* parm/gpr */ + {REG_GPR, R17_IDX,REG_GPR , "r17", "r17","",0, 1, 0}, /* parm/gpr */ {REG_GPR|REG_PAIR, R18_IDX,REG_GPR|REG_PAIR, "r18", "r18","",0, 1, 0}, /* parm/gpr */ - {REG_GPR, R19_IDX,REG_GPR , "r19", "r19","",0, 1, 0}, /* parm/gpr */ + {REG_GPR, R19_IDX,REG_GPR , "r19", "r19","",0, 1, 0}, /* parm/gpr */ {REG_GPR|REG_PAIR, R20_IDX,REG_GPR|REG_PAIR, "r20", "r20","",0, 1, 0}, /* parm/gpr */ - {REG_GPR, R21_IDX,REG_GPR , "r21", "r21","",0, 1, 0}, /* parm/gpr */ + {REG_GPR, R21_IDX,REG_GPR , "r21", "r21","",0, 1, 0}, /* parm/gpr */ {REG_GPR|REG_PAIR, R22_IDX,REG_GPR|REG_PAIR, "r22", "r22","",0, 1, 0}, /* parm/gpr */ - {REG_GPR, R23_IDX,REG_GPR , "r23", "r23","",0, 1, 0}, /* parm/gpr */ + {REG_GPR, R23_IDX,REG_GPR , "r23", "r23","",0, 1, 0}, /* parm/gpr */ {REG_GPR|REG_PAIR, R24_IDX,REG_GPR|REG_PAIR, "r24", "r24","",0, 0, 0}, /* scratch */ - {REG_GPR, R25_IDX,REG_GPR , "r25", "r25","",0, 0, 0}, /* scratch */ + {REG_GPR, R25_IDX,REG_GPR , "r25", "r25","",0, 0, 0}, /* scratch */ {REG_GPR|REG_PAIR, R26_IDX,REG_GPR|REG_PAIR, "r26", "r26","",0, 1, 1}, /* used as pointer reg X */ - {REG_GPR, R27_IDX,REG_GPR , "r27", "r27","",0, 1, 1}, /* used as pointer reg X */ + {REG_GPR, R27_IDX,REG_GPR , "r27", "r27","",0, 1, 1}, /* used as pointer reg X */ {REG_GPR|REG_PAIR, R28_IDX,REG_GPR|REG_PAIR, "r28", "r28","",0, 1, 0}, /* stack frame Y */ - {REG_GPR, R29_IDX,REG_GPR , "r29", "r29","",0, 1, 0}, /* stack frame Y */ + {REG_GPR, R29_IDX,REG_GPR , "r29", "r29","",0, 1, 0}, /* stack frame Y */ {REG_GPR|REG_PAIR, R30_IDX,REG_GPR|REG_PAIR, "r30", "r30","",0, 1, 1}, /* used as pointer reg Z */ - {REG_GPR, R31_IDX,REG_GPR , "r31", "r31","",0, 1, 1}, /* used as pointer reg Z */ + {REG_GPR, R31_IDX,REG_GPR , "r31", "r31","",0, 1, 1}, /* used as pointer reg Z */ {REG_PTR, X_IDX, REG_PTR, "X", "X", "", 0, 1, 0}, {REG_PTR, Z_IDX, REG_PTR, "Z", "Z", "", 0, 1, 0}, }; @@ -95,6 +95,343 @@ int avr_fReg = 0; /* first allocatable register */ static void spillThis (symbol *); +#if 0 +// PENDING: Unused +/*-----------------------------------------------------------------*/ +/* findAssignToSym : scanning backwards looks for first assig found */ +/*-----------------------------------------------------------------*/ +static iCode * +findAssignToSym (operand * op, iCode * ic) +{ + iCode *dic; + + for (dic = ic->prev; dic; dic = dic->prev) { + + /* if definition by assignment */ + if (dic->op == '=' && + !POINTER_SET (dic) && IC_RESULT (dic)->key == op->key +/* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */ + ) { + + /* we are interested only if defined in far space */ + /* or in stack space in case of + & - */ + + /* if assigned to a non-symbol then return + true */ + if (!IS_SYMOP (IC_RIGHT (dic))) + break; + + /* 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; + + } + + /* if we find an usage then we cannot delete it */ + if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key) + return NULL; + + if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key) + return NULL; + + if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key) + return NULL; + } + + /* now make sure that the right side of dic + is not defined between ic & dic */ + if (dic) { + iCode *sic = dic->next; + + for (; sic != ic; sic = sic->next) + if (IC_RESULT (sic) && + IC_RESULT (sic)->key == IC_RIGHT (dic)->key) + return NULL; + } + + return dic; + + +} + +/*-----------------------------------------------------------------*/ +/* packForPush - hueristics to reduce iCode for pushing */ +/*-----------------------------------------------------------------*/ +static void +packForPush (iCode * ic, eBBlock * ebp) +{ + iCode *dic; + + if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic))) + return; + + /* must have only definition & one usage */ + if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 || + bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1) + return; + + /* find the definition */ + if (!(dic = hTabItemWithKey (iCodehTab, + bitVectFirstBit (OP_DEFS + (IC_LEFT (ic)))))) + return; + + if (dic->op != '=' || POINTER_SET (dic)) + return; + + /* 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); +} + +/*-----------------------------------------------------------------*/ +/* packRegsForSupport :- reduce some registers for support calls */ +/*-----------------------------------------------------------------*/ +static int +packRegsForSupport (iCode * ic, eBBlock * ebp) +{ + int change = 0; + /* for the left & right operand :- look to see if the + left was assigned a true symbol in far space in that + case replace them */ + if (IS_ITEMP (IC_LEFT (ic)) && + OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq) { + iCode *dic = findAssignToSym (IC_LEFT (ic), ic); + iCode *sic; + + 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); + + IC_LEFT (ic)->operand.symOperand = + IC_RIGHT (dic)->operand.symOperand; + IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key; + remiCodeFromeBBlock (ebp, dic); + hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); + change++; + } + + /* do the same for the right operand */ + right: + if (!change && + 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))) { + sym_link *etype = + getSpec (operandType (IC_RESULT (dic))); + if (IN_FARSPACE (SPEC_OCLS (etype))) + return change; + } + /* found it we need to remove it from the + block */ + for (sic = dic; sic != ic; sic = sic->next) + bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key); + + 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; +} + +/*-----------------------------------------------------------------*/ +/* farSpacePackable - returns the packable icode for far variables */ +/*-----------------------------------------------------------------*/ +static iCode * +farSpacePackable (iCode * ic) +{ + iCode *dic; + + /* go thru till we find a definition for the + symbol on the right */ + for (dic = ic->prev; dic; dic = dic->prev) { + + /* if the definition is a call then no */ + if ((dic->op == CALL || dic->op == PCALL) && + IC_RESULT (dic)->key == IC_RIGHT (ic)->key) { + return NULL; + } + + /* if shift by unknown amount then not */ + if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) && + IC_RESULT (dic)->key == IC_RIGHT (ic)->key) + return NULL; + + /* if pointer get and size > 1 */ + if (POINTER_GET (dic) && + getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > + 1) return NULL; + + if (POINTER_SET (dic) && + 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 (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 (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic))) { + if ((dic->op == LEFT_OP || + dic->op == RIGHT_OP || + dic->op == '-') && + IS_OP_LITERAL (IC_RIGHT (dic))) return NULL; + else + return dic; + } + } + + return NULL; +} + +/*-----------------------------------------------------------------*/ +/* rematStr - returns the rematerialized string for a remat var */ +/*-----------------------------------------------------------------*/ +static char * +rematStr (symbol * sym) +{ + char *s = buffer; + iCode *ic = sym->rematiCode; + + while (1) { + + /* if plus or minus print the right hand side */ + if (ic->op == '+' || ic->op == '-') { + sprintf (s, "0x%04x %c ", + (int) operandLitValue (IC_RIGHT (ic)), + ic->op); + s += strlen (s); + ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; + continue; + } + + /* we reached the end */ + sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname); + break; + } + + return buffer; +} + +/*-----------------------------------------------------------------*/ +/* isSpiltOnStack - returns true if the spil location is on stack */ +/*-----------------------------------------------------------------*/ +static bool +isSpiltOnStack (symbol * sym) +{ + sym_link *etype; + + if (!sym) + return FALSE; + + if (!sym->isspilt) + return FALSE; + + + if (!sym->usl.spillLoc) + return FALSE; + + etype = getSpec (sym->usl.spillLoc->type); + if (IN_STACK (etype)) + return TRUE; + + return FALSE; +} + +/*-----------------------------------------------------------------*/ +/* spillLRWithPtrReg :- will spil those live ranges which use PTR */ +/*-----------------------------------------------------------------*/ +static void +spillLRWithPtrReg (symbol * forSym) +{ + symbol *lrsym; + regs *X, *Z, *X1, *Z1; + int k; + + if (!_G.regAssigned || bitVectIsZero (_G.regAssigned)) + return; + + X = avr_regWithIdx (R26_IDX); + X1= avr_regWithIdx (R27_IDX); + Z = avr_regWithIdx (R30_IDX); + Z1= avr_regWithIdx (R31_IDX); + + /* for all live ranges */ + for (lrsym = hTabFirstItem (liveRanges, &k); lrsym; + lrsym = hTabNextItem (liveRanges, &k)) { + int j; + + /* if no registers assigned to it or + spilt */ + /* if it does not overlap with this then + not need to spill it */ + + if (lrsym->isspilt || !lrsym->nRegs || + (lrsym->liveTo < forSym->liveFrom)) continue; + + /* go thru the registers : if it is either + r0 or r1 then spil it */ + for (j = 0; j < lrsym->nRegs; j++) + if (lrsym->regs[j] == X || lrsym->regs[j] == Z || + lrsym->regs[j] == X1 || lrsym->regs[j] == Z1) { + spillThis (lrsym); + break; + } + } + +} +#endif + /*-----------------------------------------------------------------*/ /* allocReg - allocates register of given type */ /*-----------------------------------------------------------------*/ @@ -212,31 +549,6 @@ nfreeRegsType (int type) return nFreeRegs (type); } - -/*-----------------------------------------------------------------*/ -/* 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 */ /*-----------------------------------------------------------------*/ @@ -298,16 +610,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)); -} - /*-----------------------------------------------------------------*/ /* notUsedInRemaining - not used or defined in remain of the block */ /*-----------------------------------------------------------------*/ @@ -390,7 +692,7 @@ leastUsedLR (set * sset) } - setToNull ((void **) &sset); + setToNull ((void *) &sset); sym->blockSpil = 0; return sym; } @@ -442,49 +744,6 @@ DEFSETFUNC (isFree) return 0; } -/*-----------------------------------------------------------------*/ -/* spillLRWithPtrReg :- will spil those live ranges which use PTR */ -/*-----------------------------------------------------------------*/ -static void -spillLRWithPtrReg (symbol * forSym) -{ - symbol *lrsym; - regs *X, *Z, *X1, *Z1; - int k; - - if (!_G.regAssigned || bitVectIsZero (_G.regAssigned)) - return; - - X = avr_regWithIdx (R26_IDX); - X1= avr_regWithIdx (R27_IDX); - Z = avr_regWithIdx (R30_IDX); - Z1= avr_regWithIdx (R31_IDX); - - /* for all live ranges */ - for (lrsym = hTabFirstItem (liveRanges, &k); lrsym; - lrsym = hTabNextItem (liveRanges, &k)) { - int j; - - /* if no registers assigned to it or - spilt */ - /* if it does not overlap with this then - not need to spill it */ - - if (lrsym->isspilt || !lrsym->nRegs || - (lrsym->liveTo < forSym->liveFrom)) continue; - - /* go thru the registers : if it is either - r0 or r1 then spil it */ - for (j = 0; j < lrsym->nRegs; j++) - if (lrsym->regs[j] == X || lrsym->regs[j] == Z || - lrsym->regs[j] == X1 || lrsym->regs[j] == Z1) { - spillThis (lrsym); - break; - } - } - -} - /*-----------------------------------------------------------------*/ /* createStackSpil - create a location on the stack to spil */ /*-----------------------------------------------------------------*/ @@ -570,31 +829,6 @@ createStackSpil (symbol * sym) return sym; } -/*-----------------------------------------------------------------*/ -/* isSpiltOnStack - returns true if the spil location is on stack */ -/*-----------------------------------------------------------------*/ -static bool -isSpiltOnStack (symbol * sym) -{ - sym_link *etype; - - if (!sym) - return FALSE; - - if (!sym->isspilt) - return FALSE; - - - if (!sym->usl.spillLoc) - return FALSE; - - etype = getSpec (sym->usl.spillLoc->type); - if (IN_STACK (etype)) - return TRUE; - - return FALSE; -} - /*-----------------------------------------------------------------*/ /* spillThis - spils a specific operand */ /*-----------------------------------------------------------------*/ @@ -667,7 +901,8 @@ selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym) /* check if there are any live ranges that not used in the remainder of the block */ if (!_G.blockSpil && - (selectS = + !isiCodeInFunctionCall (ic) && + (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic))) { sym = leastUsedLR (selectS); if (sym != forSym) { @@ -929,6 +1164,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 */ @@ -1070,10 +1306,10 @@ static int needsPair (iCode *ic) int ikey = bitVectFirstBit(uses_defs); iCode *uic = hTabItemWithKey(iCodehTab,ikey); sym_link *otype = NULL; + bitVectUnSetBit(uses_defs,ikey); if (!uic) continue; otype = (IC_RIGHT(uic) ? operandType(IC_RIGHT(uic)) : NULL); if (otype && IS_LITERAL(otype)) return 1; - bitVectUnSetBit(uses_defs,ikey); } return 0; } @@ -1129,6 +1365,12 @@ serialRegAssign (eBBlock ** ebbs, int count) int willCS; int j=0; + /* Make sure any spill location is definately allocated */ + if (sym->isspilt && !sym->remat && sym->usl.spillLoc && + !sym->usl.spillLoc->allocreq) { + sym->usl.spillLoc->allocreq++; + } + /* if it does not need or is spilt or is already assigned to registers or will not live beyond this instructions */ @@ -1159,6 +1401,17 @@ serialRegAssign (eBBlock ** ebbs, int count) continue; } + /* If the live range preceeds the point of definition + then ideally we must take into account registers that + have been allocated after sym->liveFrom but freed + before ic->seq. This is complicated, so spill this + symbol instead and let fillGaps handle the allocation. */ + if (sym->liveFrom < ic->seq) + { + spillThis (sym); + continue; + } + /* if it has a spillocation & is used less than all other live ranges then spill this */ if (willCS) { @@ -1345,51 +1598,24 @@ createRegMask (eBBlock ** ebbs, int count) if (!sym->nRegs || sym->isspilt) continue; - /* for all the registers allocated to it */ - for (k = 0; k < sym->nRegs; k++) { - if (sym->regs[k]) { - ic->rMask = bitVectSetBit (ic-> rMask, sym->regs[k]->rIdx); - /* special case for X & Z registers */ - if (k == R26_IDX || k == R27_IDX) - ic->rMask = bitVectSetBit (ic->rMask, X_IDX); - if (k == R30_IDX || k == R31_IDX) - ic->rMask = bitVectSetBit (ic->rMask, Z_IDX); - } - } - } - } - } -} - -/*-----------------------------------------------------------------*/ -/* rematStr - returns the rematerialized string for a remat var */ -/*-----------------------------------------------------------------*/ -static char * -rematStr (symbol * sym) -{ - char *s = buffer; - iCode *ic = sym->rematiCode; - - while (1) { - - /* if plus or minus print the right hand side */ - if (ic->op == '+' || ic->op == '-') { - sprintf (s, "0x%04x %c ", - (int) operandLitValue (IC_RIGHT (ic)), - ic->op); - s += strlen (s); - ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; - continue; - } - - /* we reached the end */ - sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname); - break; + /* for all the registers allocated to it */ + for (k = 0; k < sym->nRegs; k++) { + if (sym->regs[k]) { + int rIdx = sym->regs[k]->rIdx; + ic->rMask = bitVectSetBit (ic-> rMask,rIdx); + /* special case for X & Z registers */ + if (rIdx == R26_IDX || rIdx == R27_IDX) + ic->rMask = bitVectSetBit (ic->rMask, X_IDX); + if (rIdx == R30_IDX || rIdx == R31_IDX) + ic->rMask = bitVectSetBit (ic->rMask, Z_IDX); + } + } + } + } } - - return buffer; } + /*-----------------------------------------------------------------*/ /* regTypeNum - computes the type & number of registers required */ /*-----------------------------------------------------------------*/ @@ -1490,70 +1716,6 @@ DEFSETFUNC (deallocStackSpil) return 0; } -/*-----------------------------------------------------------------*/ -/* farSpacePackable - returns the packable icode for far variables */ -/*-----------------------------------------------------------------*/ -static iCode * -farSpacePackable (iCode * ic) -{ - iCode *dic; - - /* go thru till we find a definition for the - symbol on the right */ - for (dic = ic->prev; dic; dic = dic->prev) { - - /* if the definition is a call then no */ - if ((dic->op == CALL || dic->op == PCALL) && - IC_RESULT (dic)->key == IC_RIGHT (ic)->key) { - return NULL; - } - - /* if shift by unknown amount then not */ - if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) && - IC_RESULT (dic)->key == IC_RIGHT (ic)->key) - return NULL; - - /* if pointer get and size > 1 */ - if (POINTER_GET (dic) && - getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > - 1) return NULL; - - if (POINTER_SET (dic) && - 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 (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 (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic))) { - if ((dic->op == LEFT_OP || - dic->op == RIGHT_OP || - dic->op == '-') && - IS_OP_LITERAL (IC_RIGHT (dic))) return NULL; - else - return dic; - } - } - - return NULL; -} - /*-----------------------------------------------------------------*/ /* packRegsForAssign - register reduction for assignment */ /*-----------------------------------------------------------------*/ @@ -1667,148 +1829,6 @@ packRegsForAssign (iCode * ic, eBBlock * ebp) } -/*-----------------------------------------------------------------*/ -/* findAssignToSym : scanning backwards looks for first assig found */ -/*-----------------------------------------------------------------*/ -static iCode * -findAssignToSym (operand * op, iCode * ic) -{ - iCode *dic; - - for (dic = ic->prev; dic; dic = dic->prev) { - - /* if definition by assignment */ - if (dic->op == '=' && - !POINTER_SET (dic) && IC_RESULT (dic)->key == op->key -/* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */ - ) { - - /* we are interested only if defined in far space */ - /* or in stack space in case of + & - */ - - /* if assigned to a non-symbol then return - true */ - if (!IS_SYMOP (IC_RIGHT (dic))) - break; - - /* 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; - - } - - /* if we find an usage then we cannot delete it */ - if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key) - return NULL; - - if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key) - return NULL; - - if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key) - return NULL; - } - - /* now make sure that the right side of dic - is not defined between ic & dic */ - if (dic) { - iCode *sic = dic->next; - - for (; sic != ic; sic = sic->next) - if (IC_RESULT (sic) && - IC_RESULT (sic)->key == IC_RIGHT (dic)->key) - return NULL; - } - - return dic; - - -} - -/*-----------------------------------------------------------------*/ -/* packRegsForSupport :- reduce some registers for support calls */ -/*-----------------------------------------------------------------*/ -static int -packRegsForSupport (iCode * ic, eBBlock * ebp) -{ - int change = 0; - /* for the left & right operand :- look to see if the - left was assigned a true symbol in far space in that - case replace them */ - if (IS_ITEMP (IC_LEFT (ic)) && - OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq) { - iCode *dic = findAssignToSym (IC_LEFT (ic), ic); - iCode *sic; - - 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); - - IC_LEFT (ic)->operand.symOperand = - IC_RIGHT (dic)->operand.symOperand; - IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key; - remiCodeFromeBBlock (ebp, dic); - hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL); - change++; - } - - /* do the same for the right operand */ - right: - if (!change && - 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))) { - sym_link *etype = - getSpec (operandType (IC_RESULT (dic))); - if (IN_FARSPACE (SPEC_OCLS (etype))) - return change; - } - /* found it we need to remove it from the - block */ - for (sic = dic; sic != ic; sic = sic->next) - bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key); - - 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; -} - -#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly) - /*-----------------------------------------------------------------*/ /* packRegsForOneuse : - will reduce some registers for single Use */ @@ -1854,7 +1874,8 @@ packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp) /* now check if it is the return from 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; } @@ -1952,39 +1973,6 @@ isBitwiseOptimizable (iCode * ic) return FALSE; } -/*-----------------------------------------------------------------*/ -/* packForPush - hueristics to reduce iCode for pushing */ -/*-----------------------------------------------------------------*/ -static void -packForPush (iCode * ic, eBBlock * ebp) -{ - iCode *dic; - - if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic))) - return; - - /* must have only definition & one usage */ - if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 || - bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1) - return; - - /* find the definition */ - if (!(dic = hTabItemWithKey (iCodehTab, - bitVectFirstBit (OP_DEFS - (IC_LEFT (ic)))))) - return; - - if (dic->op != '=' || POINTER_SET (dic)) - return; - - /* 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); -} - /*-----------------------------------------------------------------*/ /* packRegisters - does some transformations to reduce register */ /* pressure */ @@ -2069,8 +2057,11 @@ packRegisters (eBBlock * ebp) if (POINTER_SET (ic)) OP_SYMBOL (IC_RESULT (ic))->uptr = 1; - if (POINTER_GET (ic)) + if (POINTER_GET (ic)) { OP_SYMBOL (IC_LEFT (ic))->uptr = 1; + if (OP_SYMBOL (IC_LEFT(ic))->remat) + OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL; + } /* if the condition of an if instruction is defined in the previous instruction then @@ -2129,7 +2120,7 @@ packRegisters (eBBlock * ebp) /* if the type from and type to are the same then if this is the only use then packit */ - if (checkType (operandType (IC_RIGHT (ic)), + if (compareType (operandType (IC_RIGHT (ic)), operandType (IC_LEFT (ic))) == 1) { iCode *dic = @@ -2214,8 +2205,8 @@ setDefaultRegs (eBBlock ** ebbs, int count) else { regsAVR[R26_IDX].type = (regsAVR[R26_IDX].type & ~REG_MASK) | REG_PTR; regsAVR[R27_IDX].type = (regsAVR[R27_IDX].type & ~REG_MASK) | REG_PTR; - regsAVR[R28_IDX].type = (regsAVR[R28_IDX].type & ~REG_MASK) | REG_PTR; - regsAVR[R29_IDX].type = (regsAVR[R29_IDX].type & ~REG_MASK) | REG_PTR; + regsAVR[R30_IDX].type = (regsAVR[R30_IDX].type & ~REG_MASK) | REG_PTR; + regsAVR[R31_IDX].type = (regsAVR[R31_IDX].type & ~REG_MASK) | REG_PTR; } /* registers 0-1 / 24-25 used as scratch */ @@ -2232,7 +2223,7 @@ setDefaultRegs (eBBlock ** ebbs, int count) regsAVR[i].type = (regsAVR[i].type & ~REG_MASK) | REG_SCR; regsAVR[i].isFree = 1; } - if (!currFunc->hasFcall) { + if (!IFFUNC_HASFCALL(currFunc->type)) { preAssignParms (ebbs[0]->sch); } /* Y - is not allocated (it is the stack frame) */ @@ -2243,8 +2234,10 @@ setDefaultRegs (eBBlock ** ebbs, int count) /* assignRegisters - assigns registers to each live range as need */ /*-----------------------------------------------------------------*/ void -avr_assignRegisters (eBBlock ** ebbs, int count) +avr_assignRegisters (ebbIndex * ebbi) { + eBBlock ** ebbs = ebbi->bbOrder; + int count = ebbi->count; iCode *ic; int i; @@ -2256,8 +2249,12 @@ avr_assignRegisters (eBBlock ** ebbs, int count) for (i = 0; i < count; i++) packRegisters (ebbs[i]); + /* liveranges probably changed by register packing + so we compute them again */ + recomputeLiveRanges (ebbs, count); + if (options.dump_pack) - dumpEbbsToFileExt (DUMP_PACK, ebbs, count); + dumpEbbsToFileExt (DUMP_PACK, ebbi); /* first determine for each live range the number of registers & the type of registers required for each */ @@ -2290,7 +2287,7 @@ avr_assignRegisters (eBBlock ** ebbs, int count) redoStackOffsets (); if (options.dump_rassgn) - dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count); + dumpEbbsToFileExt (DUMP_RASSGN, ebbi); /* now get back the chain */ ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count)); @@ -2302,8 +2299,8 @@ avr_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 */ return;