X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCcse.c;h=350e6bb92abe46548b6510e023843eeb539734ff;hb=acf1ab48b8630cd93e3223be40695e6049b061e0;hp=7d1de84be8631cbe2286e244b95321e6a58aee12;hpb=356b9e6840e7ec836bbf69ee0dfca7c6d07fb9a4;p=fw%2Fsdcc diff --git a/src/SDCCcse.c b/src/SDCCcse.c index 7d1de84b..350e6bb9 100644 --- a/src/SDCCcse.c +++ b/src/SDCCcse.c @@ -34,7 +34,7 @@ newCseDef (operand * sym, iCode * ic) cseDef *cdp; assert (sym); - cdp = Safe_calloc (1, sizeof (cseDef)); + cdp = Safe_alloc (sizeof (cseDef)); cdp->sym = sym; cdp->diCode = ic; @@ -81,11 +81,33 @@ pcseDef (void *item, va_list ap) return 1; } +void ReplaceOpWithCheaperOp(operand **op, operand *cop) { +#ifdef RANGEHUNT + 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; + if (isOperandEqual(*rop, *op)) { + printf ("true"); + *rop=cop; + OP_SYMBOL((*op))->isreqv=0; + OP_SYMBOL(cop)->isreqv=1; + } else { + printf ("false"); + } + } + printf ("\n"); +#endif + *op=cop; +} + /*-----------------------------------------------------------------*/ /* replaceAllSymBySym - replaces all operands by operand in an */ /* instruction chain */ /*-----------------------------------------------------------------*/ -void +void replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) { iCode *lic; @@ -102,7 +124,7 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) { bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES (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; @@ -118,7 +140,7 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) { bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES (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; @@ -127,13 +149,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 (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 */ @@ -147,7 +170,7 @@ replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) else { bitVectUnSetBit (OP_DEFS (from), lic->key); - OP_DEFS (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); @@ -158,7 +181,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 (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; @@ -168,7 +191,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 (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; @@ -240,6 +263,7 @@ DEFSETFUNC (findCheaperOp) cseDef *cdp = item; V_ARG (operand *, cop); V_ARG (operand **, opp); + V_ARG (int, checkSign); /* if we have already found it */ if (*opp) @@ -257,7 +281,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 */ @@ -276,6 +300,7 @@ DEFSETFUNC (findCheaperOp) IS_ITEMP (IC_RESULT (cdp->diCode)) && IS_ITEMP (IC_RIGHT (cdp->diCode)) && !OP_SYMBOL (IC_RIGHT (cdp->diCode))->isind && + !OP_SYMBOL(IC_RIGHT (cdp->diCode))->isreqv && ((!SPIL_LOC (IC_RIGHT (cdp->diCode)) && SPIL_LOC (IC_RESULT (cdp->diCode))) || (SPIL_LOC (IC_RESULT (cdp->diCode)) && @@ -300,10 +325,13 @@ DEFSETFUNC (findCheaperOp) IS_ITEMP (IC_RESULT (cdp->diCode))) *opp = IC_RESULT (cdp->diCode); - if ((*opp) && - (SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp))) && - (SPEC_LONG(operandType (cop))==SPEC_LONG(operandType (*opp)))) - { + 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))))))) + { if ((isGlobalInNearSpace (cop) && !isOperandLiteral (*opp)) || @@ -326,6 +354,27 @@ DEFSETFUNC (findCheaperOp) (*opp)->isaddr = cop->isaddr; } + 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; } @@ -393,6 +442,20 @@ DEFSETFUNC (findPrevIc) return 0; } +/*-------------------------------------------------------------------*/ +/* ifAssignedFromGlobal - if definition is an assignment from global */ +/*-------------------------------------------------------------------*/ +DEFSETFUNC (ifAssignedFromGlobal) +{ + cseDef *cdp = item; + iCode *dic=cdp->diCode; + + if (dic->op=='=' && isOperandGlobal(IC_RIGHT(dic))) { + return 1; + } + return 0; +} + /*-----------------------------------------------------------------*/ /* ifDefGlobal - if definition is global */ /*-----------------------------------------------------------------*/ @@ -454,7 +517,7 @@ DEFSETFUNC (ifOperandsHave) /*-----------------------------------------------------------------*/ /* ifDefSymIs - if a definition is found in the set */ /*-----------------------------------------------------------------*/ -int +int ifDefSymIs (set * cseSet, operand * sym) { cseDef *loop; @@ -491,7 +554,7 @@ DEFSETFUNC (ifDefSymIsX) /*-----------------------------------------------------------------*/ /* ifDiCodeIs - returns truw if diCode is same */ /*-----------------------------------------------------------------*/ -int +int ifDiCodeIs (set * cseSet, iCode * ic) { cseDef *loop; @@ -553,11 +616,25 @@ DEFSETFUNC (ifDiCodeIsX) } +/*-----------------------------------------------------------------*/ +/* findBackwardDef - scan backwards to find deinition of operand */ +/*-----------------------------------------------------------------*/ +iCode *findBackwardDef(operand *op,iCode *ic) +{ + iCode *lic; + + for (lic = ic; lic ; lic = lic->prev) { + if (IC_RESULT(lic) && isOperandEqual(op,IC_RESULT(lic))) + return lic; + } + return NULL; +} + /*-----------------------------------------------------------------*/ /* 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 */ @@ -735,9 +812,22 @@ 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)->type = TYPE; + IC_LEFT (ic)->isLiteral = 0; + setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic))); + } return; } } @@ -755,10 +845,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) = op; + IC_LEFT (ic)->type = TYPE; + IC_LEFT (ic)->isLiteral = 0; + setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic))); + } return; } } @@ -772,6 +880,7 @@ algebraicOpts (iCode * ic) IC_LEFT (ic) = NULL; IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); IC_RESULT (ic)->isaddr = 0; + break; } /* if this is a division then check if right */ /* is one then change it to an assignment */ @@ -810,35 +919,233 @@ algebraicOpts (iCode * ic) } break; case CAST: - /* if this is a cast of a literal value */ - if (IS_OP_LITERAL (IC_RIGHT (ic))) + { + sym_link *otype = operandType(IC_RIGHT(ic)); + sym_link *ctype = operandType(IC_LEFT(ic)); + /* if this is a cast of a literal value */ + if (IS_OP_LITERAL (IC_RIGHT (ic)) && + !(IS_GENPTR(ctype) && (IS_PTR(otype) && !IS_GENPTR(otype)))) { + ic->op = '='; + IC_RIGHT (ic) = + operandFromValue (valCastLiteral (operandType (IC_LEFT (ic)), + operandLitValue (IC_RIGHT (ic)))); + IC_LEFT (ic) = NULL; + SET_ISADDR (IC_RESULT (ic), 0); + } + /* if casting to the same */ + if (compareType (operandType (IC_RESULT (ic)), + operandType (IC_RIGHT (ic))) == 1) { + ic->op = '='; + IC_LEFT (ic) = NULL; + SET_ISADDR (IC_RESULT (ic), 0); + } + } + break; + case '!': + if (IS_OP_LITERAL (IC_LEFT (ic))) { ic->op = '='; IC_RIGHT (ic) = - operandFromValue (valCastLiteral (operandType (IC_LEFT (ic)), - operandLitValue (IC_RIGHT (ic)))); + (operandLitValue (IC_LEFT (ic)) == 0 ? + operandFromLit (1) : operandFromLit (0)); IC_LEFT (ic) = NULL; SET_ISADDR (IC_RESULT (ic), 0); } - /* if casting to the same */ - if (compareType (operandType (IC_RESULT (ic)), - operandType (IC_RIGHT (ic))) == 1) - { + 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_ISADDR (IC_RESULT (ic), 0); + 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 '!': + 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))) { - ic->op = '='; - IC_RIGHT (ic) = - (operandLitValue (IC_LEFT (ic)) == 0 ? - operandFromLit (1) : operandFromLit (0)); - IC_LEFT (ic) = NULL; - SET_ISADDR (IC_RESULT (ic), 0); + 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; @@ -847,10 +1154,9 @@ algebraicOpts (iCode * ic) /*-----------------------------------------------------------------*/ /* updateSpillLocation - keeps track of register spill location */ /*-----------------------------------------------------------------*/ -void +void updateSpillLocation (iCode * ic, int induction) { - sym_link *setype; if (POINTER_SET (ic)) @@ -869,11 +1175,23 @@ 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; + } + } +#if 0 /* this needs furthur investigation can save a lot of code */ + if (ASSIGN_SYM_TO_ITEMP(ic) && + !SPIL_LOC(IC_RESULT(ic))) { + if (!OTHERS_PARM (OP_SYMBOL (IC_RIGHT (ic)))) + SPIL_LOC (IC_RESULT (ic)) = + IC_RIGHT (ic)->operand.symOperand; + } +#endif if (ASSIGN_ITEMP_TO_ITEMP (ic)) { if (!SPIL_LOC (IC_RIGHT (ic)) && @@ -969,10 +1287,10 @@ ifxOptimize (iCode * ic, set * cseSet, if (!computeOnly) { pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_COND (ic), &pdop); + applyToSetFTrue (cseSet, findCheaperOp, IC_COND (ic), &pdop, 0); if (pdop) { - IC_COND (ic) = pdop; + ReplaceOpWithCheaperOp(&IC_COND (ic), pdop); (*change)++; } } @@ -1013,7 +1331,9 @@ ifxOptimize (iCode * ic, set * cseSet, /* too often, if it does happen then the user pays */ /* the price */ computeControlFlow (ebbs, count, 1); - werror (W_CONTROL_FLOW, ic->filename, ic->lineno); + if (!options.lessPedantic) { + werror (W_CONTROL_FLOW, ic->filename, ic->lineno); + } return; } @@ -1027,13 +1347,15 @@ ifxOptimize (iCode * ic, set * cseSet, remiCodeFromeBBlock (ebb, ic); computeControlFlow (ebbs, count, 1); - werror (W_CONTROL_FLOW, ic->filename, ic->lineno); + if (!options.lessPedantic) { + werror (W_CONTROL_FLOW, ic->filename, ic->lineno); + } return; } /* if it remains an IFX the update the use Set */ - OP_USES (IC_COND (ic)) = bitVectSetBit (OP_USES (IC_COND (ic)), ic->key); + OP_USES(IC_COND (ic))=bitVectSetBit (OP_USES (IC_COND (ic)), ic->key); setUsesDefs (IC_COND (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); return; } @@ -1083,7 +1405,7 @@ constFold (iCode * ic, set * cseSet) /* this check is a hueristic to prevent live ranges from becoming too long */ if (IS_PTR (operandType (IC_RESULT (ic)))) - return 0; + return 0; /* check if operation with a literal */ if (!IS_OP_LITERAL (IC_RIGHT (ic))) @@ -1166,9 +1488,9 @@ deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb) list . This will take care of situations like iTemp1 = iTemp0 + 8; iTemp2 = iTemp1 + 8; */ - if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode), + if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode), (insetwithFunc)isOperandEqual) || - isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode), + isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode), (insetwithFunc)isOperandEqual)) { addSet (&compItems, IC_RESULT (cdp->diCode)); @@ -1216,7 +1538,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; @@ -1237,13 +1559,63 @@ fixUpTypes (iCode * ic) } } +/*-----------------------------------------------------------------*/ +/* isSignedOp - will return 1 if sign is important to operation */ +/*-----------------------------------------------------------------*/ +static int isSignedOp (iCode *ic) +{ + switch (ic->op) { + case '!': + case '~': + case UNARYMINUS: + case IPUSH: + case IPOP: + case CALL: + case PCALL: + case RETURN: + case '+': + case '-': + case EQ_OP: + case AND_OP: + case OR_OP: + case '^': + case '|': + case BITWISEAND: + case INLINEASM: + case LEFT_OP: + case GET_VALUE_AT_ADDRESS: + case '=': + case IFX: + case RECEIVE: + case SEND: + return 0; + case '*': + case '/': + case '%': + case '>': + case '<': + case LE_OP: + case GE_OP: + case NE_OP: + case RRC: + case RLC: + case GETHBIT: + case RIGHT_OP: + case CAST: + case ARRAYINIT: + return 1; + default: + return 0; + } + } + /*-----------------------------------------------------------------*/ /* 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) { @@ -1255,18 +1627,18 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* 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; @@ -1276,10 +1648,12 @@ 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; + int checkSign ; + + ic->eBBlockNum = ebb->bbnum; if (SKIP_IC2 (ic)) continue; @@ -1299,7 +1673,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, if (ic->op == PCALL || ic->op == CALL || ic->op == RECEIVE) { /* add to defSet of the symbol */ - OP_DEFS (IC_RESULT (ic)) = + 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); @@ -1309,6 +1683,10 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* delete global variables from the cseSet since they can be modified by the function call */ deleteItemIf (&cseSet, ifDefGlobal); + + /* and also itemps assigned from globals */ + deleteItemIf (&cseSet, ifAssignedFromGlobal); + /* 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 */ @@ -1327,14 +1705,14 @@ cseBBlock (eBBlock * ebb, int computeOnly, if (!computeOnly) { pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop); + applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop, 0); if (pdop) - IC_LEFT (ic) = pdop; + ReplaceOpWithCheaperOp(&IC_LEFT(ic), pdop); } /* the lookup could have changed it */ if (IS_SYMOP (IC_LEFT (ic))) { - OP_USES (IC_LEFT (ic)) = + OP_USES(IC_LEFT (ic))= bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key); setUsesDefs (IC_LEFT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); @@ -1359,19 +1737,24 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* if jumptable then mark the usage */ if (ic->op == JUMPTABLE) { - OP_USES (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)))) @@ -1387,7 +1770,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) { @@ -1399,7 +1782,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 */ @@ -1409,12 +1792,15 @@ cseBBlock (eBBlock * ebb, int computeOnly, !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype))) { pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop); - if (pdop && IS_ITEMP (pdop) && !computeOnly) - IC_RESULT (ic) = pdop; + applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop, 0); + if (pdop && !computeOnly && + IS_ITEMP (pdop) && IS_PTR(operandType(pdop))) + ReplaceOpWithCheaperOp (&IC_RESULT(ic), pdop); } } + checkSign = isSignedOp(ic); + /* do the operand lookup i.e. for both the */ /* right & left operand : check the cseSet */ /* to see if they have been replaced if yes */ @@ -1426,14 +1812,18 @@ cseBBlock (eBBlock * ebb, int computeOnly, { pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop); + applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop, checkSign); if (pdop) { if (POINTER_GET (ic)) { if (IS_ITEMP (pdop) || IS_OP_LITERAL (pdop)) { - IC_LEFT (ic) = pdop; + /* some non dominating block does POINTER_SET with + this variable .. unsafe to remove any POINTER_GETs */ + if (bitVectBitValue(ebb->ndompset,IC_LEFT(ic)->key)) + ebb->ptrsSet = bitVectSetBit(ebb->ptrsSet,pdop->key); + ReplaceOpWithCheaperOp(&IC_LEFT(ic), pdop); change = 1; } /* check if there is a pointer set @@ -1445,14 +1835,14 @@ cseBBlock (eBBlock * ebb, int computeOnly, { ic->op = '='; IC_LEFT (ic) = NULL; - IC_RIGHT (ic) = pdop; + ReplaceOpWithCheaperOp(&IC_RIGHT(ic), pdop); SET_ISADDR (IC_RESULT (ic), 0); } } else { - IC_LEFT (ic) = pdop; + ReplaceOpWithCheaperOp(&IC_LEFT(ic), pdop); change = 1; } } @@ -1463,23 +1853,21 @@ cseBBlock (eBBlock * ebb, int computeOnly, { pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_RIGHT (ic), &pdop); - if (pdop) - { - - IC_RIGHT (ic) = pdop; - change = 1; - } + applyToSetFTrue (cseSet, findCheaperOp, IC_RIGHT (ic), &pdop, checkSign); + if (pdop) { + ReplaceOpWithCheaperOp(&IC_RIGHT(ic), pdop); + 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)) { @@ -1502,69 +1890,35 @@ cseBBlock (eBBlock * ebb, int computeOnly, IS_ITEMP (IC_RESULT (ic)) && !computeOnly) { - applyToSet (cseSet, findPrevIc, ic, &pdic); + applyToSet (cseSet, findPrevIc, ic, &pdic); if (pdic && compareType (operandType (IC_RESULT (pdic)), operandType (IC_RESULT (ic))) != 1) pdic = NULL; + if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0) + pdic = NULL; } - /* if found then eliminate this and add to */ - /* to cseSet an element containing result */ - /* of this with previous opcode */ - if (pdic) - { - - if (IS_ITEMP (IC_RESULT (ic))) - { - - /* replace in the remaining of this block */ - replaceAllSymBySym (ic->next, IC_RESULT (ic), IC_RESULT (pdic), &ebb->ndompset); - /* remove this iCode from inexpressions of all - its successors, it cannot be in the in expressions - of any of the predecessors */ - for (i = 0; i < count; ebbs[i++]->visited = 0); - applyToSet (ebb->succList, removeFromInExprs, ic, IC_RESULT (ic), - IC_RESULT (pdic), ebb); - - /* if this was moved from another block */ - /* then replace in those blocks too */ - if (ic->movedFrom) - { - eBBlock *owner; - for (owner = setFirstItem (ic->movedFrom); owner; - owner = setNextItem (ic->movedFrom)) - replaceAllSymBySym (owner->sch, IC_RESULT (ic), IC_RESULT (pdic), &owner->ndompset); - } - pdic->movedFrom = unionSets (pdic->movedFrom, ic->movedFrom, THROW_NONE); - } - else - addSetHead (&cseSet, newCseDef (IC_RESULT (ic), pdic)); - - if (!computeOnly) - /* eliminate this */ - remiCodeFromeBBlock (ebb, ic); - - defic = pdic; - change++; - - if (IS_ITEMP (IC_RESULT (ic))) - continue; - + /* 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 + later on */ + } else { + /* if previous definition found change this to an assignment */ + ic->op = '='; + IC_LEFT(ic) = NULL; + IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic)); + SET_ISADDR(IC_RESULT(ic),0); + SET_ISADDR(IC_RIGHT (ic),0); } - else - { - - /* just add this as a previous expression except in */ - /* case of a pointer access in which case this is a */ - /* usage not a definition */ - if (!(POINTER_SET (ic)) && IC_RESULT (ic)) - { - deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic)); - addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic)); - } - defic = ic; + } - } + if (!(POINTER_SET (ic)) && IC_RESULT (ic)) { + deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic)); + addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic)); + } + defic = ic; /* if assignment to a parameter which is not mine and type is a pointer then delete @@ -1609,7 +1963,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* add the left & right to the defUse set */ if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic))) { - OP_USES (IC_LEFT (ic)) = + OP_USES(IC_LEFT (ic))= bitVectSetBit (OP_USES (IC_LEFT (ic)), ic->key); setUsesDefs (IC_LEFT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); @@ -1617,7 +1971,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))) { - OP_USES (IC_RIGHT (ic)) = + OP_USES(IC_RIGHT (ic))= bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key); setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); @@ -1627,7 +1981,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* in the defuseSet if it a pointer or array access */ if (POINTER_SET (defic)) { - OP_USES (IC_RESULT (ic)) = + 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)); @@ -1646,7 +2000,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, else /* add the result to defintion set */ if (IC_RESULT (ic)) { - OP_DEFS (IC_RESULT (ic)) = + 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))); @@ -1664,7 +2018,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, } } - setToNull ((void **) &ebb->outExprs); + setToNull ((void *) &ebb->outExprs); ebb->outExprs = cseSet; ebb->outDefs = bitVectUnion (ebb->outDefs, ebb->defSet); ebb->ptrsSet = bitVectUnion (ebb->ptrsSet, ebb->inPtrsSet); @@ -1674,8 +2028,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; @@ -1683,7 +2037,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; }