Message ID | 8446b785-aa35-ebd9-9351-2be5cc9c39e3@redhat.com |
---|---|
State | New |
Headers | show |
On Tue, Feb 7, 2017 at 7:32 PM, Jeff Law <law@redhat.com> wrote: > 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? Ok. Richard. > 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; >
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;