* device/include/pic16/pic18f*.h: add bit aliases in INTCONbits_t
[fw/sdcc] / src / SDCCcse.c
index ba572b6aded494d0b7568d79d19f96a5ca54612c..1b43a42850a335c01fc35c78d708e5cddef2da30 100644 (file)
    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!  
+   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 *
+newCseDef (operand * sym, iCode * ic)
 {
-    cseDef *cdp ;
-    
-    assert (sym);
-    ALLOC(cdp,sizeof(cseDef));    
-
-    cdp->sym = sym;
-    cdp->diCode = ic;
-    cdp->key = sym->key;       
-         
-    return cdp;
+  cseDef *cdp;
+
+  assert (sym);
+  cdp = Safe_alloc (sizeof (cseDef));
+
+  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 isCseDefEqual ( void *vsrc, void *vdest)
+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 ) ;
-     
+  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)
+int
+pcseDef (void *item, va_list ap)
 {
-    cseDef *cdp = item;
-    iCodeTable *icTab ;
-
-    (void)ap;
-    
-    if (!cdp->sym)
-       fprintf(stdout,"**null op**");
-    printOperand(cdp->sym,stdout);
-    icTab = getTableEntry(cdp->diCode->op) ;
-    icTab->iCodePrint(stdout,cdp->diCode,icTab->printName);
-    return 1;
+  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)
+void
+replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset)
 {
-    iCode *lic;
-
-    for (lic = ic ; lic ; lic = lic->next ) {
-       int siaddr ;
-
-       /* 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);
-                       siaddr = IC_COND(lic)->isaddr ;
-                       IC_COND(lic) = operandFromOperand(to);
-                       IC_COND(lic)->isaddr = siaddr ;
-                       
-               }
-               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);
-                       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(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);
-           }       
-           siaddr = IC_RESULT(lic)->isaddr ;       
-           IC_RESULT(lic) = operandFromOperand(to);
-           IC_RESULT(lic)->isaddr = siaddr ;
-       }
-
-       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);
-           siaddr = IC_RIGHT(lic)->isaddr ;
-           IC_RIGHT(lic) = operandFromOperand(to);
-           IC_RIGHT(lic)->isaddr = siaddr ;
-       }
-
-       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);
-           siaddr = IC_LEFT(lic)->isaddr ;
-           IC_LEFT(lic) = operandFromOperand(to);
-           IC_LEFT(lic)->isaddr = siaddr ;
-       }       
+  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)
+DEFSETFUNC (iCodeKeyIs)
 {
-    cseDef *cdp = item;
-    V_ARG(int,key);
+  cseDef *cdp = item;
+  V_ARG (int, key);
 
-    if (cdp->diCode->key == key)
-       return 1;
-    else
-       return 0;
+  if (cdp->diCode->key == key)
+    return 1;
+  else
+    return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* removeFromInExprs - removes an icode from inexpressions         */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(removeFromInExprs)
+DEFSETFUNC (removeFromInExprs)
 {
-    eBBlock *ebp = item;
-    V_ARG(iCode *,ic);
-    V_ARG(operand *,from);
-    V_ARG(operand *,to);
-    V_ARG(eBBlock *,cbp);
+  eBBlock *ebp = item;
+  V_ARG (iCode *, ic);
+  V_ARG (operand *, from);
+  V_ARG (operand *, to);
+  V_ARG (eBBlock *, cbp);
 
-    if (ebp->visited)
-       return 0;
+  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);
+  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;
+  applyToSet (ebp->succList, removeFromInExprs, ic, from, to, cbp);
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* isGlobalInNearSpace - return TRUE if valriable is a globalin data */
 /*-----------------------------------------------------------------*/
-static bool isGlobalInNearSpace (operand *op)
+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;
+  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) 
+DEFSETFUNC (findCheaperOp)
 {
-    cseDef *cdp = item ;   
-    V_ARG(operand *,cop);
-    V_ARG(operand **,opp);
-
-    /* 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 == 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 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 &&
-                       ( (!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) ;
+  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 == 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) {
-
-       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;
-       }
-       
-       return 1;
-       
+  /* 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;
+
     }
-       
-    return 0;
+  *opp=NULL;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* findPointerSet - finds the right side of a pointer set op       */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(findPointerSet)
+DEFSETFUNC (findPointerSet)
 {
-    cseDef *cdp = item;
-    V_ARG(operand *,op);
-    V_ARG(operand **,opp);
-    V_ARG(operand *,rop);
-
-    if (POINTER_SET(cdp->diCode)               &&
-       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))) {
-       *opp = IC_RIGHT(cdp->diCode);
-       return 1;
+  cseDef *cdp = item;
+  V_ARG (operand *, op);
+  V_ARG (operand **, opp);
+  V_ARG (operand *, rop);
+
+  if (POINTER_SET (cdp->diCode) &&
+      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;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* findPrevIc - cseBBlock support function will return the iCode   */
 /*              which matches the current one                      */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(findPrevIc)
+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;
+  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          &&
-       ( ic->op == '+' || ic->op == '*' ) &&
-       isOperandEqual(IC_LEFT(ic),IC_RIGHT(cdp->diCode)) &&
-       isOperandEqual(IC_RIGHT(ic),IC_LEFT(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_ASSOCIATIVE(ic) &&
+      isOperandEqual (IC_LEFT (ic), IC_RIGHT (cdp->diCode)) &&
+      isOperandEqual (IC_RIGHT (ic), IC_LEFT (cdp->diCode)))
+    {
+      *icp = cdp->diCode;
+      return 1;
     }
 
-    return 0;
+  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;
 }
 
 /*-----------------------------------------------------------------*/
 /* ifDefGlobal - if definition is global                           */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(ifDefGlobal)
+DEFSETFUNC (ifDefGlobal)
+{
+  cseDef *cdp = item;
+
+  return (isOperandGlobal (cdp->sym));
+}
+
+/*-------------------------------------------------------------------*/
+/* ifFromAddrTaken - if definition is derived from a symbol whose    */
+/*                   address was taken                               */
+/*-------------------------------------------------------------------*/
+DEFSETFUNC (ifFromAddrTaken)
 {
-    cseDef *cdp = item;
-    
-    return (isOperandGlobal(cdp->sym));
+  cseDef *cdp = item;
+
+  return cdp->fromAddrTaken;
 }
 
+
 /*-----------------------------------------------------------------*/
 /* ifAnyGetPointer - if get pointer icode                          */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(ifAnyGetPointer)
+DEFSETFUNC (ifAnyGetPointer)
 {
-    cseDef *cdp = item;
-    
-    if (cdp->diCode && POINTER_GET(cdp->diCode)) return 1;
-    return 0;
+  cseDef *cdp = item;
+
+  if (cdp->diCode && POINTER_GET (cdp->diCode))
+    return 1;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* ifOperandsHave - if any of the operand are the same as this     */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(ifOperandsHave)
+DEFSETFUNC (ifOperandsHave)
 {
-    cseDef *cdp = item;    
-    V_ARG(operand *,op);    
-
-    
-    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;
-    
-    /* 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;    
+  cseDef *cdp = item;
+  V_ARG (operand *, op);
 
-    return 0;
+  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;
+
+  /* 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)
+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;   
-    }
+  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);    
-
-    if (op && cdp->sym)
-       return cdp->sym->key == op->key ;
-    else
-       return ( isOperandEqual(cdp->sym,op) );
-            
-} 
+DEFSETFUNC (ifDefSymIsX)
+{
+  cseDef *cdp = item;
+  V_ARG (operand *, op);
+  int match;
+
+  if (op && cdp->sym)
+    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 truw if diCode is same                     */
+/* ifDiCodeIs - returns true if diCode is same                     */
 /*-----------------------------------------------------------------*/
- int ifDiCodeIs (set *cseSet, iCode *ic)
+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;
-    }
+  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)
+DEFSETFUNC (ifPointerGet)
 {
-    cseDef *cdp = item;
-    V_ARG(operand *,op);
-    iCode *dic = cdp->diCode;
-    operand *left = IC_LEFT(cdp->diCode);
+  cseDef *cdp = item;
+  V_ARG (operand *, op);
+  iCode *dic = cdp->diCode;
+  operand *left = IC_LEFT (cdp->diCode);
 
-    if (POINTER_GET(dic) && left->key == op->key)
-       return 1;
+  if (POINTER_GET (dic) && left->key == op->key)
+    return 1;
 
-    return 0;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* ifPointerSet - returns true if the icode is pointer set sym     */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(ifPointerSet)
+DEFSETFUNC (ifPointerSet)
 {
-    cseDef *cdp = item;
-    V_ARG(operand *,op);
+  cseDef *cdp = item;
+  V_ARG (operand *, op);
 
-    if (POINTER_SET(cdp->diCode) &&
-       IC_RESULT(cdp->diCode)->key == op->key)
-       return 1;
+  if (POINTER_SET (cdp->diCode) &&
+      IC_RESULT (cdp->diCode)->key == op->key)
+    return 1;
 
-    return 0;
+  return 0;
 }
 
 /*-----------------------------------------------------------------*/
 /* ifDiCodeIsX - will return 1 if the symbols match                 */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(ifDiCodeIsX)
-{     
-    cseDef *cdp  = item;
-    V_ARG(iCode *,ic);    
+DEFSETFUNC (ifDiCodeIsX)
+{
+  cseDef *cdp = item;
+  V_ARG (iCode *, ic);
+
+  return cdp->diCode == ic;
 
-    return cdp->diCode == ic;
-            
+}
+
+/*-----------------------------------------------------------------*/
+/* findBackwardDef - scan backwards to find deinition of operand   */
+/*-----------------------------------------------------------------*/
+iCode *findBackwardDef(operand *op,iCode *ic)
+{
+    iCode *lic;
+
+    for (lic = ic; lic ; lic = lic->prev) {
+        if (IC_RESULT(lic) && isOperandEqual(op,IC_RESULT(lic)))
+            return lic;
+    }
+    return NULL;
 }
 
 /*-----------------------------------------------------------------*/
 /* algebraicOpts - does some algebraic optimizations               */
 /*-----------------------------------------------------------------*/
-void algebraicOpts (iCode *ic)
+static void
+algebraicOpts (iCode * ic, eBBlock * ebp)
 {
-    /* we don't deal with the following iCodes
-       here */
-    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 ;
-       
+  /* 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 ;
+  /* 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)));
-           return;
-       }
-
-       if (IS_ITEMP(IC_LEFT(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;
-       }
+
+  /* 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)));
+          return;
+        }
+
+      if (IS_ITEMP (IC_LEFT (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;
+        }
 
     }
-   
 
-    /* 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_FLOAT(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 (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 ;
-       }
-       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 ;
-       }
-       break ;
-    case '-' :
-       /* if subtracting the 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 ;
-       }           
-           
-       /* 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 ;
-       }
-       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 ;
-       }
-       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 (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 ;
-           }       
-       }
-       
-       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 ;
-           }
-       }
-       break ;
+
+  /* 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_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)) &&
+          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)
+        {
+          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)
+        {
+          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;
+        }
+      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;
+        }
+      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)))
+        {
+         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)))
+        {
+          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;
-       }
-       /* 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 ;
-       }
-       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);
-       }
-       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);
-       }
-       break ;
-    case CAST :
-       /* if this is a cast of a literal value */
-       if ( IS_OP_LITERAL(IC_RIGHT(ic))) {
-           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 ( checkType(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);            
-       }
+      /* 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 */
+      /* 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)))
+        {
+          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);
+        }
+      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);
+        }
+      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;
+    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);
+        }
+      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 ;
+
+  return;
 }
 #define OTHERS_PARM(s) (s->_isparm && !s->ismyparm)
 /*-----------------------------------------------------------------*/
 /* updateSpillLocation - keeps track of register spill location    */
 /*-----------------------------------------------------------------*/
-void updateSpillLocation ( iCode *ic)
+void
+updateSpillLocation (iCode * ic, int induction)
 {
-
-    sym_link *setype;
-
-    if (POINTER_SET(ic)) 
-       return;
-    
-    if (ic->nosupdate)
-       return;       
-
-    /* for the form true_symbol := iTempNN */
-    if (ASSIGN_ITEMP_TO_SYM(ic)
-       && !SPIL_LOC(IC_RIGHT(ic))) {
-
-       setype = getSpec(operandType(IC_RESULT(ic)));
-       
-        if (!IC_RIGHT(ic)->noSpilLoc           &&
-           !IS_VOLATILE(setype)               &&
-           !IN_FARSPACE(SPEC_OCLS(setype))    &&
-           !OTHERS_PARM(OP_SYMBOL(IC_RESULT(ic))) )
-           
-           SPIL_LOC(IC_RIGHT(ic))  =
-               IC_RESULT(ic)->operand.symOperand;   
-    }
-
-    if (ASSIGN_ITEMP_TO_ITEMP(ic) &&
-       !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 (!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));
-    }
+        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)
+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 = bitVectIntersect(adefs,OP_DEFS(op));
-    
-    /* these are the definitions that this operand can use */
-    op->usesDefs = adefs;
-    
-    /* the out defs is an union */
-    *oud = bitVectUnion(*oud,adefs);
+  /* compute the definitions alive at this point */
+  bitVect *adefs = bitVectUnion (bdefs, idefs);
+
+  /* of these definitions find the ones that are */
+  /* for this operand */
+  adefs = bitVectIntersect (adefs, OP_DEFS (op));
+
+  /* these are the definitions that this operand can use */
+  op->usesDefs = adefs;
+
+  /* the out defs is an union */
+  *oud = bitVectUnion (*oud, adefs);
 }
 
 /*-----------------------------------------------------------------*/
 /* unsetDefsAndUses - clear this operation for the operands        */
 /*-----------------------------------------------------------------*/
-void unsetDefsAndUses ( iCode *ic ) 
+void
+unsetDefsAndUses (iCode * ic)
 {
-    if ( ic->op == JUMPTABLE)
-       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);
+  if (ic->op == JUMPTABLE)
+    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);    
+  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,
-                        eBBlock **ebbs, int count)
+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);
-       if (pdop) {
-           IC_COND(ic) = pdop ;
-           (*change)++;
-       }
+  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)++;
+        }
     }
-    
-    /* 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 (ebbs,count,1);
-       werror (W_CONTROL_FLOW,ic->filename,ic->lineno);
-       return ;
+
+  /* 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);
+      if (!options.lessPedantic)
+        {
+          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(ebbs,label,count))) {
-
-       remiCodeFromeBBlock(ebb,ic);
-       computeControlFlow (ebbs,count,1);
-       werror (W_CONTROL_FLOW,ic->filename,ic->lineno);
-       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)))
+    {
+      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(IC_COND(ic)) = bitVectSetBit(OP_USES(IC_COND(ic)),ic->key);
-    setUsesDefs(IC_COND(ic),ebb->defSet,ebb->outDefs,&ebb->usesDefs);
-    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)
+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;
-    }
+  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)
+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 != '-' )
-       return 0;
-
-    /* this check is a hueristic to prevent live ranges
-       from becoming too long */
-    if (IS_PTR(operandType(IC_RESULT(ic))))
-       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
-       right hand side */
-    if (!(applyToSet(cseSet,diCodeForSym,IC_LEFT(ic),&dic)))
-       return 0;
-
-    /* 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;
-       IC_RESULT(ic)->noSpilLoc = 1;
+  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 != '-')
+    return 0;
+
+  /* this check is a heuristic to prevent live ranges
+     from becoming too long */
+  if (IS_PTR (operandType (IC_RESULT (ic))))
+      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;
+
+  /* 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;
+
+
+  return 1;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1052,93 +1717,176 @@ int 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 deleteGetPointers (set **cseSet, set **pss, operand *op,eBBlock *ebb)
+static void
+deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb)
 {
-    set *compItems = NULL;
-    cseDef *cdp ;
-    operand *cop;
-    
-    /* easy return */
-    if (!*cseSet && !*pss)
-       return ;
-    
-    /* first 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)) {
-       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,IC_LEFT(cdp->diCode),isOperandEqual) ||
-               isinSetWith(compItems,IC_RIGHT(cdp->diCode),isOperandEqual)) {
-                   addSet(&compItems,IC_RESULT(cdp->diCode));
-           }
-       }
+  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++;
+                    }
+                }
+            }
+        }
     }
-    
-    /* 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(pss,ifPointerSet,cop);
+  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);
     }
 }
 
 /*-----------------------------------------------------------------*/
-/* delGetPointerSucc - delete get pointer from inExprs of succ with*/
+/* delGetPointerSucc - delete get pointer from inExprs of succ with */
 /*                     dfnum > supplied                            */
 /*-----------------------------------------------------------------*/
-DEFSETFUNC(delGetPointerSucc)
+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);
+  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);
-}    
+  return applyToSet (ebp->succList, delGetPointerSucc, op, dfnum);
+}
 
 /*-----------------------------------------------------------------*/
 /* fixUpTypes - KLUGE HACK fixup a lowering problem                */
 /*-----------------------------------------------------------------*/
-static void fixUpTypes(iCode *ic)
+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)
 {
-       sym_link *t1 = operandType(IC_LEFT(ic)) ,*t2;
-       
-       if (IS_DS390_PORT)
-       {
-           /* 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) &&
-           checkType(t2=operandType(IC_RESULT(ic)),t1) == 1) {
-               setOperandType(IC_RESULT(ic),t2->next);
-       }
+    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   */
@@ -1146,407 +1894,478 @@ static void fixUpTypes(iCode *ic)
 /*             system. also the most important, since almost all   */
 /*             data flow related information is computed by it     */
 /*-----------------------------------------------------------------*/
-int cseBBlock ( eBBlock *ebb, int computeOnly, 
-               eBBlock **ebbs, int count)
+int
+cseBBlock (eBBlock * ebb, int computeOnly,
+           ebbIndex * ebbi)
 {
-    set *cseSet ;
-    iCode *ic ;           
-    int change = 0 ;
-    int i;   
-    set *ptrSetSet = NULL;
-
-    /* if this block is not reachable */
-    if (ebb->noPath)
-       return change;
-
-   /* 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);
-
-    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;
-       
-       if (SKIP_IC2(ic))
-           continue ;
-
-       /* if this is an assignment from true symbol
-          to a temp then do pointer post inc/dec optimzation */
-       if (ic->op == '=' && !POINTER_SET(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(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);
-           /* 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);
-       }
-
-       /* 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);
-               if (pdop)
-                   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(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 */
-       /* check if the condition can be replaced */
-       if (ic->op == IFX ) {
-           ifxOptimize (ic, cseSet, computeOnly, 
-                        ebb, &change, 
-                        ebbs, count);
-           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);
-
-           if (POINTER_SET(ic) &&
-               !(IS_BITFIELD(OP_SYMBOL(IC_RESULT(ic))->etype))) {
-               pdop = NULL ;
-               applyToSetFTrue (cseSet,findCheaperOp,IC_RESULT(ic),&pdop);
-               if (pdop && IS_ITEMP(pdop) && !computeOnly)                 
-                   IC_RESULT(ic) = pdop;                               
-           }
-       }           
-       
-       /* 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 (IS_SYMOP(IC_LEFT(ic)) && 
-           !computeOnly && ic->op != ADDRESS_OF ) {  
-           
-           pdop = NULL;                
-           applyToSetFTrue (cseSet,findCheaperOp,IC_LEFT(ic),&pdop) ;
-           if (pdop)  { 
-               if (POINTER_GET(ic)) {
-                   if (IS_ITEMP(pdop) || IS_OP_LITERAL(pdop)) {
-                       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 */
-       if (IS_SYMOP(IC_RIGHT(ic)) && !computeOnly) {
-           
-           pdop = NULL ;
-           applyToSetFTrue (cseSet,findCheaperOp,IC_RIGHT(ic),&pdop);
-           if (pdop) {
-               
-               IC_RIGHT(ic) = pdop;
-               change = 1;
-           }
-       }
-       
-       /* if left or right changed then do algebraic */
-       if (change) {
-           algebraicOpts(ic);
-           while(constFold(ic,cseSet));
-       }
-
-       /* if after all this it becomes a assignment to self 
-          then delete it and continue */
-       if (ASSIGNMENT_TO_SELF(ic)) {      
-           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)           ||
-              bitVectBitValue(ebb->ndompset,IC_LEFT(ic)->key))) &&
-           ! ASSIGNMENT(ic)                        && 
-             IS_ITEMP(IC_RESULT(ic))               &&
-           ! computeOnly) {
-           applyToSet (cseSet,findPrevIc,ic,&pdic);
-           if (pdic && checkType(operandType(IC_RESULT(pdic)),
-                                 operandType(IC_RESULT(ic))) != 1)
-                   pdic = NULL;
-       } 
-       
-       /* if found then eliminate this and add to*/
-       /* to cseSet an element containing result */
-       /* of this with previous opcode           */      
-       if (pdic) {
-
-           if (IS_ITEMP(IC_RESULT(ic))) {
-
-               /* replace in the remaining of this block */
-               replaceAllSymBySym(ic->next,IC_RESULT(ic),IC_RESULT(pdic),&ebb->ndompset);
-               /* remove this iCode from inexpressions of all
-                  its successors, it cannot be in the in expressions
-                  of any of the predecessors */        
-               for (i = 0 ; i < count ;ebbs[i++]->visited = 0);
-               applyToSet(ebb->succList,removeFromInExprs,ic,IC_RESULT(ic),
-                          IC_RESULT(pdic),ebb);
-
-               /* if this was moved from another block */
-               /* then replace in those blocks too     */
-               if ( ic->movedFrom ) {
-                   eBBlock *owner ;
-                   for (owner = setFirstItem(ic->movedFrom); owner ;
-                        owner = setNextItem(ic->movedFrom))
-                       replaceAllSymBySym(owner->sch,IC_RESULT(ic),IC_RESULT(pdic),&owner->ndompset);
-               }
-               pdic->movedFrom = unionSets(pdic->movedFrom,ic->movedFrom,THROW_NONE);
-           } 
-           else
-               addSetHead (&cseSet,newCseDef(IC_RESULT(ic),pdic));                     
-           
-           if (!computeOnly) 
-               /* eliminate this */
-               remiCodeFromeBBlock (ebb,ic);               
-                   
-           defic = pdic ;          
-           change++ ;
-
-           if (IS_ITEMP(IC_RESULT(ic)))
-               continue ;
-
-       } else {
-
-           /* just add this as a previous expression except in */
-           /* case of a pointer access in which case this is a */
-           /* usage not a definition                           */
-           if (! (POINTER_SET(ic)) && IC_RESULT(ic)){
-               deleteItemIf (&cseSet, ifDefSymIsX,IC_RESULT(ic));
-               addSetHead(&cseSet,newCseDef(IC_RESULT(ic),ic));
-           }
-           defic = ic;
-
-       }
-       
-       /* if assignment to a parameter which is not
-          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);
-       }
-
-       /* 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)) && 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(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 a pointer or array access  */
-       if ( POINTER_SET(defic) ) {
-           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(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));
-       }
+  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 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);
+
+  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);
+        }
+
+      /* 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 */
+          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)
+                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)
+        {
+          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));
+        }
+
+      /* 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);
+
+      /* 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 (IS_SYMOP (IC_LEFT (ic)) &&
+          !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) {
+            ReplaceOpWithCheaperOp(&IC_RIGHT(ic), pdop);
+            change = 1;
+          }
+        }
+
+      /* if left or right changed then do algebraic */
+      if (!computeOnly && change)
+        {
+          algebraicOpts (ic, ebb);
+          while (constFold (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))
+        {
+          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) ||
+             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;
+          deleteItemIf (&cseSet, 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)))
+        {
+          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(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 a pointer or array access  */
+      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 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));
+        }
     }
 
-    setToNull ((void **)&ebb->outExprs);
-    ebb->outExprs = cseSet;        
-    ebb->outDefs = bitVectUnion (ebb->outDefs,ebb->defSet);
-    ebb->ptrsSet = bitVectUnion (ebb->ptrsSet,ebb->inPtrsSet);
-    return change ;
+  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);
+  return change;
 }
 
 /*-----------------------------------------------------------------*/
-/* cseAllBlocks - will sequentially go thru & do cse for all blocks*/
+/* cseAllBlocks - will sequentially go thru & do cse for all blocks */
 /*-----------------------------------------------------------------*/
-int cseAllBlocks (eBBlock **ebbs,int count)
+int
+cseAllBlocks (ebbIndex * ebbi, int computeOnly)
 {
-    int i;
-    int change = 0 ;
+  eBBlock ** ebbs = ebbi->dfOrder;
+  int count = ebbi->count;
+  int i;
+  int change = 0;
 
-    /* if optimization turned off */
+  /* if optimization turned off */
 
-    for (i = 0 ; i < count ;i++ ) 
-       change += cseBBlock (ebbs[i],FALSE,ebbs,count);
+  for (i = 0; i < count; i++)
+    change += cseBBlock (ebbs[i], computeOnly, ebbi);
 
-    return change;
+  return change;
 }