X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCcse.c;h=1b43a42850a335c01fc35c78d708e5cddef2da30;hb=bb226788dab3832b0ec0cda70874ce3fce4eebc6;hp=319c3e22378e15c9eef0b2e4785f1143c0e6b6ec;hpb=9b6292c6f1828886ea5bacb609e63403823e3c06;p=fw%2Fsdcc diff --git a/src/SDCCcse.c b/src/SDCCcse.c index 319c3e22..1b43a428 100644 --- a/src/SDCCcse.c +++ b/src/SDCCcse.c @@ -24,6 +24,8 @@ #include "common.h" #include "newalloc.h" +#include "dbuf_string.h" + /*-----------------------------------------------------------------*/ /* newCseDef - new cseDef */ @@ -39,16 +41,76 @@ newCseDef (operand * sym, iCode * ic) cdp->sym = sym; cdp->diCode = ic; cdp->key = sym->key; + cdp->ancestors = newBitVect(iCodeKey); + cdp->fromGlobal = 0; + cdp->fromAddrTaken = 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)); + cdp->fromAddrTaken |= OP_SYMBOL (IC_LEFT (ic))->addrtaken; + } + if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic))) + { + bitVectSetBit (cdp->ancestors, IC_RIGHT (ic)->key); + cdp->fromGlobal |= isOperandGlobal (IC_RIGHT (ic)); + cdp->fromAddrTaken |= OP_SYMBOL (IC_RIGHT (ic))->addrtaken; + } + } 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; + cdp->fromAddrTaken |= loop->fromAddrTaken; + 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; + cdp->fromAddrTaken |= loop->fromAddrTaken; + break; + } + } + } + } +} /*-----------------------------------------------------------------*/ /* int isCseDefEqual - two definitions are equal */ /*-----------------------------------------------------------------*/ -int +int isCseDefEqual (void *vsrc, void *vdest) { cseDef *src = vsrc; @@ -58,18 +120,19 @@ isCseDefEqual (void *vsrc, void *vdest) return 1; return (src->key == dest->key && - src->diCode == dest->diCode); + src->diCode == dest->diCode); } /*-----------------------------------------------------------------*/ /* pcseDef - in the cseDef */ /*-----------------------------------------------------------------*/ -int +int pcseDef (void *item, va_list ap) { cseDef *cdp = item; iCodeTable *icTab; + struct dbuf_s dbuf; (void) ap; @@ -77,102 +140,136 @@ pcseDef (void *item, va_list ap) fprintf (stdout, "**null op**"); printOperand (cdp->sym, stdout); icTab = getTableEntry (cdp->diCode->op); - icTab->iCodePrint (stdout, cdp->diCode, icTab->printName); + dbuf_init (&dbuf, 1024); + icTab->iCodePrint (&dbuf, cdp->diCode, icTab->printName); + dbuf_write_and_destroy (&dbuf, stdout); return 1; } +void ReplaceOpWithCheaperOp(operand **op, operand *cop) { +#ifdef RANGEHUNT + printf ("ReplaceOpWithCheaperOp\n\t"); + printOperand (*op, stdout); + printf ("\nwith\t"); + printOperand (cop, stdout); + + // if op is a register equivalent + if (IS_ITEMP(cop) && IS_SYMOP((*op)) && 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; +#ifdef RANGEHUNT + printf ("replaceAllSymBySym\n\t"); + printOperand (from, stdout); + printf ("\nwith\t"); + printOperand (to, stdout); + printf ("\n"); +#endif for (lic = ic; lic; lic = lic->next) { - int siaddr; + int isaddr; /* do the special cases first */ if (lic->op == IFX) - { - if (IS_SYMOP (to) && - IC_COND (lic)->key == from->key) - { + { + if (IS_SYMOP (to) && + IC_COND (lic)->key == from->key) + { - bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES_SET ((to), bitVectSetBit (OP_USES (to), lic->key)); - siaddr = IC_COND (lic)->isaddr; - IC_COND (lic) = operandFromOperand (to); - IC_COND (lic)->isaddr = siaddr; + bitVectUnSetBit (OP_USES (from), lic->key); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); + isaddr = IC_COND (lic)->isaddr; + IC_COND (lic) = operandFromOperand (to); + IC_COND (lic)->isaddr = isaddr; - } - continue; - } + } + continue; + } if (lic->op == JUMPTABLE) - { - if (IS_SYMOP (to) && - IC_JTCOND (lic)->key == from->key) - { - - bitVectUnSetBit (OP_USES (from), lic->key); - OP_USES_SET ((to), bitVectSetBit (OP_USES (to), lic->key)); - siaddr = IC_COND (lic)->isaddr; - IC_JTCOND (lic) = operandFromOperand (to); - IC_JTCOND (lic)->isaddr = siaddr; - - } - continue; - } - - if (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)); - - /* also check if the "from" was in the non-dominating - pointer sets and replace it with "to" in the bitVector */ - if (bitVectBitValue (*ndpset, from->key)) - { - bitVectUnSetBit (*ndpset, from->key); - bitVectSetBit (*ndpset, to->key); - } - - } - else - { - bitVectUnSetBit (OP_DEFS (from), lic->key); - OP_DEFS_SET ((to), bitVectSetBit (OP_DEFS (to), lic->key)); - } - siaddr = IC_RESULT (lic)->isaddr; - IC_RESULT (lic) = operandFromOperand (to); - IC_RESULT (lic)->isaddr = siaddr; - } + { + if (IS_SYMOP (to) && + IC_JTCOND (lic)->key == from->key) + { + + bitVectUnSetBit (OP_USES (from), lic->key); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); + isaddr = IC_COND (lic)->isaddr; + IC_JTCOND (lic) = operandFromOperand (to); + IC_JTCOND (lic)->isaddr = isaddr; + + } + continue; + } + + 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); + + /* also check if the "from" was in the non-dominating + pointer sets and replace it with "to" in the bitVector */ + if (bitVectBitValue (*ndpset, from->key)) + { + bitVectUnSetBit (*ndpset, from->key); + bitVectSetBit (*ndpset, to->key); + } + + } + else + { + bitVectUnSetBit (OP_DEFS (from), lic->key); + OP_DEFS(to)=bitVectSetBit (OP_DEFS (to), lic->key); + } + isaddr = IC_RESULT (lic)->isaddr; + IC_RESULT (lic) = operandFromOperand (to); + IC_RESULT (lic)->isaddr = isaddr; + } if (IS_SYMOP (to) && - 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)); - siaddr = IC_RIGHT (lic)->isaddr; - IC_RIGHT (lic) = operandFromOperand (to); - IC_RIGHT (lic)->isaddr = siaddr; - } + IC_RIGHT (lic) && IC_RIGHT (lic)->key == from->key) + { + bitVectUnSetBit (OP_USES (from), lic->key); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); + isaddr = IC_RIGHT (lic)->isaddr; + IC_RIGHT (lic) = operandFromOperand (to); + IC_RIGHT (lic)->isaddr = isaddr; + } if (IS_SYMOP (to) && - 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)); - siaddr = IC_LEFT (lic)->isaddr; - IC_LEFT (lic) = operandFromOperand (to); - IC_LEFT (lic)->isaddr = siaddr; - } + IC_LEFT (lic) && IC_LEFT (lic)->key == from->key) + { + bitVectUnSetBit (OP_USES (from), lic->key); + OP_USES(to)=bitVectSetBit (OP_USES (to), lic->key); + isaddr = IC_LEFT (lic)->isaddr; + IC_LEFT (lic) = operandFromOperand (to); + IC_LEFT (lic)->isaddr = isaddr; + } } } @@ -216,7 +313,7 @@ DEFSETFUNC (removeFromInExprs) /*-----------------------------------------------------------------*/ /* isGlobalInNearSpace - return TRUE if valriable is a globalin data */ /*-----------------------------------------------------------------*/ -static bool +static bool isGlobalInNearSpace (operand * op) { sym_link *type = getSpec (operandType (op)); @@ -255,41 +352,41 @@ DEFSETFUNC (findCheaperOp) /* constant propagation & dead code elim */ /* for assignments only */ if (cdp->diCode->op == '=') { - /* if the result is volatile then return result */ - if (IS_OP_VOLATILE (IC_RESULT (cdp->diCode))) - *opp = IC_RESULT (cdp->diCode); - else - /* if this is a straight assignment and - left is a temp then prefer the temporary to the - true symbol */ - if (!POINTER_SET (cdp->diCode) && - IS_ITEMP (IC_RESULT (cdp->diCode)) && - IS_TRUE_SYMOP (IC_RIGHT (cdp->diCode))) - *opp = IC_RESULT (cdp->diCode); - else { - /* if straight assignement && and both - are temps then prefer the one that - will not need extra space to spil, also - take into consideration if right side - an induction variable - */ - if (!POINTER_SET (cdp->diCode) && - 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)) && - SPIL_LOC (IC_RESULT (cdp->diCode)) == - SPIL_LOC (IC_RIGHT (cdp->diCode))))) - *opp = IC_RESULT (cdp->diCode); - else - *opp = IC_RIGHT (cdp->diCode); - } + /* if the result is volatile then return result */ + if (IS_OP_VOLATILE (IC_RESULT (cdp->diCode))) + *opp = IC_RESULT (cdp->diCode); + else + /* if this is a straight assignment and + left is a temp then prefer the temporary to the + true symbol */ + if (!POINTER_SET (cdp->diCode) && + IS_ITEMP (IC_RESULT (cdp->diCode)) && + IS_TRUE_SYMOP (IC_RIGHT (cdp->diCode))) + *opp = IC_RESULT (cdp->diCode); + else { + /* if straight assignment and both + are temps then prefer the one that + will not need extra space to spil, also + take into consideration if right side + is an induction variable + */ + if (!POINTER_SET (cdp->diCode) && + 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)) && + SPIL_LOC (IC_RESULT (cdp->diCode)) == + SPIL_LOC (IC_RIGHT (cdp->diCode))))) + *opp = IC_RESULT (cdp->diCode); + else + *opp = IC_RIGHT (cdp->diCode); + } } else - *opp = IC_RESULT (cdp->diCode); + *opp = IC_RESULT (cdp->diCode); } /* if this is an assign to a temp. then check @@ -302,33 +399,64 @@ DEFSETFUNC (findCheaperOp) IS_ITEMP (IC_RESULT (cdp->diCode))) *opp = IC_RESULT (cdp->diCode); - if ((*opp) && - (isOperandLiteral(*opp) || !checkSign || + if ((*opp) && + (isOperandLiteral(*opp) || !checkSign || (checkSign && - (SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) && - (SPEC_LONG(operandType (cop))==SPEC_LONG(operandType (*opp))))))) + 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)) || - isOperandVolatile (*opp, FALSE) - ) - { - *opp = NULL; - return 0; - } + !isOperandLiteral (*opp)) || + isOperandVolatile (*opp, FALSE) + ) + { + *opp = NULL; + return 0; + } if (cop->key == (*opp)->key) - { - *opp = NULL; - return 0; - } + { + *opp = NULL; + return 0; + } if ((*opp)->isaddr != cop->isaddr && IS_ITEMP (cop)) - { - *opp = operandFromOperand (*opp); - (*opp)->isaddr = cop->isaddr; - } + { + *opp = operandFromOperand (*opp); + (*opp)->isaddr = cop->isaddr; + } + + /* copy signedness to literal operands */ + if (IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) + && isOperandLiteral(*opp) + && SPEC_NOUN(operandType(*opp)) == SPEC_NOUN(operandType(cop)) + && SPEC_USIGN(operandType(*opp)) != SPEC_USIGN(operandType(cop))) + { + SPEC_USIGN(operandType(*opp)) = SPEC_USIGN(operandType(cop)); + } + + 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; @@ -354,6 +482,16 @@ DEFSETFUNC (findPointerSet) getSize (operandType (IC_RIGHT (cdp->diCode))) == getSize (operandType (rop))) { + if (IS_SPEC (operandType (IC_RIGHT (cdp->diCode))) && + SPEC_USIGN (operandType (IC_RIGHT (cdp->diCode))) != + SPEC_USIGN (operandType (rop))) + { + /* bug #1493710 + Reminder for Bernhard: check of signedness + could be unnecessary together with 'checkSign', if + signedness of operation is stored in ic */ + return 0; + } *opp = IC_RIGHT (cdp->diCode); return 1; } @@ -379,14 +517,14 @@ DEFSETFUNC (findPrevIc) if (isiCodeEqual (ic, cdp->diCode) && isOperandEqual (cdp->sym, IC_RESULT (cdp->diCode))) { - *icp = cdp->diCode; + *icp = cdp->diCode; return 1; } /* if iCodes are not the same */ /* see the operands maybe interchanged */ if (ic->op == cdp->diCode->op && - (ic->op == '+' || ic->op == '*') && + IS_ASSOCIATIVE(ic) && isOperandEqual (IC_LEFT (ic), IC_RIGHT (cdp->diCode)) && isOperandEqual (IC_RIGHT (ic), IC_LEFT (cdp->diCode))) { @@ -411,6 +549,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 */ /*-----------------------------------------------------------------*/ @@ -421,6 +569,18 @@ DEFSETFUNC (ifDefGlobal) return (isOperandGlobal (cdp->sym)); } +/*-------------------------------------------------------------------*/ +/* ifFromAddrTaken - if definition is derived from a symbol whose */ +/* address was taken */ +/*-------------------------------------------------------------------*/ +DEFSETFUNC (ifFromAddrTaken) +{ + cseDef *cdp = item; + + return cdp->fromAddrTaken; +} + + /*-----------------------------------------------------------------*/ /* ifAnyGetPointer - if get pointer icode */ /*-----------------------------------------------------------------*/ @@ -441,6 +601,8 @@ 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)) && @@ -472,7 +634,7 @@ DEFSETFUNC (ifOperandsHave) /*-----------------------------------------------------------------*/ /* ifDefSymIs - if a definition is found in the set */ /*-----------------------------------------------------------------*/ -int +int ifDefSymIs (set * cseSet, operand * sym) { cseDef *loop; @@ -484,7 +646,7 @@ ifDefSymIs (set * cseSet, operand * sym) { loop = sl->item; if (loop->sym->key == sym->key) - return 1; + return 1; } return 0; } @@ -497,19 +659,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 */ +/* ifDiCodeIs - returns true if diCode is same */ /*-----------------------------------------------------------------*/ -int +int ifDiCodeIs (set * cseSet, iCode * ic) { cseDef *loop; @@ -522,7 +689,7 @@ ifDiCodeIs (set * cseSet, iCode * ic) { loop = sl->item; if (loop->diCode == ic) - return 1; + return 1; } return 0; @@ -579,8 +746,8 @@ 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; + if (IC_RESULT(lic) && isOperandEqual(op,IC_RESULT(lic))) + return lic; } return NULL; } @@ -588,8 +755,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 */ @@ -613,9 +780,9 @@ algebraicOpts (iCode * ic) { IC_RIGHT (ic) = operandOperation (IC_LEFT (ic), - IC_RIGHT (ic), - ic->op, - operandType (IC_RESULT (ic))); + IC_RIGHT (ic), + ic->op, + operandType (IC_RESULT (ic))); ic->op = '='; IC_LEFT (ic) = NULL; SET_RESULT_RIGHT (ic); @@ -630,9 +797,9 @@ algebraicOpts (iCode * ic) { IC_RIGHT (ic) = operandOperation (IC_LEFT (ic), - IC_RIGHT (ic), - ic->op, - operandType (IC_RESULT (ic))); + IC_RIGHT (ic), + ic->op, + operandType (IC_RESULT (ic))); ic->op = '='; IC_LEFT (ic) = NULL; SET_RESULT_RIGHT (ic); @@ -646,33 +813,33 @@ algebraicOpts (iCode * ic) { if (IS_ITEMP (IC_RESULT (ic)) && - IS_TRUE_SYMOP (IC_LEFT (ic))) - { - - ic->op = '='; - IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic)); - IC_RIGHT (ic)->isaddr = 0; - IC_LEFT (ic) = NULL; - IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); - IC_RESULT (ic)->isaddr = 0; - setOperandType (IC_RESULT (ic), operandType (IC_RIGHT (ic))); - return; - } + IS_TRUE_SYMOP (IC_LEFT (ic))) + { + + ic->op = '='; + IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic)); + IC_RIGHT (ic)->isaddr = 0; + IC_LEFT (ic) = NULL; + IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); + IC_RESULT (ic)->isaddr = 0; + setOperandType (IC_RESULT (ic), operandType (IC_RIGHT (ic))); + return; + } if (IS_ITEMP (IC_LEFT (ic)) && - IS_ITEMP (IC_RESULT (ic)) && + IS_ITEMP (IC_RESULT (ic)) && /* !OP_SYMBOL(IC_RESULT(ic))->isreqv && */ /* !OP_SYMBOL(IC_LEFT(ic))->isreqv && */ - !IC_LEFT (ic)->isaddr) - { - ic->op = '='; - IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic)); - IC_RIGHT (ic)->isaddr = 0; - IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); - IC_RESULT (ic)->isaddr = 0; - IC_LEFT (ic) = NULL; - return; - } + !IC_LEFT (ic)->isaddr) + { + ic->op = '='; + IC_RIGHT (ic) = operandFromOperand (IC_LEFT (ic)); + IC_RIGHT (ic)->isaddr = 0; + IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); + IC_RESULT (ic)->isaddr = 0; + IC_LEFT (ic) = NULL; + return; + } } @@ -683,71 +850,105 @@ algebraicOpts (iCode * ic) case '+': /* if adding the same thing change to left shift by 1 */ if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key && - !IS_FLOAT (operandType (IC_RESULT (ic)))) - { - ic->op = LEFT_OP; - IC_RIGHT (ic) = operandFromLit (1); - return; - } + !(IS_FLOAT (operandType (IC_RESULT (ic))) + || IS_FIXED(operandType (IC_RESULT (ic))))) + { + ic->op = LEFT_OP; + IC_RIGHT (ic) = operandFromLit (1); + return; + } /* if addition then check if one of them is a zero */ - /* if yes turn it into assignmnt */ + /* if yes turn it into assignment or cast */ if (IS_OP_LITERAL (IC_LEFT (ic)) && - operandLitValue (IC_LEFT (ic)) == 0.0) - { - - ic->op = '='; - IC_LEFT (ic) = NULL; - SET_ISADDR (IC_RESULT (ic), 0); - SET_ISADDR (IC_RIGHT (ic), 0); - return; - } + operandLitValue (IC_LEFT (ic)) == 0.0) + { + int typematch; + typematch = compareType (operandType (IC_RESULT (ic)), + operandType (IC_RIGHT (ic))); + if ((typematch<0) || (IS_TRUE_SYMOP (IC_RIGHT (ic)))) + { + ic->op = CAST; + IC_LEFT (ic) = operandFromLink (operandType (IC_RESULT (ic))); + } + else + { + ic->op = '='; + IC_LEFT (ic) = NULL; + if (typematch==0) + { + /* for completely different types, preserve the source type */ + IC_RIGHT (ic) = operandFromOperand (IC_RIGHT (ic)); + setOperandType (IC_RIGHT (ic), operandType (IC_RESULT (ic))); + } + } + SET_ISADDR (IC_RESULT (ic), 0); + SET_ISADDR (IC_RIGHT (ic), 0); + return; + } 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; - SET_ISADDR (IC_RIGHT (ic), 0); - SET_ISADDR (IC_RESULT (ic), 0); - return; - } + operandLitValue (IC_RIGHT (ic)) == 0.0) + { + int typematch; + typematch = compareType (operandType (IC_RESULT (ic)), + operandType (IC_LEFT (ic))); + if ((typematch<0) || (IS_TRUE_SYMOP (IC_LEFT (ic)))) + { + 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; + if (typematch==0) + { + /* for completely different types, preserve the source type */ + IC_RIGHT (ic) = operandFromOperand (IC_RIGHT (ic)); + setOperandType (IC_RIGHT (ic), operandType (IC_RESULT (ic))); + } + } + SET_ISADDR (IC_RIGHT (ic), 0); + SET_ISADDR (IC_RESULT (ic), 0); + return; + } break; case '-': - /* if subtracting the the same thing then zero */ + /* if subtracting the same thing then zero */ if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key) - { - ic->op = '='; - IC_RIGHT (ic) = operandFromLit (0); - IC_LEFT (ic) = NULL; - IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); - IC_RESULT (ic)->isaddr = 0; - return; - } + { + ic->op = '='; + IC_RIGHT (ic) = operandFromLit (0); + IC_LEFT (ic) = NULL; + IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); + IC_RESULT (ic)->isaddr = 0; + return; + } /* if subtraction then check if one of the operand */ /* is zero then depending on which operand change */ /* to assignment or unary minus */ if (IS_OP_LITERAL (IC_RIGHT (ic)) && - operandLitValue (IC_RIGHT (ic)) == 0.0) - { - /* right size zero change to assignment */ - 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; - } + operandLitValue (IC_RIGHT (ic)) == 0.0) + { + /* right size zero change to assignment */ + 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; + } if (IS_OP_LITERAL (IC_LEFT (ic)) && - operandLitValue (IC_LEFT (ic)) == 0.0) - { - /* left zero turn into an unary minus */ - ic->op = UNARYMINUS; - IC_LEFT (ic) = IC_RIGHT (ic); - IC_RIGHT (ic) = NULL; - return; - } + operandLitValue (IC_LEFT (ic)) == 0.0) + { + /* left zero turn into an unary minus */ + ic->op = UNARYMINUS; + IC_LEFT (ic) = IC_RIGHT (ic); + IC_RIGHT (ic) = NULL; + return; + } break; /* if multiplication then check if either of */ /* them is zero then the result is zero */ @@ -755,126 +956,434 @@ algebraicOpts (iCode * ic) /* the other one */ case '*': if (IS_OP_LITERAL (IC_LEFT (ic))) - { - - if (operandLitValue (IC_LEFT (ic)) == 0.0) - { - ic->op = '='; - IC_RIGHT (ic) = IC_LEFT (ic); - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); - return; - } - if (operandLitValue (IC_LEFT (ic)) == 1.0) - { - ic->op = '='; - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); - return; - } - } + { + double leftValue = operandLitValue (IC_LEFT (ic)); + + if (leftValue == 0.0) + { + ic->op = '='; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + if (leftValue == 1.0) + { + /* '*' 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; + } + if (leftValue == -1.0) + { + /* convert -1 * x to -x */ + ic->op = UNARYMINUS; + IC_LEFT (ic) = IC_RIGHT (ic); + IC_RIGHT (ic) = NULL; + return; + } + } if (IS_OP_LITERAL (IC_RIGHT (ic))) - { - - if (operandLitValue (IC_RIGHT (ic)) == 0.0) - { - ic->op = '='; - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); - return; - } - - if (operandLitValue (IC_RIGHT (ic)) == 1.0) - { - ic->op = '='; - IC_RIGHT (ic) = IC_LEFT (ic); - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); - return; - } - } + { + double rightValue = operandLitValue (IC_RIGHT (ic)); + + if (rightValue == 0.0) + { + ic->op = '='; + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + + if (rightValue == 1.0) + { + /* '*' 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; + } + if (rightValue == -1.0) + { + /* '*' can have two unsigned chars as operands */ + /* and an unsigned int as result. */ + if (IS_INTEGRAL (operandType (IC_LEFT (ic)))) + { + if ((getSize (operandType (IC_LEFT (ic))) < (unsigned int) INTSIZE) && + (getSize (operandType (IC_LEFT (ic))) < getSize (operandType (IC_RESULT (ic))))) + { + operand * op; + iCode * newic; + /* Widen to int. */ + op = operandFromOperand (IC_RESULT (ic)); + op->type = TYPE; + setOperandType (op, INTTYPE); + newic = newiCode (CAST, op, IC_LEFT (ic)); + IC_RESULT (newic) = newiTempOperand (INTTYPE, TRUE); + addiCodeToeBBlock (ebp, newic, ic); + IC_LEFT (ic) = IC_RESULT (newic); + } + } + /* convert x * -1 to -x */ + ic->op = UNARYMINUS; + IC_RIGHT (ic) = NULL; + return; + } + } break; case '/': /* if division by self then 1 */ if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key) - { - ic->op = '='; - IC_RIGHT (ic) = operandFromLit (1); - IC_LEFT (ic) = NULL; - IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); - IC_RESULT (ic)->isaddr = 0; - break; - } + { + ic->op = '='; + IC_RIGHT (ic) = operandFromLit (1); + IC_LEFT (ic) = NULL; + IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic)); + IC_RESULT (ic)->isaddr = 0; + return; + } + /* if this is a division then check if left is zero */ + /* and right is not then change it to an assignment */ + if (IS_OP_LITERAL (IC_LEFT (ic)) && IS_OP_LITERAL (IC_RIGHT (ic)) && + (operandLitValue (IC_LEFT (ic)) == 0.0) && (operandLitValue (IC_RIGHT (ic)) != 0.0)) + { + ic->op = '='; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } /* if this is a division then check if right */ /* is one then change it to an assignment */ - if (IS_OP_LITERAL (IC_RIGHT (ic)) && - operandLitValue (IC_RIGHT (ic)) == 1.0) - { - - ic->op = '='; - IC_RIGHT (ic) = IC_LEFT (ic); - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); - return; - } + if (IS_OP_LITERAL (IC_RIGHT (ic))) + { + double rightValue = operandLitValue (IC_RIGHT (ic)); + if (rightValue == 1.0) + { + ic->op = '='; + IC_RIGHT (ic) = IC_LEFT (ic); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + return; + } + if (rightValue == -1.0) + { + /* '/' can have two unsigned chars as operands */ + /* and an unsigned int as result. */ + if (IS_INTEGRAL (operandType (IC_LEFT (ic)))) + { + if ((getSize (operandType (IC_LEFT (ic))) < (unsigned int) INTSIZE) && + (getSize (operandType (IC_LEFT (ic))) < getSize (operandType (IC_RESULT (ic))))) + { + operand * op; + iCode * newic; + /* Widen to int. */ + op = operandFromOperand (IC_RESULT (ic)); + op->type = TYPE; + setOperandType (op, INTTYPE); + newic = newiCode (CAST, op, IC_LEFT (ic)); + IC_RESULT (newic) = newiTempOperand (INTTYPE, TRUE); + addiCodeToeBBlock (ebp, newic, ic); + IC_LEFT (ic) = IC_RESULT (newic); + } + } + /* convert x / -1 to -x */ + ic->op = UNARYMINUS; + IC_RIGHT (ic) = NULL; + return; + } + } break; /* if both are the same for an comparison operators */ case EQ_OP: case LE_OP: case GE_OP: if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic))) - { - ic->op = '='; - IC_RIGHT (ic) = operandFromLit (1); - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); - } + { + ic->op = '='; + IC_RIGHT (ic) = operandFromLit (1); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + } break; case NE_OP: case '>': case '<': if (isOperandEqual (IC_LEFT (ic), IC_RIGHT (ic))) - { - ic->op = '='; - IC_RIGHT (ic) = operandFromLit (0); - IC_LEFT (ic) = NULL; - SET_RESULT_RIGHT (ic); - } + { + ic->op = '='; + IC_RIGHT (ic) = operandFromLit (0); + IC_LEFT (ic) = NULL; + SET_RESULT_RIGHT (ic); + } break; case CAST: - { - 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; + { + 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) = - (operandLitValue (IC_LEFT (ic)) == 0 ? - operandFromLit (1) : operandFromLit (0)); - IC_LEFT (ic) = NULL; - SET_ISADDR (IC_RESULT (ic), 0); - } + { + ic->op = '='; + IC_RIGHT (ic) = + (operandLitValue (IC_LEFT (ic)) == 0 ? + operandFromLit (1) : operandFromLit (0)); + 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->filename = ic->filename; + 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->filename = ic->filename; + 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) double2ul (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->filename = ic->filename; + 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) double2ul (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->filename = ic->filename; + 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->filename = ic->filename; + 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->filename = ic->filename; + 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; @@ -883,72 +1392,82 @@ algebraicOpts (iCode * ic) /*-----------------------------------------------------------------*/ /* updateSpillLocation - keeps track of register spill location */ /*-----------------------------------------------------------------*/ -void +void updateSpillLocation (iCode * ic, int induction) { + sym_link *setype; - sym_link *setype; - - if (POINTER_SET (ic)) - return; + if (POINTER_SET (ic)) + return; - if (ic->nosupdate) - return; + if (ic->nosupdate) + return; - /* for the form true_symbol := iTempNN */ - if (ASSIGN_ITEMP_TO_SYM (ic) && - !SPIL_LOC (IC_RIGHT (ic))) { +#if 0 + /* for the form true_symbol := iTempNN */ + if (ASSIGN_ITEMP_TO_SYM (ic) && + !SPIL_LOC (IC_RIGHT (ic))) { - setype = getSpec (operandType (IC_RESULT (ic))); + setype = getSpec (operandType (IC_RESULT (ic))); - if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc && - !IS_VOLATILE (setype) && - !IN_FARSPACE (SPEC_OCLS (setype)) && - !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic)))) + if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc && + !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; + } - 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) && - !SPIL_LOC(IC_RESULT(ic))) { - if (!OTHERS_PARM (OP_SYMBOL (IC_RIGHT (ic)))) - SPIL_LOC (IC_RESULT (ic)) = - IC_RIGHT (ic)->operand.symOperand; - } + 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)) && - !bitVectBitsInCommon (OP_DEFS (IC_RIGHT (ic)), OP_USES (IC_RESULT (ic))) && - OP_SYMBOL (IC_RESULT (ic))->isreqv) { - - setype = getSpec (operandType (IC_RESULT (ic))); - - if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc && - !IS_VOLATILE (setype) && - !IN_FARSPACE (SPEC_OCLS (setype)) && - !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic)))) - - SPIL_LOC (IC_RIGHT (ic)) = - SPIL_LOC (IC_RESULT (ic)); - } - /* special case for inductions */ - if (induction && - OP_SYMBOL(IC_RIGHT(ic))->isreqv && - !OP_SYMBOL(IC_RESULT (ic))->noSpilLoc && - !SPIL_LOC(IC_RESULT(ic))) { - SPIL_LOC (IC_RESULT (ic)) = SPIL_LOC (IC_RIGHT (ic)); - } - } + if (ASSIGN_ITEMP_TO_ITEMP (ic)) { + + if (!SPIL_LOC (IC_RIGHT (ic)) && + !bitVectBitsInCommon (OP_DEFS (IC_RIGHT (ic)), OP_USES (IC_RESULT (ic))) && + OP_SYMBOL (IC_RESULT (ic))->isreqv) { + + setype = getSpec (operandType (IC_RESULT (ic))); + + if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc && + !IS_VOLATILE (setype) && + !IN_FARSPACE (SPEC_OCLS (setype)) && + !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 && + OP_SYMBOL(IC_RIGHT(ic))->isreqv && + !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; + } + } } /*-----------------------------------------------------------------*/ /* setUsesDef - sets the uses def bitvector for a given operand */ /*-----------------------------------------------------------------*/ -void +void setUsesDefs (operand * op, bitVect * bdefs, - bitVect * idefs, bitVect ** oud) + bitVect * idefs, bitVect ** oud) { /* compute the definitions alive at this point */ bitVect *adefs = bitVectUnion (bdefs, idefs); @@ -967,7 +1486,7 @@ setUsesDefs (operand * op, bitVect * bdefs, /*-----------------------------------------------------------------*/ /* unsetDefsAndUses - clear this operation for the operands */ /*-----------------------------------------------------------------*/ -void +void unsetDefsAndUses (iCode * ic) { if (ic->op == JUMPTABLE) @@ -979,18 +1498,18 @@ unsetDefsAndUses (iCode * ic) { /* turn off def set */ if (IS_SYMOP (IC_RESULT (ic))) - { - if (!POINTER_SET (ic)) - bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key); - else - bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key); - } + { + if (!POINTER_SET (ic)) + bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key); + else + bitVectUnSetBit (OP_USES (IC_RESULT (ic)), ic->key); + } /* turn off the useSet for the operands */ if (IS_SYMOP (IC_LEFT (ic))) - bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key); + bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key); if (IS_SYMOP (IC_RIGHT (ic))) - bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key); + bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key); } else /* must be ifx turn off the use */ if (IS_SYMOP (IC_COND (ic))) @@ -1000,11 +1519,11 @@ unsetDefsAndUses (iCode * ic) /*-----------------------------------------------------------------*/ /* ifxOptimize - changes ifx conditions if it can */ /*-----------------------------------------------------------------*/ -void +void ifxOptimize (iCode * ic, set * cseSet, - int computeOnly, - eBBlock * ebb, int *change, - eBBlock ** ebbs, int count) + int computeOnly, + eBBlock * ebb, int *change, + ebbIndex * ebbi) { operand *pdop; symbol *label; @@ -1015,51 +1534,47 @@ ifxOptimize (iCode * ic, set * cseSet, pdop = NULL; applyToSetFTrue (cseSet, findCheaperOp, IC_COND (ic), &pdop, 0); if (pdop) - { - IC_COND (ic) = pdop; - (*change)++; - } + { + ReplaceOpWithCheaperOp(&IC_COND (ic), pdop); + (*change)++; + } } /* if the conditional is a literal then */ if (IS_OP_LITERAL (IC_COND (ic))) { - if ((operandLitValue (IC_COND (ic)) != 0.0) && IC_TRUE (ic)) - { - - /* change to a goto */ - ic->op = GOTO; - IC_LABEL (ic) = IC_TRUE (ic); - (*change)++; - - } + { + /* change to a goto */ + ic->op = GOTO; + IC_LABEL (ic) = IC_TRUE (ic); + (*change)++; + } else - { - - if (!operandLitValue (IC_COND (ic)) && IC_FALSE (ic)) - { - ic->op = GOTO; - IC_LABEL (ic) = IC_FALSE (ic); - (*change)++; - - } - else - { - /* then kill this if condition */ - remiCodeFromeBBlock (ebb, ic); - } - } + { + if (!operandLitValue (IC_COND (ic)) && IC_FALSE (ic)) + { + ic->op = GOTO; + IC_LABEL (ic) = IC_FALSE (ic); + (*change)++; + } + else + { + /* then kill this if condition */ + remiCodeFromeBBlock (ebb, ic); + } + } /* now we need to recompute the control flow */ /* since the control flow has changed */ /* this is very expensive but it does not happen */ /* too often, if it does happen then the user pays */ /* the price */ - computeControlFlow (ebbs, count, 1); - if (!options.lessPedantic) { - werror (W_CONTROL_FLOW, ic->filename, ic->lineno); - } + computeControlFlow (ebbi); + if (!options.lessPedantic) + { + werrorfl (ic->filename, ic->lineno, W_CONTROL_FLOW); + } return; } @@ -1068,21 +1583,38 @@ ifxOptimize (iCode * ic, set * cseSet, we can remove this conditional statement */ label = (IC_TRUE (ic) ? IC_TRUE (ic) : IC_FALSE (ic)); if (elementsInSet (ebb->succList) == 1 && - isinSet (ebb->succList, eBBWithEntryLabel (ebbs, label, count))) + isinSet (ebb->succList, eBBWithEntryLabel (ebbi, label))) { - - remiCodeFromeBBlock (ebb, ic); - computeControlFlow (ebbs, count, 1); - if (!options.lessPedantic) { - werror (W_CONTROL_FLOW, ic->filename, ic->lineno); - } - return; + if (!options.lessPedantic) + { + werrorfl (ic->filename, ic->lineno, W_CONTROL_FLOW); + } + 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 (ebbi); + 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 it remains an IFX then update the use Set */ + 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; } @@ -1112,7 +1644,7 @@ DEFSETFUNC (diCodeForSym) /*-----------------------------------------------------------------*/ /* constFold - does some constant folding */ /*-----------------------------------------------------------------*/ -int +int constFold (iCode * ic, set * cseSet) { iCode *dic = NULL; @@ -1128,7 +1660,7 @@ constFold (iCode * ic, set * cseSet) ic->op != '-') return 0; - /* this check is a hueristic to prevent live ranges + /* this check is a heuristic to prevent live ranges from becoming too long */ if (IS_PTR (operandType (IC_RESULT (ic)))) return 0; @@ -1138,7 +1670,7 @@ constFold (iCode * ic, set * cseSet) return 0; /* check if we can find a definition for the - right hand side */ + left hand side */ if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (ic), &dic))) return 0; @@ -1165,10 +1697,10 @@ constFold (iCode * ic, set * cseSet) IC_LEFT (ic) = operandFromOperand (IC_LEFT (dic)); if (ic->op == dic->op) IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) + - operandLitValue (IC_RIGHT (dic))); + operandLitValue (IC_RIGHT (dic))); else IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) - - operandLitValue (IC_RIGHT (dic))); + operandLitValue (IC_RIGHT (dic))); if (IS_ITEMP (IC_RESULT (ic))) { @@ -1185,56 +1717,58 @@ constFold (iCode * ic, set * cseSet) /* will delete from cseSet all get pointers computed from this */ /* pointer. A simple ifOperandsHave is not good enough here */ /*-----------------------------------------------------------------*/ -static void +static void 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)) - { - 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)) - { - addSet (&compItems, IC_RESULT (cdp->diCode)); - } - } + changes = 0; + for (cdp = setFirstItem (*cseSet); cdp; cdp = setNextItem (*cseSet)) + { + if (IS_ARITHMETIC_OP (cdp->diCode) || POINTER_GET(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++; + } + } + } + } } + while (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); /* 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); } } @@ -1264,7 +1798,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; @@ -1314,7 +1848,7 @@ static int isSignedOp (iCode *ic) case IFX: case RECEIVE: case SEND: - return 0; + return 0; case '*': case '/': case '%': @@ -1326,44 +1860,67 @@ static int isSignedOp (iCode *ic) case RRC: case RLC: case GETHBIT: + case GETABIT: + case GETBYTE: + case GETWORD: case RIGHT_OP: case CAST: case ARRAYINIT: - return 1; + return 1; default: - return 0; + return 0; } } + +#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) + ebbIndex * ebbi) { + eBBlock ** ebbs = ebbi->bbOrder; + int count = ebbi->count; set *cseSet; iCode *ic; 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; @@ -1373,7 +1930,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; @@ -1382,142 +1938,183 @@ cseBBlock (eBBlock * ebb, int computeOnly, ic->eBBlockNum = ebb->bbnum; if (SKIP_IC2 (ic)) - continue; + continue; /* if this is an assignment from true symbol - to a temp then do pointer post inc/dec optimzation */ + to a temp then do pointer post inc/dec optimization */ if (ic->op == '=' && !POINTER_SET (ic) && - IS_PTR (operandType (IC_RESULT (ic)))) - { - ptrPostIncDecOpt (ic); - } + 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 */ unsetDefsAndUses (ic); 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)); - /* add to the definition set of this block */ - ebb->defSet = bitVectSetBit (ebb->defSet, ic->key); - ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key); - ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic))); - setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); - /* 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 */ - deleteItemIf (&cseSet, ifAnyGetPointer); - } + { + /* add to defSet of the symbol */ + 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); + ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic))); + setUsesDefs (IC_RESULT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); + /* delete global variables from the cseSet + since they can be modified by the function call */ + deleteItemIf (&cseSet, ifDefGlobal); + + /* and also iTemps derived from globals */ + deleteItemIf (&cseSet, ifFromGlobal); + + /* Delete iTemps derived from symbols whose address */ + /* has been taken */ + deleteItemIf (&cseSet, ifFromAddrTaken); + + /* 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 */ if ((ic->op == PCALL || - ic->op == IPUSH || - ic->op == IPOP || - ic->op == SEND) && - IS_SYMOP (IC_LEFT (ic))) - { - - /* check if they can be replaced */ - if (!computeOnly) - { - pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop, 0); - if (pdop) - IC_LEFT (ic) = pdop; - } - /* 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)); - setUsesDefs (IC_LEFT (ic), ebb->defSet, - ebb->outDefs, &ebb->usesDefs); - } - - - /* if we a sending a pointer as a parameter - then kill all cse since the pointed to item - might be changed in the function being called */ - if ((ic->op == IPUSH || ic->op == SEND) && - IS_PTR (operandType (IC_LEFT (ic)))) - { - deleteGetPointers (&cseSet, &ptrSetSet, IC_LEFT (ic), ebb); - ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_LEFT (ic)->key); - for (i = 0; i < count; ebbs[i++]->visited = 0); - applyToSet (ebb->succList, delGetPointerSucc, - IC_LEFT (ic), ebb->dfnum); - } - continue; - } + ic->op == IPUSH || + ic->op == IPOP || + ic->op == SEND) && + IS_SYMOP (IC_LEFT (ic))) + { + + /* check if they can be replaced */ + if (!computeOnly) + { + pdop = NULL; + applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop, 0); + if (pdop) + ReplaceOpWithCheaperOp(&IC_LEFT(ic), pdop); + } + /* the lookup could have changed it */ + if (IS_SYMOP (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); + } + + + /* if we a sending a pointer as a parameter + then kill all cse since the pointed to item + might be changed in the function being called */ + if ((ic->op == IPUSH || ic->op == SEND) && + IS_PTR (operandType (IC_LEFT (ic)))) + { + deleteGetPointers (&cseSet, &ptrSetSet, IC_LEFT (ic), ebb); + ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_LEFT (ic)->key); + for (i = 0; i < count; ebbs[i++]->visited = 0); + applyToSet (ebb->succList, delGetPointerSucc, + IC_LEFT (ic), ebb->dfnum); + } + continue; + } /* 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); - continue; - } + { + 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)); - - /* small klugde */ - if (POINTER_GET (ic) && !IS_PTR (operandType (IC_LEFT (ic)))) - { - setOperandType (IC_LEFT (ic), - aggrToPtr (operandType (IC_LEFT (ic)), FALSE)); - fixUpTypes (ic); - - } - if (POINTER_SET (ic) && !IS_PTR (operandType (IC_RESULT (ic)))) - { - setOperandType (IC_RESULT (ic), - aggrToPtr (operandType (IC_RESULT (ic)), FALSE)); - } - - /* if this is a condition statment then */ + continue; + + if (!computeOnly) + { + /* do some algebraic optimizations if possible */ + algebraicOpts (ic, ebb); + while (constFold (ic, cseSet)); + } + + /* small kludge */ + if (POINTER_GET (ic)) + { + if (!IS_PTR (operandType (IC_LEFT (ic)))) + { + setOperandType (IC_LEFT (ic), + aggrToPtr (operandType (IC_LEFT (ic)), FALSE)); + IC_LEFT (ic)->aggr2ptr = 0; + fixUpTypes (ic); + } + else if (IC_LEFT (ic)->aggr2ptr == 1) + {/* band aid for kludge */ + setOperandType (IC_LEFT (ic), + aggrToPtr (operandType (IC_LEFT (ic)), TRUE)); + IC_LEFT (ic)->aggr2ptr++; + fixUpTypes (ic); + } + } + + if (POINTER_SET (ic)) + { + if (!IS_PTR (operandType (IC_RESULT (ic)))) + { + setOperandType (IC_RESULT (ic), + aggrToPtr (operandType (IC_RESULT (ic)), FALSE)); + IC_RESULT (ic)->aggr2ptr = 0; + } + else if (IC_RESULT (ic)->aggr2ptr == 1) + {/* band aid for kludge */ + setOperandType (IC_RESULT (ic), + aggrToPtr (operandType (IC_RESULT (ic)), TRUE)); + IC_RESULT (ic)->aggr2ptr++; + } + } + + /* if this is a condition statement then */ /* check if the condition can be replaced */ if (ic->op == IFX) - { - ifxOptimize (ic, cseSet, computeOnly, - ebb, &change, - ebbs, count); - continue; - } + { + ifxOptimize (ic, cseSet, computeOnly, + ebb, &change, + ebbi); + continue; + } /* if the assignment & result is a temp */ /* see if we can replace it */ - if (ic->op == '=') - { - - /* update the spill location for this */ - updateSpillLocation (ic,0); - - if (POINTER_SET (ic) && - !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype))) - { - pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop, 0); - if (pdop && IS_ITEMP (pdop) && !computeOnly) - IC_RESULT (ic) = pdop; - } - } + if (!computeOnly && ic->op == '=') + { + + /* update the spill location for this */ + updateSpillLocation (ic,0); + + if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic)) && + !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype))) + { + pdop = NULL; + applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop, 0); + if (pdop && !computeOnly && IS_ITEMP (pdop)) + { + ReplaceOpWithCheaperOp (&IC_RESULT(ic), pdop); + if (!IS_PTR (operandType (IC_RESULT (ic)))) + { + setOperandType (IC_RESULT (ic), + aggrToPtr (operandType (IC_RESULT (ic)), FALSE)); + } + } + } + } checkSign = isSignedOp(ic); @@ -1528,73 +2125,73 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* left operand */ /* and left is a symbol */ if (IS_SYMOP (IC_LEFT (ic)) && - !computeOnly && ic->op != ADDRESS_OF) - { - - pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop, checkSign); - if (pdop) - { - if (POINTER_GET (ic)) - { - if (IS_ITEMP (pdop) || IS_OP_LITERAL (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); - IC_LEFT (ic) = pdop; - change = 1; - } - /* check if there is a pointer set - for the same pointer visible if yes - then change this into an assignment */ - pdop = NULL; - if (applyToSetFTrue (cseSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic)) && - !bitVectBitValue (ebb->ptrsSet, pdop->key)) - { - ic->op = '='; - IC_LEFT (ic) = NULL; - IC_RIGHT (ic) = pdop; - SET_ISADDR (IC_RESULT (ic), 0); - } - - } - else - { - IC_LEFT (ic) = pdop; - change = 1; - } - } - } - - /*right operand */ + !IS_BITFIELD (OP_SYM_ETYPE (IC_LEFT (ic))) && + !computeOnly && ic->op != ADDRESS_OF) + { + + pdop = NULL; + applyToSetFTrue (cseSet, findCheaperOp, IC_LEFT (ic), &pdop, checkSign); + if (pdop) + { + if (POINTER_GET (ic)) + { + if (IS_ITEMP (pdop) || IS_OP_LITERAL (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 + for the same pointer visible if yes + then change this into an assignment */ + pdop = NULL; + if (applyToSetFTrue (cseSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic)) && + !bitVectBitValue (ebb->ptrsSet, pdop->key)) + { + ic->op = '='; + IC_LEFT (ic) = NULL; + ReplaceOpWithCheaperOp(&IC_RIGHT(ic), pdop); + SET_ISADDR (IC_RESULT (ic), 0); + } + + } + else + { + ReplaceOpWithCheaperOp(&IC_LEFT(ic), pdop); + change = 1; + } + } + } + + /* right operand */ if (IS_SYMOP (IC_RIGHT (ic)) && !computeOnly) - { + { - pdop = NULL; - applyToSetFTrue (cseSet, findCheaperOp, IC_RIGHT (ic), &pdop, checkSign); - if (pdop) - { - IC_RIGHT (ic) = pdop; - change = 1; - } - } + pdop = NULL; + 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) - { - algebraicOpts (ic); - while (constFold (ic, cseSet)); - } + if (!computeOnly && change) + { + 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)) - { - remiCodeFromeBBlock (ebb, ic); - continue; - } + if (ASSIGNMENT_TO_SELF (ic) && !isOperandVolatile (IC_RIGHT(ic), FALSE)) + { + remiCodeFromeBBlock (ebb, ic); + continue; + } /* now we will check to see if the entire */ /* operation has been performed before */ @@ -1604,40 +2201,43 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* it only if result is a temporary */ pdic = NULL; if (!(POINTER_GET (ic) && - (IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) || - isOperandVolatile (IC_LEFT (ic), TRUE) || - bitVectBitValue (ebb->ndompset, IC_LEFT (ic)->key))) && - !ASSIGNMENT (ic) && - IS_ITEMP (IC_RESULT (ic)) && - !computeOnly) - { - 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; - } + (IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) || + isOperandVolatile (IC_LEFT (ic), TRUE) || + bitVectBitValue (ebb->ndompset, IC_LEFT (ic)->key))) && + !ASSIGNMENT (ic) && + IS_ITEMP (IC_RESULT (ic)) && + !computeOnly) + { + 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; + } /* 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); - } + 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); + } } if (!(POINTER_SET (ic)) && IC_RESULT (ic)) { - deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic)); - addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic)); + cseDef *csed; + deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic)); + csed = newCseDef (IC_RESULT (ic), ic); + updateCseDefAncestors (csed, cseSet); + addSetHead (&cseSet, csed); } defic = ic; @@ -1645,101 +2245,106 @@ cseBBlock (eBBlock * ebb, int computeOnly, mine and type is a pointer then delete pointerGets to take care of aliasing */ if (ASSIGNMENT (ic) && - OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))) && - IS_PTR (operandType (IC_RESULT (ic)))) - { - deleteGetPointers (&cseSet, &ptrSetSet, IC_RIGHT (ic), ebb); - for (i = 0; i < count; ebbs[i++]->visited = 0); - applyToSet (ebb->succList, delGetPointerSucc, IC_RIGHT (ic), ebb->dfnum); - ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RIGHT (ic)->key); - } + IS_SYMOP (IC_RESULT (ic)) && + OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))) && + IS_PTR (operandType (IC_RESULT (ic)))) + { + deleteGetPointers (&cseSet, &ptrSetSet, IC_RIGHT (ic), ebb); + for (i = 0; i < count; ebbs[i++]->visited = 0); + applyToSet (ebb->succList, delGetPointerSucc, IC_RIGHT (ic), ebb->dfnum); + ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RIGHT (ic)->key); + } /* if this is a pointerget then see if we can replace this with a previously assigned pointer value */ if (POINTER_GET (ic) && - !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) || - isOperandVolatile (IC_LEFT (ic), TRUE))) - { - pdop = NULL; - applyToSet (ptrSetSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic)); - /* if we find it then locally replace all - references to the result with what we assigned */ - if (pdop) - { - replaceAllSymBySym (ic->next, IC_RESULT (ic), pdop, &ebb->ndompset); - } - } + !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype) || + isOperandVolatile (IC_LEFT (ic), TRUE))) + { + pdop = NULL; + applyToSet (ptrSetSet, findPointerSet, IC_LEFT (ic), &pdop, IC_RESULT (ic)); + /* if we find it then locally replace all + references to the result with what we assigned */ + if (pdop) + { + replaceAllSymBySym (ic->next, IC_RESULT (ic), pdop, &ebb->ndompset); + } + } /* delete from the cseSet anything that has */ /* operands matching the result of this */ /* except in case of pointer access */ - if (!(POINTER_SET (ic)) && IC_RESULT (ic)) - { - deleteItemIf (&cseSet, ifOperandsHave, IC_RESULT (ic)); - /* delete any previous definitions */ - ebb->defSet = bitVectCplAnd (ebb->defSet, OP_DEFS (IC_RESULT (ic))); - - } + if (!(POINTER_SET (ic)) && IS_SYMOP (IC_RESULT (ic))) + { + deleteItemIf (&cseSet, ifOperandsHave, IC_RESULT (ic)); + /* delete any previous definitions */ + ebb->defSet = bitVectCplAnd (ebb->defSet, OP_DEFS (IC_RESULT (ic))); + } /* 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)); - setUsesDefs (IC_LEFT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); - - } + { + 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)); - setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); - - } + { + OP_USES(IC_RIGHT (ic))= + bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key); + setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs); + } /* for the result it is special case, put the result */ /* 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)); - 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); - /* delete from inexpressions of all successors which - have dfNum > than this block */ - for (i = 0; i < count; ebbs[i++]->visited = 0); - applyToSet (ebb->succList, delGetPointerSucc, IC_RESULT (ic), ebb->dfnum); - - /* delete from cseSet all other pointer sets - for this operand */ - deleteItemIf (&ptrSetSet, ifPointerSet, IC_RESULT (ic)); - /* add to the local pointerset set */ - addSetHead (&ptrSetSet, newCseDef (IC_RESULT (ic), ic)); - } + if (POINTER_SET (defic) && IS_SYMOP (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)); + ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, IC_RESULT (ic)->key); + /* delete from inexpressions of all successors which + have dfNum > than this block */ + for (i = 0; i < count; ebbs[i++]->visited = 0); + applyToSet (ebb->succList, delGetPointerSucc, IC_RESULT (ic), ebb->dfnum); + + /* delete from cseSet all other pointer sets + for this operand */ + deleteItemIf (&ptrSetSet, ifPointerSet, IC_RESULT (ic)); + /* add to the local pointerset set */ + addSetHead (&ptrSetSet, newCseDef (IC_RESULT (ic), ic)); + } 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)); - ebb->defSet = bitVectSetBit (ebb->defSet, ic->key); - ebb->outDefs = bitVectCplAnd (ebb->outDefs, OP_DEFS (IC_RESULT (ic))); - ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key); - } - + { + /* add the result to definition set */ + if (IS_SYMOP (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))); + ebb->ldefs = bitVectSetBit (ebb->ldefs, ic->key); + } + } /* if this is an addressof instruction then */ /* put the symbol in the address of list & */ /* delete it from the cseSet */ if (defic->op == ADDRESS_OF) - { - addSetHead (&ebb->addrOf, IC_LEFT (ic)); - deleteItemIf (&cseSet, ifDefSymIsX, IC_LEFT (ic)); - } + { + addSetHead (&ebb->addrOf, IC_LEFT (ic)); + deleteItemIf (&cseSet, ifDefSymIsX, IC_LEFT (ic)); + } } - 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); @@ -1749,16 +2354,18 @@ cseBBlock (eBBlock * ebb, int computeOnly, /*-----------------------------------------------------------------*/ /* cseAllBlocks - will sequentially go thru & do cse for all blocks */ /*-----------------------------------------------------------------*/ -int -cseAllBlocks (eBBlock ** ebbs, int count) +int +cseAllBlocks (ebbIndex * ebbi, int computeOnly) { + eBBlock ** ebbs = ebbi->dfOrder; + int count = ebbi->count; int i; int change = 0; /* if optimization turned off */ for (i = 0; i < count; i++) - change += cseBBlock (ebbs[i], FALSE, ebbs, count); + change += cseBBlock (ebbs[i], computeOnly, ebbi); return change; }