* src/SDCCglue.c (printChar): fixed bug #973350, patch provided by Phuah Yee Keat...
[fw/sdcc] / src / SDCCcse.c
index 71d0963324dd4360bfe97cb852aa6f25c3566e7d..6094b0444d6a1efd22dfe76234e4dac7968af1e1 100644 (file)
@@ -40,10 +40,65 @@ newCseDef (operand * sym, iCode * ic)
   cdp->sym = sym;
   cdp->diCode = ic;
   cdp->key = sym->key;
+  cdp->ancestors = newBitVect(iCodeKey);
+  cdp->fromGlobal = 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));
+        }
+      if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)))
+        {
+          bitVectSetBit (cdp->ancestors, IC_RIGHT (ic)->key);
+          cdp->fromGlobal |= isOperandGlobal (IC_RIGHT (ic));
+        }
+    }
+  
   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;
+                  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;
+                  break;
+                }
+            }
+        }
+    }
+}
 
 
 /*-----------------------------------------------------------------*/
@@ -457,6 +512,16 @@ DEFSETFUNC (ifAssignedFromGlobal)
   return 0;
 }
 
+/*-------------------------------------------------------------------*/
+/* ifFromGlobal - if definition is derived from global               */
+/*-------------------------------------------------------------------*/
+DEFSETFUNC (ifFromGlobal)
+{
+  cseDef *cdp = item;
+  
+  return cdp->fromGlobal;
+}
+
 /*-----------------------------------------------------------------*/
 /* ifDefGlobal - if definition is global                           */
 /*-----------------------------------------------------------------*/
@@ -487,7 +552,9 @@ DEFSETFUNC (ifOperandsHave)
   cseDef *cdp = item;
   V_ARG (operand *, op);
 
-
+  if (bitVectBitValue(cdp->ancestors, op->key))
+    return 1;
+  
   if (IC_LEFT (cdp->diCode) &&
       IS_SYMOP (IC_LEFT (cdp->diCode)) &&
       IC_LEFT (cdp->diCode)->key == op->key)
@@ -543,12 +610,17 @@ DEFSETFUNC (ifDefSymIsX)
 {
   cseDef *cdp = item;
   V_ARG (operand *, op);
-
+  int match;
+  
   if (op && cdp->sym)
-    return cdp->sym->key == op->key;
+    match = cdp->sym->key == op->key;
   else
-    return (isOperandEqual (cdp->sym, op));
-
+    match = (isOperandEqual (cdp->sym, op));
+  #if 0
+  if (match)
+    printf("%s ",OP_SYMBOL(cdp->sym)->name);
+  #endif
+  return match;
 }
 
 
@@ -736,13 +808,21 @@ algebraicOpts (iCode * ic, eBBlock * ebp)
          return;
        }
       /* if addition then check if one of them is a zero */
-      /* if yes turn it  into assignmnt */
+      /* if yes turn it into assignmnt or cast */
       if (IS_OP_LITERAL (IC_LEFT (ic)) &&
          operandLitValue (IC_LEFT (ic)) == 0.0)
        {
-
-         ic->op = '=';
-         IC_LEFT (ic) = NULL;
+         if (compareType (operandType (IC_RESULT (ic)),
+                          operandType (IC_RIGHT (ic)))<0)
+           {
+             ic->op = CAST;
+             IC_LEFT (ic) = operandFromLink (operandType (IC_RESULT (ic)));
+           }
+         else
+            {
+             ic->op = '=';
+             IC_LEFT (ic) = NULL;
+            }
          SET_ISADDR (IC_RESULT (ic), 0);
          SET_ISADDR (IC_RIGHT (ic), 0);
          return;
@@ -750,10 +830,19 @@ algebraicOpts (iCode * ic, eBBlock * ebp)
       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;
+         if (compareType (operandType (IC_RESULT (ic)),
+                          operandType (IC_LEFT (ic)))<0)
+           {
+             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;
+            }
          SET_ISADDR (IC_RIGHT (ic), 0);
          SET_ISADDR (IC_RESULT (ic), 0);
          return;
@@ -825,6 +914,7 @@ algebraicOpts (iCode * ic, eBBlock * ebp)
              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)));
@@ -863,7 +953,7 @@ algebraicOpts (iCode * ic, eBBlock * ebp)
                  ic->op = CAST;
                  op = IC_RIGHT (ic);
                  IC_RIGHT (ic) = IC_LEFT (ic);
-                 IC_LEFT (ic) = op;
+                 IC_LEFT (ic) = operandFromOperand (op);
                  IC_LEFT (ic)->type = TYPE;
                  IC_LEFT (ic)->isLiteral = 0;
                  setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic)));
@@ -1206,10 +1296,13 @@ updateSpillLocation (iCode * ic, int induction)
                        if (!OP_SYMBOL(IC_RIGHT (ic))->noSpilLoc &&
                            !IS_VOLATILE (setype) &&
                            !IN_FARSPACE (SPEC_OCLS (setype)) &&
-                           !OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))))
+                           !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 && 
@@ -1217,6 +1310,8 @@ updateSpillLocation (iCode * ic, int induction)
                    !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;
                }
        }
 }
@@ -1335,7 +1430,7 @@ ifxOptimize (iCode * ic, set * cseSet,
       /* the price */
       computeControlFlow (ebbs, count, 1);
       if (!options.lessPedantic) {
-       werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
+       werrorfl (ic->filename, ic->lineno, W_CONTROL_FLOW);
       }
       return;
     }
@@ -1349,7 +1444,7 @@ ifxOptimize (iCode * ic, set * cseSet,
     {
 
       if (!options.lessPedantic) {
-       werror (W_CONTROL_FLOW, ic->filename, ic->lineno);
+       werrorfl (ic->filename, ic->lineno, W_CONTROL_FLOW);
       }
       if (IS_OP_VOLATILE (IC_COND (ic)))
        {
@@ -1531,6 +1626,7 @@ deleteGetPointers (set ** cseSet, set ** pss, operand * op, eBBlock * ebb)
     {
       ebb->ptrsSet = bitVectSetBit (ebb->ptrsSet, cop->key);
       deleteItemIf (cseSet, ifPointerGet, cop);
+      deleteItemIf (cseSet, ifDefSymIsX, cop);
       deleteItemIf (pss, ifPointerSet, cop);
     }
 }
@@ -1662,6 +1758,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
   int change = 0;
   int i;
   set *ptrSetSet = NULL;
+  cseDef *expr;
 
   /* if this block is not reachable */
   if (ebb->noPath)
@@ -1702,7 +1799,7 @@ cseBBlock (eBBlock * ebb, int computeOnly,
          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  */
@@ -1722,8 +1819,8 @@ cseBBlock (eBBlock * ebb, int computeOnly,
             since they can be modified by the function call */
          deleteItemIf (&cseSet, ifDefGlobal);
 
-         /* and also itemps assigned from globals */
-         deleteItemIf (&cseSet, ifAssignedFromGlobal);
+         /* and also itemps derived from globals */
+         deleteItemIf (&cseSet, ifFromGlobal);
 
          /* delete all getpointer iCodes from cseSet, this should
             be done only for global arrays & pointers but at this
@@ -1834,9 +1931,15 @@ cseBBlock (eBBlock * ebb, int computeOnly,
            {
              pdop = NULL;
              applyToSetFTrue (cseSet, findCheaperOp, IC_RESULT (ic), &pdop, 0);
-             if (pdop && !computeOnly &&
-                 IS_ITEMP (pdop) && IS_PTR(operandType(pdop)))
-               ReplaceOpWithCheaperOp (&IC_RESULT(ic), pdop);
+             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));
+                   }
+               }
            }
        }
 
@@ -1956,8 +2059,11 @@ cseBBlock (eBBlock * ebb, int computeOnly,
       }
 
       if (!(POINTER_SET (ic)) && IC_RESULT (ic)) {
+          cseDef *csed;
          deleteItemIf (&cseSet, ifDefSymIsX, IC_RESULT (ic));
-         addSetHead (&cseSet, newCseDef (IC_RESULT (ic), ic));
+          csed = newCseDef (IC_RESULT (ic), ic);
+          updateCseDefAncestors (csed, cseSet);
+         addSetHead (&cseSet, csed);
       }
       defic = ic;
 
@@ -2059,6 +2165,11 @@ cseBBlock (eBBlock * ebb, int computeOnly,
        }
     }
 
+  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);