Commit 73c4b4df by Bin Cheng Committed by Bin Cheng

re PR tree-optimization/81388 (Incorrect code generation with -O1)


	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: r250384
parent 77e5edaf
2017-07-20 Bin Cheng <bin.cheng@arm.com>
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-18 Jan Hubicka <hubicka@ucw.cz> 2017-07-18 Jan Hubicka <hubicka@ucw.cz>
Tom de Vries <tom@codesourcery.com> Tom de Vries <tom@codesourcery.com>
......
2017-07-20 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/81388
* gcc.dg/tree-ssa/pr81388-1.c: New test.
* gcc.dg/tree-ssa/pr81388-2.c: New test.
2017-07-17 Tom de Vries <tom@codesourcery.com> 2017-07-17 Tom de Vries <tom@codesourcery.com>
PR middle-end/81030 PR middle-end/81030
......
/* { 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-times " zero if " 1 "ivcanon" } } */
/* { 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-times " zero if " 1 "ivcanon" } } */
...@@ -1142,8 +1142,12 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1, ...@@ -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 niter_type = TREE_TYPE (step);
tree mod = fold_build2 (FLOOR_MOD_EXPR, niter_type, *delta, step); tree mod = fold_build2 (FLOOR_MOD_EXPR, niter_type, *delta, step);
tree tmod; tree tmod;
tree assumption = boolean_true_node, bound; mpz_t mmod;
tree type1 = (POINTER_TYPE_P (type)) ? sizetype : type; 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) if (TREE_CODE (mod) != INTEGER_CST)
return false; return false;
...@@ -1151,51 +1155,96 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1, ...@@ -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); mod = fold_build2 (MINUS_EXPR, niter_type, step, mod);
tmod = fold_convert (type1, 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, /* If the induction variable does not overflow and the exit is taken,
then the computation of the final value does not overflow. There then the computation of the final value does not overflow. This is
are three cases: also obviously the case if the new final value is equal to the
1) The case if the new final value is equal to the current one. current one. Finally, we postulate this for pointer type variables,
2) Induction varaible has pointer type, as the code cannot rely as the code cannot rely on the object to that the pointer points being
on the object to that the pointer points being placed at the placed at the end of the address space (and more pragmatically,
end of the address space (and more pragmatically, TYPE_{MIN,MAX}_VALUE is not defined for pointers). */
TYPE_{MIN,MAX}_VALUE is not defined for pointers). if (integer_zerop (mod) || POINTER_TYPE_P (type))
3) EXIT_MUST_BE_TAKEN is true, note it implies that the induction fv_comp_no_overflow = true;
variable does not overflow. */ else if (!exit_must_be_taken)
if (!integer_zerop (mod) && !POINTER_TYPE_P (type) && !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 /* The final value of the iv is iv1->base + MOD, assuming that this
that this computation does not overflow, and that computation does not overflow, and that
iv0->base <= iv1->base + MOD. */ iv0->base <= iv1->base + MOD. */
if (!fv_comp_no_overflow)
{
bound = fold_build2 (MINUS_EXPR, type1, bound = fold_build2 (MINUS_EXPR, type1,
TYPE_MAX_VALUE (type1), tmod); TYPE_MAX_VALUE (type1), tmod);
assumption = fold_build2 (LE_EXPR, boolean_type_node, assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound); 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 else
{ {
/* The final value of the iv is iv0->base - MOD, assuming /* The final value of the iv is iv0->base - MOD, assuming that this
that this computation does not overflow, and that computation does not overflow, and that
iv0->base - MOD <= iv1->base. */ iv0->base - MOD <= iv1->base. */
if (!fv_comp_no_overflow)
{
bound = fold_build2 (PLUS_EXPR, type1, bound = fold_build2 (PLUS_EXPR, type1,
TYPE_MIN_VALUE (type1), tmod); TYPE_MIN_VALUE (type1), tmod);
assumption = fold_build2 (GE_EXPR, boolean_type_node, assumption = fold_build2 (GE_EXPR, boolean_type_node,
iv0->base, bound); iv0->base, bound);
}
if (integer_zerop (assumption)) if (integer_zerop (assumption))
return false; goto end;
else if (!integer_nonzerop (assumption)) }
niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, if (mpz_cmp (mmod, bnds->below) < 0)
niter->assumptions, assumption); 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 if (!integer_nonzerop (assumption))
is no need to compute may_be_zero because this loop must roll. */ 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); bounds_add (bnds, wi::to_widest (mod), type);
*delta = fold_build2 (PLUS_EXPR, niter_type, *delta, mod); *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 /* Add assertions to NITER that ensure that the control variable of the loop
......
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