re PR tree-optimization/55875 (IVopts caused miscompilation)

PR tree-optimiation/55875
	* gcc.c-torture/execute/pr55875.c: New testcase.
	* g++.dg/torture/pr55875.C: New testcase.

	* tree-ssa-loop-niter.c (number_of_iterations_cond): Add
	EVERY_ITERATION parameter.
	(number_of_iterations_exit): Check if exit is executed every
	iteration.
	(idx_infer_loop_bounds): Similarly here.
	(n_of_executions_at_most): Simplify
	to only test for cases where statement is dominated by the
	particular bound; handle correctly the "postdominance"
	test.
	(scev_probably_wraps_p): Use max loop iterations info
	as a global bound first.

From-SVN: r195054
This commit is contained in:
Jan Hubicka 2013-01-09 16:10:43 +01:00 committed by Jan Hubicka
parent 3cd232b5aa
commit 870ca33128
5 changed files with 178 additions and 31 deletions

View File

@ -1,3 +1,18 @@
2013-01-09 Jan Hubicka <jh@suse.cz>
PR tree-optimiation/55875
* tree-ssa-loop-niter.c (number_of_iterations_cond): Add
EVERY_ITERATION parameter.
(number_of_iterations_exit): Check if exit is executed every
iteration.
(idx_infer_loop_bounds): Similarly here.
(n_of_executions_at_most): Simplify
to only test for cases where statement is dominated by the
particular bound; handle correctly the "postdominance"
test.
(scev_probably_wraps_p): Use max loop iterations info
as a global bound first.
2013-01-09 Nguyen Duy Dat
Nick Clifton <nickc@redhat.com>

View File

@ -1,3 +1,9 @@
2013-01-09 Jan Hubicka <jh@suse.cz>
PR tree-optimiation/55875
* gcc.c-torture/execute/pr55875.c: New testcase.
* g++.dg/torture/pr55875.C: New testcase.
2013-01-09 Jakub Jelinek <jakub@redhat.com>
PR c/48418

View File

@ -0,0 +1,55 @@
// { dg-do run }
struct A
{
short int a1;
unsigned char a2;
unsigned int a3;
};
struct B
{
unsigned short b1;
const A *b2;
};
B b;
__attribute__((noinline, noclone))
int foo (unsigned x)
{
__asm volatile ("" : "+r" (x) : : "memory");
return x;
}
inline void
bar (const int &)
{
}
__attribute__((noinline)) void
baz ()
{
const A *a = b.b2;
unsigned int i;
unsigned short n = b.b1;
for (i = 0; i < n; ++i)
if (a[i].a1 == 11)
{
if (i > 0 && (a[i - 1].a2 & 1))
continue;
bar (foo (2));
return;
}
}
int
main ()
{
A a[4] = { { 10, 0, 0 }, { 11, 1, 0 }, { 11, 1, 0 }, { 11, 1, 0 } };
b.b1 = 4;
b.b2 = a;
baz ();
return 0;
}

View File

@ -0,0 +1,17 @@
int a[250];
__attribute__ ((noinline))
t(int i)
{
if (i==0)
exit(0);
if (i>255)
abort ();
}
main()
{
unsigned int i;
for (i=0;;i++)
{
a[i]=t((unsigned char)(i+5));
}
}

View File

@ -1208,6 +1208,8 @@ dump_affine_iv (FILE *file, affine_iv *iv)
-- in this case we can use the information whether the control induction
variables can overflow or not in a more efficient way.
if EVERY_ITERATION is true, we know the test is executed on every iteration.
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
@ -1217,11 +1219,21 @@ static bool
number_of_iterations_cond (struct loop *loop,
tree type, affine_iv *iv0, enum tree_code code,
affine_iv *iv1, struct tree_niter_desc *niter,
bool only_exit)
bool only_exit, bool every_iteration)
{
bool exit_must_be_taken = false, ret;
bounds bnds;
/* If the test is not executed every iteration, wrapping may make the test
to pass again.
TODO: the overflow case can be still used as unreliable estimate of upper
bound. But we have no API to pass it down to number of iterations code
and, at present, it will not use it anyway. */
if (!every_iteration
&& (!iv0->no_overflow || !iv1->no_overflow
|| code == NE_EXPR || code == EQ_EXPR))
return false;
/* The meaning of these assumptions is this:
if !assumptions
then the rest of information does not have to be valid
@ -1807,9 +1819,11 @@ number_of_iterations_exit (struct loop *loop, edge exit,
tree op0, op1;
enum tree_code code;
affine_iv iv0, iv1;
bool safe;
if (every_iteration
&& !dominated_by_p (CDI_DOMINATORS, loop->latch, exit->src))
safe = dominated_by_p (CDI_DOMINATORS, loop->latch, exit->src);
if (every_iteration && !safe)
return false;
niter->assumptions = boolean_false_node;
@ -1826,9 +1840,9 @@ number_of_iterations_exit (struct loop *loop, edge exit,
{
case GT_EXPR:
case GE_EXPR:
case NE_EXPR:
case LT_EXPR:
case LE_EXPR:
case NE_EXPR:
break;
default:
@ -1855,7 +1869,7 @@ number_of_iterations_exit (struct loop *loop, edge exit,
iv0.base = expand_simple_operations (iv0.base);
iv1.base = expand_simple_operations (iv1.base);
if (!number_of_iterations_cond (loop, type, &iv0, code, &iv1, niter,
loop_only_exit_p (loop, exit)))
loop_only_exit_p (loop, exit), safe))
{
fold_undefer_and_ignore_overflow_warnings ();
return false;
@ -2657,6 +2671,7 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta)
tree low, high, type, next;
bool sign, upper = true, at_end = false;
struct loop *loop = data->loop;
bool reliable = true;
if (TREE_CODE (base) != ARRAY_REF)
return true;
@ -2728,7 +2743,14 @@ idx_infer_loop_bounds (tree base, tree *idx, void *dta)
&& tree_int_cst_compare (next, high) <= 0)
return true;
record_nonwrapping_iv (loop, init, step, data->stmt, low, high, true, upper);
/* If access is not executed on every iteration, we must ensure that overlow may
not make the access valid later. */
if (!dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (data->stmt))
&& scev_probably_wraps_p (initial_condition_in_loop_num (ev, loop->num),
step, data->stmt, loop, true))
reliable = false;
record_nonwrapping_iv (loop, init, step, data->stmt, low, high, reliable, upper);
return true;
}
@ -3549,8 +3571,15 @@ stmt_dominates_stmt_p (gimple s1, gimple s2)
/* Returns true when we can prove that the number of executions of
STMT in the loop is at most NITER, according to the bound on
the number of executions of the statement NITER_BOUND->stmt recorded in
NITER_BOUND. If STMT is NULL, we must prove this bound for all
statements in the loop. */
NITER_BOUND and fact that NITER_BOUND->stmt dominate STMT.
??? This code can become quite a CPU hog - we can have many bounds,
and large basic block forcing stmt_dominates_stmt_p to be queried
many times on a large basic blocks, so the whole thing is O(n^2)
for scev_probably_wraps_p invocation (that can be done n times).
It would make more sense (and give better answers) to remember BB
bounds computed by discover_iteration_bound_by_body_walk. */
static bool
n_of_executions_at_most (gimple stmt,
@ -3571,32 +3600,43 @@ n_of_executions_at_most (gimple stmt,
/* We know that NITER_BOUND->stmt is executed at most NITER_BOUND->bound + 1
times. This means that:
-- if NITER_BOUND->is_exit is true, then everything before
NITER_BOUND->stmt is executed at most NITER_BOUND->bound + 1
times, and everything after it at most NITER_BOUND->bound times.
-- if NITER_BOUND->is_exit is true, then everything after
it at most NITER_BOUND->bound times.
-- If NITER_BOUND->is_exit is false, then if we can prove that when STMT
is executed, then NITER_BOUND->stmt is executed as well in the same
iteration (we conclude that if both statements belong to the same
basic block, or if STMT is after NITER_BOUND->stmt), then STMT
is executed at most NITER_BOUND->bound + 1 times. Otherwise STMT is
executed at most NITER_BOUND->bound + 2 times. */
iteration then STMT is executed at most NITER_BOUND->bound + 1 times.
If we can determine that NITER_BOUND->stmt is always executed
after STMT, then STMT is executed at most NITER_BOUND->bound + 2 times.
We conclude that if both statements belong to the same
basic block and STMT is before NITER_BOUND->stmt and there are no
statements with side effects in between. */
if (niter_bound->is_exit)
{
if (stmt
&& stmt != niter_bound->stmt
&& stmt_dominates_stmt_p (niter_bound->stmt, stmt))
cmp = GE_EXPR;
else
cmp = GT_EXPR;
if (stmt == niter_bound->stmt
|| !stmt_dominates_stmt_p (niter_bound->stmt, stmt))
return false;
cmp = GE_EXPR;
}
else
{
if (!stmt
|| (gimple_bb (stmt) != gimple_bb (niter_bound->stmt)
&& !stmt_dominates_stmt_p (niter_bound->stmt, stmt)))
if (!stmt_dominates_stmt_p (niter_bound->stmt, stmt))
{
gimple_stmt_iterator bsi;
if (gimple_bb (stmt) != gimple_bb (niter_bound->stmt)
|| gimple_code (stmt) == GIMPLE_PHI
|| gimple_code (niter_bound->stmt) == GIMPLE_PHI)
return false;
/* By stmt_dominates_stmt_p we already know that STMT appears
before NITER_BOUND->STMT. Still need to test that the loop
can not be terinated by a side effect in between. */
for (bsi = gsi_for_stmt (stmt); gsi_stmt (bsi) != niter_bound->stmt;
gsi_next (&bsi))
if (gimple_has_side_effects (gsi_stmt (bsi)))
return false;
bound += double_int_one;
if (bound.is_zero ()
|| !double_int_fits_to_tree_p (nit_type, bound))
@ -3640,10 +3680,12 @@ scev_probably_wraps_p (tree base, tree step,
gimple at_stmt, struct loop *loop,
bool use_overflow_semantics)
{
struct nb_iter_bound *bound;
tree delta, step_abs;
tree unsigned_type, valid_niter;
tree type = TREE_TYPE (step);
tree e;
double_int niter;
struct nb_iter_bound *bound;
/* FIXME: We really need something like
http://gcc.gnu.org/ml/gcc-patches/2005-06/msg02025.html.
@ -3706,14 +3748,26 @@ scev_probably_wraps_p (tree base, tree step,
valid_niter = fold_build2 (FLOOR_DIV_EXPR, unsigned_type, delta, step_abs);
estimate_numbers_of_iterations_loop (loop);
for (bound = loop->bounds; bound; bound = bound->next)
if (max_loop_iterations (loop, &niter)
&& double_int_fits_to_tree_p (TREE_TYPE (valid_niter), niter)
&& (e = fold_binary (GT_EXPR, boolean_type_node, valid_niter,
double_int_to_tree (TREE_TYPE (valid_niter),
niter))) != NULL
&& integer_nonzerop (e))
{
if (n_of_executions_at_most (at_stmt, bound, valid_niter))
{
fold_undefer_and_ignore_overflow_warnings ();
return false;
}
fold_undefer_and_ignore_overflow_warnings ();
return false;
}
if (at_stmt)
for (bound = loop->bounds; bound; bound = bound->next)
{
if (n_of_executions_at_most (at_stmt, bound, valid_niter))
{
fold_undefer_and_ignore_overflow_warnings ();
return false;
}
}
fold_undefer_and_ignore_overflow_warnings ();