Commit 7f17528a by Zdenek Dvorak Committed by Zdenek Dvorak

tree-ssa-loop-niter.c (number_of_iterations_cond): Split into several functions.

	* tree-ssa-loop-niter.c (number_of_iterations_cond): Split into several
	functions.
	(number_of_iterations_ne, number_of_iterations_lt_to_ne,
	assert_no_overflow_lt, assert_loop_rolls_lt, number_of_iterations_lt,
	number_of_iterations_le): New functions.
	(number_of_iterations_special): Removed.
	(number_of_iterations_exit): Do not use number_of_iterations_special.
	* tree.c (unsigned_type_for): Always return integer type.

	* gcc.dg/tree-ssa/pr19210-1.c: Update outcome.  Add new test loop.
	* gcc.dg/tree-ssa/pr19210-2.c: Ditto.

From-SVN: r109702
parent 26fb114d
2006-01-14 Zdenek Dvorak <dvorakz@suse.cz>
* tree-ssa-loop-niter.c (number_of_iterations_cond): Split into several
functions.
(number_of_iterations_ne, number_of_iterations_lt_to_ne,
assert_no_overflow_lt, assert_loop_rolls_lt, number_of_iterations_lt,
number_of_iterations_le): New functions.
(number_of_iterations_special): Removed.
(number_of_iterations_exit): Do not use number_of_iterations_special.
* tree.c (unsigned_type_for): Always return integer type.
2006-01-14 Steven Bosscher <stevenb.gcc@gmail.com> 2006-01-14 Steven Bosscher <stevenb.gcc@gmail.com>
Richard Guenther <rguenther@suse.de> Richard Guenther <rguenther@suse.de>
......
2005-01-14 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/pr19210-1.c: Update outcome. Add new test loop.
* gcc.dg/tree-ssa/pr19210-2.c: Ditto.
2006-01-14 Steven Bosscher <stevenb.gcc@gmail.com> 2006-01-14 Steven Bosscher <stevenb.gcc@gmail.com>
Richard Guenther <rguenther@suse.de> Richard Guenther <rguenther@suse.de>
...@@ -12,9 +12,18 @@ f (unsigned n) ...@@ -12,9 +12,18 @@ f (unsigned n)
for(k = 0;k <= n;k += 4) /* { dg-warning "cannot optimize.*overflow" } */ for(k = 0;k <= n;k += 4) /* { dg-warning "cannot optimize.*overflow" } */
g(); g();
for(k = 5;k <= n;k += 5) /* { dg-warning "cannot optimize.*overflow" } */ /* We used to get warning for this loop. However, since then # of iterations
analysis improved, and we can now prove that this loop does not verflow.
This is because the only case when it would overflow is if n = ~0 (since
~0 is divisible by 5), and this cannot be the case, since when we got
here, the previous loop exited, thus there exists k > n. */
for(k = 5;k <= n;k += 5)
g(); g();
/* So we need the following loop, instead. */
for(k = 4;k <= n;k += 5) /* { dg-warning "cannot optimize.*overflow" } */
g();
for(k = 15;k >= n;k--) /* { dg-warning "cannot optimize.*infinite" } */ for(k = 15;k >= n;k--) /* { dg-warning "cannot optimize.*infinite" } */
g(); g();
} }
...@@ -12,7 +12,15 @@ f (unsigned n) ...@@ -12,7 +12,15 @@ f (unsigned n)
for(k = 5;k <= n;k += 4) /* { dg-warning "assuming.*not overflow" } */ for(k = 5;k <= n;k += 4) /* { dg-warning "assuming.*not overflow" } */
g(); g();
for(k = 5;k <= n;k += 5) /* { dg-warning "assuming.*not overflow" } */ /* We used to get warning for this loop. However, since then # of iterations
analysis improved, and we can now prove that this loop does not verflow.
This is because the only case when it would overflow is if n = ~0 (since
~0 is divisible by 5), and this cannot be the case, since when we got
here, the previous loop exited, thus there exists k > n. */
for(k = 5;k <= n;k += 5)
g();
for(k = 4;k <= n;k += 5) /* { dg-warning "assuming.*not overflow" } */
g(); g();
for(k = 15;k >= n;k--) /* { dg-warning "assuming.*not infinite" } */ for(k = 15;k >= n;k--) /* { dg-warning "assuming.*not infinite" } */
......
...@@ -126,490 +126,504 @@ inverse (tree x, tree mask) ...@@ -126,490 +126,504 @@ inverse (tree x, tree mask)
return rslt; return rslt;
} }
/* Determine the number of iterations according to condition (for staying /* Determines number of iterations of loop whose ending condition
inside loop) which compares two induction variables using comparison is IV <> FINAL. TYPE is the type of the iv. The number of
operator CODE. The induction variable on left side of the comparison iterations is stored to NITER. NEVER_INFINITE is true if
is IV0, the right-hand side is IV1. Both induction variables must have we know that the loop cannot be infinite (we derived this
type TYPE, which must be an integer or pointer type. The steps of the earlier, and possibly set NITER->assumptions to make sure this
ivs must be constants (or NULL_TREE, which is interpreted as constant zero). is the case. */
The results (number of iterations and assumptions as described in
comments at struct tree_niter_desc in tree-flow.h) are stored to NITER.
In case we are unable to determine number of iterations, contents of
this structure is unchanged. */
static void static bool
number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code, number_of_iterations_ne (tree type, affine_iv *iv, tree final,
affine_iv *iv1, struct tree_niter_desc *niter) struct tree_niter_desc *niter, bool never_infinite)
{ {
tree step, delta, mmin, mmax; tree niter_type = unsigned_type_for (type);
tree may_xform, bound, s, d, tmp; tree s, c, d, bits, assumption, tmp, bound;
bool was_sharp = false, never_infinite;
tree assumption;
tree assumptions = boolean_true_node;
tree noloop_assumptions = boolean_false_node;
tree niter_type, signed_niter_type;
tree bits;
/* The meaning of these assumptions is this: /* Rearrange the terms so that we get inequality s * i <> c, with s
if !assumptions positive. Also cast everything to the unsigned type. */
then the rest of information does not have to be valid if (tree_int_cst_sign_bit (iv->step))
if noloop_assumptions then the loop does not have to roll
(but it is only conservative approximation, i.e. it only says that
if !noloop_assumptions, then the loop does not end before the computed
number of iterations) */
/* Make < comparison from > ones. */
if (code == GE_EXPR
|| code == GT_EXPR)
{ {
SWAP (iv0, iv1); s = fold_convert (niter_type,
code = swap_tree_comparison (code); fold_build1 (NEGATE_EXPR, type, iv->step));
c = fold_build2 (MINUS_EXPR, niter_type,
fold_convert (niter_type, iv->base),
fold_convert (niter_type, final));
} }
/* If the control induction variable does not overflow, the loop obviously
cannot be infinite. */
if (!zero_p (iv0->step) && iv0->no_overflow)
never_infinite = true;
else if (!zero_p (iv1->step) && iv1->no_overflow)
never_infinite = true;
else else
never_infinite = false;
/* We can handle the case when neither of the sides of the comparison is
invariant, provided that the test is NE_EXPR. This rarely occurs in
practice, but it is simple enough to manage. */
if (!zero_p (iv0->step) && !zero_p (iv1->step))
{ {
if (code != NE_EXPR) s = fold_convert (niter_type, iv->step);
return; c = fold_build2 (MINUS_EXPR, niter_type,
fold_convert (niter_type, final),
fold_convert (niter_type, iv->base));
}
iv0->step = fold_binary_to_constant (MINUS_EXPR, type, /* First the trivial cases -- when the step is 1. */
iv0->step, iv1->step); if (integer_onep (s))
iv0->no_overflow = false; {
iv1->step = NULL_TREE; niter->niter = c;
iv1->no_overflow = true; return true;
} }
/* If the result is a constant, the loop is weird. More precise handling /* Let nsd (step, size of mode) = d. If d does not divide c, the loop
would be possible, but the situation is not common enough to waste time is infinite. Otherwise, the number of iterations is
on it. */ (inverse(s/d) * (c/d)) mod (size of mode/d). */
if (zero_p (iv0->step) && zero_p (iv1->step)) bits = num_ending_zeros (s);
return; bound = build_low_bits_mask (niter_type,
(TYPE_PRECISION (niter_type)
- tree_low_cst (bits, 1)));
/* Ignore loops of while (i-- < 10) type. */ d = fold_binary_to_constant (LSHIFT_EXPR, niter_type,
if (code != NE_EXPR) build_int_cst_type (niter_type, 1), bits);
{ s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, s, bits);
if (iv0->step && tree_int_cst_sign_bit (iv0->step))
return;
if (!zero_p (iv1->step) && !tree_int_cst_sign_bit (iv1->step)) if (!never_infinite)
return; {
/* If we cannot assume that the loop is not infinite, record the
assumptions for divisibility of c. */
assumption = fold_build2 (FLOOR_MOD_EXPR, niter_type, c, d);
assumption = fold_build2 (EQ_EXPR, boolean_type_node,
assumption, build_int_cst (niter_type, 0));
if (!nonzero_p (assumption))
niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
niter->assumptions, assumption);
} }
c = fold_build2 (EXACT_DIV_EXPR, niter_type, c, d);
tmp = fold_build2 (MULT_EXPR, niter_type, c, inverse (s, bound));
niter->niter = fold_build2 (BIT_AND_EXPR, niter_type, tmp, bound);
return true;
}
if (POINTER_TYPE_P (type)) /* Checks whether we can determine the final value of the control variable
of the loop with ending condition IV0 < IV1 (computed in TYPE).
DELTA is the difference IV1->base - IV0->base, STEP is the absolute value
of the step. The assumptions necessary to ensure that the computation
of the final value does not overflow are recorded in NITER. If we
find the final value, we adjust DELTA and return TRUE. Otherwise
we return false. */
static bool
number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
struct tree_niter_desc *niter,
tree *delta, tree step)
{
tree niter_type = TREE_TYPE (step);
tree mod = fold_build2 (FLOOR_MOD_EXPR, niter_type, *delta, step);
tree tmod;
tree assumption = boolean_true_node, bound, noloop;
if (TREE_CODE (mod) != INTEGER_CST)
return false;
if (nonzero_p (mod))
mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
tmod = fold_convert (type, mod);
if (nonzero_p (iv0->step))
{ {
/* We assume pointer arithmetic never overflows. */ /* The final value of the iv is iv1->base + MOD, assuming that this
mmin = mmax = NULL_TREE; computation does not overflow, and that
iv0->base <= iv1->base + MOD. */
if (!iv1->no_overflow && !zero_p (mod))
{
bound = fold_build2 (MINUS_EXPR, type,
TYPE_MAX_VALUE (type), tmod);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
if (zero_p (assumption))
return false;
}
noloop = fold_build2 (GT_EXPR, boolean_type_node,
iv0->base,
fold_build2 (PLUS_EXPR, type,
iv1->base, tmod));
} }
else else
{ {
mmin = TYPE_MIN_VALUE (type); /* The final value of the iv is iv0->base - MOD, assuming that this
mmax = TYPE_MAX_VALUE (type); computation does not overflow, and that
iv0->base - MOD <= iv1->base. */
if (!iv0->no_overflow && !zero_p (mod))
{
bound = fold_build2 (PLUS_EXPR, type,
TYPE_MIN_VALUE (type), tmod);
assumption = fold_build2 (GE_EXPR, boolean_type_node,
iv0->base, bound);
if (zero_p (assumption))
return false;
}
noloop = fold_build2 (GT_EXPR, boolean_type_node,
fold_build2 (MINUS_EXPR, type,
iv0->base, tmod),
iv1->base);
} }
/* Some more condition normalization. We must record some assumptions if (!nonzero_p (assumption))
due to overflows. */ niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
niter->assumptions,
assumption);
if (!zero_p (noloop))
niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
niter->may_be_zero,
noloop);
*delta = fold_build2 (PLUS_EXPR, niter_type, *delta, mod);
return true;
}
/* Add assertions to NITER that ensure that the control variable of the loop
with ending condition IV0 < IV1 does not overflow. Types of IV0 and IV1
are TYPE. Returns false if we can prove that there is an overflow, true
otherwise. STEP is the absolute value of the step. */
static bool
assert_no_overflow_lt (tree type, affine_iv *iv0, affine_iv *iv1,
struct tree_niter_desc *niter, tree step)
{
tree bound, d, assumption, diff;
tree niter_type = TREE_TYPE (step);
if (code == LT_EXPR) if (nonzero_p (iv0->step))
{ {
/* We want to take care only of <=; this is easy, /* for (i = iv0->base; i < iv1->base; i += iv0->step) */
as in cases the overflow would make the transformation unsafe the loop if (iv0->no_overflow)
does not roll. Seemingly it would make more sense to want to take return true;
care of <, as NE is more similar to it, but the problem is that here
the transformation would be more difficult due to possibly infinite /* If iv0->base is a constant, we can determine the last value before
loops. */ overflow precisely; otherwise we conservatively assume
if (zero_p (iv0->step)) MAX - STEP + 1. */
if (TREE_CODE (iv0->base) == INTEGER_CST)
{ {
if (mmax) d = fold_build2 (MINUS_EXPR, niter_type,
assumption = fold_build2 (EQ_EXPR, boolean_type_node, fold_convert (niter_type, TYPE_MAX_VALUE (type)),
iv0->base, mmax); fold_convert (niter_type, iv0->base));
else diff = fold_build2 (FLOOR_MOD_EXPR, niter_type, d, step);
assumption = boolean_false_node;
if (nonzero_p (assumption))
goto zero_iter;
iv0->base = fold_build2 (PLUS_EXPR, type, iv0->base,
build_int_cst_type (type, 1));
} }
else else
diff = fold_build2 (MINUS_EXPR, niter_type, step,
build_int_cst_type (niter_type, 1));
bound = fold_build2 (MINUS_EXPR, type,
TYPE_MAX_VALUE (type), fold_convert (type, diff));
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
}
else
{
/* for (i = iv1->base; i > iv0->base; i += iv1->step) */
if (iv1->no_overflow)
return true;
if (TREE_CODE (iv1->base) == INTEGER_CST)
{ {
if (mmin) d = fold_build2 (MINUS_EXPR, niter_type,
assumption = fold_build2 (EQ_EXPR, boolean_type_node, fold_convert (niter_type, iv1->base),
iv1->base, mmin); fold_convert (niter_type, TYPE_MIN_VALUE (type)));
else diff = fold_build2 (FLOOR_MOD_EXPR, niter_type, d, step);
assumption = boolean_false_node;
if (nonzero_p (assumption))
goto zero_iter;
iv1->base = fold_build2 (MINUS_EXPR, type, iv1->base,
build_int_cst_type (type, 1));
} }
noloop_assumptions = assumption; else
code = LE_EXPR; diff = fold_build2 (MINUS_EXPR, niter_type, step,
build_int_cst_type (niter_type, 1));
/* It will be useful to be able to tell the difference once more in bound = fold_build2 (PLUS_EXPR, type,
<= -> != reduction. */ TYPE_MIN_VALUE (type), fold_convert (type, diff));
was_sharp = true; assumption = fold_build2 (GE_EXPR, boolean_type_node,
iv0->base, bound);
} }
/* Take care of trivially infinite loops. */ if (zero_p (assumption))
if (code != NE_EXPR) return false;
{ if (!nonzero_p (assumption))
if (zero_p (iv0->step) niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
&& mmin niter->assumptions, assumption);
&& operand_equal_p (iv0->base, mmin, 0))
return; iv0->no_overflow = true;
if (zero_p (iv1->step) iv1->no_overflow = true;
&& mmax return true;
&& operand_equal_p (iv1->base, mmax, 0)) }
return;
}
/* If we can we want to take care of NE conditions instead of size /* Add an assumption to NITER that a loop whose ending condition
comparisons, as they are much more friendly (most importantly is IV0 < IV1 rolls. TYPE is the type of the control iv. */
this takes care of special handling of loops with step 1). We can
do it if we first check that upper bound is greater or equal to static void
lower bound, their difference is constant c modulo step and that assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1,
there is not an overflow. */ struct tree_niter_desc *niter)
if (code != NE_EXPR) {
tree assumption = boolean_true_node, bound, diff;
tree mbz, mbzl, mbzr;
if (nonzero_p (iv0->step))
{ {
if (zero_p (iv0->step)) diff = fold_build2 (MINUS_EXPR, type,
step = fold_unary_to_constant (NEGATE_EXPR, type, iv1->step); iv0->step, build_int_cst_type (type, 1));
else
step = iv0->step;
delta = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
delta = fold_build2 (FLOOR_MOD_EXPR, type, delta, step);
may_xform = boolean_false_node;
if (TREE_CODE (delta) == INTEGER_CST) /* We need to know that iv0->base >= MIN + iv0->step - 1. Since
0 address never belongs to any object, we can assume this for
pointers. */
if (!POINTER_TYPE_P (type))
{ {
tmp = fold_binary_to_constant (MINUS_EXPR, type, step, bound = fold_build2 (PLUS_EXPR, type,
build_int_cst_type (type, 1)); TYPE_MIN_VALUE (type), diff);
if (was_sharp assumption = fold_build2 (GE_EXPR, boolean_type_node,
&& operand_equal_p (delta, tmp, 0)) iv0->base, bound);
{
/* A special case. We have transformed condition of type
for (i = 0; i < 4; i += 4)
into
for (i = 0; i <= 3; i += 4)
obviously if the test for overflow during that transformation
passed, we cannot overflow here. Most importantly any
loop with sharp end condition and step 1 falls into this
category, so handling this case specially is definitely
worth the troubles. */
may_xform = boolean_true_node;
}
else if (zero_p (iv0->step))
{
if (!mmin || iv1->no_overflow)
may_xform = boolean_true_node;
else
{
bound = fold_binary_to_constant (PLUS_EXPR, type,
mmin, step);
bound = fold_binary_to_constant (MINUS_EXPR, type,
bound, delta);
may_xform = fold_build2 (LE_EXPR, boolean_type_node,
bound, iv0->base);
}
}
else
{
if (!mmax || iv0->no_overflow)
may_xform = boolean_true_node;
else
{
bound = fold_binary_to_constant (MINUS_EXPR, type,
mmax, step);
bound = fold_binary_to_constant (PLUS_EXPR, type,
bound, delta);
may_xform = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
}
}
} }
if (!zero_p (may_xform)) /* And then we can compute iv0->base - diff, and compare it with
{ iv1->base. */
/* We perform the transformation always provided that it is not mbzl = fold_build2 (MINUS_EXPR, type, iv0->base, diff);
completely senseless. This is OK, as we would need this assumption mbzr = iv1->base;
to determine the number of iterations anyway. */
if (!nonzero_p (may_xform))
assumptions = may_xform;
if (zero_p (iv0->step))
{
iv0->base = fold_build2 (PLUS_EXPR, type, iv0->base, delta);
iv0->base = fold_build2 (MINUS_EXPR, type, iv0->base, step);
}
else
{
iv1->base = fold_build2 (MINUS_EXPR, type, iv1->base, delta);
iv1->base = fold_build2 (PLUS_EXPR, type, iv1->base, step);
}
assumption = fold_build2 (GT_EXPR, boolean_type_node,
iv0->base, iv1->base);
noloop_assumptions = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
noloop_assumptions, assumption);
code = NE_EXPR;
}
} }
else
/* Count the number of iterations. */
niter_type = unsigned_type_for (type);
signed_niter_type = signed_type_for (type);
if (code == NE_EXPR)
{ {
/* Everything we do here is just arithmetics modulo size of mode. This diff = fold_build2 (PLUS_EXPR, type,
makes us able to do more involved computations of number of iterations iv1->step, build_int_cst_type (type, 1));
than in other cases. First transform the condition into shape
s * i <> c, with s positive. */ if (!POINTER_TYPE_P (type))
iv1->base = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
iv0->base = NULL_TREE;
if (!zero_p (iv1->step))
iv0->step = fold_unary_to_constant (NEGATE_EXPR, type, iv1->step);
iv1->step = NULL_TREE;
if (tree_int_cst_sign_bit (fold_convert (signed_niter_type, iv0->step)))
{ {
iv0->step = fold_unary_to_constant (NEGATE_EXPR, type, iv0->step); bound = fold_build2 (PLUS_EXPR, type,
iv1->base = fold_build1 (NEGATE_EXPR, type, iv1->base); TYPE_MAX_VALUE (type), diff);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
} }
iv1->base = fold_convert (niter_type, iv1->base); mbzl = iv0->base;
iv0->step = fold_convert (niter_type, iv0->step); mbzr = fold_build2 (MINUS_EXPR, type, iv1->base, diff);
}
mbz = fold_build2 (GT_EXPR, boolean_type_node, mbzl, mbzr);
/* Let nsd (step, size of mode) = d. If d does not divide c, the loop if (!nonzero_p (assumption))
is infinite. Otherwise, the number of iterations is niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
(inverse(s/d) * (c/d)) mod (size of mode/d). */ niter->assumptions, assumption);
bits = num_ending_zeros (iv0->step); if (!zero_p (mbz))
d = fold_binary_to_constant (LSHIFT_EXPR, niter_type, niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
build_int_cst_type (niter_type, 1), bits); niter->may_be_zero, mbz);
s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, iv0->step, bits); }
bound = build_low_bits_mask (niter_type, /* Determines number of iterations of loop whose ending condition
(TYPE_PRECISION (niter_type) is IV0 < IV1. TYPE is the type of the iv. The number of
- tree_low_cst (bits, 1))); iterations is stored to NITER. */
if (!never_infinite) static bool
{ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
/* If we cannot assume that the loop is not infinite, record the struct tree_niter_desc *niter,
assumptions for divisibility of c. */ bool never_infinite ATTRIBUTE_UNUSED)
assumption = fold_build2 (FLOOR_MOD_EXPR, niter_type, iv1->base, d); {
assumption = fold_build2 (EQ_EXPR, boolean_type_node, tree niter_type = unsigned_type_for (type);
assumption, tree delta, step, s;
build_int_cst (niter_type, 0));
assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, delta = fold_build2 (MINUS_EXPR, niter_type,
assumptions, assumption); fold_convert (niter_type, iv1->base),
} fold_convert (niter_type, iv0->base));
/* First handle the special case that the step is +-1. */
if ((iv0->step && integer_onep (iv0->step)
&& zero_p (iv1->step))
|| (iv1->step && integer_all_onesp (iv1->step)
&& zero_p (iv0->step)))
{
/* for (i = iv0->base; i < iv1->base; i++)
or
tmp = fold_build2 (EXACT_DIV_EXPR, niter_type, iv1->base, d); for (i = iv1->base; i > iv0->base; i--).
tmp = fold_build2 (MULT_EXPR, niter_type, tmp, inverse (s, bound));
niter->niter = fold_build2 (BIT_AND_EXPR, niter_type, tmp, bound); In both cases # of iterations is iv1->base - iv0->base, assuming that
iv1->base >= iv0->base. */
niter->may_be_zero = fold_build2 (LT_EXPR, boolean_type_node,
iv1->base, iv0->base);
niter->niter = delta;
return true;
} }
if (nonzero_p (iv0->step))
step = fold_convert (niter_type, iv0->step);
else else
step = fold_convert (niter_type,
fold_build1 (NEGATE_EXPR, type, iv1->step));
/* If we can determine the final value of the control iv exactly, we can
transform the condition to != comparison. In particular, this will be
the case if DELTA is constant. */
if (number_of_iterations_lt_to_ne (type, iv0, iv1, niter, &delta, step))
{ {
if (zero_p (iv1->step)) affine_iv zps;
/* Condition in shape a + s * i <= b
We must know that b + s does not overflow and a <= b + s and then we
can compute number of iterations as (b + s - a) / s. (It might
seem that we in fact could be more clever about testing the b + s
overflow condition using some information about b - a mod s,
but it was already taken into account during LE -> NE transform). */
{
if (mmax && !iv0->no_overflow)
{
bound = fold_binary_to_constant (MINUS_EXPR, type,
mmax, iv0->step);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
assumptions, assumption);
}
step = iv0->step; zps.base = build_int_cst_type (niter_type, 0);
tmp = fold_build2 (PLUS_EXPR, type, iv1->base, iv0->step); zps.step = step;
assumption = fold_build2 (GT_EXPR, boolean_type_node, /* number_of_iterations_lt_to_ne will add assumptions that ensure that
iv0->base, tmp); zps does not overflow. */
delta = fold_build2 (PLUS_EXPR, type, iv1->base, step); zps.no_overflow = true;
delta = fold_build2 (MINUS_EXPR, type, delta, iv0->base);
delta = fold_convert (niter_type, delta); return number_of_iterations_ne (type, &zps, delta, niter, true);
}
else
{
/* Condition in shape a <= b - s * i
We must know that a - s does not overflow and a - s <= b and then
we can again compute number of iterations as (b - (a - s)) / s. */
if (mmin && !iv1->no_overflow)
{
bound = fold_binary_to_constant (MINUS_EXPR, type,
mmin, iv1->step);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
bound, iv0->base);
assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
assumptions, assumption);
}
step = fold_build1 (NEGATE_EXPR, type, iv1->step);
tmp = fold_build2 (PLUS_EXPR, type, iv0->base, iv1->step);
assumption = fold_build2 (GT_EXPR, boolean_type_node, tmp, iv1->base);
delta = fold_build2 (MINUS_EXPR, type, iv0->base, step);
delta = fold_build2 (MINUS_EXPR, type, iv1->base, delta);
delta = fold_convert (niter_type, delta);
}
noloop_assumptions = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
noloop_assumptions, assumption);
delta = fold_build2 (FLOOR_DIV_EXPR, niter_type, delta,
fold_convert (niter_type, step));
niter->niter = delta;
} }
niter->assumptions = assumptions; /* Make sure that the control iv does not overflow. */
niter->may_be_zero = noloop_assumptions; if (!assert_no_overflow_lt (type, iv0, iv1, niter, step))
return; return false;
zero_iter: /* We determine the number of iterations as (delta + step - 1) / step. For
niter->assumptions = boolean_true_node; this to work, we must know that iv1->base >= iv0->base - step + 1,
niter->may_be_zero = boolean_true_node; otherwise the loop does not roll. */
niter->niter = build_int_cst_type (type, 0); assert_loop_rolls_lt (type, iv0, iv1, niter);
return;
s = fold_build2 (MINUS_EXPR, niter_type,
step, build_int_cst_type (niter_type, 1));
delta = fold_build2 (PLUS_EXPR, niter_type, delta, s);
niter->niter = fold_build2 (FLOOR_DIV_EXPR, niter_type, delta, step);
return true;
} }
/* Determines number of iterations of loop whose ending condition
is IV0 <= IV1. TYPE is the type of the iv. The number of
iterations is stored to NITER. NEVER_INFINITE is true if
we know that the loop cannot be infinite (we derived this
earlier, and possibly set NITER->assumptions to make sure this
is the case. */
static bool
number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
struct tree_niter_desc *niter, bool never_infinite)
{
tree assumption;
/* Similar to number_of_iterations_cond, but only handles the special /* Say that IV0 is the control variable. Then IV0 <= IV1 iff
case of loops with step 1 or -1. The meaning of the arguments IV0 < IV1 + 1, assuming that IV1 is not equal to the greatest
is the same as in number_of_iterations_cond. The function value of the type. This we must know anyway, since if it is
returns true if the special case was recognized, false otherwise. */ equal to this value, the loop rolls forever. */
if (!never_infinite)
{
if (nonzero_p (iv0->step))
assumption = fold_build2 (NE_EXPR, boolean_type_node,
iv1->base, TYPE_MAX_VALUE (type));
else
assumption = fold_build2 (NE_EXPR, boolean_type_node,
iv0->base, TYPE_MIN_VALUE (type));
if (zero_p (assumption))
return false;
if (!nonzero_p (assumption))
niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
niter->assumptions, assumption);
}
if (nonzero_p (iv0->step))
iv1->base = fold_build2 (PLUS_EXPR, type,
iv1->base, build_int_cst_type (type, 1));
else
iv0->base = fold_build2 (MINUS_EXPR, type,
iv0->base, build_int_cst_type (type, 1));
return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite);
}
/* Determine the number of iterations according to condition (for staying
inside loop) which compares two induction variables using comparison
operator CODE. The induction variable on left side of the comparison
is IV0, the right-hand side is IV1. Both induction variables must have
type TYPE, which must be an integer or pointer type. The steps of the
ivs must be constants (or NULL_TREE, which is interpreted as constant zero).
The results (number of iterations and assumptions as described in
comments at struct tree_niter_desc in tree-flow.h) are stored to NITER.
Returns false if it fails to determine number of iterations, true if it
was determined (possibly with some assumptions). */
static bool static bool
number_of_iterations_special (tree type, affine_iv *iv0, enum tree_code code, number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code,
affine_iv *iv1, struct tree_niter_desc *niter) affine_iv *iv1, struct tree_niter_desc *niter)
{ {
tree niter_type = unsigned_type_for (type), mmax, mmin; bool never_infinite;
/* The meaning of these assumptions is this:
if !assumptions
then the rest of information does not have to be valid
if may_be_zero then the loop does not roll, even if
niter != 0. */
niter->assumptions = boolean_true_node;
niter->may_be_zero = boolean_false_node;
niter->niter = NULL_TREE;
niter->additional_info = boolean_true_node;
/* Make < comparison from > ones. */ /* Make < comparison from > ones, and for NE_EXPR comparisons, ensure that
if (code == GE_EXPR the control variable is on lhs. */
|| code == GT_EXPR) if (code == GE_EXPR || code == GT_EXPR
|| (code == NE_EXPR && zero_p (iv0->step)))
{ {
SWAP (iv0, iv1); SWAP (iv0, iv1);
code = swap_tree_comparison (code); code = swap_tree_comparison (code);
} }
switch (code) if (POINTER_TYPE_P (type))
{ {
case NE_EXPR: /* Comparison of pointers is undefined unless both iv0 and iv1 point
if (zero_p (iv0->step)) to the same object. If they do, the control variable cannot wrap
{ (as wrap around the bounds of memory will never return a pointer
if (zero_p (iv1->step)) that would be guaranteed to point to the same object, even if we
return false; avoid undefined behavior by casting to size_t and back). */
SWAP (iv0, iv1); iv0->no_overflow = true;
} iv1->no_overflow = true;
else if (!zero_p (iv1->step)) }
return false;
if (integer_onep (iv0->step)) /* If the control induction variable does not overflow, the loop obviously
{ cannot be infinite. */
/* for (i = iv0->base; i != iv1->base; i++) */ if (!zero_p (iv0->step) && iv0->no_overflow)
niter->assumptions = boolean_true_node; never_infinite = true;
niter->may_be_zero = boolean_false_node; else if (!zero_p (iv1->step) && iv1->no_overflow)
niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base); never_infinite = true;
niter->additional_info = boolean_true_node; else
} never_infinite = false;
else if (integer_all_onesp (iv0->step))
{
/* for (i = iv0->base; i != iv1->base; i--) */
niter->assumptions = boolean_true_node;
niter->may_be_zero = boolean_false_node;
niter->niter = fold_build2 (MINUS_EXPR, type, iv0->base, iv1->base);
}
else
return false;
break; /* We can handle the case when neither of the sides of the comparison is
invariant, provided that the test is NE_EXPR. This rarely occurs in
practice, but it is simple enough to manage. */
if (!zero_p (iv0->step) && !zero_p (iv1->step))
{
if (code != NE_EXPR)
return false;
case LT_EXPR: iv0->step = fold_binary_to_constant (MINUS_EXPR, type,
if ((iv0->step && integer_onep (iv0->step) iv0->step, iv1->step);
&& zero_p (iv1->step)) iv0->no_overflow = false;
|| (iv1->step && integer_all_onesp (iv1->step) iv1->step = NULL_TREE;
&& zero_p (iv0->step))) iv1->no_overflow = true;
{ }
/* for (i = iv0->base; i < iv1->base; i++)
or
for (i = iv1->base; i > iv0->base; i--). /* If the result of the comparison is a constant, the loop is weird. More
precise handling would be possible, but the situation is not common enough
In both cases # of iterations is iv1->base - iv0->base. */ to waste time on it. */
if (zero_p (iv0->step) && zero_p (iv1->step))
return false;
niter->assumptions = boolean_true_node; /* Ignore loops of while (i-- < 10) type. */
niter->may_be_zero = fold_build2 (GT_EXPR, boolean_type_node, if (code != NE_EXPR)
iv0->base, iv1->base); {
niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base); if (iv0->step && tree_int_cst_sign_bit (iv0->step))
}
else
return false; return false;
break;
case LE_EXPR: if (!zero_p (iv1->step) && !tree_int_cst_sign_bit (iv1->step))
if (POINTER_TYPE_P (type))
{
/* We assume pointer arithmetic never overflows. */
mmin = mmax = NULL_TREE;
}
else
{
mmin = TYPE_MIN_VALUE (type);
mmax = TYPE_MAX_VALUE (type);
}
if (iv0->step && integer_onep (iv0->step)
&& zero_p (iv1->step))
{
/* for (i = iv0->base; i <= iv1->base; i++) */
if (mmax && !iv0->no_overflow)
niter->assumptions = fold_build2 (NE_EXPR, boolean_type_node,
iv1->base, mmax);
else
niter->assumptions = boolean_true_node;
iv1->base = fold_build2 (PLUS_EXPR, type, iv1->base,
build_int_cst_type (type, 1));
}
else if (iv1->step && integer_all_onesp (iv1->step)
&& zero_p (iv0->step))
{
/* for (i = iv1->base; i >= iv0->base; i--) */
if (mmin && !iv1->no_overflow)
niter->assumptions = fold_build2 (NE_EXPR, boolean_type_node,
iv0->base, mmin);
else
niter->assumptions = boolean_true_node;
iv0->base = fold_build2 (MINUS_EXPR, type, iv0->base,
build_int_cst_type (type, 1));
}
else
return false; return false;
}
niter->may_be_zero = fold_build2 (GT_EXPR, boolean_type_node, /* If the loop exits immediatelly, there is nothing to do. */
iv0->base, iv1->base); if (zero_p (fold_build2 (code, boolean_type_node, iv0->base, iv1->base)))
niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base); {
break; niter->niter = build_int_cst_type (unsigned_type_for (type), 0);
return true;
}
/* OK, now we know we have a senseful loop. Handle several cases, depending
on what comparison operator is used. */
switch (code)
{
case NE_EXPR:
gcc_assert (zero_p (iv1->step));
return number_of_iterations_ne (type, iv0, iv1->base, niter, never_infinite);
case LT_EXPR:
return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite);
case LE_EXPR:
return number_of_iterations_le (type, iv0, iv1, niter, never_infinite);
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
niter->niter = fold_convert (niter_type, niter->niter);
niter->additional_info = boolean_true_node;
return true;
} }
/* Substitute NEW for OLD in EXPR and fold the result. */ /* Substitute NEW for OLD in EXPR and fold the result. */
...@@ -987,18 +1001,10 @@ number_of_iterations_exit (struct loop *loop, edge exit, ...@@ -987,18 +1001,10 @@ number_of_iterations_exit (struct loop *loop, edge exit,
if (!simple_iv (loop, stmt, op1, &iv1, false)) if (!simple_iv (loop, stmt, op1, &iv1, false))
return false; return false;
niter->niter = NULL_TREE; iv0.base = expand_simple_operations (iv0.base);
iv1.base = expand_simple_operations (iv1.base);
/* Handle common special cases first, so that we do not need to use if (!number_of_iterations_cond (type, &iv0, code, &iv1, niter))
generic (and slow) analysis very often. */ return false;
if (!number_of_iterations_special (type, &iv0, code, &iv1, niter))
{
number_of_iterations_cond (type, &iv0, code, &iv1, niter);
if (!niter->niter)
return false;
}
if (optimize >= 3) if (optimize >= 3)
{ {
......
...@@ -6809,6 +6809,8 @@ tree_fold_gcd (tree a, tree b) ...@@ -6809,6 +6809,8 @@ tree_fold_gcd (tree a, tree b)
tree tree
unsigned_type_for (tree type) unsigned_type_for (tree type)
{ {
if (POINTER_TYPE_P (type))
return size_type_node;
return lang_hooks.types.unsigned_type (type); return lang_hooks.types.unsigned_type (type);
} }
......
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