/* Analyze scalar evolution of use of VERSION in USE_LOOP with respect to
WRTO_LOOP (which should be a superloop of both USE_LOOP and definition
- of VERSION). */
+ of VERSION).
+
+ FOLDED_CASTS is set to true if resolve_mixers used
+ chrec_convert_aggressive (TODO -- not really, we are way too conservative
+ at the moment in order to keep things simple). */
static tree
analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop,
- tree version)
+ tree version, bool *folded_casts)
{
bool val = false;
- tree ev = version;
+ tree ev = version, tmp;
+ if (folded_casts)
+ *folded_casts = false;
while (1)
{
- ev = analyze_scalar_evolution (use_loop, ev);
- ev = resolve_mixers (use_loop, ev);
+ tmp = analyze_scalar_evolution (use_loop, ev);
+ ev = resolve_mixers (use_loop, tmp);
+
+ if (folded_casts && tmp != ev)
+ *folded_casts = true;
if (use_loop == wrto_loop)
return ev;
}
/* Checks whether OP behaves as a simple affine iv of LOOP in STMT and returns
- its BASE and STEP if possible. If ALLOW_NONCONSTANT_STEP is true, we
- want STEP to be invariant in LOOP. Otherwise we require it to be an
- integer constant. */
+ its base and step in IV if possible. If ALLOW_NONCONSTANT_STEP is true, we
+ want step to be invariant in LOOP. Otherwise we require it to be an
+ integer constant. IV->no_overflow is set to true if we are sure the iv cannot
+ overflow (e.g. because it is computed in signed arithmetics). */
bool
-simple_iv (struct loop *loop, tree stmt, tree op, tree *base, tree *step,
+simple_iv (struct loop *loop, tree stmt, tree op, affine_iv *iv,
bool allow_nonconstant_step)
{
basic_block bb = bb_for_stmt (stmt);
tree type, ev;
+ bool folded_casts;
- *base = NULL_TREE;
- *step = NULL_TREE;
+ iv->base = NULL_TREE;
+ iv->step = NULL_TREE;
+ iv->no_overflow = false;
type = TREE_TYPE (op);
if (TREE_CODE (type) != INTEGER_TYPE
&& TREE_CODE (type) != POINTER_TYPE)
return false;
- ev = analyze_scalar_evolution_in_loop (loop, bb->loop_father, op);
+ ev = analyze_scalar_evolution_in_loop (loop, bb->loop_father, op,
+ &folded_casts);
if (chrec_contains_undetermined (ev))
return false;
if (tree_does_not_contain_chrecs (ev)
&& !chrec_contains_symbols_defined_in_loop (ev, loop->num))
{
- *base = ev;
+ iv->base = ev;
+ iv->no_overflow = true;
return true;
}
|| CHREC_VARIABLE (ev) != (unsigned) loop->num)
return false;
- *step = CHREC_RIGHT (ev);
+ iv->step = CHREC_RIGHT (ev);
if (allow_nonconstant_step)
{
- if (tree_contains_chrecs (*step, NULL)
- || chrec_contains_symbols_defined_in_loop (*step, loop->num))
+ if (tree_contains_chrecs (iv->step, NULL)
+ || chrec_contains_symbols_defined_in_loop (iv->step, loop->num))
return false;
}
- else if (TREE_CODE (*step) != INTEGER_CST)
+ else if (TREE_CODE (iv->step) != INTEGER_CST)
return false;
- *base = CHREC_LEFT (ev);
- if (tree_contains_chrecs (*base, NULL)
- || chrec_contains_symbols_defined_in_loop (*base, loop->num))
+ iv->base = CHREC_LEFT (ev);
+ if (tree_contains_chrecs (iv->base, NULL)
+ || chrec_contains_symbols_defined_in_loop (iv->base, loop->num))
return false;
+ iv->no_overflow = (!folded_casts
+ && !flag_wrapv
+ && !TYPE_UNSIGNED (type));
return true;
}
for (i = current_loops->num - 1; i > 0; i--)
{
edge exit;
- tree def, rslt, ass;
+ tree def, rslt, ass, niter;
block_stmt_iterator bsi;
loop = current_loops->parray[i];
/* If we do not know exact number of iterations of the loop, we cannot
replace the final value. */
exit = loop->single_exit;
- if (!exit
- || number_of_iterations_in_loop (loop) == chrec_dont_know)
+ if (!exit)
+ continue;
+
+ niter = number_of_iterations_in_loop (loop);
+ if (niter == chrec_dont_know
+ /* If computing the number of iterations is expensive, it may be
+ better not to introduce computations involving it. */
+ || expression_expensive_p (niter))
continue;
/* Ensure that it is possible to insert new statements somewhere. */
&& !INTEGRAL_TYPE_P (TREE_TYPE (def)))
continue;
- def = analyze_scalar_evolution_in_loop (ex_loop, loop, def);
+ def = analyze_scalar_evolution_in_loop (ex_loop, loop, def, NULL);
def = compute_overall_effect_of_inner_loop (ex_loop, def);
if (!tree_does_not_contain_chrecs (def)
|| chrec_contains_symbols_defined_in_loop (def, ex_loop->num))
continue;
- /* If computing the expression is expensive, let it remain in the
- loop. */
- if (expression_expensive_p (def))
- continue;
-
/* Eliminate the phi node and replace it by a computation outside
the loop. */
def = unshare_expr (def);
/* 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
- has base BASE0 and step STEP0. the right-hand side one has base
- BASE1 and step STEP1. Both induction variables must have type TYPE,
- which must be an integer or pointer type. STEP0 and STEP1 must be
- constants (or NULL_TREE, which is interpreted as constant zero).
+ 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.
this structure is unchanged. */
static void
-number_of_iterations_cond (tree type, tree base0, tree step0,
- enum tree_code code, tree base1, tree step1,
- struct tree_niter_desc *niter)
+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;
+ bool was_sharp = false, never_infinite;
tree assumption;
tree assumptions = boolean_true_node;
tree noloop_assumptions = boolean_false_node;
if (code == GE_EXPR
|| code == GT_EXPR)
{
- SWAP (base0, base1);
- SWAP (step0, step1);
+ SWAP (iv0, iv1);
code = swap_tree_comparison (code);
}
+ /* 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
+ 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 (step0) && !zero_p (step1))
+ if (!zero_p (iv0->step) && !zero_p (iv1->step))
{
if (code != NE_EXPR)
return;
- step0 = fold_binary_to_constant (MINUS_EXPR, type, step0, step1);
- step1 = NULL_TREE;
+ iv0->step = fold_binary_to_constant (MINUS_EXPR, type,
+ iv0->step, iv1->step);
+ iv0->no_overflow = false;
+ iv1->step = NULL_TREE;
+ 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 (zero_p (step0) && zero_p (step1))
+ if (zero_p (iv0->step) && zero_p (iv1->step))
return;
/* Ignore loops of while (i-- < 10) type. */
if (code != NE_EXPR)
{
- if (step0 && tree_int_cst_sign_bit (step0))
+ if (iv0->step && tree_int_cst_sign_bit (iv0->step))
return;
- if (!zero_p (step1) && !tree_int_cst_sign_bit (step1))
+ if (!zero_p (iv1->step) && !tree_int_cst_sign_bit (iv1->step))
return;
}
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 (step0))
+ if (zero_p (iv0->step))
{
if (mmax)
- assumption = fold_build2 (EQ_EXPR, boolean_type_node, base0, mmax);
+ assumption = fold_build2 (EQ_EXPR, boolean_type_node,
+ iv0->base, mmax);
else
assumption = boolean_false_node;
if (nonzero_p (assumption))
goto zero_iter;
- base0 = fold_build2 (PLUS_EXPR, type, base0,
- build_int_cst_type (type, 1));
+ 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, base1, mmin);
+ assumption = fold_build2 (EQ_EXPR, boolean_type_node,
+ iv1->base, mmin);
else
assumption = boolean_false_node;
if (nonzero_p (assumption))
goto zero_iter;
- base1 = fold_build2 (MINUS_EXPR, type, base1,
- build_int_cst_type (type, 1));
+ iv1->base = fold_build2 (MINUS_EXPR, type, iv1->base,
+ build_int_cst_type (type, 1));
}
noloop_assumptions = assumption;
code = LE_EXPR;
/* Take care of trivially infinite loops. */
if (code != NE_EXPR)
{
- if (zero_p (step0)
+ if (zero_p (iv0->step)
&& mmin
- && operand_equal_p (base0, mmin, 0))
+ && operand_equal_p (iv0->base, mmin, 0))
return;
- if (zero_p (step1)
+ if (zero_p (iv1->step)
&& mmax
- && operand_equal_p (base1, mmax, 0))
+ && operand_equal_p (iv1->base, mmax, 0))
return;
}
there is not an overflow. */
if (code != NE_EXPR)
{
- if (zero_p (step0))
- step = fold_unary_to_constant (NEGATE_EXPR, type, step1);
+ if (zero_p (iv0->step))
+ step = fold_unary_to_constant (NEGATE_EXPR, type, iv1->step);
else
- step = step0;
- delta = fold_build2 (MINUS_EXPR, type, base1, base0);
+ 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;
worth the troubles. */
may_xform = boolean_true_node;
}
- else if (zero_p (step0))
+ else if (zero_p (iv0->step))
{
- if (!mmin)
+ if (!mmin || iv1->no_overflow)
may_xform = boolean_true_node;
else
{
bound = fold_binary_to_constant (MINUS_EXPR, type,
bound, delta);
may_xform = fold_build2 (LE_EXPR, boolean_type_node,
- bound, base0);
+ bound, iv0->base);
}
}
else
{
- if (!mmax)
+ if (!mmax || iv0->no_overflow)
may_xform = boolean_true_node;
else
{
bound = fold_binary_to_constant (PLUS_EXPR, type,
bound, delta);
may_xform = fold_build2 (LE_EXPR, boolean_type_node,
- base1, bound);
+ iv1->base, bound);
}
}
}
if (!nonzero_p (may_xform))
assumptions = may_xform;
- if (zero_p (step0))
+ if (zero_p (iv0->step))
{
- base0 = fold_build2 (PLUS_EXPR, type, base0, delta);
- base0 = fold_build2 (MINUS_EXPR, type, base0, step);
+ iv0->base = fold_build2 (PLUS_EXPR, type, iv0->base, delta);
+ iv0->base = fold_build2 (MINUS_EXPR, type, iv0->base, step);
}
else
{
- base1 = fold_build2 (MINUS_EXPR, type, base1, delta);
- base1 = fold_build2 (PLUS_EXPR, type, base1, step);
+ 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, base0, base1);
+ 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;
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. */
- base1 = fold_build2 (MINUS_EXPR, type, base1, base0);
- base0 = NULL_TREE;
- if (!zero_p (step1))
- step0 = fold_unary_to_constant (NEGATE_EXPR, type, step1);
- step1 = NULL_TREE;
- if (tree_int_cst_sign_bit (fold_convert (signed_niter_type, step0)))
+ 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)))
{
- step0 = fold_unary_to_constant (NEGATE_EXPR, type, step0);
- base1 = fold_build1 (NEGATE_EXPR, type, base1);
+ iv0->step = fold_unary_to_constant (NEGATE_EXPR, type, iv0->step);
+ iv1->base = fold_build1 (NEGATE_EXPR, type, iv1->base);
}
- base1 = fold_convert (niter_type, base1);
- step0 = fold_convert (niter_type, step0);
+ 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 (step0);
+ 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, step0, 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)));
- assumption = fold_build2 (FLOOR_MOD_EXPR, niter_type, base1, 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);
+ 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, base1, d);
+ 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 (step1))
+ 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
overflow condition using some information about b - a mod s,
but it was already taken into account during LE -> NE transform). */
{
- if (mmax)
+ if (mmax && !iv0->no_overflow)
{
- bound = fold_binary_to_constant (MINUS_EXPR, type, mmax, step0);
+ bound = fold_binary_to_constant (MINUS_EXPR, type,
+ mmax, iv0->step);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
- base1, bound);
+ iv1->base, bound);
assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
assumptions, assumption);
}
- step = step0;
- tmp = fold_build2 (PLUS_EXPR, type, base1, step0);
- assumption = fold_build2 (GT_EXPR, boolean_type_node, base0, tmp);
- delta = fold_build2 (PLUS_EXPR, type, base1, step);
- delta = fold_build2 (MINUS_EXPR, type, delta, base0);
+ 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)
+ if (mmin && !iv1->no_overflow)
{
- bound = fold_binary_to_constant (MINUS_EXPR, type, mmin, step1);
+ bound = fold_binary_to_constant (MINUS_EXPR, type,
+ mmin, iv1->step);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
- bound, base0);
+ bound, iv0->base);
assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
assumptions, assumption);
}
- step = fold_build1 (NEGATE_EXPR, type, step1);
- tmp = fold_build2 (PLUS_EXPR, type, base0, step1);
- assumption = fold_build2 (GT_EXPR, boolean_type_node, tmp, base1);
- delta = fold_build2 (MINUS_EXPR, type, base0, step);
- delta = fold_build2 (MINUS_EXPR, type, base1, delta);
+ 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,
returns true if the special case was recognized, false otherwise. */
static bool
-number_of_iterations_special (tree type, tree base0, tree step0,
- enum tree_code code, tree base1, tree step1,
- struct tree_niter_desc *niter)
+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;
if (code == GE_EXPR
|| code == GT_EXPR)
{
- SWAP (base0, base1);
- SWAP (step0, step1);
+ SWAP (iv0, iv1);
code = swap_tree_comparison (code);
}
switch (code)
{
case NE_EXPR:
- if (zero_p (step0))
+ if (zero_p (iv0->step))
{
- if (zero_p (step1))
+ if (zero_p (iv1->step))
return false;
- SWAP (base0, base1);
- SWAP (step0, step1);
+ SWAP (iv0, iv1);
}
- else if (!zero_p (step1))
+ else if (!zero_p (iv1->step))
return false;
- if (integer_onep (step0))
+ if (integer_onep (iv0->step))
{
- /* for (i = base0; i != base1; i++) */
+ /* 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, base1, base0);
+ niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
niter->additional_info = boolean_true_node;
}
- else if (integer_all_onesp (step0))
+ else if (integer_all_onesp (iv0->step))
{
- /* for (i = base0; i != base1; i--) */
+ /* 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, base0, base1);
+ niter->niter = fold_build2 (MINUS_EXPR, type, iv0->base, iv1->base);
}
else
return false;
break;
case LT_EXPR:
- if ((step0 && integer_onep (step0) && zero_p (step1))
- || (step1 && integer_all_onesp (step1) && zero_p (step0)))
+ if ((iv0->step && integer_onep (iv0->step)
+ && zero_p (iv1->step))
+ || (iv1->step && integer_all_onesp (iv1->step)
+ && zero_p (iv0->step)))
{
- /* for (i = base0; i < base1; i++)
+ /* for (i = iv0->base; i < iv1->base; i++)
or
- for (i = base1; i > base0; i--).
+ for (i = iv1->base; i > iv0->base; i--).
- In both cases # of iterations is base1 - base0. */
+ 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,
- base0, base1);
- niter->niter = fold_build2 (MINUS_EXPR, type, base1, base0);
+ iv0->base, iv1->base);
+ niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
}
else
return false;
mmax = TYPE_MAX_VALUE (type);
}
- if (step0 && integer_onep (step0) && zero_p (step1))
+ if (iv0->step && integer_onep (iv0->step)
+ && zero_p (iv1->step))
{
- /* for (i = base0; i <= base1; i++) */
- if (mmax)
+ /* for (i = iv0->base; i <= iv1->base; i++) */
+ if (mmax && !iv0->no_overflow)
niter->assumptions = fold_build2 (NE_EXPR, boolean_type_node,
- base1, mmax);
+ iv1->base, mmax);
else
niter->assumptions = boolean_true_node;
- base1 = fold_build2 (PLUS_EXPR, type, base1,
- build_int_cst_type (type, 1));
+ iv1->base = fold_build2 (PLUS_EXPR, type, iv1->base,
+ build_int_cst_type (type, 1));
}
- else if (step1 && integer_all_onesp (step1) && zero_p (step0))
+ else if (iv1->step && integer_all_onesp (iv1->step)
+ && zero_p (iv0->step))
{
- /* for (i = base1; i >= base0; i--) */
- if (mmin)
+ /* for (i = iv1->base; i >= iv0->base; i--) */
+ if (mmin && !iv1->no_overflow)
niter->assumptions = fold_build2 (NE_EXPR, boolean_type_node,
- base0, mmin);
+ iv0->base, mmin);
else
niter->assumptions = boolean_true_node;
- base0 = fold_build2 (MINUS_EXPR, type, base0,
- build_int_cst_type (type, 1));
+ 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,
- base0, base1);
- niter->niter = fold_build2 (MINUS_EXPR, type, base1, base0);
+ iv0->base, iv1->base);
+ niter->niter = fold_build2 (MINUS_EXPR, type, iv1->base, iv0->base);
break;
default:
bool warn)
{
tree stmt, cond, type;
- tree op0, base0, step0;
- tree op1, base1, step1;
+ tree op0, op1;
enum tree_code code;
+ affine_iv iv0, iv1;
if (!dominated_by_p (CDI_DOMINATORS, loop->latch, exit->src))
return false;
&& !POINTER_TYPE_P (type))
return false;
- if (!simple_iv (loop, stmt, op0, &base0, &step0, false))
+ if (!simple_iv (loop, stmt, op0, &iv0, false))
return false;
- if (!simple_iv (loop, stmt, op1, &base1, &step1, false))
+ 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, base0, step0, code, base1, step1,
- niter))
+ if (!number_of_iterations_special (type, &iv0, code, &iv1, niter))
{
- number_of_iterations_cond (type, base0, step0, code, base1, step1,
- niter);
+ number_of_iterations_cond (type, &iv0, code, &iv1, niter);
if (!niter->niter)
return false;
/* We can provide a more specific warning if one of the operator is
constant and the other advances by +1 or -1. */
- if (step1 ? !step0 && (integer_onep (step1) || integer_all_onesp (step1))
- : step0 && (integer_onep (step0) || integer_all_onesp (step0)))
+ if (!zero_p (iv1.step)
+ ? (zero_p (iv0.step)
+ && (integer_onep (iv1.step) || integer_all_onesp (iv1.step)))
+ : (iv0.step
+ && (integer_onep (iv0.step) || integer_all_onesp (iv0.step))))
wording =
flag_unsafe_loop_optimizations
? N_("assuming that the loop is not infinite")