backport: re PR tree-optimization/81388 (Incorrect code generation with -O1)
Backport from 2017-07-20 trunk r250384. PR tree-optimization/81388 Revert r238585: 2016-07-21 Bin Cheng <bin.cheng@arm.com> * tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne): Clean up by removing computation of may_be_zero. gcc/testsuite PR tree-optimization/81388 * gcc.dg/tree-ssa/pr81388-1.c: New test. * gcc.dg/tree-ssa/pr81388-2.c: New test. From-SVN: r250497
This commit is contained in:
parent
cc30cfd553
commit
16ac9369b0
|
@ -1,3 +1,14 @@
|
|||
2017-07-25 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
Backport from 2017-07-20 trunk r250384.
|
||||
|
||||
PR tree-optimization/81388
|
||||
Revert r238585:
|
||||
2016-07-21 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
* tree-ssa-loop-niter.c (number_of_iterations_lt_to_ne): Clean up
|
||||
by removing computation of may_be_zero.
|
||||
|
||||
2017-07-23 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/80569
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
2017-07-25 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
Backport from 2017-07-20 trunk r250384.
|
||||
|
||||
PR tree-optimization/81388
|
||||
* gcc.dg/tree-ssa/pr81388-1.c: New test.
|
||||
* gcc.dg/tree-ssa/pr81388-2.c: New test.
|
||||
|
||||
2017-07-23 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/80569
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fno-strict-overflow -fdump-tree-ivcanon-details" } */
|
||||
|
||||
void bar();
|
||||
void foo(char *dst)
|
||||
{
|
||||
char *const end = dst;
|
||||
do {
|
||||
bar();
|
||||
dst += 2;
|
||||
} while (dst < end);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump " zero if " "ivcanon" } } */
|
|
@ -0,0 +1,14 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-ivcanon-details" } */
|
||||
|
||||
void bar();
|
||||
void foo(unsigned dst)
|
||||
{
|
||||
unsigned end = dst;
|
||||
do {
|
||||
bar();
|
||||
dst += 2;
|
||||
} while (dst < end);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump " zero if " "ivcanon" } } */
|
|
@ -1142,8 +1142,12 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
|
|||
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;
|
||||
tree type1 = (POINTER_TYPE_P (type)) ? sizetype : type;
|
||||
mpz_t mmod;
|
||||
tree assumption = boolean_true_node, bound, noloop;
|
||||
bool ret = false, fv_comp_no_overflow;
|
||||
tree type1 = type;
|
||||
if (POINTER_TYPE_P (type))
|
||||
type1 = sizetype;
|
||||
|
||||
if (TREE_CODE (mod) != INTEGER_CST)
|
||||
return false;
|
||||
|
@ -1151,51 +1155,96 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
|
|||
mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
|
||||
tmod = fold_convert (type1, mod);
|
||||
|
||||
mpz_init (mmod);
|
||||
wi::to_mpz (mod, mmod, UNSIGNED);
|
||||
mpz_neg (mmod, mmod);
|
||||
|
||||
/* If the induction variable does not overflow and the exit is taken,
|
||||
then the computation of the final value does not overflow. There
|
||||
are three cases:
|
||||
1) The case if the new final value is equal to the current one.
|
||||
2) Induction varaible has pointer type, as the code cannot rely
|
||||
on the object to that the pointer points being placed at the
|
||||
end of the address space (and more pragmatically,
|
||||
TYPE_{MIN,MAX}_VALUE is not defined for pointers).
|
||||
3) EXIT_MUST_BE_TAKEN is true, note it implies that the induction
|
||||
variable does not overflow. */
|
||||
if (!integer_zerop (mod) && !POINTER_TYPE_P (type) && !exit_must_be_taken)
|
||||
then the computation of the final value does not overflow. This is
|
||||
also obviously the case if the new final value is equal to the
|
||||
current one. Finally, we postulate this for pointer type variables,
|
||||
as the code cannot rely on the object to that the pointer points being
|
||||
placed at the end of the address space (and more pragmatically,
|
||||
TYPE_{MIN,MAX}_VALUE is not defined for pointers). */
|
||||
if (integer_zerop (mod) || POINTER_TYPE_P (type))
|
||||
fv_comp_no_overflow = true;
|
||||
else if (!exit_must_be_taken)
|
||||
fv_comp_no_overflow = false;
|
||||
else
|
||||
fv_comp_no_overflow =
|
||||
(iv0->no_overflow && integer_nonzerop (iv0->step))
|
||||
|| (iv1->no_overflow && integer_nonzerop (iv1->step));
|
||||
|
||||
if (integer_nonzerop (iv0->step))
|
||||
{
|
||||
if (integer_nonzerop (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 (!fv_comp_no_overflow)
|
||||
{
|
||||
/* The final value of the iv is iv1->base + MOD, assuming
|
||||
that this computation does not overflow, and that
|
||||
iv0->base <= iv1->base + MOD. */
|
||||
bound = fold_build2 (MINUS_EXPR, type1,
|
||||
TYPE_MAX_VALUE (type1), tmod);
|
||||
assumption = fold_build2 (LE_EXPR, boolean_type_node,
|
||||
iv1->base, bound);
|
||||
if (integer_zerop (assumption))
|
||||
goto end;
|
||||
}
|
||||
if (mpz_cmp (mmod, bnds->below) < 0)
|
||||
noloop = boolean_false_node;
|
||||
else if (POINTER_TYPE_P (type))
|
||||
noloop = fold_build2 (GT_EXPR, boolean_type_node,
|
||||
iv0->base,
|
||||
fold_build_pointer_plus (iv1->base, tmod));
|
||||
else
|
||||
noloop = fold_build2 (GT_EXPR, boolean_type_node,
|
||||
iv0->base,
|
||||
fold_build2 (PLUS_EXPR, type1,
|
||||
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 (!fv_comp_no_overflow)
|
||||
{
|
||||
/* The final value of the iv is iv0->base - MOD, assuming
|
||||
that this computation does not overflow, and that
|
||||
iv0->base - MOD <= iv1->base. */
|
||||
bound = fold_build2 (PLUS_EXPR, type1,
|
||||
TYPE_MIN_VALUE (type1), tmod);
|
||||
assumption = fold_build2 (GE_EXPR, boolean_type_node,
|
||||
iv0->base, bound);
|
||||
if (integer_zerop (assumption))
|
||||
goto end;
|
||||
}
|
||||
if (integer_zerop (assumption))
|
||||
return false;
|
||||
else if (!integer_nonzerop (assumption))
|
||||
niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
niter->assumptions, assumption);
|
||||
if (mpz_cmp (mmod, bnds->below) < 0)
|
||||
noloop = boolean_false_node;
|
||||
else if (POINTER_TYPE_P (type))
|
||||
noloop = fold_build2 (GT_EXPR, boolean_type_node,
|
||||
fold_build_pointer_plus (iv0->base,
|
||||
fold_build1 (NEGATE_EXPR,
|
||||
type1, tmod)),
|
||||
iv1->base);
|
||||
else
|
||||
noloop = fold_build2 (GT_EXPR, boolean_type_node,
|
||||
fold_build2 (MINUS_EXPR, type1,
|
||||
iv0->base, tmod),
|
||||
iv1->base);
|
||||
}
|
||||
|
||||
/* Since we are transforming LT to NE and DELTA is constant, there
|
||||
is no need to compute may_be_zero because this loop must roll. */
|
||||
|
||||
if (!integer_nonzerop (assumption))
|
||||
niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
niter->assumptions,
|
||||
assumption);
|
||||
if (!integer_zerop (noloop))
|
||||
niter->may_be_zero = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
|
||||
niter->may_be_zero,
|
||||
noloop);
|
||||
bounds_add (bnds, wi::to_widest (mod), type);
|
||||
*delta = fold_build2 (PLUS_EXPR, niter_type, *delta, mod);
|
||||
return true;
|
||||
|
||||
ret = true;
|
||||
end:
|
||||
mpz_clear (mmod);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add assertions to NITER that ensure that the control variable of the loop
|
||||
|
|
Loading…
Reference in New Issue