summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-niter.c
diff options
context:
space:
mode:
authorBin Cheng <bin.cheng@arm.com>2015-12-01 05:22:16 +0000
committerBin Cheng <amker@gcc.gnu.org>2015-12-01 05:22:16 +0000
commitcdf66caf4fa836a4398f74faceb373d84e019bb7 (patch)
treeb0feb2d5b46ce5a54088544843561463d10ac4f5 /gcc/tree-ssa-loop-niter.c
parent6ea98dee208bef31e56452969bfa7e85d0dd3c36 (diff)
re PR tree-optimization/68529 (scev failed for while(i--))
PR tree-optimization/68529 * tree-ssa-loop-niter.c (number_of_iterations_ne): Add new param. Compute no-overflow information for control iv. (number_of_iterations_lt, number_of_iterations_le): Add new param. (number_of_iterations_cond): Pass new argument to above functions. PR tree-optimization/68529 * gcc.dg/tree-ssa/pr68529-1.c: New test. * gcc.dg/tree-ssa/pr68529-2.c: New test. * gcc.dg/tree-ssa/pr68529-3.c: New test. From-SVN: r231097
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r--gcc/tree-ssa-loop-niter.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 6d480c0df41..67080a35fb9 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -957,13 +957,14 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
bounds on the difference FINAL - IV->base. */
static bool
-number_of_iterations_ne (tree type, affine_iv *iv, tree final,
- struct tree_niter_desc *niter, bool exit_must_be_taken,
- bounds *bnds)
+number_of_iterations_ne (struct loop *loop, tree type, affine_iv *iv,
+ tree final, struct tree_niter_desc *niter,
+ bool exit_must_be_taken, bounds *bnds)
{
tree niter_type = unsigned_type_for (type);
tree s, c, d, bits, assumption, tmp, bound;
mpz_t max;
+ tree e;
niter->control = *iv;
niter->bound = final;
@@ -998,6 +999,23 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
TYPE_SIGN (niter_type));
mpz_clear (max);
+ /* Compute no-overflow information for the control iv. Note we are
+ handling NE_EXPR, if iv base equals to final value, the loop exits
+ immediately, and the iv does not overflow. */
+ if (tree_int_cst_sign_bit (iv->step))
+ e = fold_build2 (GE_EXPR, boolean_type_node, iv->base, final);
+ else
+ e = fold_build2 (LE_EXPR, boolean_type_node, iv->base, final);
+ e = simplify_using_initial_conditions (loop, e);
+ if (integer_onep (e)
+ && (integer_onep (s)
+ || (TREE_CODE (c) == INTEGER_CST
+ && TREE_CODE (s) == INTEGER_CST
+ && wi::mod_trunc (c, s, TYPE_SIGN (type)) == 0)))
+ {
+ niter->control.no_overflow = true;
+ }
+
/* First the trivial cases -- when the step is 1. */
if (integer_onep (s))
{
@@ -1361,8 +1379,8 @@ assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1,
that the exit must be taken eventually. */
static bool
-number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
- struct tree_niter_desc *niter,
+number_of_iterations_lt (struct loop *loop, tree type, affine_iv *iv0,
+ affine_iv *iv1, struct tree_niter_desc *niter,
bool exit_must_be_taken, bounds *bnds)
{
tree niter_type = unsigned_type_for (type);
@@ -1434,7 +1452,8 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
zps does not overflow. */
zps.no_overflow = true;
- return number_of_iterations_ne (type, &zps, delta, niter, true, bnds);
+ return number_of_iterations_ne (loop, type, &zps,
+ delta, niter, true, bnds);
}
/* Make sure that the control iv does not overflow. */
@@ -1473,9 +1492,9 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
is the case). BNDS bounds the difference IV1->base - IV0->base. */
static bool
-number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
- struct tree_niter_desc *niter, bool exit_must_be_taken,
- bounds *bnds)
+number_of_iterations_le (struct loop *loop, tree type, affine_iv *iv0,
+ affine_iv *iv1, struct tree_niter_desc *niter,
+ bool exit_must_be_taken, bounds *bnds)
{
tree assumption;
tree type1 = type;
@@ -1523,7 +1542,7 @@ number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
bounds_add (bnds, 1, type1);
- return number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
+ return number_of_iterations_lt (loop, type, iv0, iv1, niter, exit_must_be_taken,
bnds);
}
@@ -1698,18 +1717,18 @@ number_of_iterations_cond (struct loop *loop,
{
case NE_EXPR:
gcc_assert (integer_zerop (iv1->step));
- ret = number_of_iterations_ne (type, iv0, iv1->base, niter,
+ ret = number_of_iterations_ne (loop, type, iv0, iv1->base, niter,
exit_must_be_taken, &bnds);
break;
case LT_EXPR:
- ret = number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
- &bnds);
+ ret = number_of_iterations_lt (loop, type, iv0, iv1, niter,
+ exit_must_be_taken, &bnds);
break;
case LE_EXPR:
- ret = number_of_iterations_le (type, iv0, iv1, niter, exit_must_be_taken,
- &bnds);
+ ret = number_of_iterations_le (loop, type, iv0, iv1, niter,
+ exit_must_be_taken, &bnds);
break;
default: