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);
ChangeLog
Description: Binary data
