* src/SDCCcse.c (cseBBlock): fixed bug #527779
[fw/sdcc] / src / SDCCcse.c
index 32badbcc36cbc60151fc12144d3c66f81a96d669..71d0963324dd4360bfe97cb852aa6f25c3566e7d 100644 (file)
@@ -25,6 +25,7 @@
 #include "common.h"
 #include "newalloc.h"
 
+
 /*-----------------------------------------------------------------*/
 /* newCseDef - new cseDef                                          */
 /*-----------------------------------------------------------------*/
@@ -83,8 +84,8 @@ pcseDef (void *item, va_list ap)
 
 void ReplaceOpWithCheaperOp(operand **op, operand *cop) {
 #ifdef RANGEHUNT
-  printf ("ReplaceOpWithCheaperOp %s with %s: ", 
-         IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM", 
+  printf ("ReplaceOpWithCheaperOp %s with %s: ",
+         IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM",
          IS_SYMOP(cop) ? OP_SYMBOL(cop)->name : "!SYM");
   // if op is a register equivalent
   if (IS_ITEMP(cop) && OP_SYMBOL((*op))->isreqv) {
@@ -107,7 +108,7 @@ void ReplaceOpWithCheaperOp(operand **op, operand *cop) {
 /* replaceAllSymBySym - replaces all operands by operand in an     */
 /*                      instruction chain                          */
 /*-----------------------------------------------------------------*/
-void 
+void
 replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset)
 {
   iCode *lic;
@@ -325,8 +326,8 @@ DEFSETFUNC (findCheaperOp)
       IS_ITEMP (IC_RESULT (cdp->diCode)))
     *opp = IC_RESULT (cdp->diCode);
 
-  if ((*opp) && 
-      (isOperandLiteral(*opp) || !checkSign || 
+  if ((*opp) &&
+      (isOperandLiteral(*opp) || !checkSign ||
        (checkSign &&
        IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) &&
        (SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) &&
@@ -353,11 +354,11 @@ DEFSETFUNC (findCheaperOp)
          *opp = operandFromOperand (*opp);
          (*opp)->isaddr = cop->isaddr;
        }
-         
+
       if (IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) &&
          SPEC_NOUN(operandType(cop)) != SPEC_NOUN(operandType(*opp)))
        {
-           // special case: we can make an unsigned char literal 
+           // 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
@@ -372,9 +373,9 @@ DEFSETFUNC (findCheaperOp)
                *opp = NULL;
                return 0;
            }
-           
+
         }
-         
+
       return 1;
 
     }
@@ -517,7 +518,7 @@ DEFSETFUNC (ifOperandsHave)
 /*-----------------------------------------------------------------*/
 /* ifDefSymIs - if a definition is found in the set                */
 /*-----------------------------------------------------------------*/
-int 
+int
 ifDefSymIs (set * cseSet, operand * sym)
 {
   cseDef *loop;
@@ -554,7 +555,7 @@ DEFSETFUNC (ifDefSymIsX)
 /*-----------------------------------------------------------------*/
 /* ifDiCodeIs - returns truw if diCode is same                     */
 /*-----------------------------------------------------------------*/
-int 
+int
 ifDiCodeIs (set * cseSet, iCode * ic)
 {
   cseDef *loop;
@@ -825,6 +826,7 @@ algebraicOpts (iCode * ic, eBBlock * ebp)
                {
                  ic->op = CAST;
                  IC_LEFT (ic)->type = TYPE;
+                 IC_LEFT (ic)->isLiteral = 0;
                  setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic)));
                }
              return;
@@ -863,6 +865,7 @@ algebraicOpts (iCode * ic, eBBlock * ebp)
                  IC_RIGHT (ic) = IC_LEFT (ic);
                  IC_LEFT (ic) = op;
                  IC_LEFT (ic)->type = TYPE;
+                 IC_LEFT (ic)->isLiteral = 0;
                  setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic)));
                }
              return;
@@ -1163,6 +1166,7 @@ updateSpillLocation (iCode * ic, int induction)
        if (ic->nosupdate)
                return;
 
+#if 0
        /* for the form true_symbol := iTempNN */
        if (ASSIGN_ITEMP_TO_SYM (ic) && 
            !SPIL_LOC (IC_RIGHT (ic))) {
@@ -1181,6 +1185,7 @@ updateSpillLocation (iCode * ic, int induction)
                }
            
        }
+#endif
 
 #if 0 /* this needs furthur investigation can save a lot of code */
        if (ASSIGN_SYM_TO_ITEMP(ic) &&
@@ -1343,18 +1348,36 @@ ifxOptimize (iCode * ic, set * cseSet,
       isinSet (ebb->succList, eBBWithEntryLabel (ebbs, label, count)))
     {
 
-      remiCodeFromeBBlock (ebb, ic);
-      computeControlFlow (ebbs, count, 1);
       if (!options.lessPedantic) {
        werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
       }
-      return;
+      if (IS_OP_VOLATILE (IC_COND (ic)))
+       {
+         IC_RIGHT (ic) = IC_COND (ic);
+         IC_LEFT (ic) = NULL;
+         IC_RESULT (ic) = NULL;
+         ic->op = DUMMY_READ_VOLATILE;
+       }
+      else
+        {
+         remiCodeFromeBBlock (ebb, ic);
+         computeControlFlow (ebbs, count, 1);
+         return;
+       }      
     }
 
 
   /* if it remains an IFX the update the use Set */
-  OP_USES(IC_COND (ic))=bitVectSetBit (OP_USES (IC_COND (ic)), ic->key);
-  setUsesDefs (IC_COND (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
+  if (ic->op == IFX)
+    {
+      OP_USES(IC_COND (ic))=bitVectSetBit (OP_USES (IC_COND (ic)), ic->key);
+      setUsesDefs (IC_COND (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
+    }
+  else if (ic->op == DUMMY_READ_VOLATILE)
+    {
+      OP_USES(IC_RIGHT (ic))=bitVectSetBit (OP_USES (IC_RIGHT (ic)), ic->key);
+      setUsesDefs (IC_RIGHT (ic), ebb->defSet, ebb->outDefs, &ebb->usesDefs);
+    }
   return;
 }
 
@@ -1463,45 +1486,46 @@ deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb)
   set *compItems = NULL;
   cseDef *cdp;
   operand *cop;
+  int changes;
 
   /* easy return */
   if (!*cseSet && !*pss)
     return;
 
-  /* first find all items computed from this operand .
+  addSet (&compItems, op);
+  
+  /* Recursively find all items computed from this operand .
      This done fairly simply go thru the list and find
-     those that are computed by arthimetic with this
-     op */
-  for (cdp = setFirstItem (*cseSet); cdp; cdp = setNextItem (*cseSet))
+     those that are computed by arthimetic with these
+     ops */
+  /* Also check for those computed from our computed
+     list . This will take care of situations like
+     iTemp1 = iTemp0 + 8;
+     iTemp2 = iTemp1 + 8; */
+  do
     {
-      if (IS_ARITHMETIC_OP (cdp->diCode))
+      changes = 0;
+      for (cdp = setFirstItem (*cseSet); cdp; cdp = setNextItem (*cseSet))
        {
-         if (isOperandEqual (IC_LEFT (cdp->diCode), op) ||
-             isOperandEqual (IC_RIGHT (cdp->diCode), op))
-           {
-             /* save it in our list of items */
-             addSet (&compItems, IC_RESULT (cdp->diCode));
-           }
-         /* also check for those computed from our computed
-            list . This will take care of situations like
-            iTemp1 = iTemp0 + 8;
-            iTemp2 = iTemp1 + 8; */
-         if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode),
-                          (insetwithFunc)isOperandEqual) ||
-             isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode),
-                          (insetwithFunc)isOperandEqual))
+         if (IS_ARITHMETIC_OP (cdp->diCode) || POINTER_GET(cdp->diCode))
            {
-             addSet (&compItems, IC_RESULT (cdp->diCode));
+             if (isinSetWith (compItems, (void*)IC_LEFT (cdp->diCode),
+                              (insetwithFunc)isOperandEqual) ||
+                 isinSetWith (compItems, (void*)IC_RIGHT (cdp->diCode),
+                              (insetwithFunc)isOperandEqual))
+               {
+                 if (!isinSetWith (compItems, (void*)IC_RESULT (cdp->diCode),
+                                   (insetwithFunc)isOperandEqual))
+                   {
+                 addSet (&compItems, IC_RESULT (cdp->diCode));
+                 changes++;
+                   }
+               }
            }
        }
     }
-
-  /* now delete all pointer gets with this op */
-  deleteItemIf (cseSet, ifPointerGet, op);
-  deleteItemIf (pss, ifPointerSet, op);
-
-  /* set the bit vector used by dataFlow computation later */
-  ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, op->key);
+  while (changes);
+  
   /* now for the computed items */
   for (cop = setFirstItem (compItems); cop; cop = setNextItem (compItems))
     {
@@ -1607,6 +1631,22 @@ static int isSignedOp (iCode *ic)
     }
  }
 
+#if 0
+static void
+dumpCseSet(set *cseSet)
+{
+  while (cseSet)
+    {
+      cseDef *item=cseSet->item;
+      printf("->");
+      printOperand (item->sym, NULL);
+      printf("  ");
+      piCode (item->diCode, NULL);
+      cseSet = cseSet->next;
+    }
+}
+#endif
+
 /*-----------------------------------------------------------------*/
 /* cseBBlock - common subexpression elimination for basic blocks   */
 /*             this is the hackiest kludgiest routine in the whole */
@@ -1631,12 +1671,12 @@ cseBBlock (eBBlock * ebb, int computeOnly,
   cseSet = setFromSet (ebb->inExprs);
 
   /* these will be computed by this routine */
-  setToNull ((void **) &ebb->outDefs);
-  setToNull ((void **) &ebb->defSet);
-  setToNull ((void **) &ebb->usesDefs);
-  setToNull ((void **) &ebb->ptrsSet);
-  setToNull ((void **) &ebb->addrOf);
-  setToNull ((void **) &ebb->ldefs);
+  setToNull ((void *) &ebb->outDefs);
+  setToNull ((void *) &ebb->defSet);
+  setToNull ((void *) &ebb->usesDefs);
+  setToNull ((void *) &ebb->ptrsSet);
+  setToNull ((void *) &ebb->addrOf);
+  setToNull ((void *) &ebb->ldefs);
 
   ebb->outDefs = bitVectCopy (ebb->inDefs);
   bitVectDefault = iCodeKey;
@@ -1689,6 +1729,9 @@ cseBBlock (eBBlock * ebb, int computeOnly,
             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 */
@@ -1735,10 +1778,13 @@ cseBBlock (eBBlock * ebb, int computeOnly,
       /* if jumptable then mark the usage */
       if (ic->op == JUMPTABLE)
        {
-         OP_USES(IC_JTCOND (ic))=
-           bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key);
-         setUsesDefs (IC_JTCOND (ic), ebb->defSet,
-                      ebb->outDefs, &ebb->usesDefs);
+          if (IS_SYMOP (IC_JTCOND (ic)))
+           {
+             OP_USES(IC_JTCOND (ic)) =
+               bitVectSetBit (OP_USES (IC_JTCOND (ic)), ic->key);
+             setUsesDefs (IC_JTCOND (ic), ebb->defSet,
+                          ebb->outDefs, &ebb->usesDefs);
+           }
          continue;
        }
 
@@ -1783,7 +1829,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
          /* update the spill location for this */
          updateSpillLocation (ic,0);
 
-         if (POINTER_SET (ic) && 
+         if (POINTER_SET (ic) &&
              !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype)))
            {
              pdop = NULL;
@@ -1854,7 +1900,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
            change = 1;
          }
        }
-       
+
       /* if left or right changed then do algebraic */
       if (!computeOnly && change)
        {
@@ -1889,15 +1935,15 @@ cseBBlock (eBBlock * ebb, int computeOnly,
          if (pdic && compareType (operandType (IC_RESULT (pdic)),
                                 operandType (IC_RESULT (ic))) != 1)
            pdic = NULL;
-         if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0) 
+         if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0)
              pdic = NULL;
        }
 
       /* Alternate code */
       if (pdic && IS_ITEMP(IC_RESULT(ic))) {
        if (POINTER_GET(ic) && bitVectBitValue(ebb->ptrsSet,IC_LEFT(ic)->key)) {
-         /* Mmm, found an equivalent pointer get at a lower level. 
-            This could be a loop however with the same pointer set 
+         /* Mmm, found an equivalent pointer get at a lower level.
+            This could be a loop however with the same pointer set
             later on */
        } else {
          /* if previous definition found change this to an assignment */
@@ -1905,7 +1951,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
          IC_LEFT(ic) = NULL;
          IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic));
          SET_ISADDR(IC_RESULT(ic),0);
-         SET_ISADDR(IC_RIGHT (ic),0);    
+         SET_ISADDR(IC_RIGHT (ic),0);
        }
       }
 
@@ -2013,7 +2059,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
        }
     }
 
-  setToNull ((void **) &ebb->outExprs);
+  setToNull ((void *) &ebb->outExprs);
   ebb->outExprs = cseSet;
   ebb->outDefs = bitVectUnion (ebb->outDefs, ebb->defSet);
   ebb->ptrsSet = bitVectUnion (ebb->ptrsSet, ebb->inPtrsSet);