summaryrefslogtreecommitdiff
path: root/src/SDCCcse.c
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/SDCCcse.c
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/SDCCcse.c')
-rw-r--r--src/SDCCcse.c2736
1 files changed, 2736 insertions, 0 deletions
diff --git a/src/SDCCcse.c b/src/SDCCcse.c
new file mode 100644
index 0000000..dc6d8aa
--- /dev/null
+++ b/src/SDCCcse.c
@@ -0,0 +1,2736 @@
+/*-------------------------------------------------------------------------
+ SDCCcse.c - source file for Common Subexpressions and other utility
+
+ Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#include "common.h"
+#include "newalloc.h"
+#include "dbuf_string.h"
+
+/*-----------------------------------------------------------------*/
+/* newCseDef - new cseDef */
+/*-----------------------------------------------------------------*/
+cseDef *
+newCseDef (operand * sym, iCode * ic)
+{
+ cseDef *cdp;
+ memmap *map;
+
+ assert (sym);
+ cdp = Safe_alloc (sizeof (cseDef));
+
+ cdp->sym = sym;
+ cdp->diCode = ic;
+ cdp->key = sym->key;
+ cdp->ancestors = newBitVect(operandKey);
+ cdp->fromGlobal = 0;
+ cdp->fromAddrTaken = 0;
+
+ if (ic->op != IF && ic->op != JUMPTABLE)
+ {
+ if (ic->op != ADDRESS_OF && IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)))
+ {
+ bitVectSetBit (cdp->ancestors, IC_LEFT (ic)->key);
+ if (isOperandGlobal (IC_LEFT (ic)))
+ {
+ map = SPEC_OCLS (getSpec (operandType (IC_LEFT (ic))));
+ if (map)
+ cdp->fromGlobal |= (1 << map->ptrType);
+ }
+ cdp->fromAddrTaken |= OP_SYMBOL (IC_LEFT (ic))->addrtaken;
+ }
+ if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)))
+ {
+ bitVectSetBit (cdp->ancestors, IC_RIGHT (ic)->key);
+ if (isOperandGlobal (IC_RIGHT (ic)))
+ {
+ map = SPEC_OCLS (getSpec (operandType (IC_RIGHT (ic))));
+ if (map)
+ cdp->fromGlobal |= (1 << map->ptrType);
+ }
+ cdp->fromAddrTaken |= OP_SYMBOL (IC_RIGHT (ic))->addrtaken;
+ }
+ }
+
+ return cdp;
+}
+
+void
+freeLocalCseDef (void *item)
+{
+ cseDef * cse = (cseDef *)item;
+
+ /* If this CSE definition being deleted is not visible outside */
+ /* its defining eBBlock, we can safely deallocate it completely */
+ if (!cse->nonLocalCSE)
+ {
+ freeBitVect(cse->ancestors);
+ Safe_free(cse);
+ }
+}
+
+
+void
+updateCseDefAncestors(cseDef *cdp, set * cseSet)
+{
+ cseDef *loop;
+ set *sl;
+ iCode *ic = cdp->diCode;
+
+ if (ic->op!=IF && ic->op!=JUMPTABLE)
+ {
+ if (ic->op != ADDRESS_OF && 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 = bitVectInplaceUnion (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 = bitVectInplaceUnion (cdp->ancestors, loop->ancestors);
+ cdp->fromGlobal |= loop->fromGlobal;
+ cdp->fromAddrTaken |= loop->fromAddrTaken;
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* int isCseDefEqual - two definitions are equal */
+/*-----------------------------------------------------------------*/
+int
+isCseDefEqual (void *vsrc, void *vdest)
+{
+ cseDef *src = vsrc;
+ cseDef *dest = vdest;
+
+ if (src == dest)
+ return 1;
+
+ return (src->key == dest->key &&
+ src->diCode == dest->diCode);
+}
+
+/*-----------------------------------------------------------------*/
+/* pcseDef - in the cseDef */
+/*-----------------------------------------------------------------*/
+int
+pcseDef (void *item, va_list ap)
+{
+ cseDef *cdp = item;
+ iCodeTable *icTab;
+ struct dbuf_s dbuf;
+
+ (void) ap;
+
+ if (!cdp->sym)
+ fprintf (stdout, "**null op**");
+ printOperand (cdp->sym, stdout);
+ icTab = getTableEntry (cdp->diCode->op);
+ 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
+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 isaddr;
+
+ /* do the special cases first */
+ if (lic->op == IFX)
+ {
+ if (IS_SYMOP (to) &&
+ IC_COND (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_COND (lic) = operandFromOperand (to);
+ IC_COND (lic)->isaddr = isaddr;
+
+ }
+ continue;
+ }
+
+ if (lic->op == JUMPTABLE)
+ {
+ 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(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(to)=bitVectSetBit (OP_USES (to), lic->key);
+ isaddr = IC_LEFT (lic)->isaddr;
+ IC_LEFT (lic) = operandFromOperand (to);
+ IC_LEFT (lic)->isaddr = isaddr;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* iCodeKeyIs - if the icode keys match then return 1 */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (iCodeKeyIs)
+{
+ cseDef *cdp = item;
+ V_ARG (int, key);
+
+ if (cdp->diCode->key == key)
+ return 1;
+ else
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* removeFromInExprs - removes an icode from inexpressions */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (removeFromInExprs)
+{
+ eBBlock *ebp = item;
+ V_ARG (iCode *, ic);
+ V_ARG (operand *, from);
+ V_ARG (operand *, to);
+ V_ARG (eBBlock *, cbp);
+
+ if (ebp->visited)
+ return 0;
+
+ ebp->visited = 1;
+ deleteItemIf (&ebp->inExprs, iCodeKeyIs, ic->key);
+ if (ebp != cbp && !bitVectBitValue (cbp->domVect, ebp->bbnum))
+ replaceAllSymBySym (ebp->sch, from, to, &ebp->ndompset);
+
+ applyToSet (ebp->succList, removeFromInExprs, ic, from, to, cbp);
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* isGlobalInNearSpace - return TRUE if variable is a globalin data */
+/*-----------------------------------------------------------------*/
+static bool
+isGlobalInNearSpace (operand * op)
+{
+ sym_link *type = getSpec (operandType (op));
+ /* this is 8051 specific: optimization
+ suggested by Jean-Louis VERN, with 8051s we have no
+ advantage of putting variables in near space into
+ registers */
+ if (isOperandGlobal (op) && !IN_FARSPACE (SPEC_OCLS (type)) &&
+ IN_DIRSPACE (SPEC_OCLS (type)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* findCheaperOp - cseBBlock support routine, will check to see if */
+/* we have a operand previously defined */
+/*-----------------------------------------------------------------*/
+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)
+ return 1;
+
+ /* not found it yet check if this is the one */
+ /* and this is not the defining one */
+ if (cop->key && cop->key == cdp->key)
+ {
+ /* do a special check this will help in */
+ /* 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 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);
+ }
+ }
+
+ /* if this is an assign to a temp. then check
+ if the right side is this then return this */
+ if (IS_TRUE_SYMOP (cop) &&
+ cdp->diCode->op == '=' &&
+ !POINTER_SET (cdp->diCode) &&
+ cop->key == IC_RIGHT (cdp->diCode)->key &&
+ !isGlobalInNearSpace (IC_RIGHT (cdp->diCode)) &&
+ IS_ITEMP (IC_RESULT (cdp->diCode)))
+ {
+ *opp = IC_RESULT (cdp->diCode);
+ }
+
+ 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)) ||
+ isOperandVolatile (*opp, FALSE))
+ {
+ *opp = NULL;
+ return 0;
+ }
+
+ if (cop->key == (*opp)->key)
+ {
+ *opp = NULL;
+ return 0;
+ }
+
+ if ((*opp)->isaddr != cop->isaddr && IS_ITEMP (cop))
+ {
+ *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;
+ }
+ *opp=NULL;
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* findPointerSet - finds the right side of a pointer set op */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (findPointerSet)
+{
+ cseDef *cdp = item;
+ V_ARG (operand *, op);
+ V_ARG (operand **, opp);
+ V_ARG (operand *, rop);
+
+ if (POINTER_SET (cdp->diCode) &&
+ op->key &&
+ IC_RESULT (cdp->diCode)->key == op->key &&
+ !isOperandVolatile (IC_RESULT (cdp->diCode), TRUE) &&
+ !isOperandVolatile (IC_RIGHT (cdp->diCode), TRUE) &&
+ 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;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* findPrevIc - cseBBlock support function will return the iCode */
+/* which matches the current one */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (findPrevIc)
+{
+ cseDef *cdp = item;
+ V_ARG (iCode *, ic);
+ V_ARG (iCode **, icp);
+
+ /* if already found */
+ if (*icp)
+ return 1;
+
+ /* if the iCodes are the same */
+ if (isiCodeEqual (ic, cdp->diCode) &&
+ isOperandEqual (cdp->sym, IC_RESULT (cdp->diCode)))
+ {
+ *icp = cdp->diCode;
+ return 1;
+ }
+
+ /* if iCodes are not the same */
+ /* see the operands maybe interchanged */
+ if (ic->op == cdp->diCode->op &&
+ IS_COMMUTATIVE (ic) &&
+ isOperandEqual (IC_LEFT (ic), IC_RIGHT (cdp->diCode)) &&
+ isOperandEqual (IC_RIGHT (ic), IC_LEFT (cdp->diCode)))
+ {
+ *icp = cdp->diCode;
+ return 1;
+ }
+
+ 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;
+}
+
+/*-------------------------------------------------------------------*/
+/* ifFromGlobal - if definition is derived from global */
+/*-------------------------------------------------------------------*/
+DEFSETFUNC (ifFromGlobal)
+{
+ cseDef *cdp = item;
+
+ return cdp->fromGlobal;
+}
+
+/*-------------------------------------------------------------------*/
+/* ifFromGlobalAliasableByPtr - if definition is derived from global */
+/* that may be aliasble by a particular pointer type */
+/*-------------------------------------------------------------------*/
+DEFSETFUNC (ifFromGlobalAliasableByPtr)
+{
+ cseDef *cdp = item;
+ V_ARG (DECLARATOR_TYPE, decl);
+
+ if (decl == GPOINTER && cdp->fromGlobal)
+ return 1;
+ else if (cdp->fromGlobal & (1 << decl))
+ return 1;
+ else
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* ifDefGlobal - if definition is global */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifDefGlobal)
+{
+ cseDef *cdp = item;
+
+ return (isOperandGlobal (cdp->sym));
+}
+
+/*-----------------------------------------------------------------*/
+/* ifDefGlobalAliasableByPtr - if definition is global */
+/* and may be aliasble by a particular pointer type */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifDefGlobalAliasableByPtr)
+{
+ cseDef *cdp = item;
+ V_ARG (DECLARATOR_TYPE, decl);
+ memmap *map;
+
+ if (!isOperandGlobal (cdp->sym))
+ return 0;
+ if (decl == GPOINTER)
+ return 1;
+ map = SPEC_OCLS (getSpec (operandType (cdp->sym)));
+ return (map->ptrType == decl);
+}
+
+/*-------------------------------------------------------------------*/
+/* ifFromAddrTaken - if definition is derived from a symbol whose */
+/* address was taken */
+/*-------------------------------------------------------------------*/
+DEFSETFUNC (ifFromAddrTaken)
+{
+ cseDef *cdp = item;
+
+ if (OP_SYMBOL(cdp->sym)->addrtaken)
+ return 1;
+ return cdp->fromAddrTaken;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* ifAnyGetPointer - if get pointer icode */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifAnyGetPointer)
+{
+ cseDef *cdp = item;
+
+ if (cdp->diCode && POINTER_GET (cdp->diCode))
+ return 1;
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* ifAnyUnrestrictedGetPointer - if get pointer icode */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifAnyUnrestrictedGetPointer)
+{
+ cseDef *cdp = item;
+ V_ARG (DECLARATOR_TYPE, decl);
+
+ if (cdp->diCode && POINTER_GET (cdp->diCode))
+ {
+ sym_link *ptype;
+ ptype = operandType (IC_LEFT (cdp->diCode));
+ if (!IS_PTR_RESTRICT (ptype))
+ {
+ if (DCL_TYPE (ptype) == decl || IS_GENPTR (ptype))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* ifAnyUnrestrictedSetPointer - if set pointer icode */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifAnyUnrestrictedSetPointer)
+{
+ cseDef *cdp = item;
+ V_ARG (DECLARATOR_TYPE, decl);
+
+ if (cdp->diCode && POINTER_SET (cdp->diCode))
+ {
+ sym_link *ptype;
+ ptype = operandType (IC_RESULT (cdp->diCode));
+ if (!IS_PTR_RESTRICT (ptype))
+ {
+ if (DCL_TYPE (ptype) == decl || IS_GENPTR (ptype))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* ifOperandsHave - if any of the operand are the same as this */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifOperandsHave)
+{
+ cseDef *cdp = item;
+ V_ARG (operand *, op);
+
+ if (bitVectBitValue(cdp->ancestors, op->key))
+ return 1;
+
+ if (IC_LEFT (cdp->diCode) &&
+ IS_SYMOP (IC_LEFT (cdp->diCode)) &&
+ IC_LEFT (cdp->diCode)->key == op->key)
+ return 1;
+
+ if (IC_RIGHT (cdp->diCode) &&
+ IS_SYMOP (IC_RIGHT (cdp->diCode)) &&
+ IC_RIGHT (cdp->diCode)->key == op->key)
+ return 1;
+
+ if (POINTER_SET (cdp->diCode) &&
+ IS_SYMOP (IC_RESULT (cdp->diCode)) &&
+ IC_RESULT (cdp->diCode)->key == op->key)
+ return 1;
+
+ /* or if any of the operands are volatile */
+ if (IC_LEFT (cdp->diCode) &&
+ IS_OP_VOLATILE (IC_LEFT (cdp->diCode)))
+ return 1;
+
+ if (IC_RIGHT (cdp->diCode) &&
+ IS_OP_VOLATILE (IC_RIGHT (cdp->diCode)))
+ return 1;
+
+
+ if (IC_RESULT (cdp->diCode) &&
+ IS_OP_VOLATILE (IC_RESULT (cdp->diCode)))
+ return 1;
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* ifDefSymIs - if a definition is found in the set */
+/*-----------------------------------------------------------------*/
+int
+ifDefSymIs (set * cseSet, operand * sym)
+{
+ cseDef *loop;
+ set *sl;
+
+ if (!sym || !IS_SYMOP (sym))
+ return 0;
+ for (sl = cseSet; sl; sl = sl->next)
+ {
+ loop = sl->item;
+ if (loop->sym->key == sym->key)
+ return 1;
+ }
+ return 0;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* ifDefSymIsX - will return 1 if the symbols match */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifDefSymIsX)
+{
+ cseDef *cdp = item;
+ V_ARG (operand *, op);
+ int match;
+
+ if (op && cdp->sym && op->key)
+ match = cdp->sym->key == op->key;
+ else
+ match = (isOperandEqual (cdp->sym, op));
+ #if 0
+ if (match)
+ printf("%s ",OP_SYMBOL(cdp->sym)->name);
+ #endif
+ return match;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* ifDiCodeIs - returns true if diCode is same */
+/*-----------------------------------------------------------------*/
+int
+ifDiCodeIs (set * cseSet, iCode * ic)
+{
+ cseDef *loop;
+ set *sl;
+
+ if (!ic)
+ return 0;
+
+ for (sl = cseSet; sl; sl = sl->next)
+ {
+ loop = sl->item;
+ if (loop->diCode == ic)
+ return 1;
+ }
+ return 0;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* ifPointerGet - returns true if the icode is pointer get sym */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifPointerGet)
+{
+ cseDef *cdp = item;
+ V_ARG (operand *, op);
+ iCode *dic = cdp->diCode;
+ operand *left = IC_LEFT (cdp->diCode);
+
+ if (POINTER_GET (dic) && op->key && left->key == op->key)
+ return 1;
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* ifPointerSet - returns true if the icode is pointer set sym */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifPointerSet)
+{
+ cseDef *cdp = item;
+ V_ARG (operand *, op);
+
+ if (POINTER_SET (cdp->diCode) && op->key &&
+ IC_RESULT (cdp->diCode)->key == op->key)
+ return 1;
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* ifDiCodeIsX - will return 1 if the symbols match */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (ifDiCodeIsX)
+{
+ cseDef *cdp = item;
+ V_ARG (iCode *, ic);
+
+ return cdp->diCode == ic;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* findBackwardDef - scan backwards to find definition 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 */
+/*-----------------------------------------------------------------*/
+static void
+algebraicOpts (iCode * ic, eBBlock * ebp)
+{
+ /* we don't deal with the following iCodes
+ here */
+ if (ic->op == IFX ||
+ ic->op == IPUSH ||
+ ic->op == IPOP ||
+ ic->op == CALL ||
+ ic->op == PCALL ||
+ ic->op == RETURN ||
+ POINTER_GET (ic))
+ return;
+
+ /* if both operands present & ! IFX */
+ /* then if they are both literal we */
+ /* perform the operation right now */
+ if (IC_RESULT (ic) &&
+ IC_RIGHT (ic) &&
+ IC_LEFT (ic) &&
+ IS_OP_LITERAL (IC_LEFT (ic)) &&
+ IS_OP_LITERAL (IC_RIGHT (ic)))
+ {
+ IC_RIGHT (ic) = operandOperation (IC_LEFT (ic),
+ IC_RIGHT (ic),
+ ic->op,
+ operandType (IC_RESULT (ic)));
+ ic->op = '=';
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ /* if not ifx & only one operand present */
+ if (IC_RESULT (ic) &&
+ IC_LEFT (ic) &&
+ IS_OP_LITERAL (IC_LEFT (ic)) &&
+ !IC_RIGHT (ic))
+ {
+ IC_RIGHT (ic) = operandOperation (IC_LEFT (ic),
+ IC_RIGHT (ic),
+ ic->op,
+ operandType (IC_RESULT (ic)));
+ ic->op = '=';
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+
+ /* a special case : or in short a kludgy solution will think
+ about a better solution over a glass of wine someday */
+ if (ic->op == GET_VALUE_AT_ADDRESS)
+ {
+ 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)));
+ if (IS_DECL (operandType (IC_RESULT (ic))))
+ {
+ DCL_PTR_VOLATILE (operandType (IC_RESULT (ic))) = 0;
+ DCL_PTR_ADDRSPACE (operandType (IC_RESULT (ic))) = 0;
+ }
+ return;
+ }
+
+ if (IS_ITEMP (IC_LEFT (ic)) &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ !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;
+ }
+ }
+
+ /* depending on the operation */
+ switch (ic->op)
+ {
+ case '+':
+ /* if adding the same thing change to left shift by 1 */
+ if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key &&
+ !IS_OP_VOLATILE (IC_LEFT (ic)) &&
+ !(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 assignment or cast */
+ if (IS_OP_LITERAL (IC_LEFT (ic)) &&
+ isEqualVal (OP_VALUE (IC_LEFT (ic)), 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)) &&
+ isEqualVal (OP_VALUE (IC_RIGHT (ic)), 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 same thing then zero */
+ if (IC_LEFT (ic)->key == IC_RIGHT (ic)->key &&
+ !IS_OP_VOLATILE (IC_LEFT (ic)))
+ {printf("Sub. at %d\n", 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;
+ }
+
+ /* 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)) &&
+ isEqualVal (OP_VALUE (IC_RIGHT (ic)), 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)) &&
+ isEqualVal (OP_VALUE (IC_LEFT (ic)), 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 */
+ /* if either of them is one then result is */
+ /* the other one */
+ case '*':
+ if (IS_OP_LITERAL (IC_LEFT (ic)))
+ {
+ if (isEqualVal (OP_VALUE (IC_LEFT (ic)), 0))
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ if (isEqualVal (OP_VALUE (IC_LEFT (ic)), 1))
+ {
+ /* '*' 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 (isEqualVal (OP_VALUE (IC_LEFT (ic)), -1))
+ {
+ /* 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 (isEqualVal (OP_VALUE (IC_RIGHT (ic)), 0))
+ {
+ ic->op = '=';
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+
+ if (isEqualVal (OP_VALUE (IC_RIGHT (ic)), 1))
+ {
+ /* '*' 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 (isEqualVal (OP_VALUE (IC_RIGHT (ic)), -1))
+ {
+ /* '*' 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;
+ return;
+ }
+ /* if this is a division then check if left is zero */
+ /* then change it to an assignment */
+ if (IS_OP_LITERAL (IC_LEFT (ic)) && isEqualVal (OP_VALUE (IC_LEFT (ic)), 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)))
+ {
+ if (isEqualVal (OP_VALUE (IC_RIGHT (ic)), 1))
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ if (isEqualVal (OP_VALUE (IC_RIGHT (ic)), -1))
+ {
+ /* '/' 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)) &&
+ !IS_OP_VOLATILE (IC_LEFT (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)) &&
+ !IS_OP_VOLATILE (IC_LEFT (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)))
+ {
+ double litval = operandLitValue (IC_RIGHT (ic));
+ if (IS_GENPTR(ctype) && IS_PTR(otype))
+ {
+ unsigned long gpVal = 0;
+ const char *name = IS_SYMOP (IC_RESULT (ic)) ? OP_SYMBOL (IC_RESULT (ic))->name : NULL;
+ if (IS_FUNCPTR(otype))
+ gpVal = pointerTypeToGPByte (DCL_TYPE (otype->next), NULL, name);
+ if (!IS_GENPTR(otype))
+ gpVal = pointerTypeToGPByte (DCL_TYPE (otype), NULL, name);
+ gpVal <<= ((GPTRSIZE - 1) * 8);
+ gpVal |= (unsigned long)litval;
+ litval = gpVal;
+ }
+ ic->op = '=';
+ IC_RIGHT (ic) = operandFromValue (valCastLiteral (operandType (IC_LEFT (ic)), litval, litval));
+ 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) =
+ (isEqualVal (OP_VALUE (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)))
+ {
+ unsigned val;
+
+ /* if BITWISEAND then check if one of them is a zero */
+ /* if yes turn it into 0 assignment */
+ if (isEqualVal (OP_VALUE (IC_RIGHT (ic)), 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 */
+ if (IS_BOOLEAN (operandType (IC_RIGHT (ic)))) /* Special handling since _Bool is stored in 8 bits */
+ goto boolcase;
+ switch (bitsForType (operandType (IC_RIGHT (ic))))
+ {
+ case 1:
+ boolcase:
+ val = 0x01;
+ break;
+ case 8:
+ val = 0xff;
+ break;
+ case 16:
+ val = 0xffff;
+ break;
+ case 32:
+ 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)))
+ {
+ unsigned val;
+
+ /* if BITWISEOR then check if one of them is a zero */
+ /* if yes turn it into assignment */
+ if (isEqualVal (OP_VALUE (IC_RIGHT (ic)), 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 */
+ switch (bitsForType (operandType (IC_RIGHT (ic))))
+ {
+ case 1:
+ val = 0x01;
+ break;
+ case 8:
+ val = 0xff;
+ break;
+ case 16:
+ val = 0xffff;
+ break;
+ case 32:
+ 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 (isEqualVal (OP_VALUE (IC_RIGHT (ic)), 0))
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ }
+ /* if XOR then check if one of them is a zero or one */
+ /* if yes turn it into assignment or invert */
+ if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
+ IS_BOOLEAN (operandType (IC_LEFT (ic))) &&
+ IS_BOOLEAN (operandType (IC_RESULT (ic)))
+ )
+ {
+ if (isEqualVal (OP_VALUE (IC_RIGHT (ic)), 1))
+ {
+ ic->op = '!';
+ IC_RIGHT (ic) = NULL;
+ return;
+ }
+ else
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = operandFromLit (1);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ }
+ break;
+ }
+
+ return;
+}
+
+#define OTHERS_PARM(s) (s->_isparm && !s->ismyparm)
+/*-----------------------------------------------------------------*/
+/* updateSpillLocation - keeps track of register spill location */
+/*-----------------------------------------------------------------*/
+void
+updateSpillLocation (iCode * ic, int induction)
+{
+ sym_link *setype;
+
+ if (POINTER_SET (ic))
+ return;
+
+ if (ic->nosupdate)
+ return;
+
+#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)));
+
+ 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;
+ }
+ }
+#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;
+ }
+#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));
+ 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
+setUsesDefs (operand * op, bitVect * bdefs,
+ bitVect * idefs, bitVect ** oud)
+{
+ /* compute the definitions alive at this point */
+ bitVect *adefs = bitVectUnion (bdefs, idefs);
+
+ /* of these definitions find the ones that are */
+ /* for this operand */
+ adefs = bitVectInplaceIntersect (adefs, OP_DEFS (op));
+
+ /* these are the definitions that this operand can use */
+ /* Nothing uses op->usesDefs, so why? EEP - 2018-06-10 */
+ //op->usesDefs = adefs;
+
+ /* the out defs is an union */
+ *oud = bitVectInplaceUnion (*oud, adefs);
+
+ /* If not assigning op->usesDefs, we can safely free adefs */
+ freeBitVect(adefs);
+}
+
+/*-----------------------------------------------------------------*/
+/* unsetDefsAndUses - clear this operation for the operands */
+/*-----------------------------------------------------------------*/
+void
+unsetDefsAndUses (iCode * ic)
+{
+ if (ic->op == JUMPTABLE)
+ {
+ if (IS_SYMOP (IC_JTCOND (ic)))
+ bitVectUnSetBit (OP_USES (IC_JTCOND (ic)), ic->key);
+ return;
+ }
+
+ /* take away this definition from the def chain of the */
+ /* result & take away from use set of the operands */
+ if (ic->op != IFX)
+ {
+ /* 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);
+ }
+ /* turn off the useSet for the operands */
+ if (IS_SYMOP (IC_LEFT (ic)))
+ bitVectUnSetBit (OP_USES (IC_LEFT (ic)), ic->key);
+
+ if (IS_SYMOP (IC_RIGHT (ic)))
+ bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
+ }
+ else
+ /* must be ifx turn off the use */
+ if (IS_SYMOP (IC_COND (ic)))
+ bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
+}
+
+/*-----------------------------------------------------------------*/
+/* ifxOptimize - changes ifx conditions if it can */
+/*-----------------------------------------------------------------*/
+void
+ifxOptimize (iCode * ic, set * cseSet,
+ int computeOnly,
+ eBBlock * ebb, int *change,
+ ebbIndex * ebbi)
+{
+ operand *pdop;
+ symbol *label;
+
+ /* if the condition can be replaced */
+ if (!computeOnly)
+ {
+ pdop = NULL;
+ applyToSetFTrue (cseSet, findCheaperOp, IC_COND (ic), &pdop, 0);
+ if (pdop)
+ {
+ ReplaceOpWithCheaperOp(&IC_COND (ic), pdop);
+ (*change)++;
+ }
+ else if(ic->prev && /* Remove unnecessary casts */
+ (ic->prev->op == '=' || ic->prev->op == CAST || ic->prev->op == '!') && IS_ITEMP (IC_RESULT (ic->prev)) &&
+ IC_RESULT (ic->prev)->key == IC_COND (ic)->key && bitVectnBitsOn (OP_USES (IC_RESULT (ic->prev))) <= 1)
+ {
+ sym_link *type = operandType (IC_RESULT (ic->prev));
+ if (ic->prev->op != CAST || IS_BOOL (type) || bitsForType (operandType (IC_RIGHT (ic->prev))) < bitsForType (type))
+ {
+ if (!isOperandVolatile (ic->prev->op == '!' ? IC_LEFT (ic->prev) : IC_RIGHT (ic->prev), FALSE))
+ {
+ if (ic->prev->op =='!') /* Invert jump logic */
+ {
+ symbol *tmp = IC_TRUE (ic);
+ IC_TRUE (ic) = IC_FALSE (ic);
+ IC_FALSE (ic) = tmp;
+ }
+ bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
+ ReplaceOpWithCheaperOp(&IC_COND (ic), ic->prev->op == '!' ? IC_LEFT (ic->prev) : IC_RIGHT (ic->prev));
+ (*change)++;
+ }
+/* There's an optimization opportunity here, but OP_USES doesn't seem to be */
+/* initialized properly at this point. - EEP 2016-08-04 */
+#if 0
+ else if (bitVectnBitsOn (OP_USES(IC_COND (ic))) == 1)
+ {
+ /* We can replace the iTemp with the original volatile symbol */
+ /* but we must make sure the volatile symbol is still accessed */
+ /* only once. */
+ bitVectUnSetBit (OP_USES (IC_COND (ic)), ic->key);
+ ReplaceOpWithCheaperOp(&IC_COND (ic), IC_RIGHT (ic->prev));
+ (*change)++;
+ /* Make previous assignment an assignment to self. */
+ /* killDeadCode() will eliminiate it. */
+ IC_RIGHT (ic->prev) = IC_RESULT (ic->prev);
+ IC_LEFT (ic->prev) = NULL;
+ ic->prev->op = '=';
+ }
+#endif
+ }
+ }
+ }
+
+ /* 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)++;
+ }
+ 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);
+ }
+ }
+
+ /* 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 (ebbi);
+ werrorfl (ic->filename, ic->lineno, W_CONTROL_FLOW);
+ return;
+ }
+
+ /* if there is only one successor and that successor
+ is the same one we are conditionally going to then
+ 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 (ebbi, label)))
+ {
+ 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 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* diCodeForSym - finds the definiting instruction for a symbol */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (diCodeForSym)
+{
+ cseDef *cdp = item;
+ V_ARG (operand *, sym);
+ V_ARG (iCode **, dic);
+
+ /* if already found */
+ if (*dic)
+ return 0;
+
+ /* if not if this is the defining iCode */
+ if (sym->key == cdp->key)
+ {
+ *dic = cdp->diCode;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* constFold - does some constant folding */
+/*-----------------------------------------------------------------*/
+int
+constFold (iCode * ic, set * cseSet)
+{
+ iCode *dic = NULL;
+ iCode *ldic = NULL;
+ /* this routine will change
+ a = b + 10;
+ c = a + 10;
+ to
+ c = b + 20; */
+
+ /* deal with only + & - */
+ if (ic->op != '+' &&
+ ic->op != '-' &&
+ ic->op != BITWISEAND)
+ return 0;
+
+ /* check if operation with a literal */
+ if (!IS_OP_LITERAL (IC_RIGHT (ic)))
+ return 0;
+
+ /* check if we can find a definition for the
+ left hand side */
+ if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (ic), &dic)))
+ return 0;
+
+ if (ic->op == BITWISEAND) /* Optimize out bitwise and of comparion results */
+ {
+ /* check that this results in 0 or 1 only */
+ if(dic->op != EQ_OP && dic->op != NE_OP && dic->op != LE_OP && dic->op != GE_OP && dic->op != '<' && dic->op != '>' && dic->op != '!')
+ return 0;
+
+ IC_RIGHT (ic) = (operandLitValueUll (IC_RIGHT (ic)) & 1) ? IC_LEFT (ic) : operandFromLit (0);
+
+ ic->op = '=';
+ IC_LEFT (ic) = 0;
+
+ return 1;
+ }
+
+ /* check that this is also a +/- */
+ if (dic->op != '+' && dic->op != '-')
+ return 0;
+
+ /* with a literal */
+ if (!IS_OP_LITERAL (IC_RIGHT (dic)))
+ return 0;
+
+ /* find the definition of the left operand
+ of dic.then check if this defined with a
+ get_pointer return 0 if the pointer size is
+ less than 2 (MCS51 specific) */
+ if (!(applyToSet (cseSet, diCodeForSym, IC_LEFT (dic), &ldic)))
+ return 0;
+
+ if (POINTER_GET (ldic) && getSize (operandType (IC_LEFT (ldic))) <= 1)
+ return 0;
+
+ /* it is if the operations are the same */
+ /* the literal parts need to be added */
+ IC_LEFT (ic) = operandFromOperand (IC_LEFT (dic));
+ if (ic->op == dic->op)
+ IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) +
+ operandLitValue (IC_RIGHT (dic)));
+ else
+ IC_RIGHT (ic) = operandFromLit (operandLitValue (IC_RIGHT (ic)) -
+ operandLitValue (IC_RIGHT (dic)));
+
+ if (IS_ITEMP (IC_RESULT (ic)))
+ {
+ SPIL_LOC (IC_RESULT (ic)) = NULL;
+ OP_SYMBOL(IC_RESULT (ic))->noSpilLoc = 1;
+ }
+
+ return 1;
+}
+
+/* Remove casts to bool from results of logical operations. */
+static int
+boolCast (iCode * ic, set * cseSet)
+{
+ iCode *dic = NULL;
+
+ /* Only casts to booleans are optimized away. */
+ if (ic->op != CAST || !IS_BOOL ( operandType (IC_RESULT (ic))))
+ return 0;
+
+ /* Find the definition for the right hand side. */
+ if (!(applyToSet (cseSet, diCodeForSym, IC_RIGHT (ic), &dic)))
+ return 0;
+
+ /* Check that this is a logic op. */
+ switch (dic->op)
+ {
+ case '!':
+ case '<':
+ case '>':
+ case LE_OP:
+ case GE_OP:
+ case EQ_OP:
+ case NE_OP:
+ case AND_OP:
+ case OR_OP:
+ case GETHBIT:
+ case GETABIT:
+ break;
+ case BITWISEAND:
+ if (IS_BOOL (operandType (IC_LEFT (dic))) || IS_BOOL (operandType (IC_RIGHT (dic))))
+ break;
+ if (IS_OP_LITERAL (IC_RIGHT (dic)) && operandLitValue (IC_RIGHT (dic)) == 1)
+ break;
+ default:
+ return 0;
+ }
+
+ /* Replace cast by assignment. */
+ ic->op = '=';
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* deleteGetPointers - called when a pointer is passed as parm */
+/* will delete from cseSet all get pointers computed from this */
+/* pointer. A simple ifOperandsHave is not good enough here */
+/*-----------------------------------------------------------------*/
+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;
+
+ 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 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
+ {
+ 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 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);
+ }
+ deleteSet (&compItems);
+}
+
+/*-----------------------------------------------------------------*/
+/* delGetPointerSucc - delete get pointer from inExprs of succ with */
+/* dfnum > supplied */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC (delGetPointerSucc)
+{
+ eBBlock *ebp = item;
+ V_ARG (operand *, op);
+ V_ARG (int, dfnum);
+
+ if (ebp->visited)
+ return 0;
+
+ ebp->visited = 1;
+ if (ebp->dfnum > dfnum)
+ {
+ deleteItemIf (&ebp->inExprs, ifPointerGet, op);
+ }
+
+ return applyToSet (ebp->succList, delGetPointerSucc, op, dfnum);
+}
+
+/*-----------------------------------------------------------------*/
+/* fixUpTypes - KLUGE HACK fixup a lowering problem */
+/*-----------------------------------------------------------------*/
+static void
+fixUpTypes (iCode * ic)
+{
+ sym_link *t1 = operandType (IC_LEFT (ic)), *t2;
+
+ /* if (TARGET_IS_DS390) */
+ if (options.model == MODEL_FLAT24)
+ {
+ /* hack-o-matic! */
+ return;
+ }
+
+ /* for pointer_gets if the types of result & left r the
+ same then change it type of result to next */
+ if (IS_PTR (t1) &&
+ compareType (t2 = operandType (IC_RESULT (ic)), t1) == 1)
+ {
+ setOperandType (IC_RESULT (ic), t2->next);
+ }
+}
+
+/*-----------------------------------------------------------------*/
+/* 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 GETABIT:
+ case GETBYTE:
+ case GETWORD:
+ case RIGHT_OP:
+ case CAST:
+ case ARRAYINIT:
+ return 1;
+ default:
+ 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
+cseBBlock (eBBlock * ebb, int computeOnly, ebbIndex * ebbi)
+{
+ eBBlock ** ebbs = ebbi->bbOrder;
+ int count = ebbi->count;
+ set *cseSet;
+ set *setnode;
+ iCode *ic;
+ int change = 0;
+ int i;
+ set *ptrSetSet = NULL;
+ cseDef *expr;
+ int replaced;
+ int recomputeDataFlow = 0;
+
+ /* if this block is not reachable */
+ if (ebb->noPath)
+ {
+ for (ic = ebb->sch; ic; ic = ic->next)
+ if (!SKIP_IC2 (ic))
+ unsetDefsAndUses (ic);
+ return 0;
+ }
+
+ /* Mark incoming subexpressions as non-local */
+ for (setnode = ebb->inExprs; setnode; setnode = setnode->next)
+ {
+ expr = (cseDef *)setnode->item;
+ expr->nonLocalCSE = 1;
+ }
+ /* set of common subexpressions */
+ cseSet = setFromSet (ebb->inExprs);
+
+
+ /* these will be computed by this routine */
+ freeBitVect(ebb->outDefs); ebb->outDefs = NULL;
+ freeBitVect(ebb->defSet); ebb->defSet = NULL;
+ freeBitVect(ebb->usesDefs); ebb->usesDefs = NULL;
+ freeBitVect(ebb->ptrsSet); ebb->ptrsSet = NULL;
+ deleteSet(&ebb->addrOf);
+ freeBitVect(ebb->ldefs); ebb->ldefs = NULL;
+ ebb->outDefs = bitVectCopy (ebb->inDefs);
+ bitVectDefault = iCodeKey;
+ ebb->defSet = newBitVect (iCodeKey);
+ ebb->usesDefs = newBitVect (iCodeKey);
+
+ /* 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;
+
+ /* if this is an assignment from true symbol
+ to a temp then do pointer post inc/dec optimization */
+ if (ic->op == '=' && !POINTER_SET (ic) &&
+ IS_PTR (operandType (IC_RESULT (ic))))
+ {
+ ptrPostIncDecOpt (ic, ebb);
+ }
+
+ /* 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 (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 */
+ destructItemIf (&cseSet, freeLocalCseDef, ifDefGlobal);
+
+ /* and also iTemps derived from globals */
+ destructItemIf (&cseSet, freeLocalCseDef, ifFromGlobal);
+
+ /* Delete iTemps derived from symbols whose address */
+ /* has been taken */
+ destructItemIf (&cseSet, freeLocalCseDef, 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 */
+ destructItemIf (&cseSet, freeLocalCseDef, 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)
+ 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 are 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)
+ {
+ 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;
+
+ if (!computeOnly)
+ {
+ /* do some algebraic optimizations if possible */
+ algebraicOpts (ic, ebb);
+ while (constFold (ic, cseSet));
+ while (boolCast (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, ebbi);
+ continue;
+ }
+
+ /* if the assignment & result is a temp */
+ /* see if we can replace it */
+ 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);
+ replaced = 0;
+
+ /* do the operand lookup i.e. for both the */
+ /* right & left operand : check the cseSet */
+ /* to see if they have been replaced if yes */
+ /* then replace them with those from cseSet */
+ /* left operand */
+ /* and left is a symbol */
+ if (!computeOnly &&
+ ic->op != ADDRESS_OF &&
+ IS_SYMOP (IC_LEFT (ic)) &&
+ !IS_BITFIELD (OP_SYM_ETYPE (IC_LEFT (ic))))
+ {
+ 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 = replaced = 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);
+ replaced = 1;
+ }
+ }
+ else
+ {
+ ReplaceOpWithCheaperOp (&IC_LEFT (ic), pdop);
+ change = replaced = 1;
+ }
+ }
+ }
+
+ /* right operand */
+ if (!computeOnly && IS_SYMOP (IC_RIGHT (ic)))
+ {
+ pdop = NULL;
+ applyToSetFTrue (cseSet, findCheaperOp, IC_RIGHT (ic), &pdop, checkSign);
+ if (pdop)
+ {
+ ReplaceOpWithCheaperOp (&IC_RIGHT (ic), pdop);
+ change = replaced = 1;
+ }
+ }
+
+ if (!computeOnly &&
+ POINTER_SET (ic) &&
+ IS_SYMOP (IC_RESULT (ic)) &&
+ !IS_BITFIELD (OP_SYM_ETYPE (IC_RESULT (ic))))
+ {
+ pdop = NULL;
+ applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop, checkSign);
+ if (pdop)
+ {
+ ReplaceOpWithCheaperOp (&IC_RESULT (ic), pdop);
+ change = 1;
+ }
+ }
+
+ /* if left or right changed then do algebraic */
+ if (!computeOnly && change)
+ {
+ algebraicOpts (ic, ebb);
+ while (constFold (ic, cseSet));
+ while (boolCast (ic, cseSet));
+ }
+
+ /* if after all this it becomes an assignment to self
+ then delete it and continue */
+ if (ASSIGNMENT_TO_SELF (ic) && !isOperandVolatile (IC_RIGHT(ic), FALSE))
+ {
+ bitVectUnSetBit (OP_DEFS (IC_RESULT (ic)), ic->key);
+ if (IS_SYMOP (IC_RIGHT (ic)))
+ bitVectUnSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
+ remiCodeFromeBBlock (ebb, ic);
+ continue;
+ }
+
+ /* now we will check to see if the entire */
+ /* operation has been performed before */
+ /* and is available */
+ /* don't do assignments they will be killed */
+ /* by dead code elimination if required do */
+ /* 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) || IS_VOLATILE (operandType (IC_LEFT (ic))->next) ||
+ 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_SET (ic)) && IC_RESULT (ic))
+ {
+ cseDef *csed;
+ destructItemIf (&cseSet, freeLocalCseDef, ifDefSymIsX, IC_RESULT (ic));
+ csed = newCseDef (IC_RESULT (ic), ic);
+ updateCseDefAncestors (csed, cseSet);
+ addSetHead (&cseSet, csed);
+ }
+ defic = ic;
+
+ /* if assignment to a parameter which is not
+ mine and type is a pointer then delete
+ pointerGets to take care of aliasing */
+ if (ASSIGNMENT (ic) &&
+ 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);
+ }
+ }
+
+ /* delete from the cseSet anything that has */
+ /* operands matching the result of this */
+ /* except in case of pointer access */
+ if (!(POINTER_SET (ic)) && IS_SYMOP (IC_RESULT (ic)))
+ {
+ destructItemIf (&cseSet, freeLocalCseDef, ifOperandsHave, IC_RESULT (ic));
+ deleteItemIf (&ptrSetSet, ifOperandsHave, IC_RESULT (ic));
+ /* delete any previous definitions */
+ ebb->defSet = bitVectCplAnd (ebb->defSet, OP_DEFS (IC_RESULT (ic)));
+
+ /* Until pointer tracking is complete, by conservative and delete all */
+ /* pointer accesses that might alias this symbol. */
+ if (isOperandGlobal (IC_RESULT (ic)) || OP_SYMBOL (IC_RESULT (ic))->addrtaken)
+ {
+ memmap *map = SPEC_OCLS (getSpec (operandType (IC_RESULT (ic))));
+ destructItemIf (&cseSet, freeLocalCseDef, ifAnyUnrestrictedGetPointer, map->ptrType);
+ deleteItemIf (&ptrSetSet, ifAnyUnrestrictedSetPointer, map->ptrType);
+ }
+ }
+
+ /* add the left & right to the defUse set */
+ if (IC_LEFT (ic) && 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 (IC_RIGHT (ic) && IS_SYMOP (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);
+ }
+
+ /* for the result it is special case, put the result */
+ /* in the defuseSet if it is a pointer or array access */
+ if (POINTER_SET (defic) &&
+ (IS_SYMOP (IC_RESULT (ic)) || IS_OP_LITERAL (IC_RESULT (ic))))
+ {
+ sym_link *ptype = operandType (IC_RESULT (ic));
+
+ if (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));
+
+ /* A write via a non-restrict pointer may modify a global */
+ /* variable used by this function, so delete them */
+ /* and any derived symbols from cseSet. */
+ if (!IS_PTR_RESTRICT (ptype))
+ {
+ destructItemIf (&cseSet, freeLocalCseDef, ifDefGlobalAliasableByPtr, DCL_TYPE(ptype));
+ destructItemIf (&cseSet, freeLocalCseDef, ifFromGlobalAliasableByPtr, DCL_TYPE(ptype));
+ }
+
+ /* This could be made more specific for better optimization, but */
+ /* for safety, delete anything this write may have modified. */
+ destructItemIf (&cseSet, freeLocalCseDef, ifFromAddrTaken);
+ destructItemIf (&cseSet, freeLocalCseDef, ifAnyGetPointer);
+ }
+ else
+ {
+ /* 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));
+ destructItemIf (&cseSet, freeLocalCseDef, ifDefSymIsX, IC_LEFT (ic));
+ }
+
+ /* If this was previously in the out expressions in the */
+ /* original form, it might need to be killed by another block */
+ /* in the new form if we have replaced operands, so recompute */
+ /* the data flow after we finish this block */
+ if (replaced && ifDiCodeIs (ebb->outExprs, ic))
+ recomputeDataFlow = 1;
+ }
+
+ for (expr=setFirstItem (ebb->inExprs); expr; expr=setNextItem (ebb->inExprs))
+ if (!isinSetWith (cseSet, expr, isCseDefEqual) &&
+ !isinSetWith (ebb->killedExprs, expr, isCseDefEqual))
+ {
+ addSetHead (&ebb->killedExprs, expr);
+ }
+
+ deleteSet (&ptrSetSet);
+ deleteSet (&ebb->outExprs);
+ ebb->outExprs = cseSet;
+ ebb->outDefs = bitVectInplaceUnion (ebb->outDefs, ebb->defSet);
+ ebb->ptrsSet = bitVectInplaceUnion (ebb->ptrsSet, ebb->inPtrsSet);
+
+ for (setnode = ebb->outExprs; setnode; setnode = setnode->next)
+ {
+ expr = (cseDef *)setnode->item;
+ expr->nonLocalCSE = 1;
+ }
+
+ if (recomputeDataFlow)
+ computeDataFlow (ebbi);
+
+ return change;
+}
+
+/*------------------------------------------------------------------*/
+/* cseAllBlocks - will sequentially go thru & do cse for all blocks */
+/*------------------------------------------------------------------*/
+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], computeOnly, ebbi);
+
+ return change;
+}
+
+
+/*------------------------------------------------------------------*/
+/* freeCSEdata - free data created by cseBBlock */
+/*------------------------------------------------------------------*/
+void
+freeCSEdata (eBBlock * ebb)
+{
+ set * s;
+
+ /* We should really free the cseDefs too, but I haven't */
+ /* found a good way to do this yet. For the moment, at */
+ /* least free up the associated bitVects - EEP */
+ for (s = ebb->outExprs; s; s = s->next)
+ {
+ cseDef *cdp = s->item;
+ if (!cdp) continue;
+ if (cdp->ancestors)
+ {
+ freeBitVect (cdp->ancestors);
+ cdp->ancestors = NULL;
+ }
+ }
+
+ deleteSet (&ebb->inExprs);
+ deleteSet (&ebb->outExprs);
+ deleteSet (&ebb->killedExprs);
+
+ freeBitVect (ebb->inDefs);
+ freeBitVect (ebb->outDefs);
+ freeBitVect (ebb->defSet);
+ freeBitVect (ebb->ldefs);
+ freeBitVect (ebb->usesDefs);
+ freeBitVect (ebb->ptrsSet);
+ freeBitVect (ebb->inPtrsSet);
+ freeBitVect (ebb->ndompset);
+ deleteSet (&ebb->addrOf);
+
+}