X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCcse.c;h=c57509201370e3d868ad059ec95cfe12ba7293a5;hb=5d609f8d1aef366db39770b8e9c26757b7e7622e;hp=2854a5bf956afe04e4ee431ea4836b4af29f7016;hpb=cfacc9043f84988c742792b7907cb74f670589f1;p=fw%2Fsdcc diff --git a/src/SDCCcse.c b/src/SDCCcse.c index 2854a5bf..c5750920 100644 --- a/src/SDCCcse.c +++ b/src/SDCCcse.c @@ -1,9 +1,3 @@ -//#define LIVERANGEHUNT -#ifdef LIVERANGEHUNT - #define LRH(x) x -#else - #define LRH(x) -#endif /*------------------------------------------------------------------------- SDCCcse.c - source file for Common Subexpressions and other utility @@ -31,6 +25,7 @@ #include "common.h" #include "newalloc.h" + /*-----------------------------------------------------------------*/ /* newCseDef - new cseDef */ /*-----------------------------------------------------------------*/ @@ -45,10 +40,65 @@ newCseDef (operand * sym, iCode * ic) cdp->sym = sym; cdp->diCode = ic; cdp->key = sym->key; + cdp->ancestors = newBitVect(iCodeKey); + cdp->fromGlobal = 0; + if (ic->op!=IF && ic->op!=JUMPTABLE) + { + if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))) + { + bitVectSetBit (cdp->ancestors, IC_LEFT (ic)->key); + cdp->fromGlobal |= isOperandGlobal (IC_LEFT (ic)); + } + if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))) + { + bitVectSetBit (cdp->ancestors, IC_RIGHT (ic)->key); + cdp->fromGlobal |= isOperandGlobal (IC_RIGHT (ic)); + } + } + return cdp; } +void +updateCseDefAncestors(cseDef *cdp, set * cseSet) +{ + cseDef *loop; + set *sl; + iCode *ic = cdp->diCode; + + if (ic->op!=IF && ic->op!=JUMPTABLE) + { + if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))) + { + bitVectSetBit (cdp->ancestors, IC_LEFT (ic)->key); + for (sl = cseSet; sl; sl = sl->next) + { + loop = sl->item; + if (loop->sym->key == IC_LEFT (ic)->key) + { + cdp->ancestors = bitVectUnion (cdp->ancestors, loop->ancestors); + cdp->fromGlobal |= loop->fromGlobal; + break; + } + } + } + if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))) + { + bitVectSetBit (cdp->ancestors, IC_RIGHT (ic)->key); + for (sl = cseSet; sl; sl = sl->next) + { + loop = sl->item; + if (loop->sym->key == IC_RIGHT (ic)->key) + { + cdp->ancestors = bitVectUnion (cdp->ancestors, loop->ancestors); + cdp->fromGlobal |= loop->fromGlobal; + break; + } + } + } + } +} /*-----------------------------------------------------------------*/ @@ -89,9 +139,9 @@ pcseDef (void *item, va_list ap) void ReplaceOpWithCheaperOp(operand **op, operand *cop) { #ifdef RANGEHUNT - printf ("ReplaceOpWithCheaperOp (%s:%d with %s:%d): ", - OP_SYMBOL((*op))->name, OP_SYMBOL((*op))->isreqv, - OP_SYMBOL(cop)->name, OP_SYMBOL(cop)->isreqv); + printf ("ReplaceOpWithCheaperOp %s with %s: ", + IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM", + IS_SYMOP(cop) ? OP_SYMBOL(cop)->name : "!SYM"); // if op is a register equivalent if (IS_ITEMP(cop) && OP_SYMBOL((*op))->isreqv) { operand **rop = &OP_SYMBOL((*op))->usl.spillLoc->reqv; @@ -113,12 +163,11 @@ void ReplaceOpWithCheaperOp(operand **op, operand *cop) { /* replaceAllSymBySym - replaces all operands by operand in an */ /* instruction chain */ /*-----------------------------------------------------------------*/ -void +void replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) { iCode *lic; - LRH(printf ("replaceAllSymBySym: from %s to %s\n", OP_SYMBOL(from)->name, OP_SYMBOL(to)->name)); for (lic = ic; lic; lic = lic->next) { int siaddr; @@ -131,7 +180,7 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) { bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES_SET ((to), bitVectSetBit (OP_USES (to), lic->key)); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); siaddr = IC_COND (lic)->isaddr; IC_COND (lic) = operandFromOperand (to); IC_COND (lic)->isaddr = siaddr; @@ -147,7 +196,7 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) { bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES_SET ((to), bitVectSetBit (OP_USES (to), lic->key)); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); siaddr = IC_COND (lic)->isaddr; IC_JTCOND (lic) = operandFromOperand (to); IC_JTCOND (lic)->isaddr = siaddr; @@ -156,13 +205,14 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) continue; } - if (IC_RESULT (lic) && IC_RESULT (lic)->key == from->key) + if (IS_SYMOP(to) && + IC_RESULT (lic) && IC_RESULT (lic)->key == from->key) { /* maintain du chains */ if (POINTER_SET (lic)) { bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES_SET ((to), bitVectSetBit (OP_USES (to), lic->key)); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); /* also check if the "from" was in the non-dominating pointer sets and replace it with "to" in the bitVector */ @@ -176,7 +226,7 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) else { bitVectUnSetBit (OP_DEFS (from), lic->key); - OP_DEFS_SET ((to), bitVectSetBit (OP_DEFS (to), lic->key)); + OP_DEFS(to)=bitVectSetBit (OP_DEFS (to), lic->key); } siaddr = IC_RESULT (lic)->isaddr; IC_RESULT (lic) = operandFromOperand (to); @@ -187,7 +237,7 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) IC_RIGHT (lic) && IC_RIGHT (lic)->key == from->key) { bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES_SET ((to), bitVectSetBit (OP_USES (to), lic->key)); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); siaddr = IC_RIGHT (lic)->isaddr; IC_RIGHT (lic) = operandFromOperand (to); IC_RIGHT (lic)->isaddr = siaddr; @@ -197,7 +247,7 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) IC_LEFT (lic) && IC_LEFT (lic)->key == from->key) { bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES_SET ((to), bitVectSetBit (OP_USES (to), lic->key)); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); siaddr = IC_LEFT (lic)->isaddr; IC_LEFT (lic) = operandFromOperand (to); IC_LEFT (lic)->isaddr = siaddr; @@ -287,7 +337,7 @@ DEFSETFUNC (findCheaperOp) /* if the result is volatile then return result */ if (IS_OP_VOLATILE (IC_RESULT (cdp->diCode))) *opp = IC_RESULT (cdp->diCode); - else + else /* if this is a straight assignment and left is a temp then prefer the temporary to the true symbol */ @@ -331,9 +381,10 @@ DEFSETFUNC (findCheaperOp) IS_ITEMP (IC_RESULT (cdp->diCode))) *opp = IC_RESULT (cdp->diCode); - if ((*opp) && - (isOperandLiteral(*opp) || !checkSign || + if ((*opp) && + (isOperandLiteral(*opp) || !checkSign || (checkSign && + IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) && (SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) && (SPEC_LONG(operandType (cop))==SPEC_LONG(operandType (*opp))))))) { @@ -358,9 +409,28 @@ DEFSETFUNC (findCheaperOp) *opp = operandFromOperand (*opp); (*opp)->isaddr = cop->isaddr; } - LRH(printf ("findCheaperOp: %s < %s\n",\ - IS_SYMOP((*opp)) ? OP_SYMBOL((*opp))->name : "!SYM",\ - OP_SYMBOL(cop)->name)); + + if (IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) && + SPEC_NOUN(operandType(cop)) != SPEC_NOUN(operandType(*opp))) + { + // special case: we can make an unsigned char literal + // into an int literal with no cost. + if (isOperandLiteral(*opp) + && SPEC_NOUN(operandType(*opp)) == V_CHAR + && SPEC_NOUN(operandType(cop)) == V_INT) + { + *opp = operandFromOperand (*opp); + SPEC_NOUN(operandType(*opp)) = V_INT; + } + else + { + // No clue... + *opp = NULL; + return 0; + } + + } + return 1; } @@ -410,8 +480,7 @@ DEFSETFUNC (findPrevIc) if (isiCodeEqual (ic, cdp->diCode) && isOperandEqual (cdp->sym, IC_RESULT (cdp->diCode))) { - LRH(printf ("findPrevIc same: %d %d\n", ic->key, cdp->diCode->key)); - *icp = cdp->diCode; + *icp = cdp->diCode; return 1; } @@ -422,7 +491,6 @@ DEFSETFUNC (findPrevIc) isOperandEqual (IC_LEFT (ic), IC_RIGHT (cdp->diCode)) && isOperandEqual (IC_RIGHT (ic), IC_LEFT (cdp->diCode))) { - LRH(printf ("findPrevIc inter: %d %d\n", ic->key, cdp->diCode->key)); *icp = cdp->diCode; return 1; } @@ -444,6 +512,16 @@ DEFSETFUNC (ifAssignedFromGlobal) return 0; } +/*-------------------------------------------------------------------*/ +/* ifFromGlobal - if definition is derived from global */ +/*-------------------------------------------------------------------*/ +DEFSETFUNC (ifFromGlobal) +{ + cseDef *cdp = item; + + return cdp->fromGlobal; +} + /*-----------------------------------------------------------------*/ /* ifDefGlobal - if definition is global */ /*-----------------------------------------------------------------*/ @@ -474,7 +552,9 @@ DEFSETFUNC (ifOperandsHave) cseDef *cdp = item; V_ARG (operand *, op); - + if (bitVectBitValue(cdp->ancestors, op->key)) + return 1; + if (IC_LEFT (cdp->diCode) && IS_SYMOP (IC_LEFT (cdp->diCode)) && IC_LEFT (cdp->diCode)->key == op->key) @@ -505,7 +585,7 @@ DEFSETFUNC (ifOperandsHave) /*-----------------------------------------------------------------*/ /* ifDefSymIs - if a definition is found in the set */ /*-----------------------------------------------------------------*/ -int +int ifDefSymIs (set * cseSet, operand * sym) { cseDef *loop; @@ -530,19 +610,24 @@ DEFSETFUNC (ifDefSymIsX) { cseDef *cdp = item; V_ARG (operand *, op); - + int match; + if (op && cdp->sym) - return cdp->sym->key == op->key; + match = cdp->sym->key == op->key; else - return (isOperandEqual (cdp->sym, op)); - + match = (isOperandEqual (cdp->sym, op)); + #if 0 + if (match) + printf("%s ",OP_SYMBOL(cdp->sym)->name); + #endif + return match; } /*-----------------------------------------------------------------*/ /* ifDiCodeIs - returns truw if diCode is same */ /*-----------------------------------------------------------------*/ -int +int ifDiCodeIs (set * cseSet, iCode * ic) { cseDef *loop; @@ -612,7 +697,7 @@ iCode *findBackwardDef(operand *op,iCode *ic) iCode *lic; for (lic = ic; lic ; lic = lic->prev) { - if (IC_RESULT(lic) && isOperandEqual(op,IC_RESULT(lic))) + if (IC_RESULT(lic) && isOperandEqual(op,IC_RESULT(lic))) return lic; } return NULL; @@ -621,8 +706,8 @@ iCode *findBackwardDef(operand *op,iCode *ic) /*-----------------------------------------------------------------*/ /* algebraicOpts - does some algebraic optimizations */ /*-----------------------------------------------------------------*/ -void -algebraicOpts (iCode * ic) +static void +algebraicOpts (iCode * ic, eBBlock * ebp) { /* we don't deal with the following iCodes here */ @@ -723,13 +808,21 @@ algebraicOpts (iCode * ic) return; } /* if addition then check if one of them is a zero */ - /* if yes turn it into assignmnt */ + /* if yes turn it into assignmnt or cast */ if (IS_OP_LITERAL (IC_LEFT (ic)) && operandLitValue (IC_LEFT (ic)) == 0.0) { - - ic->op = '='; - IC_LEFT (ic) = NULL; + if (compareType (operandType (IC_RESULT (ic)), + operandType (IC_RIGHT (ic)))<0) + { + ic->op = CAST; + IC_LEFT (ic) = operandFromLink (operandType (IC_RESULT (ic))); + } + else + { + ic->op = '='; + IC_LEFT (ic) = NULL; + } SET_ISADDR (IC_RESULT (ic), 0); SET_ISADDR (IC_RIGHT (ic), 0); return; @@ -737,10 +830,19 @@ algebraicOpts (iCode * ic) if (IS_OP_LITERAL (IC_RIGHT (ic)) && operandLitValue (IC_RIGHT (ic)) == 0.0) { - - ic->op = '='; - IC_RIGHT (ic) = IC_LEFT (ic); - IC_LEFT (ic) = 0; + if (compareType (operandType (IC_RESULT (ic)), + operandType (IC_LEFT (ic)))<0) + { + ic->op = CAST; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = operandFromLink (operandType (IC_RESULT (ic))); + } + else + { + ic->op = '='; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = NULL; + } SET_ISADDR (IC_RIGHT (ic), 0); SET_ISADDR (IC_RESULT (ic), 0); return; @@ -800,9 +902,23 @@ algebraicOpts (iCode * ic) } if (operandLitValue (IC_LEFT (ic)) == 1.0) { - ic->op = '='; - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); + /* '*' can have two unsigned chars as operands */ + /* and an unsigned int as result. */ + if (compareType (operandType (IC_RESULT (ic)), + operandType (IC_RIGHT (ic))) == 1) + { + ic->op = '='; + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + } + else + { + ic->op = CAST; + IC_LEFT (ic) = operandFromOperand (IC_LEFT (ic)); + IC_LEFT (ic)->type = TYPE; + IC_LEFT (ic)->isLiteral = 0; + setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic))); + } return; } } @@ -820,10 +936,28 @@ algebraicOpts (iCode * ic) if (operandLitValue (IC_RIGHT (ic)) == 1.0) { - ic->op = '='; - IC_RIGHT (ic) = IC_LEFT (ic); - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); + /* '*' can have two unsigned chars as operands */ + /* and an unsigned int as result. */ + if (compareType (operandType (IC_RESULT (ic)), + operandType (IC_LEFT (ic))) == 1) + { + ic->op = '='; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + } + else + { + operand *op; + + ic->op = CAST; + op = IC_RIGHT (ic); + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = operandFromOperand (op); + IC_LEFT (ic)->type = TYPE; + IC_LEFT (ic)->isLiteral = 0; + setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic))); + } return; } } @@ -908,6 +1042,201 @@ algebraicOpts (iCode * ic) IC_LEFT (ic) = NULL; SET_ISADDR (IC_RESULT (ic), 0); } + break; + case BITWISEAND: + /* if both operands are equal */ + /* if yes turn it into assignment */ + if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic))) + { + if (IS_OP_VOLATILE (IC_LEFT (ic))) + { + iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic)); + IC_RESULT (newic) = IC_LEFT (ic); + newic->lineno = ic->lineno; + addiCodeToeBBlock (ebp, newic, ic->next); + } + ic->op = '='; + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + /* swap literal to right ic */ + if (IS_OP_LITERAL (IC_LEFT (ic))) + { + operand *op; + + op = IC_LEFT (ic); + IC_LEFT (ic) = IC_RIGHT (ic); + IC_RIGHT (ic) = op; + } + if (IS_OP_LITERAL (IC_RIGHT (ic))) + { + /* if BITWISEAND then check if one of them is a zero */ + /* if yes turn it into 0 assignment */ + if (operandLitValue (IC_RIGHT (ic)) == 0.0) + { + if (IS_OP_VOLATILE (IC_LEFT (ic))) + { + iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic)); + IC_RESULT (newic) = IC_LEFT (ic); + newic->lineno = ic->lineno; + addiCodeToeBBlock (ebp, newic, ic->next); + } + ic->op = '='; + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + /* if BITWISEAND then check if one of them is 0xff... */ + /* if yes turn it into assignment */ + { + unsigned val; + + switch (getSize (operandType (IC_RIGHT (ic)))) + { + case 1: + val = 0xff; + break; + case 2: + val = 0xffff; + break; + case 4: + val = 0xffffffff; + break; + default: + return; + } + if (((unsigned) operandLitValue (IC_RIGHT (ic)) & val) == val) + { + ic->op = '='; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + } + } + break; + case '|': + /* if both operands are equal */ + /* if yes turn it into assignment */ + if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic))) + { + if (IS_OP_VOLATILE (IC_LEFT (ic))) + { + iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic)); + IC_RESULT (newic) = IC_LEFT (ic); + newic->lineno = ic->lineno; + addiCodeToeBBlock (ebp, newic, ic->next); + } + ic->op = '='; + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + /* swap literal to right ic */ + if (IS_OP_LITERAL (IC_LEFT (ic))) + { + operand *op; + + op = IC_LEFT (ic); + IC_LEFT (ic) = IC_RIGHT (ic); + IC_RIGHT (ic) = op; + } + if (IS_OP_LITERAL (IC_RIGHT (ic))) + { + /* if BITWISEOR then check if one of them is a zero */ + /* if yes turn it into assignment */ + if (operandLitValue (IC_RIGHT (ic)) == 0.0) + { + ic->op = '='; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + /* if BITWISEOR then check if one of them is 0xff... */ + /* if yes turn it into 0xff... assignment */ + { + unsigned val; + + switch (getSize (operandType (IC_RIGHT (ic)))) + { + case 1: + val = 0xff; + break; + case 2: + val = 0xffff; + break; + case 4: + val = 0xffffffff; + break; + default: + return; + } + if (((unsigned) operandLitValue (IC_RIGHT (ic)) & val) == val) + { + if (IS_OP_VOLATILE (IC_LEFT (ic))) + { + iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic)); + IC_RESULT (newic) = IC_LEFT (ic); + newic->lineno = ic->lineno; + addiCodeToeBBlock (ebp, newic, ic->next); + } + ic->op = '='; + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + } + } + break; + case '^': + /* if both operands are equal */ + /* if yes turn it into 0 assignment */ + if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic))) + { + if (IS_OP_VOLATILE (IC_LEFT (ic))) + { + iCode *newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic)); + IC_RESULT (newic) = IC_LEFT (ic); + newic->lineno = ic->lineno; + addiCodeToeBBlock (ebp, newic, ic->next); + + newic = newiCode (DUMMY_READ_VOLATILE, NULL, IC_LEFT (ic)); + IC_RESULT (newic) = IC_LEFT (ic); + newic->lineno = ic->lineno; + addiCodeToeBBlock (ebp, newic, ic->next); + } + ic->op = '='; + IC_RIGHT (ic) = operandFromLit (0); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + /* swap literal to right ic */ + if (IS_OP_LITERAL (IC_LEFT (ic))) + { + operand *op; + + op = IC_LEFT (ic); + IC_LEFT (ic) = IC_RIGHT (ic); + IC_RIGHT (ic) = op; + } + /* if XOR then check if one of them is a zero */ + /* if yes turn it into assignment */ + if (IS_OP_LITERAL (IC_RIGHT (ic))) + { + if (operandLitValue (IC_RIGHT (ic)) == 0.0) + { + ic->op = '='; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + } + break; } return; @@ -916,7 +1245,7 @@ algebraicOpts (iCode * ic) /*-----------------------------------------------------------------*/ /* updateSpillLocation - keeps track of register spill location */ /*-----------------------------------------------------------------*/ -void +void updateSpillLocation (iCode * ic, int induction) { sym_link *setype; @@ -927,6 +1256,7 @@ updateSpillLocation (iCode * ic, int induction) if (ic->nosupdate) return; +#if 0 /* for the form true_symbol := iTempNN */ if (ASSIGN_ITEMP_TO_SYM (ic) && !SPIL_LOC (IC_RIGHT (ic))) { @@ -937,10 +1267,15 @@ updateSpillLocation (iCode * ic, int induction) !IS_VOLATILE (setype) && !IN_FARSPACE (SPEC_OCLS (setype)) && !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic)))) - + { + wassert(IS_SYMOP(IC_RESULT (ic))); + wassert(IS_SYMOP(IC_RIGHT (ic))); SPIL_LOC (IC_RIGHT (ic)) = IC_RESULT (ic)->operand.symOperand; + } + } +#endif #if 0 /* this needs furthur investigation can save a lot of code */ if (ASSIGN_SYM_TO_ITEMP(ic) && @@ -961,10 +1296,13 @@ updateSpillLocation (iCode * ic, int induction) if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc && !IS_VOLATILE (setype) && !IN_FARSPACE (SPEC_OCLS (setype)) && - !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic)))) + !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic)))) { SPIL_LOC (IC_RIGHT (ic)) = SPIL_LOC (IC_RESULT (ic)); + OP_SYMBOL (IC_RIGHT (ic))->prereqv = + OP_SYMBOL (IC_RESULT (ic))->prereqv; + } } /* special case for inductions */ if (induction && @@ -972,6 +1310,8 @@ updateSpillLocation (iCode * ic, int induction) !OP_SYMBOL(IC_RESULT (ic))->noSpilLoc && !SPIL_LOC(IC_RESULT(ic))) { SPIL_LOC (IC_RESULT (ic)) = SPIL_LOC (IC_RIGHT (ic)); + OP_SYMBOL (IC_RESULT (ic))->prereqv = + OP_SYMBOL (IC_RIGHT (ic))->prereqv; } } } @@ -1090,7 +1430,7 @@ ifxOptimize (iCode * ic, set * cseSet, /* the price */ computeControlFlow (ebbs, count, 1); if (!options.lessPedantic) { - werror (W_CONTROL_FLOW, ic->filename, ic->lineno); + werrorfl (ic->filename, ic->lineno, W_CONTROL_FLOW); } return; } @@ -1103,18 +1443,36 @@ ifxOptimize (iCode * ic, set * cseSet, isinSet (ebb->succList, eBBWithEntryLabel (ebbs, label, count))) { - remiCodeFromeBBlock (ebb, ic); - computeControlFlow (ebbs, count, 1); if (!options.lessPedantic) { - werror (W_CONTROL_FLOW, ic->filename, ic->lineno); + werrorfl (ic->filename, ic->lineno, W_CONTROL_FLOW); } - return; + if (IS_OP_VOLATILE (IC_COND (ic))) + { + IC_RIGHT (ic) = IC_COND (ic); + IC_LEFT (ic) = NULL; + IC_RESULT (ic) = NULL; + ic->op = DUMMY_READ_VOLATILE; + } + else + { + remiCodeFromeBBlock (ebb, ic); + computeControlFlow (ebbs, count, 1); + return; + } } /* if it remains an IFX the update the use Set */ - OP_USES_SET ((IC_COND (ic)), bitVectSetBit (OP_USES (IC_COND (ic)), ic->key)); - setUsesDefs (IC_COND (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); + if (ic->op == IFX) + { + OP_USES(IC_COND (ic))=bitVectSetBit (OP_USES (IC_COND (ic)), ic->key); + setUsesDefs (IC_COND (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); + } + else if (ic->op == DUMMY_READ_VOLATILE) + { + OP_USES(IC_RIGHT (ic))=bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key); + setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); + } return; } @@ -1223,50 +1581,52 @@ deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb) set *compItems = NULL; cseDef *cdp; operand *cop; + int changes; /* easy return */ if (!*cseSet && !*pss) return; - /* first find all items computed from this operand . + addSet (&compItems, op); + + /* Recursively find all items computed from this operand . This done fairly simply go thru the list and find - those that are computed by arthimetic with this - op */ - for (cdp = setFirstItem (*cseSet); cdp; cdp = setNextItem (*cseSet)) + those that are computed by arthimetic with these + ops */ + /* Also check for those computed from our computed + list . This will take care of situations like + iTemp1 = iTemp0 + 8; + iTemp2 = iTemp1 + 8; */ + do { - if (IS_ARITHMETIC_OP (cdp->diCode)) + changes = 0; + for (cdp = setFirstItem (*cseSet); cdp; cdp = setNextItem (*cseSet)) { - if (isOperandEqual (IC_LEFT (cdp->diCode), op) || - isOperandEqual (IC_RIGHT (cdp->diCode), op)) - { - /* save it in our list of items */ - addSet (&compItems, IC_RESULT (cdp->diCode)); - } - /* also check for those computed from our computed - list . This will take care of situations like - iTemp1 = iTemp0 + 8; - iTemp2 = iTemp1 + 8; */ - if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode), - (insetwithFunc)isOperandEqual) || - isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode), - (insetwithFunc)isOperandEqual)) + if (IS_ARITHMETIC_OP (cdp->diCode) || POINTER_GET(cdp->diCode)) { - addSet (&compItems, IC_RESULT (cdp->diCode)); + if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode), + (insetwithFunc)isOperandEqual) || + isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode), + (insetwithFunc)isOperandEqual)) + { + if (!isinSetWith (compItems, (void*)IC_RESULT (cdp->diCode), + (insetwithFunc)isOperandEqual)) + { + addSet (&compItems, IC_RESULT (cdp->diCode)); + changes++; + } + } } } } - - /* now delete all pointer gets with this op */ - deleteItemIf (cseSet, ifPointerGet, op); - deleteItemIf (pss, ifPointerSet, op); - - /* set the bit vector used by dataFlow computation later */ - ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, op->key); + while (changes); + /* now for the computed items */ for (cop = setFirstItem (compItems); cop; cop = setNextItem (compItems)) { ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, cop->key); deleteItemIf (cseSet, ifPointerGet, cop); + deleteItemIf (cseSet, ifDefSymIsX, cop); deleteItemIf (pss, ifPointerSet, cop); } } @@ -1296,7 +1656,7 @@ DEFSETFUNC (delGetPointerSucc) /*-----------------------------------------------------------------*/ /* fixUpTypes - KLUGE HACK fixup a lowering problem */ /*-----------------------------------------------------------------*/ -static void +static void fixUpTypes (iCode * ic) { sym_link *t1 = operandType (IC_LEFT (ic)), *t2; @@ -1367,13 +1727,29 @@ static int isSignedOp (iCode *ic) } } +#if 0 +static void +dumpCseSet(set *cseSet) +{ + while (cseSet) + { + cseDef *item=cseSet->item; + printf("->"); + printOperand (item->sym, NULL); + printf(" "); + piCode (item->diCode, NULL); + cseSet = cseSet->next; + } +} +#endif + /*-----------------------------------------------------------------*/ /* cseBBlock - common subexpression elimination for basic blocks */ /* this is the hackiest kludgiest routine in the whole */ /* system. also the most important, since almost all */ /* data flow related information is computed by it */ /*-----------------------------------------------------------------*/ -int +int cseBBlock (eBBlock * ebb, int computeOnly, eBBlock ** ebbs, int count) { @@ -1382,21 +1758,22 @@ cseBBlock (eBBlock * ebb, int computeOnly, int change = 0; int i; set *ptrSetSet = NULL; + cseDef *expr; /* if this block is not reachable */ if (ebb->noPath) - return change; + return 0; /* set of common subexpressions */ cseSet = setFromSet (ebb->inExprs); /* these will be computed by this routine */ - setToNull ((void **) &ebb->outDefs); - setToNull ((void **) &ebb->defSet); - setToNull ((void **) &ebb->usesDefs); - setToNull ((void **) &ebb->ptrsSet); - setToNull ((void **) &ebb->addrOf); - setToNull ((void **) &ebb->ldefs); + setToNull ((void *) &ebb->outDefs); + setToNull ((void *) &ebb->defSet); + setToNull ((void *) &ebb->usesDefs); + setToNull ((void *) &ebb->ptrsSet); + setToNull ((void *) &ebb->addrOf); + setToNull ((void *) &ebb->ldefs); ebb->outDefs = bitVectCopy (ebb->inDefs); bitVectDefault = iCodeKey; @@ -1406,7 +1783,6 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* for all the instructions in this block do */ for (ic = ebb->sch; ic; ic = ic->next) { - iCode *pdic; operand *pdop; iCode *defic; @@ -1423,7 +1799,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, IS_PTR (operandType (IC_RESULT (ic)))) { ptrPostIncDecOpt (ic); - } + } /* clear the def & use chains for the operands involved */ /* in this operation . since it can change due to opts */ @@ -1432,8 +1808,8 @@ cseBBlock (eBBlock * ebb, int computeOnly, if (ic->op == PCALL || ic->op == CALL || ic->op == RECEIVE) { /* add to defSet of the symbol */ - OP_DEFS_SET ((IC_RESULT (ic)), - bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key)); + OP_DEFS(IC_RESULT (ic))= + bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key); /* add to the definition set of this block */ ebb->defSet = bitVectSetBit (ebb->defSet, ic->key); ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key); @@ -1443,13 +1819,16 @@ cseBBlock (eBBlock * ebb, int computeOnly, since they can be modified by the function call */ deleteItemIf (&cseSet, ifDefGlobal); - /* and also itemps assigned from globals */ - deleteItemIf (&cseSet, ifAssignedFromGlobal); + /* and also itemps derived from globals */ + deleteItemIf (&cseSet, ifFromGlobal); /* delete all getpointer iCodes from cseSet, this should be done only for global arrays & pointers but at this point we don't know if globals, so to be safe do all */ deleteItemIf (&cseSet, ifAnyGetPointer); + + /* can't cache pointer set/get operations across a call */ + deleteSet (&ptrSetSet); } /* for pcall & ipush we need to add to the useSet */ @@ -1471,8 +1850,8 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* the lookup could have changed it */ if (IS_SYMOP (IC_LEFT (ic))) { - OP_USES_SET ((IC_LEFT (ic)), - bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key)); + OP_USES(IC_LEFT (ic))= + bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key); setUsesDefs (IC_LEFT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); } @@ -1496,19 +1875,24 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* if jumptable then mark the usage */ if (ic->op == JUMPTABLE) { - OP_USES_SET ((IC_JTCOND (ic)), - bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key)); - setUsesDefs (IC_JTCOND (ic), ebb->defSet, - ebb->outDefs, &ebb->usesDefs); + if (IS_SYMOP (IC_JTCOND (ic))) + { + OP_USES(IC_JTCOND (ic)) = + bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key); + setUsesDefs (IC_JTCOND (ic), ebb->defSet, + ebb->outDefs, &ebb->usesDefs); + } continue; } if (SKIP_IC (ic)) continue; - /* do some algebraic optimizations if possible */ - algebraicOpts (ic); - while (constFold (ic, cseSet)); + if (!computeOnly) { + /* do some algebraic optimizations if possible */ + algebraicOpts (ic, ebb); + while (constFold (ic, cseSet)); + } /* small klugde */ if (POINTER_GET (ic) && !IS_PTR (operandType (IC_LEFT (ic)))) @@ -1524,7 +1908,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, aggrToPtr (operandType (IC_RESULT (ic)), FALSE)); } - /* if this is a condition statment then */ + /* if this is a condition statement then */ /* check if the condition can be replaced */ if (ic->op == IFX) { @@ -1536,7 +1920,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* if the assignment & result is a temp */ /* see if we can replace it */ - if (ic->op == '=') + if (!computeOnly && ic->op == '=') { /* update the spill location for this */ @@ -1547,7 +1931,8 @@ cseBBlock (eBBlock * ebb, int computeOnly, { pdop = NULL; applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop, 0); - if (pdop && IS_ITEMP (pdop) && !computeOnly) + if (pdop && !computeOnly && + IS_ITEMP (pdop) && IS_PTR(operandType(pdop))) ReplaceOpWithCheaperOp (&IC_RESULT(ic), pdop); } } @@ -1612,15 +1997,15 @@ cseBBlock (eBBlock * ebb, int computeOnly, change = 1; } } - + /* if left or right changed then do algebraic */ - if (change) + if (!computeOnly && change) { - algebraicOpts (ic); + algebraicOpts (ic, ebb); while (constFold (ic, cseSet)); } - /* if after all this it becomes a assignment to self + /* if after all this it becomes an assignment to self then delete it and continue */ if (ASSIGNMENT_TO_SELF (ic)) { @@ -1647,15 +2032,15 @@ cseBBlock (eBBlock * ebb, int computeOnly, if (pdic && compareType (operandType (IC_RESULT (pdic)), operandType (IC_RESULT (ic))) != 1) pdic = NULL; - if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0) + if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0) pdic = NULL; } /* Alternate code */ if (pdic && IS_ITEMP(IC_RESULT(ic))) { if (POINTER_GET(ic) && bitVectBitValue(ebb->ptrsSet,IC_LEFT(ic)->key)) { - /* Mmm, found an equivalent pointer get at a lower level. - This could be a loop however with the same pointer set + /* Mmm, found an equivalent pointer get at a lower level. + This could be a loop however with the same pointer set later on */ } else { /* if previous definition found change this to an assignment */ @@ -1663,13 +2048,16 @@ cseBBlock (eBBlock * ebb, int computeOnly, IC_LEFT(ic) = NULL; IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic)); SET_ISADDR(IC_RESULT(ic),0); - SET_ISADDR(IC_RIGHT (ic),0); + SET_ISADDR(IC_RIGHT (ic),0); } } if (!(POINTER_SET (ic)) && IC_RESULT (ic)) { + cseDef *csed; deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic)); - addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic)); + csed = newCseDef (IC_RESULT (ic), ic); + updateCseDefAncestors (csed, cseSet); + addSetHead (&cseSet, csed); } defic = ic; @@ -1716,16 +2104,16 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* add the left & right to the defUse set */ if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))) { - OP_USES_SET ((IC_LEFT (ic)), - bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key)); + OP_USES(IC_LEFT (ic))= + bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key); setUsesDefs (IC_LEFT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); } if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))) { - OP_USES_SET ((IC_RIGHT (ic)), - bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key)); + OP_USES(IC_RIGHT (ic))= + bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key); setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); } @@ -1734,8 +2122,8 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* in the defuseSet if it a pointer or array access */ if (POINTER_SET (defic)) { - OP_USES_SET ((IC_RESULT (ic)), - bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key)); + OP_USES(IC_RESULT (ic))= + bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key); setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); deleteItemIf (&cseSet, ifPointerGet, IC_RESULT (ic)); ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RESULT (ic)->key); @@ -1753,8 +2141,8 @@ cseBBlock (eBBlock * ebb, int computeOnly, else /* add the result to defintion set */ if (IC_RESULT (ic)) { - OP_DEFS_SET ((IC_RESULT (ic)), - bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key)); + OP_DEFS(IC_RESULT (ic))= + bitVectSetBit (OP_DEFS (IC_RESULT (ic)), ic->key); ebb->defSet = bitVectSetBit (ebb->defSet, ic->key); ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic))); ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key); @@ -1771,7 +2159,12 @@ cseBBlock (eBBlock * ebb, int computeOnly, } } - setToNull ((void **) &ebb->outExprs); + for (expr=setFirstItem (ebb->inExprs); expr; expr=setNextItem (ebb->inExprs)) + if (!isinSetWith (cseSet, expr, isCseDefEqual) && + !isinSetWith (ebb->killedExprs, expr, isCseDefEqual)) { + addSetHead (&ebb->killedExprs, expr); + } + setToNull ((void *) &ebb->outExprs); ebb->outExprs = cseSet; ebb->outDefs = bitVectUnion (ebb->outDefs, ebb->defSet); ebb->ptrsSet = bitVectUnion (ebb->ptrsSet, ebb->inPtrsSet); @@ -1781,8 +2174,8 @@ cseBBlock (eBBlock * ebb, int computeOnly, /*-----------------------------------------------------------------*/ /* cseAllBlocks - will sequentially go thru & do cse for all blocks */ /*-----------------------------------------------------------------*/ -int -cseAllBlocks (eBBlock ** ebbs, int count) +int +cseAllBlocks (eBBlock ** ebbs, int count, int computeOnly) { int i; int change = 0; @@ -1790,7 +2183,7 @@ cseAllBlocks (eBBlock ** ebbs, int count) /* if optimization turned off */ for (i = 0; i < count; i++) - change += cseBBlock (ebbs[i], FALSE, ebbs, count); + change += cseBBlock (ebbs[i], computeOnly, ebbs, count); return change; }