This patch addresses issues Richi raised from V1. Specifically the
users of overflow_comparison_1 don't need to worry about trying both the
original comparison and the reversed comparison. This slightly
simplifies the callers.
Bootstrapped and regression tested as part of the full patch series.
OK for the trunk?
Jeff
* tree-vrp.c (register_edge_assert_for_2): Register additional asserts
if NAME is used in an overflow test.
(vrp_evaluate_conditional_warnv_with_ops): If the ops represent an
overflow check that can be expressed as an equality test, then adjust
ops to be that equality test.
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 2c03a74..21c459c 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -5319,7 +5319,17 @@ register_edge_assert_for_2 (tree name, edge e,
gimple_stmt_iterator bsi,
/* Only register an ASSERT_EXPR if NAME was found in the sub-graph
reachable from E. */
if (live_on_edge (e, name))
- register_new_assert_for (name, name, comp_code, val, NULL, e, bsi);
+ {
+ tree x;
+ if (overflow_comparison_p (comp_code, name, val, false, &x))
+ {
+ enum tree_code new_code
+ = ((comp_code == GT_EXPR || comp_code == GE_EXPR)
+ ? GT_EXPR : LE_EXPR);
+ register_new_assert_for (name, name, new_code, x, NULL, e, bsi);
+ }
+ register_new_assert_for (name, name, comp_code, val, NULL, e, bsi);
+ }
/* In the case of NAME <= CST and NAME being defined as
NAME = (unsigned) NAME2 + CST2 we can assert NAME2 >= -CST2
@@ -7678,6 +7688,39 @@ vrp_evaluate_conditional_warnv_with_ops (enum tree_code
code, tree op0,
&& !POINTER_TYPE_P (TREE_TYPE (op0)))
return NULL_TREE;
+ /* If OP0 CODE OP1 is an overflow comparison, if it can be expressed
+ as a simple equality test, then prefer that over its current form
+ for evaluation.
+
+ An overflow test which collapses to an equality test can always be
+ expressed as a comparison of one argument against zero. Overflow
+ occurs when the chosen argument is zero and does not occur if the
+ chosen argument is not zero. */
+ tree x;
+ if (overflow_comparison_p (code, op0, op1, use_equiv_p, &x))
+ {
+ wide_int max = wi::max_value (TYPE_PRECISION (TREE_TYPE (op0)),
UNSIGNED);
+ /* B = A - 1; if (A < B) -> B = A - 1; if (A == 0)
+ B = A - 1; if (A > B) -> B = A - 1; if (A != 0)
+ B = A + 1; if (B < A) -> B = A + 1; if (B == 0)
+ B = A + 1; if (B > A) -> B = A + 1; if (B != 0) */
+ if (integer_zerop (x))
+ {
+ op1 = x;
+ code = (code == LT_EXPR || code == LE_EXPR) ? EQ_EXPR : NE_EXPR;
+ }
+ /* B = A + 1; if (A > B) -> B = A + 1; if (B == 0)
+ B = A + 1; if (A < B) -> B = A + 1; if (B != 0)
+ B = A - 1; if (B > A) -> B = A - 1; if (A == 0)
+ B = A - 1; if (B < A) -> B = A - 1; if (A != 0) */
+ else if (wi::eq_p (x, max - 1))
+ {
+ op0 = op1;
+ op1 = wide_int_to_tree (TREE_TYPE (op0), 0);
+ code = (code == GT_EXPR || code == GE_EXPR) ? EQ_EXPR : NE_EXPR;
+ }
+ }
+
if ((ret = vrp_evaluate_conditional_warnv_with_ops_using_ranges
(code, op0, op1, strict_overflow_p)))
return ret;