On Tue, Feb 7, 2017 at 7:32 PM, Jeff Law <l...@redhat.com> wrote: > > This patch addresses issues Richi raised from V1. Specifically it relieves > the callers from having to try op0 COND op1 and op1 COND' op0 separately and > adds some additional comments about motivation. There may have been minor > nits Richi pointed out, if so, they were addressed as well. > > Bootstrapped and regression tested as part of the full patch series. > > OK for the trunk?
Ok. Richard. > Jeff > > > * tree-vrp.c (overflow_comparison_p_1): New function. > (overflow_comparison_p): New function. > > diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c > index ad8173c..2c03a74 100644 > --- a/gcc/tree-vrp.c > +++ b/gcc/tree-vrp.c > @@ -5186,6 +5186,118 @@ masked_increment (const wide_int &val_in, const > wide_int &mask, > return val ^ sgnbit; > } > > +/* Helper for overflow_comparison_p > + > + OP0 CODE OP1 is a comparison. Examine the comparison and potentially > + OP1's defining statement to see if it ultimately has the form > + OP0 CODE (OP0 PLUS INTEGER_CST) > + > + If so, return TRUE indicating this is an overflow test and store into > + *NEW_CST an updated constant that can be used in a narrowed range test. > + > + REVERSED indicates if the comparison was originally: > + > + OP1 CODE' OP0. > + > + This affects how we build the updated constant. */ > + > +static bool > +overflow_comparison_p_1 (enum tree_code code, tree op0, tree op1, > + bool follow_assert_exprs, bool reversed, tree > *new_cst) > +{ > + /* See if this is a relational operation between two SSA_NAMES with > + unsigned, overflow wrapping values. If so, check it more deeply. */ > + if ((code == LT_EXPR || code == LE_EXPR > + || code == GE_EXPR || code == GT_EXPR) > + && TREE_CODE (op0) == SSA_NAME > + && TREE_CODE (op1) == SSA_NAME > + && INTEGRAL_TYPE_P (TREE_TYPE (op0)) > + && TYPE_UNSIGNED (TREE_TYPE (op0)) > + && TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0))) > + { > + gimple *op1_def = SSA_NAME_DEF_STMT (op1); > + > + /* If requested, follow any ASSERT_EXPRs backwards for OP1. */ > + if (follow_assert_exprs) > + { > + while (gimple_assign_single_p (op1_def) > + && TREE_CODE (gimple_assign_rhs1 (op1_def)) == ASSERT_EXPR) > + { > + op1 = TREE_OPERAND (gimple_assign_rhs1 (op1_def), 0); > + if (TREE_CODE (op1) != SSA_NAME) > + break; > + op1_def = SSA_NAME_DEF_STMT (op1); > + } > + } > + > + /* Now look at the defining statement of OP1 to see if it adds > + or subtracts a nonzero constant from another operand. */ > + if (op1_def > + && is_gimple_assign (op1_def) > + && gimple_assign_rhs_code (op1_def) == PLUS_EXPR > + && TREE_CODE (gimple_assign_rhs2 (op1_def)) == INTEGER_CST > + && !integer_zerop (gimple_assign_rhs2 (op1_def))) > + { > + tree target = gimple_assign_rhs1 (op1_def); > + > + /* If requested, follow ASSERT_EXPRs backwards for op0 looking > + for one where TARGET appears on the RHS. */ > + if (follow_assert_exprs) > + { > + /* Now see if that "other operand" is op0, following the chain > + of ASSERT_EXPRs if necessary. */ > + gimple *op0_def = SSA_NAME_DEF_STMT (op0); > + while (op0 != target > + && gimple_assign_single_p (op0_def) > + && TREE_CODE (gimple_assign_rhs1 (op0_def)) == > ASSERT_EXPR) > + { > + op0 = TREE_OPERAND (gimple_assign_rhs1 (op0_def), 0); > + if (TREE_CODE (op0) != SSA_NAME) > + break; > + op0_def = SSA_NAME_DEF_STMT (op0); > + } > + } > + > + /* If we did not find our target SSA_NAME, then this is not > + an overflow test. */ > + if (op0 != target) > + return false; > + > + tree type = TREE_TYPE (op0); > + wide_int max = wi::max_value (TYPE_PRECISION (type), UNSIGNED); > + tree inc = gimple_assign_rhs2 (op1_def); > + if (reversed) > + *new_cst = wide_int_to_tree (type, max + inc); > + else > + *new_cst = wide_int_to_tree (type, max - inc); > + return true; > + } > + } > + return false; > +} > + > +/* OP0 CODE OP1 is a comparison. Examine the comparison and potentially > + OP1's defining statement to see if it ultimately has the form > + OP0 CODE (OP0 PLUS INTEGER_CST) > + > + If so, return TRUE indicating this is an overflow test and store into > + *NEW_CST an updated constant that can be used in a narrowed range test. > + > + These statements are left as-is in the IL to facilitate discovery of > + {ADD,SUB}_OVERFLOW sequences later in the optimizer pipeline. But > + the alternate range representation is often useful within VRP. */ > + > +static bool > +overflow_comparison_p (tree_code code, tree name, tree val, > + bool use_equiv_p, tree *new_cst) > +{ > + if (overflow_comparison_p_1 (code, name, val, use_equiv_p, false, > new_cst)) > + return true; > + return overflow_comparison_p_1 (swap_tree_comparison (code), val, name, > + use_equiv_p, true, new_cst); > +} > + > + > /* Try to register an edge assertion for SSA name NAME on edge E for > the condition COND contributing to the conditional jump pointed to by > BSI. > Invert the condition COND if INVERT is true. */ >