Hi Richard,
For the following test-case:

int f(int x, int y)
{
   int ret;

   if (x == y)
     ret = x ^ y;
   else
     ret = 1;

   return ret;
}

I was wondering if x ^ y should be folded to 0 since
it's guarded by condition x == y ?

optimized dump shows:
f (int x, int y)
{
  int iftmp.0_1;
  int iftmp.0_4;

  <bb 2>:
  if (x_2(D) == y_3(D))
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 3>:
  iftmp.0_4 = x_2(D) ^ y_3(D);

  <bb 4>:
  # iftmp.0_1 = PHI <iftmp.0_4(3), 1(2)>
  return iftmp.0_1;

}

The attached patch tries to fold for above case.
I am checking if op0 and op1 are equal using:
if (bitmap_intersect_p (vr1->equiv, vr2->equiv)
   && operand_equal_p (vr1->min, vr1->max)
   && operand_equal_p (vr2->min, vr2->max))
  { /* equal /* }

I suppose intersection would check if op0 and op1 have equivalent ranges,
and added operand_equal_p check to ensure that there is only one
element within the range. Does that look correct ?
Bootstrap+test in progress on x86_64-unknown-linux-gnu.

Thanks,
Prathamesh
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 4333d60..787d068 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -6965,6 +6965,59 @@ vrp_valueize_1 (tree name)
   return name;
 }
 
+/* Try to fold op0 xor op1 == 0 if op0 == op1.  */ 
+static tree
+maybe_fold_xor (gassign *stmt)
+{
+  if (!stmt)
+    return NULL_TREE;
+
+  enum tree_code code = gimple_assign_rhs_code (stmt);
+  if (code != BIT_XOR_EXPR)
+    return NULL_TREE;
+
+  tree op0 = gimple_assign_rhs1 (stmt);
+  tree op1 = gimple_assign_rhs2 (stmt);
+
+  if (TREE_CODE (op0) != SSA_NAME
+      || TREE_CODE (op1) != SSA_NAME)
+    return NULL_TREE;
+
+  value_range *vr1 = get_value_range (op0);
+  value_range *vr2 = get_value_range (op1);
+
+  if (vr1 == NULL || vr2 == NULL)
+    return NULL_TREE;
+
+  if (vr1->type != VR_RANGE || vr2->type != VR_RANGE)
+    return NULL_TREE;
+
+  if (! (symbolic_range_p (vr1) && symbolic_range_p (vr2)))
+    return NULL_TREE;
+
+  if (! (TREE_CODE (vr1->min) == SSA_NAME && TREE_CODE (vr1->max) == SSA_NAME
+        && TREE_CODE (vr2->min) == SSA_NAME && TREE_CODE (vr2->max) == 
SSA_NAME))
+    return NULL_TREE;
+
+  if (! (vr1->equiv && vr2->equiv))
+    return NULL_TREE;
+
+  /* check if op0 == op1.  */
+  if (bitmap_intersect_p (vr1->equiv, vr2->equiv)
+      && operand_equal_p (vr1->min, vr1->max, 0)
+      && operand_equal_p (vr2->min, vr2->max, 0)
+      && code == BIT_XOR_EXPR)
+    {
+      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+      gimple_assign_set_rhs_from_tree (&gsi, integer_zero_node); 
+      update_stmt (stmt);
+      return integer_zero_node;
+    }
+
+  return NULL_TREE;
+}
+
+
 /* Visit assignment STMT.  If it produces an interesting range, record
    the SSA name in *OUTPUT_P.  */
 
@@ -6990,8 +7043,11 @@ vrp_visit_assignment_or_call (gimple *stmt, tree 
*output_p)
       /* Try folding the statement to a constant first.  */
       tree tem = gimple_fold_stmt_to_constant_1 (stmt, vrp_valueize,
                                                 vrp_valueize_1);
+      if (!tem)
+       tem = maybe_fold_xor (dyn_cast<gassign *> (stmt));
       if (tem && is_gimple_min_invariant (tem))
        set_value_range_to_value (&new_vr, tem, NULL);
+
       /* Then dispatch to value-range extracting functions.  */
       else if (code == GIMPLE_CALL)
        extract_range_basic (&new_vr, stmt);

Attachment: ChangeLog
Description: Binary data

Reply via email to