diff options
author | Bin Cheng <bin.cheng@arm.com> | 2016-07-21 10:52:13 +0000 |
---|---|---|
committer | Bin Cheng <amker@gcc.gnu.org> | 2016-07-21 10:52:13 +0000 |
commit | b24d94207914fb8695bd7307187a5a0bfcddc8c2 (patch) | |
tree | 5395d978a3d736c900e79a29efb655abdb1d10e6 /gcc/tree-ssa-loop-niter.c | |
parent | 106d07f8d20542c5a0acad3699843aa26b2ee84f (diff) | |
download | gcc-b24d94207914fb8695bd7307187a5a0bfcddc8c2.zip gcc-b24d94207914fb8695bd7307187a5a0bfcddc8c2.tar.gz gcc-b24d94207914fb8695bd7307187a5a0bfcddc8c2.tar.bz2 |
tree-chrec.c (convert_affine_scev): New parameter.
* 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
* gcc.dg/tree-ssa/scev-15.c: New.
From-SVN: r238586
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 113 |
1 files changed, 110 insertions, 3 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 1102c8a..3b4d4f3 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -3128,7 +3128,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_TREE, + initial_condition_in_loop_num (ev, loop->num), step, data->stmt, loop, true)) upper = false; @@ -4191,6 +4192,104 @@ loop_exits_before_overflow (tree base, tree step, return false; } +/* VAR is scev variable whose evolution part is constant STEP, this function + proves that VAR can't overflow by using value range info. If VAR's value + range is [MIN, MAX], it can be proven by: + MAX + step doesn't overflow ; if step > 0 + or + MIN + step doesn't underflow ; if step < 0. + + We can only do this if var is computed in every loop iteration, i.e, var's + definition has to dominate loop latch. Consider below example: + + { + unsigned int i; + + <bb 3>: + + <bb 4>: + # RANGE [0, 4294967294] NONZERO 65535 + # i_21 = PHI <0(3), i_18(9)> + if (i_21 != 0) + goto <bb 6>; + else + goto <bb 8>; + + <bb 6>: + # RANGE [0, 65533] NONZERO 65535 + _6 = i_21 + 4294967295; + # RANGE [0, 65533] NONZERO 65535 + _7 = (long unsigned int) _6; + # RANGE [0, 524264] NONZERO 524280 + _8 = _7 * 8; + # PT = nonlocal escaped + _9 = a_14 + _8; + *_9 = 0; + + <bb 8>: + # RANGE [1, 65535] NONZERO 65535 + i_18 = i_21 + 1; + if (i_18 >= 65535) + goto <bb 10>; + else + goto <bb 9>; + + <bb 9>: + goto <bb 4>; + + <bb 10>: + return; + } + + VAR _6 doesn't overflow only with pre-condition (i_21 != 0), here we + can't use _6 to prove no-overlfow for _7. In fact, var _7 takes value + sequence (4294967295, 0, 1, ..., 65533) in loop life time, rather than + (4294967295, 4294967296, ...). */ + +static bool +scev_var_range_cant_overflow (tree var, tree step, struct loop *loop) +{ + tree type; + wide_int minv, maxv, diff, step_wi; + enum value_range_type rtype; + + if (TREE_CODE (step) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (var))) + return false; + + /* Check if VAR evaluates in every loop iteration. It's not the case + if VAR is default definition or does not dominate loop's latch. */ + basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (var)); + if (!def_bb || !dominated_by_p (CDI_DOMINATORS, loop->latch, def_bb)) + return false; + + rtype = get_range_info (var, &minv, &maxv); + if (rtype != VR_RANGE) + return false; + + /* VAR is a scev whose evolution part is STEP and value range info + is [MIN, MAX], we can prove its no-overflowness by conditions: + + type_MAX - MAX >= step ; if step > 0 + MIN - type_MIN >= |step| ; if step < 0. + + Or VAR must take value outside of value range, which is not true. */ + 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; + } + + return (wi::geu_p (diff, step_wi)); +} + /* Return false only when the induction variable BASE + STEP * I is known to not overflow: i.e. when the number of iterations is small enough with respect to the step and initial condition in order to @@ -4199,10 +4298,13 @@ loop_exits_before_overflow (tree base, tree step, USE_OVERFLOW_SEMANTICS is true if this function should assume that the rules for overflow of the given language apply (e.g., that signed - arithmetics in C does not overflow). */ + arithmetics in C does not overflow). + + If VAR is a ssa variable, this function also returns false if VAR can + be proven not overflow with value range info. */ bool -scev_probably_wraps_p (tree base, tree step, +scev_probably_wraps_p (tree var, tree base, tree step, gimple *at_stmt, struct loop *loop, bool use_overflow_semantics) { @@ -4239,6 +4341,11 @@ scev_probably_wraps_p (tree base, tree step, if (TREE_CODE (step) != INTEGER_CST) return true; + /* Check if var can be proven not overflow with value range info. */ + if (var && TREE_CODE (var) == SSA_NAME + && scev_var_range_cant_overflow (var, step, loop)) + return false; + if (loop_exits_before_overflow (base, step, at_stmt, loop)) return false; |