On Mon, Jul 18, 2016 at 6:27 PM, Bin Cheng <bin.ch...@arm.com> wrote: > Hi, > Scalar evolution needs to prove no-overflow for source variable when handling > type conversion. This is important because otherwise we would fail to > recognize result of the conversion as SCEV, resulting in missing loop > optimizations. Take case added by this patch as an example, the loop can't > be distributed as memset call because address of memory reference is not > recognized. At the moment, we rely on type overflow semantics and loop niter > info for no-overflow checking, unfortunately that's not enough. This patch > introduces new method checking no-overflow using value range information. As > commented in the patch, value range can only be used when source operand > variable evaluates on every loop iteration, rather than guarded by some > conditions. > > This together with patch improving loop niter analysis > (https://gcc.gnu.org/ml/gcc-patches/2016-07/msg00736.html) can help various > loop passes like vectorization. > Bootstrap and test on x86_64 and AArch64. Is it OK?
@@ -3187,7 +3187,8 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta) /* If access is not executed on every iteration, we must ensure that overlow may not make the access valid later. */ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (data->stmt)) - && scev_probably_wraps_p (initial_condition_in_loop_num (ev, loop->num), + && scev_probably_wraps_p (NULL, use NULL_TREE for the null pointer constant of tree. + /* Check if VAR evaluates in every loop iteration. */ + gimple *def; + if ((def = SSA_NAME_DEF_STMT (var)) != NULL def is never NULL but it might be a GIMPLE_NOP which has a NULL gimple_bb. Better check for ! SSA_DEFAULT_DEF_P (var) + if (TREE_CODE (step) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (var))) + return false; this looks like a cheaper test so please do that first. + step_wi = step; + type = TREE_TYPE (var); + if (tree_int_cst_sign_bit (step)) + { + diff = lower_bound_in_type (type, type); + diff = minv - diff; + step_wi = - step_wi; + } + else + { + diff = upper_bound_in_type (type, type); + diff = diff - maxv; + } this lacks a comment - it's not obvious to me what the gymnastics with lower/upper_bound_in_type are supposed to achieve. As VRP uses niter analysis itself I wonder how this fires back-to-back between VRP1 and VRP2? If the def of var dominates the latch isn't it enough to do a + 1 to check whether VRP bumped the range up to INT_MAX/MIN? That is, why do we need to add step if not for the TYPE_OVERFLOW_UNDEFINED case of VRP handling the ranges optimistically? Thanks, Richard. > Thanks, > bin > > 2016-07-15 Bin Cheng <bin.ch...@arm.com> > > * tree-chrec.c (convert_affine_scev): New parameter. Pass new arg. > (chrec_convert_1, chrec_convert): Ditto. > * tree-chrec.h (chrec_convert, convert_affine_scev): New parameter. > * tree-scalar-evolution.c (interpret_rhs_expr): Pass new arg. > * tree-vrp.c (adjust_range_with_scev): Ditto. > * tree-ssa-loop-niter.c (idx_infer_loop_bounds): Ditto. > (scev_var_range_cant_overflow): New function. > (scev_probably_wraps_p): New parameter. Call above function. > * tree-ssa-loop-niter.h (scev_probably_wraps_p): New parameter. > > gcc/testsuite/ChangeLog > 2016-07-15 Bin Cheng <bin.ch...@arm.com> > > * gcc.dg/tree-ssa/scev-15.c: New.