tree-ssa-loop-niter.h (number_of_iterations_exit_assumptions): New Parameter.

* tree-ssa-loop-niter.h (number_of_iterations_exit_assumptions): New
	Parameter.
	* tree-ssa-loop-niter.c (number_of_iterations_exit_assumptions): New
	Parameter.
	(number_of_iterations_exit): Warn missed loop optimization for
	possible infinite loops.

	gcc/testsuite
	* gcc.dg/tree-ssa/pr19210-1.c: Refine test strings.
	* gcc.dg/tree-ssa/pr19210-2.c: Delete.

From-SVN: r238641
This commit is contained in:
Bin Cheng 2016-07-22 13:22:03 +00:00 committed by Bin Cheng
parent 01a0d7f57b
commit faa1612aa3
6 changed files with 41 additions and 39 deletions

View File

@ -1,3 +1,12 @@
2016-07-22 Bin Cheng <bin.cheng@arm.com>
* tree-ssa-loop-niter.h (number_of_iterations_exit_assumptions): New
Parameter.
* tree-ssa-loop-niter.c (number_of_iterations_exit_assumptions): New
Parameter.
(number_of_iterations_exit): Warn missed loop optimization for
possible infinite loops.
2016-07-22 Segher Boessenkool <segher@kernel.crashing.org> 2016-07-22 Segher Boessenkool <segher@kernel.crashing.org>
* config/rs6000/rs6000.c (rs6000_file_start): Fix condition for * config/rs6000/rs6000.c (rs6000_file_start): Fix condition for

View File

@ -1,3 +1,8 @@
2016-07-22 Bin Cheng <bin.cheng@arm.com>
* gcc.dg/tree-ssa/pr19210-1.c: Refine test strings.
* gcc.dg/tree-ssa/pr19210-2.c: Delete.
2016-07-22 Thomas Koenig <tkoenig@gcc.gnu.org> 2016-07-22 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/71795 PR fortran/71795

View File

@ -6,10 +6,10 @@ void
f (unsigned n) f (unsigned n)
{ {
unsigned k; unsigned k;
for(k = 0;k <= n;k++) /* { dg-warning "cannot optimize.*infinite loops" } */ for(k = 0;k <= n;k++) /* { dg-warning "missed loop optimization.*overflow" } */
g(); g();
for(k = 0;k <= n;k += 4) /* { dg-warning "cannot optimize.*overflow" } */ for(k = 0;k <= n;k += 4) /* { dg-warning "missed loop optimization.*overflow" } */
g(); g();
/* We used to get warning for this loop. However, since then # of iterations /* We used to get warning for this loop. However, since then # of iterations
@ -21,9 +21,9 @@ f (unsigned n)
g(); g();
/* So we need the following loop, instead. */ /* So we need the following loop, instead. */
for(k = 4;k <= n;k += 5) /* { dg-warning "cannot optimize.*overflow" } */ for(k = 4;k <= n;k += 5) /* { dg-warning "missed loop optimization.*overflow" } */
g(); g();
for(k = 15;k >= n;k--) /* { dg-warning "cannot optimize.*infinite" } */ for(k = 15;k >= n;k--) /* { dg-warning "missed loop optimization.*overflow" } */
g(); g();
} }

View File

@ -1,29 +0,0 @@
/* { dg-do compile } */
/* { dg-options "-O2 -funsafe-loop-optimizations -Wunsafe-loop-optimizations" } */
extern void g(void);
void
f (unsigned n)
{
unsigned k;
for(k = 0;k <= n;k++) /* { dg-warning "assuming.*not infinite" } */
g();
for(k = 5;k <= n;k += 4) /* { dg-warning "assuming.*not overflow" } */
g();
/* 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" } */
g();
}

View File

@ -2132,12 +2132,13 @@ loop_only_exit_p (const struct loop *loop, const_edge exit)
in comments at struct tree_niter_desc declaration), false otherwise. in comments at struct tree_niter_desc declaration), false otherwise.
When EVERY_ITERATION is true, only tests that are known to be executed When EVERY_ITERATION is true, only tests that are known to be executed
every iteration are considered (i.e. only test that alone bounds the loop). every iteration are considered (i.e. only test that alone bounds the loop).
*/ If AT_STMT is not NULL, this function stores LOOP's condition statement in
it when returning true. */
bool bool
number_of_iterations_exit_assumptions (struct loop *loop, edge exit, number_of_iterations_exit_assumptions (struct loop *loop, edge exit,
struct tree_niter_desc *niter, struct tree_niter_desc *niter,
bool every_iteration) gcond **at_stmt, bool every_iteration)
{ {
gimple *last; gimple *last;
gcond *stmt; gcond *stmt;
@ -2254,6 +2255,9 @@ number_of_iterations_exit_assumptions (struct loop *loop, edge exit,
if (TREE_CODE (niter->niter) == INTEGER_CST) if (TREE_CODE (niter->niter) == INTEGER_CST)
niter->max = wi::to_widest (niter->niter); niter->max = wi::to_widest (niter->niter);
if (at_stmt)
*at_stmt = stmt;
return (!integer_zerop (niter->assumptions)); return (!integer_zerop (niter->assumptions));
} }
@ -2263,13 +2267,26 @@ number_of_iterations_exit_assumptions (struct loop *loop, edge exit,
bool bool
number_of_iterations_exit (struct loop *loop, edge exit, number_of_iterations_exit (struct loop *loop, edge exit,
struct tree_niter_desc *niter, struct tree_niter_desc *niter,
bool, bool every_iteration) bool warn, bool every_iteration)
{ {
gcond *stmt;
if (!number_of_iterations_exit_assumptions (loop, exit, niter, if (!number_of_iterations_exit_assumptions (loop, exit, niter,
every_iteration)) &stmt, every_iteration))
return false; return false;
return (integer_nonzerop (niter->assumptions)); if (integer_nonzerop (niter->assumptions))
return true;
if (warn)
{
const char *wording;
wording = N_("missed loop optimization, the loop counter may overflow");
warning_at (gimple_location_safe (stmt),
OPT_Wunsafe_loop_optimizations, "%s", gettext (wording));
}
return false;
} }
/* Try to determine the number of iterations of LOOP. If we succeed, /* Try to determine the number of iterations of LOOP. If we succeed,

View File

@ -29,7 +29,7 @@ extern bool number_of_iterations_exit (struct loop *, edge,
bool every_iteration = true); bool every_iteration = true);
extern bool number_of_iterations_exit_assumptions (struct loop *, edge, extern bool number_of_iterations_exit_assumptions (struct loop *, edge,
struct tree_niter_desc *, struct tree_niter_desc *,
bool = true); gcond **, bool = true);
extern tree find_loop_niter (struct loop *, edge *); extern tree find_loop_niter (struct loop *, edge *);
extern bool finite_loop_p (struct loop *); extern bool finite_loop_p (struct loop *);
extern tree loop_niter_by_eval (struct loop *, edge); extern tree loop_niter_by_eval (struct loop *, edge);