Commit b24d9420 by Bin Cheng Committed by Bin Cheng

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
parent 106d07f8
2016-07-21 Bin Cheng <bin.cheng@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.
2016-07-21 Bin Cheng <bin.cheng@arm.com>
* tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne): Clean up
by removing computation of may_be_zero.
......
2016-07-21 Bin Cheng <bin.cheng@arm.com>
* gcc.dg/tree-ssa/scev-15.c: New.
2016-07-21 Bin Cheng <bin.cheng@arm.com>
* gcc.dg/vect/vect-mask-store-move-1.c: XFAIL.
2016-07-21 Jakub Jelinek <jakub@redhat.com>
......
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-tree-ldist" } */
void
foo (int *p)
{
unsigned short i, j;
for (i = 0; i < 100; i++)
for (j = 1; j < 101; j++)
{
unsigned int index = 100 * i + j;
p[index-1] = 0;
}
}
/* Loop can be transformed into builtin memset since &p[...] is SCEV. */
/* { dg-final { scan-tree-dump "builtin_memset" "ldist" } } */
......@@ -1162,16 +1162,17 @@ nb_vars_in_chrec (tree chrec)
/* Converts BASE and STEP of affine scev to TYPE. LOOP is the loop whose iv
the scev corresponds to. AT_STMT is the statement at that the scev is
evaluated. 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) -- i.e., to use them to avoid unnecessary
tests, but also to enforce that the result follows them. Returns true if the
conversion succeeded, false otherwise. */
evaluated. 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) -- i.e., to use them to avoid
unnecessary tests, but also to enforce that the result follows them.
FROM is the source variable converted if it's not NULL. Returns true if
the conversion succeeded, false otherwise. */
bool
convert_affine_scev (struct loop *loop, tree type,
tree *base, tree *step, gimple *at_stmt,
bool use_overflow_semantics)
bool use_overflow_semantics, tree from)
{
tree ct = TREE_TYPE (*step);
bool enforce_overflow_semantics;
......@@ -1230,7 +1231,7 @@ convert_affine_scev (struct loop *loop, tree type,
must_check_rslt_overflow = false;
if (must_check_src_overflow
&& scev_probably_wraps_p (*base, *step, at_stmt, loop,
&& scev_probably_wraps_p (from, *base, *step, at_stmt, loop,
use_overflow_semantics))
return false;
......@@ -1258,7 +1259,8 @@ convert_affine_scev (struct loop *loop, tree type,
if (must_check_rslt_overflow
/* Note that in this case we cannot use the fact that signed variables
do not overflow, as this is what we are verifying for the new iv. */
&& scev_probably_wraps_p (new_base, new_step, at_stmt, loop, false))
&& scev_probably_wraps_p (NULL_TREE, new_base, new_step,
at_stmt, loop, false))
return false;
*base = new_base;
......@@ -1288,12 +1290,14 @@ chrec_convert_rhs (tree type, tree chrec, gimple *at_stmt)
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) -- i.e., to use them to avoid unnecessary
tests, but also to enforce that the result follows them. */
arithmetics in C does not overflow) -- i.e., to use them to avoid
unnecessary tests, but also to enforce that the result follows them.
FROM is the source variable converted if it's not NULL. */
static tree
chrec_convert_1 (tree type, tree chrec, gimple *at_stmt,
bool use_overflow_semantics)
bool use_overflow_semantics, tree from)
{
tree ct, res;
tree base, step;
......@@ -1314,7 +1318,7 @@ chrec_convert_1 (tree type, tree chrec, gimple *at_stmt,
step = CHREC_RIGHT (chrec);
if (convert_affine_scev (loop, type, &base, &step, at_stmt,
use_overflow_semantics))
use_overflow_semantics, from))
return build_polynomial_chrec (loop->num, base, step);
/* If we cannot propagate the cast inside the chrec, just keep the cast. */
......@@ -1347,7 +1351,7 @@ keep_cast:
CHREC_LEFT (chrec)),
fold_convert (utype,
CHREC_RIGHT (chrec)));
res = chrec_convert_1 (type, res, at_stmt, use_overflow_semantics);
res = chrec_convert_1 (type, res, at_stmt, use_overflow_semantics, from);
}
else
res = fold_convert (type, chrec);
......@@ -1395,14 +1399,16 @@ keep_cast:
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) -- i.e., to use them to avoid unnecessary
tests, but also to enforce that the result follows them. */
arithmetics in C does not overflow) -- i.e., to use them to avoid
unnecessary tests, but also to enforce that the result follows them.
FROM is the source variable converted if it's not NULL. */
tree
chrec_convert (tree type, tree chrec, gimple *at_stmt,
bool use_overflow_semantics)
bool use_overflow_semantics, tree from)
{
return chrec_convert_1 (type, chrec, at_stmt, use_overflow_semantics);
return chrec_convert_1 (type, chrec, at_stmt, use_overflow_semantics, from);
}
/* Convert CHREC to TYPE, without regard to signed overflows. Returns the new
......
......@@ -59,7 +59,7 @@ enum ev_direction scev_direction (const_tree);
extern tree chrec_fold_plus (tree, tree, tree);
extern tree chrec_fold_minus (tree, tree, tree);
extern tree chrec_fold_multiply (tree, tree, tree);
extern tree chrec_convert (tree, tree, gimple *, bool = true);
extern tree chrec_convert (tree, tree, gimple *, bool = true, tree = NULL);
extern tree chrec_convert_rhs (tree, tree, gimple *);
extern tree chrec_convert_aggressive (tree, tree, bool *);
......@@ -75,7 +75,7 @@ extern tree reset_evolution_in_loop (unsigned, tree, tree);
extern tree chrec_merge (tree, tree);
extern void for_each_scev_op (tree *, bool (*) (tree *, void *), void *);
extern bool convert_affine_scev (struct loop *, tree, tree *, tree *, gimple *,
bool);
bool, tree = NULL);
/* Observers. */
extern bool eq_evolutions_p (const_tree, const_tree);
......
......@@ -1933,7 +1933,7 @@ interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
}
else
chrec1 = analyze_scalar_evolution (loop, rhs1);
res = chrec_convert (type, chrec1, at_stmt);
res = chrec_convert (type, chrec1, at_stmt, true, rhs1);
break;
case BIT_AND_EXPR:
......
......@@ -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;
......
......@@ -49,7 +49,8 @@ extern bool estimated_stmt_executions (struct loop *, widest_int *);
extern void estimate_numbers_of_iterations (void);
extern bool stmt_dominates_stmt_p (gimple *, gimple *);
extern bool nowrap_type_p (tree);
extern bool scev_probably_wraps_p (tree, tree, gimple *, struct loop *, bool);
extern bool scev_probably_wraps_p (tree, tree, tree, gimple *,
struct loop *, bool);
extern void free_loop_control_ivs (struct loop *);
extern void free_numbers_of_iterations_estimates_loop (struct loop *);
extern void free_numbers_of_iterations_estimates (function *);
......
......@@ -4156,8 +4156,8 @@ adjust_range_with_scev (value_range *vr, struct loop *loop,
or decreases, ... */
dir == EV_DIR_UNKNOWN
/* ... or if it may wrap. */
|| scev_probably_wraps_p (init, step, stmt, get_chrec_loop (chrec),
true))
|| scev_probably_wraps_p (NULL_TREE, init, step, stmt,
get_chrec_loop (chrec), true))
return;
/* We use TYPE_MIN_VALUE and TYPE_MAX_VALUE here instead of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment