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
This commit is contained in:
parent
26fb114d13
commit
7f17528ab5
@ -1,3 +1,14 @@
|
||||
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>
|
||||
Richard Guenther <rguenther@suse.de>
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
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>
|
||||
Richard Guenther <rguenther@suse.de>
|
||||
|
||||
|
@ -12,9 +12,18 @@ f (unsigned n)
|
||||
for(k = 0;k <= n;k += 4) /* { dg-warning "cannot optimize.*overflow" } */
|
||||
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();
|
||||
|
||||
/* 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" } */
|
||||
g();
|
||||
}
|
||||
|
@ -12,7 +12,15 @@ f (unsigned n)
|
||||
for(k = 5;k <= n;k += 4) /* { dg-warning "assuming.*not overflow" } */
|
||||
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();
|
||||
|
||||
for(k = 15;k >= n;k--) /* { dg-warning "assuming.*not infinite" } */
|
||||
|
@ -126,6 +126,395 @@ inverse (tree x, tree mask)
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/* Determines number of iterations of loop whose ending condition
|
||||
is IV <> FINAL. 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_ne (tree type, affine_iv *iv, tree final,
|
||||
struct tree_niter_desc *niter, bool never_infinite)
|
||||
{
|
||||
tree niter_type = unsigned_type_for (type);
|
||||
tree s, c, d, bits, assumption, tmp, bound;
|
||||
|
||||
/* Rearrange the terms so that we get inequality s * i <> c, with s
|
||||
positive. Also cast everything to the unsigned type. */
|
||||
if (tree_int_cst_sign_bit (iv->step))
|
||||
{
|
||||
s = fold_convert (niter_type,
|
||||
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));
|
||||
}
|
||||
else
|
||||
{
|
||||
s = fold_convert (niter_type, iv->step);
|
||||
c = fold_build2 (MINUS_EXPR, niter_type,
|
||||
fold_convert (niter_type, final),
|
||||
fold_convert (niter_type, iv->base));
|
||||
}
|
||||
|
||||
/* First the trivial cases -- when the step is 1. */
|
||||
if (integer_onep (s))
|
||||
{
|
||||
niter->niter = c;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Let nsd (step, size of mode) = d. If d does not divide c, the loop
|
||||
is infinite. Otherwise, the number of iterations is
|
||||
(inverse(s/d) * (c/d)) mod (size of mode/d). */
|
||||
bits = num_ending_zeros (s);
|
||||
bound = build_low_bits_mask (niter_type,
|
||||
(TYPE_PRECISION (niter_type)
|
||||
- tree_low_cst (bits, 1)));
|
||||
|
||||
d = fold_binary_to_constant (LSHIFT_EXPR, niter_type,
|
||||
build_int_cst_type (niter_type, 1), bits);
|
||||
s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, s, bits);
|
||||
|
||||
if (!never_infinite)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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))
|
||||
{
|
||||
/* The final value of the iv is iv1->base + MOD, assuming that this
|
||||
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
|
||||
{
|
||||
/* The final value of the iv is iv0->base - MOD, assuming that this
|
||||
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);
|
||||
}
|
||||
|
||||
if (!nonzero_p (assumption))
|
||||
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 (nonzero_p (iv0->step))
|
||||
{
|
||||
/* for (i = iv0->base; i < iv1->base; i += iv0->step) */
|
||||
if (iv0->no_overflow)
|
||||
return true;
|
||||
|
||||
/* If iv0->base is a constant, we can determine the last value before
|
||||
overflow precisely; otherwise we conservatively assume
|
||||
MAX - STEP + 1. */
|
||||
|
||||
if (TREE_CODE (iv0->base) == INTEGER_CST)
|
||||
{
|
||||
d = fold_build2 (MINUS_EXPR, niter_type,
|
||||
fold_convert (niter_type, TYPE_MAX_VALUE (type)),
|
||||
fold_convert (niter_type, iv0->base));
|
||||
diff = fold_build2 (FLOOR_MOD_EXPR, niter_type, d, step);
|
||||
}
|
||||
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)
|
||||
{
|
||||
d = fold_build2 (MINUS_EXPR, niter_type,
|
||||
fold_convert (niter_type, iv1->base),
|
||||
fold_convert (niter_type, TYPE_MIN_VALUE (type)));
|
||||
diff = fold_build2 (FLOOR_MOD_EXPR, niter_type, d, step);
|
||||
}
|
||||
else
|
||||
diff = fold_build2 (MINUS_EXPR, niter_type, step,
|
||||
build_int_cst_type (niter_type, 1));
|
||||
bound = fold_build2 (PLUS_EXPR, type,
|
||||
TYPE_MIN_VALUE (type), fold_convert (type, diff));
|
||||
assumption = fold_build2 (GE_EXPR, boolean_type_node,
|
||||
iv0->base, bound);
|
||||
}
|
||||
|
||||
if (zero_p (assumption))
|
||||
return false;
|
||||
if (!nonzero_p (assumption))
|
||||
niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
niter->assumptions, assumption);
|
||||
|
||||
iv0->no_overflow = true;
|
||||
iv1->no_overflow = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Add an assumption to NITER that a loop whose ending condition
|
||||
is IV0 < IV1 rolls. TYPE is the type of the control iv. */
|
||||
|
||||
static void
|
||||
assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1,
|
||||
struct tree_niter_desc *niter)
|
||||
{
|
||||
tree assumption = boolean_true_node, bound, diff;
|
||||
tree mbz, mbzl, mbzr;
|
||||
|
||||
if (nonzero_p (iv0->step))
|
||||
{
|
||||
diff = fold_build2 (MINUS_EXPR, type,
|
||||
iv0->step, build_int_cst_type (type, 1));
|
||||
|
||||
/* 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))
|
||||
{
|
||||
bound = fold_build2 (PLUS_EXPR, type,
|
||||
TYPE_MIN_VALUE (type), diff);
|
||||
assumption = fold_build2 (GE_EXPR, boolean_type_node,
|
||||
iv0->base, bound);
|
||||
}
|
||||
|
||||
/* And then we can compute iv0->base - diff, and compare it with
|
||||
iv1->base. */
|
||||
mbzl = fold_build2 (MINUS_EXPR, type, iv0->base, diff);
|
||||
mbzr = iv1->base;
|
||||
}
|
||||
else
|
||||
{
|
||||
diff = fold_build2 (PLUS_EXPR, type,
|
||||
iv1->step, build_int_cst_type (type, 1));
|
||||
|
||||
if (!POINTER_TYPE_P (type))
|
||||
{
|
||||
bound = fold_build2 (PLUS_EXPR, type,
|
||||
TYPE_MAX_VALUE (type), diff);
|
||||
assumption = fold_build2 (LE_EXPR, boolean_type_node,
|
||||
iv1->base, bound);
|
||||
}
|
||||
|
||||
mbzl = iv0->base;
|
||||
mbzr = fold_build2 (MINUS_EXPR, type, iv1->base, diff);
|
||||
}
|
||||
|
||||
mbz = fold_build2 (GT_EXPR, boolean_type_node, mbzl, mbzr);
|
||||
|
||||
if (!nonzero_p (assumption))
|
||||
niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
niter->assumptions, assumption);
|
||||
if (!zero_p (mbz))
|
||||
niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
|
||||
niter->may_be_zero, mbz);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
static bool
|
||||
number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
|
||||
struct tree_niter_desc *niter,
|
||||
bool never_infinite ATTRIBUTE_UNUSED)
|
||||
{
|
||||
tree niter_type = unsigned_type_for (type);
|
||||
tree delta, step, s;
|
||||
|
||||
delta = fold_build2 (MINUS_EXPR, niter_type,
|
||||
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
|
||||
|
||||
for (i = iv1->base; i > iv0->base; i--).
|
||||
|
||||
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
|
||||
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))
|
||||
{
|
||||
affine_iv zps;
|
||||
|
||||
zps.base = build_int_cst_type (niter_type, 0);
|
||||
zps.step = step;
|
||||
/* number_of_iterations_lt_to_ne will add assumptions that ensure that
|
||||
zps does not overflow. */
|
||||
zps.no_overflow = true;
|
||||
|
||||
return number_of_iterations_ne (type, &zps, delta, niter, true);
|
||||
}
|
||||
|
||||
/* Make sure that the control iv does not overflow. */
|
||||
if (!assert_no_overflow_lt (type, iv0, iv1, niter, step))
|
||||
return false;
|
||||
|
||||
/* We determine the number of iterations as (delta + step - 1) / step. For
|
||||
this to work, we must know that iv1->base >= iv0->base - step + 1,
|
||||
otherwise the loop does not roll. */
|
||||
assert_loop_rolls_lt (type, iv0, iv1, niter);
|
||||
|
||||
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;
|
||||
|
||||
/* Say that IV0 is the control variable. Then IV0 <= IV1 iff
|
||||
IV0 < IV1 + 1, assuming that IV1 is not equal to the greatest
|
||||
value of the type. This we must know anyway, since if it is
|
||||
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
|
||||
@ -135,38 +524,45 @@ inverse (tree x, tree mask)
|
||||
|
||||
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. */
|
||||
Returns false if it fails to determine number of iterations, true if it
|
||||
was determined (possibly with some assumptions). */
|
||||
|
||||
static void
|
||||
static bool
|
||||
number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code,
|
||||
affine_iv *iv1, struct tree_niter_desc *niter)
|
||||
{
|
||||
tree step, delta, mmin, mmax;
|
||||
tree may_xform, bound, s, d, tmp;
|
||||
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;
|
||||
bool never_infinite;
|
||||
|
||||
/* The meaning of these assumptions is this:
|
||||
if !assumptions
|
||||
then the rest of information does not have to be valid
|
||||
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) */
|
||||
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. */
|
||||
if (code == GE_EXPR
|
||||
|| code == GT_EXPR)
|
||||
/* Make < comparison from > ones, and for NE_EXPR comparisons, ensure that
|
||||
the control variable is on lhs. */
|
||||
if (code == GE_EXPR || code == GT_EXPR
|
||||
|| (code == NE_EXPR && zero_p (iv0->step)))
|
||||
{
|
||||
SWAP (iv0, iv1);
|
||||
code = swap_tree_comparison (code);
|
||||
}
|
||||
|
||||
if (POINTER_TYPE_P (type))
|
||||
{
|
||||
/* Comparison of pointers is undefined unless both iv0 and iv1 point
|
||||
to the same object. If they do, the control variable cannot wrap
|
||||
(as wrap around the bounds of memory will never return a pointer
|
||||
that would be guaranteed to point to the same object, even if we
|
||||
avoid undefined behavior by casting to size_t and back). */
|
||||
iv0->no_overflow = true;
|
||||
iv1->no_overflow = true;
|
||||
}
|
||||
|
||||
/* If the control induction variable does not overflow, the loop obviously
|
||||
cannot be infinite. */
|
||||
if (!zero_p (iv0->step) && iv0->no_overflow)
|
||||
@ -182,7 +578,7 @@ number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code,
|
||||
if (!zero_p (iv0->step) && !zero_p (iv1->step))
|
||||
{
|
||||
if (code != NE_EXPR)
|
||||
return;
|
||||
return false;
|
||||
|
||||
iv0->step = fold_binary_to_constant (MINUS_EXPR, type,
|
||||
iv0->step, iv1->step);
|
||||
@ -191,425 +587,43 @@ number_of_iterations_cond (tree type, affine_iv *iv0, enum tree_code code,
|
||||
iv1->no_overflow = true;
|
||||
}
|
||||
|
||||
/* If the result is a constant, the loop is weird. More precise handling
|
||||
would be possible, but the situation is not common enough to waste time
|
||||
on it. */
|
||||
/* 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
|
||||
to waste time on it. */
|
||||
if (zero_p (iv0->step) && zero_p (iv1->step))
|
||||
return;
|
||||
return false;
|
||||
|
||||
/* Ignore loops of while (i-- < 10) type. */
|
||||
if (code != NE_EXPR)
|
||||
{
|
||||
if (iv0->step && tree_int_cst_sign_bit (iv0->step))
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (!zero_p (iv1->step) && !tree_int_cst_sign_bit (iv1->step))
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (POINTER_TYPE_P (type))
|
||||
/* If the loop exits immediatelly, there is nothing to do. */
|
||||
if (zero_p (fold_build2 (code, boolean_type_node, iv0->base, iv1->base)))
|
||||
{
|
||||
/* We assume pointer arithmetic never overflows. */
|
||||
mmin = mmax = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
mmin = TYPE_MIN_VALUE (type);
|
||||
mmax = TYPE_MAX_VALUE (type);
|
||||
}
|
||||
|
||||
/* Some more condition normalization. We must record some assumptions
|
||||
due to overflows. */
|
||||
|
||||
if (code == LT_EXPR)
|
||||
{
|
||||
/* We want to take care only of <=; this is easy,
|
||||
as in cases the overflow would make the transformation unsafe the loop
|
||||
does not roll. Seemingly it would make more sense to want to take
|
||||
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
|
||||
loops. */
|
||||
if (zero_p (iv0->step))
|
||||
{
|
||||
if (mmax)
|
||||
assumption = fold_build2 (EQ_EXPR, boolean_type_node,
|
||||
iv0->base, mmax);
|
||||
else
|
||||
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
|
||||
{
|
||||
if (mmin)
|
||||
assumption = fold_build2 (EQ_EXPR, boolean_type_node,
|
||||
iv1->base, mmin);
|
||||
else
|
||||
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;
|
||||
code = LE_EXPR;
|
||||
|
||||
/* It will be useful to be able to tell the difference once more in
|
||||
<= -> != reduction. */
|
||||
was_sharp = true;
|
||||
}
|
||||
|
||||
/* Take care of trivially infinite loops. */
|
||||
if (code != NE_EXPR)
|
||||
{
|
||||
if (zero_p (iv0->step)
|
||||
&& mmin
|
||||
&& operand_equal_p (iv0->base, mmin, 0))
|
||||
return;
|
||||
if (zero_p (iv1->step)
|
||||
&& mmax
|
||||
&& operand_equal_p (iv1->base, mmax, 0))
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we can we want to take care of NE conditions instead of size
|
||||
comparisons, as they are much more friendly (most importantly
|
||||
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
|
||||
lower bound, their difference is constant c modulo step and that
|
||||
there is not an overflow. */
|
||||
if (code != NE_EXPR)
|
||||
{
|
||||
if (zero_p (iv0->step))
|
||||
step = fold_unary_to_constant (NEGATE_EXPR, type, iv1->step);
|
||||
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)
|
||||
{
|
||||
tmp = fold_binary_to_constant (MINUS_EXPR, type, step,
|
||||
build_int_cst_type (type, 1));
|
||||
if (was_sharp
|
||||
&& operand_equal_p (delta, tmp, 0))
|
||||
{
|
||||
/* 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))
|
||||
{
|
||||
/* We perform the transformation always provided that it is not
|
||||
completely senseless. This is OK, as we would need this assumption
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
makes us able to do more involved computations of number of iterations
|
||||
than in other cases. First transform the condition into shape
|
||||
s * i <> c, with s positive. */
|
||||
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);
|
||||
iv1->base = fold_build1 (NEGATE_EXPR, type, iv1->base);
|
||||
}
|
||||
|
||||
iv1->base = fold_convert (niter_type, iv1->base);
|
||||
iv0->step = fold_convert (niter_type, iv0->step);
|
||||
|
||||
/* Let nsd (step, size of mode) = d. If d does not divide c, the loop
|
||||
is infinite. Otherwise, the number of iterations is
|
||||
(inverse(s/d) * (c/d)) mod (size of mode/d). */
|
||||
bits = num_ending_zeros (iv0->step);
|
||||
d = fold_binary_to_constant (LSHIFT_EXPR, niter_type,
|
||||
build_int_cst_type (niter_type, 1), bits);
|
||||
s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, iv0->step, bits);
|
||||
|
||||
bound = build_low_bits_mask (niter_type,
|
||||
(TYPE_PRECISION (niter_type)
|
||||
- tree_low_cst (bits, 1)));
|
||||
|
||||
if (!never_infinite)
|
||||
{
|
||||
/* 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, iv1->base, d);
|
||||
assumption = fold_build2 (EQ_EXPR, boolean_type_node,
|
||||
assumption,
|
||||
build_int_cst (niter_type, 0));
|
||||
assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
assumptions, assumption);
|
||||
}
|
||||
|
||||
tmp = fold_build2 (EXACT_DIV_EXPR, niter_type, iv1->base, d);
|
||||
tmp = fold_build2 (MULT_EXPR, niter_type, tmp, inverse (s, bound));
|
||||
niter->niter = fold_build2 (BIT_AND_EXPR, niter_type, tmp, bound);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (zero_p (iv1->step))
|
||||
/* 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;
|
||||
tmp = fold_build2 (PLUS_EXPR, type, iv1->base, iv0->step);
|
||||
assumption = fold_build2 (GT_EXPR, boolean_type_node,
|
||||
iv0->base, tmp);
|
||||
delta = fold_build2 (PLUS_EXPR, type, iv1->base, step);
|
||||
delta = fold_build2 (MINUS_EXPR, type, delta, iv0->base);
|
||||
delta = fold_convert (niter_type, delta);
|
||||
}
|
||||
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;
|
||||
niter->may_be_zero = noloop_assumptions;
|
||||
return;
|
||||
|
||||
zero_iter:
|
||||
niter->assumptions = boolean_true_node;
|
||||
niter->may_be_zero = boolean_true_node;
|
||||
niter->niter = build_int_cst_type (type, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Similar to number_of_iterations_cond, but only handles the special
|
||||
case of loops with step 1 or -1. The meaning of the arguments
|
||||
is the same as in number_of_iterations_cond. The function
|
||||
returns true if the special case was recognized, false otherwise. */
|
||||
|
||||
static bool
|
||||
number_of_iterations_special (tree type, affine_iv *iv0, enum tree_code code,
|
||||
affine_iv *iv1, struct tree_niter_desc *niter)
|
||||
{
|
||||
tree niter_type = unsigned_type_for (type), mmax, mmin;
|
||||
|
||||
/* Make < comparison from > ones. */
|
||||
if (code == GE_EXPR
|
||||
|| code == GT_EXPR)
|
||||
{
|
||||
SWAP (iv0, iv1);
|
||||
code = swap_tree_comparison (code);
|
||||
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:
|
||||
if (zero_p (iv0->step))
|
||||
{
|
||||
if (zero_p (iv1->step))
|
||||
return false;
|
||||
SWAP (iv0, iv1);
|
||||
}
|
||||
else if (!zero_p (iv1->step))
|
||||
return false;
|
||||
|
||||
if (integer_onep (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, iv1->base, iv0->base);
|
||||
niter->additional_info = boolean_true_node;
|
||||
}
|
||||
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;
|
||||
|
||||
gcc_assert (zero_p (iv1->step));
|
||||
return number_of_iterations_ne (type, iv0, iv1->base, niter, never_infinite);
|
||||
case LT_EXPR:
|
||||
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
|
||||
|
||||
for (i = iv1->base; i > iv0->base; i--).
|
||||
|
||||
In both cases # of iterations is iv1->base - iv0->base. */
|
||||
|
||||
niter->assumptions = boolean_true_node;
|
||||
niter->may_be_zero = fold_build2 (GT_EXPR, boolean_type_node,
|
||||
iv0->base, iv1->base);
|
||||
niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
|
||||
return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite);
|
||||
case LE_EXPR:
|
||||
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;
|
||||
|
||||
niter->may_be_zero = fold_build2 (GT_EXPR, boolean_type_node,
|
||||
iv0->base, iv1->base);
|
||||
niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
|
||||
break;
|
||||
|
||||
return number_of_iterations_le (type, iv0, iv1, niter, never_infinite);
|
||||
default:
|
||||
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. */
|
||||
@ -987,18 +1001,10 @@ number_of_iterations_exit (struct loop *loop, edge exit,
|
||||
if (!simple_iv (loop, stmt, op1, &iv1, false))
|
||||
return false;
|
||||
|
||||
niter->niter = NULL_TREE;
|
||||
|
||||
/* Handle common special cases first, so that we do not need to use
|
||||
generic (and slow) analysis very often. */
|
||||
if (!number_of_iterations_special (type, &iv0, code, &iv1, niter))
|
||||
{
|
||||
|
||||
number_of_iterations_cond (type, &iv0, code, &iv1, niter);
|
||||
|
||||
if (!niter->niter)
|
||||
return false;
|
||||
}
|
||||
iv0.base = expand_simple_operations (iv0.base);
|
||||
iv1.base = expand_simple_operations (iv1.base);
|
||||
if (!number_of_iterations_cond (type, &iv0, code, &iv1, niter))
|
||||
return false;
|
||||
|
||||
if (optimize >= 3)
|
||||
{
|
||||
|
@ -6809,6 +6809,8 @@ tree_fold_gcd (tree a, tree b)
|
||||
tree
|
||||
unsigned_type_for (tree type)
|
||||
{
|
||||
if (POINTER_TYPE_P (type))
|
||||
return size_type_node;
|
||||
return lang_hooks.types.unsigned_type (type);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user