OSDN Git Service

PR c++/51812
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ccp.c
index a9c38ee..2080c06 100644 (file)
@@ -1,6 +1,6 @@
 /* Conditional constant propagation pass for the GNU compiler.
    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011 Free Software Foundation, Inc.
+   2010, 2011, 2012 Free Software Foundation, Inc.
    Adapted from original RTL SSA-CCP by Daniel Berlin <dberlin@dberlin.org>
    Adapted to GIMPLE trees by Diego Novillo <dnovillo@redhat.com>
 
@@ -657,9 +657,10 @@ likely_value (gimple stmt)
        }
     }
   /* If there was an UNDEFINED operand but the result may be not UNDEFINED
-     fall back to VARYING even if there were CONSTANT operands.  */
+     fall back to CONSTANT.  During iteration UNDEFINED may still drop
+     to CONSTANT.  */
   if (has_undefined_operand)
-    return VARYING;
+    return CONSTANT;
 
   /* We do not consider virtual operands here -- load from read-only
      memory may have only VARYING virtual operands, but still be
@@ -1368,6 +1369,10 @@ bit_value_unop (enum tree_code code, tree type, tree rhs)
   prop_value_t rval = get_value_for_expr (rhs, true);
   double_int value, mask;
   prop_value_t val;
+
+  if (rval.lattice_val == UNDEFINED)
+    return rval;
+
   gcc_assert ((rval.lattice_val == CONSTANT
               && TREE_CODE (rval.value) == INTEGER_CST)
              || double_int_minus_one_p (rval.mask));
@@ -1399,6 +1404,16 @@ bit_value_binop (enum tree_code code, tree type, tree rhs1, tree rhs2)
   prop_value_t r2val = get_value_for_expr (rhs2, true);
   double_int value, mask;
   prop_value_t val;
+
+  if (r1val.lattice_val == UNDEFINED
+      || r2val.lattice_val == UNDEFINED)
+    {
+      val.lattice_val = VARYING;
+      val.value = NULL_TREE;
+      val.mask = double_int_minus_one;
+      return val;
+    }
+
   gcc_assert ((r1val.lattice_val == CONSTANT
               && TREE_CODE (r1val.value) == INTEGER_CST)
              || double_int_minus_one_p (r1val.mask));
@@ -1878,6 +1893,7 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
     case GIMPLE_CALL:
       {
        tree lhs = gimple_call_lhs (stmt);
+       int flags = gimple_call_flags (stmt);
        tree val;
        tree argt;
        bool changed = false;
@@ -1888,7 +1904,10 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
           type issues.  */
        if (lhs
            && TREE_CODE (lhs) == SSA_NAME
-           && (val = get_constant_value (lhs)))
+           && (val = get_constant_value (lhs))
+           /* Don't optimize away calls that have side-effects.  */
+           && (flags & (ECF_CONST|ECF_PURE)) != 0
+           && (flags & ECF_LOOPING_CONST_OR_PURE) == 0)
          {
            tree new_rhs = unshare_expr (val);
            bool res;