On Tue, Feb 7, 2017 at 7:32 PM, Jeff Law 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;
>