re PR middle-end/49806 (FAIL: gcc.dg/tree-ssa/vrp47.c)
authorRichard Guenther <rguenther@suse.de>
Thu, 4 Aug 2011 14:11:30 +0000 (14:11 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 4 Aug 2011 14:11:30 +0000 (14:11 +0000)
2011-08-04  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/49806
* tree-vrp.c (op_with_boolean_value_range_p): New function.
(simplify_truth_ops_using_ranges): Simplify.  Allow inserting
a new statement for a final conversion to bool.

From-SVN: r177392

gcc/ChangeLog
gcc/tree-vrp.c

index 6e0dd68a0178aec979d749627d15964d406c0366..773df850ca1c82b2e9e26cafd5525bdd1635120b 100644 (file)
@@ -1,3 +1,10 @@
+2011-08-04  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/49806
+       * tree-vrp.c (op_with_boolean_value_range_p): New function.
+       (simplify_truth_ops_using_ranges): Simplify.  Allow inserting
+       a new statement for a final conversion to bool.
+
 2011-08-04  Romain Geissler  <romain.geissler@gmail.com>
 
        * gengtype-state.c: Include "bconfig.h" if
index 15331e1fcc69b04671d49c4b037619cc0be785a3..5aa942be611b2c57d2f6e04608825394b3a10400 100644 (file)
@@ -1454,6 +1454,28 @@ op_with_constant_singleton_value_range (tree op)
   return NULL_TREE;
 }
 
+/* Return true if op is in a boolean [0, 1] value-range.  */
+
+static bool
+op_with_boolean_value_range_p (tree op)
+{
+  value_range_t *vr;
+
+  if (TYPE_PRECISION (TREE_TYPE (op)) == 1)
+    return true;
+
+  if (integer_zerop (op)
+      || integer_onep (op))
+    return true;
+
+  if (TREE_CODE (op) != SSA_NAME)
+    return false;
+
+  vr = get_value_range (op);
+  return (vr->type == VR_RANGE
+         && integer_zerop (vr->min)
+         && integer_onep (vr->max));
+}
 
 /* Extract value range information from an ASSERT_EXPR EXPR and store
    it in *VR_P.  */
@@ -6753,115 +6775,64 @@ static bool
 simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
-  tree val = NULL;
-  tree op0, op1;
-  value_range_t *vr;
-  bool sop = false;
+  tree lhs, op0, op1;
   bool need_conversion;
 
   /* We handle only !=/== case here.  */
   gcc_assert (rhs_code == EQ_EXPR || rhs_code == NE_EXPR);
 
   op0 = gimple_assign_rhs1 (stmt);
-  if (TYPE_PRECISION (TREE_TYPE (op0)) != 1)
-    {
-      if (TREE_CODE (op0) != SSA_NAME)
-       return false;
-      vr = get_value_range (op0);
-
-      val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
-      if (!val || !integer_onep (val))
-        return false;
-
-      val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
-      if (!val || !integer_onep (val))
-        return false;
-    }
+  if (!op_with_boolean_value_range_p (op0))
+    return false;
 
   op1 = gimple_assign_rhs2 (stmt);
+  if (!op_with_boolean_value_range_p (op1))
+    return false;
 
-  /* Reduce number of cases to handle.  */
-  if (is_gimple_min_invariant (op1))
-    {
-      if (!integer_zerop (op1)
-         && !integer_onep (op1)
-         && !integer_all_onesp (op1))
-       return false;
-
-      /* Limit the number of cases we have to consider.  */
-      if (rhs_code == EQ_EXPR)
-       {
-         rhs_code = NE_EXPR;
-         /* OP1 is a constant.  */
-         op1 = fold_unary (TRUTH_NOT_EXPR, TREE_TYPE (op1), op1);
-       }
-    }
-  else
-    {
-      /* Punt on A == B as there is no BIT_XNOR_EXPR.  */
-      if (rhs_code == EQ_EXPR)
-       return false;
-
-      if (TYPE_PRECISION (TREE_TYPE (op1)) != 1)
-       {
-         vr = get_value_range (op1);
-         val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
-         if (!val || !integer_onep (val))
-           return false;
-
-         val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
-         if (!val || !integer_onep (val))
-           return false;
-       }
-    }
-
-  if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+  /* Reduce number of cases to handle to NE_EXPR.  As there is no
+     BIT_XNOR_EXPR we cannot replace A == B with a single statement.  */
+  if (rhs_code == EQ_EXPR)
     {
-      location_t location;
-
-      if (!gimple_has_location (stmt))
-       location = input_location;
+      if (TREE_CODE (op1) == INTEGER_CST)
+       op1 = int_const_binop (BIT_XOR_EXPR, op1, integer_one_node);
       else
-       location = gimple_location (stmt);
-
-      warning_at (location, OPT_Wstrict_overflow,
-                 _("assuming signed overflow does not occur when "
-                   "simplifying ==, != or ! to identity or ^"));
+       return false;
     }
 
-  need_conversion =
-    !useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (stmt)),
-                               TREE_TYPE (op0));
+  lhs = gimple_assign_lhs (stmt);
+  need_conversion
+    = !useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (op0));
 
-  /* Make sure to not sign-extend -1 as a boolean value.  */
+  /* Make sure to not sign-extend a 1-bit 1 when converting the result.  */
   if (need_conversion
       && !TYPE_UNSIGNED (TREE_TYPE (op0))
-      && TYPE_PRECISION (TREE_TYPE (op0)) == 1)
+      && TYPE_PRECISION (TREE_TYPE (op0)) == 1
+      && TYPE_PRECISION (TREE_TYPE (lhs)) > 1)
     return false;
 
-  switch (rhs_code)
-    {
-    case NE_EXPR:
-      if (integer_zerop (op1))
-       {
-         gimple_assign_set_rhs_with_ops (gsi,
-                                         need_conversion ? NOP_EXPR : SSA_NAME,
-                                         op0, NULL);
-         update_stmt (gsi_stmt (*gsi));
-         return true;
-       }
-
-      rhs_code = BIT_XOR_EXPR;
-      break;
-    default:
-      gcc_unreachable ();
-    }
-
-  if (need_conversion)
-    return false;
-
-  gimple_assign_set_rhs_with_ops (gsi, rhs_code, op0, op1);
+  /* For A != 0 we can substitute A itself.  */
+  if (integer_zerop (op1))
+    gimple_assign_set_rhs_with_ops (gsi,
+                                   need_conversion
+                                   ? NOP_EXPR : TREE_CODE (op0),
+                                   op0, NULL_TREE);
+  /* For A != B we substitute A ^ B.  Either with conversion.  */
+  else if (need_conversion)
+    {
+      gimple newop;
+      tree tem = create_tmp_reg (TREE_TYPE (op0), NULL);
+      newop = gimple_build_assign_with_ops (BIT_XOR_EXPR, tem, op0, op1);
+      tem = make_ssa_name (tem, newop);
+      gimple_assign_set_lhs (newop, tem);
+      gsi_insert_before (gsi, newop, GSI_SAME_STMT);
+      update_stmt (newop);
+      gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem, NULL_TREE);
+    }
+  /* Or without.  */
+  else
+    gimple_assign_set_rhs_with_ops (gsi, BIT_XOR_EXPR, op0, op1);
   update_stmt (gsi_stmt (*gsi));
+
   return true;
 }