cfgloop.h (get_loop_exit_edges): Add extra parameter denoting loop body, defaulted to NULL.
2019-11-25 Richard Biener <rguenther@suse.de> * cfgloop.h (get_loop_exit_edges): Add extra parameter denoting loop body, defaulted to NULL. (single_likely_exit): Add exit vector argument * tree-ssa-loop-niter.h (loop_only_exit_p): Add loop body argument. (number_of_iterations_exit): Likewise. (number_of_iterations_exit_assumptions): Likewise. * cfgloop.c (get_loop_exit_edges): Use passed in loop body if not NULL. * cfgloopanal.c (single_likely_exit): Use passed in exit vector. * tree-ssa-loop-ivcanon.c (canonicalize_loop_induction_variables): Compute exit vector around call to single_likely_exit. * tree-ssa-loop-ivopts.c (tree_ssa_iv_optimize_loop): Pass down loop body to loop_only_exit_p. * tree-ssa-loop-niter.c (loop_only_exit_p): Get loop body from caller. (number_of_iterations_exit_assumptions): Get loop body from caller if not NULL. (number_of_iterations_exit): Pass through new loop body arg. (infer_loop_bounds_from_undefined): Get loop body from caller. (estimate_numbers_of_iterations): Compute loop body once. From-SVN: r278667
This commit is contained in:
parent
5a34952edb
commit
f10d2d85c9
8 changed files with 70 additions and 38 deletions
|
@ -1,3 +1,26 @@
|
|||
2019-11-25 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* cfgloop.h (get_loop_exit_edges): Add extra parameter denoting
|
||||
loop body, defaulted to NULL.
|
||||
(single_likely_exit): Add exit vector argument
|
||||
* tree-ssa-loop-niter.h (loop_only_exit_p): Add loop body argument.
|
||||
(number_of_iterations_exit): Likewise.
|
||||
(number_of_iterations_exit_assumptions): Likewise.
|
||||
* cfgloop.c (get_loop_exit_edges): Use passed in loop body
|
||||
if not NULL.
|
||||
* cfgloopanal.c (single_likely_exit): Use passed in exit vector.
|
||||
* tree-ssa-loop-ivcanon.c (canonicalize_loop_induction_variables):
|
||||
Compute exit vector around call to single_likely_exit.
|
||||
* tree-ssa-loop-ivopts.c (tree_ssa_iv_optimize_loop): Pass down
|
||||
loop body to loop_only_exit_p.
|
||||
* tree-ssa-loop-niter.c (loop_only_exit_p): Get loop body from
|
||||
caller.
|
||||
(number_of_iterations_exit_assumptions): Get loop body from caller
|
||||
if not NULL.
|
||||
(number_of_iterations_exit): Pass through new loop body arg.
|
||||
(infer_loop_bounds_from_undefined): Get loop body from caller.
|
||||
(estimate_numbers_of_iterations): Compute loop body once.
|
||||
|
||||
2019-11-25 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* cfganal.c (pre_and_rev_post_order_compute_fn): Use an
|
||||
|
|
|
@ -1203,12 +1203,11 @@ release_recorded_exits (function *fn)
|
|||
/* Returns the list of the exit edges of a LOOP. */
|
||||
|
||||
vec<edge>
|
||||
get_loop_exit_edges (const class loop *loop)
|
||||
get_loop_exit_edges (const class loop *loop, basic_block *body)
|
||||
{
|
||||
vec<edge> edges = vNULL;
|
||||
edge e;
|
||||
unsigned i;
|
||||
basic_block *body;
|
||||
edge_iterator ei;
|
||||
struct loop_exit *exit;
|
||||
|
||||
|
@ -1223,14 +1222,20 @@ get_loop_exit_edges (const class loop *loop)
|
|||
}
|
||||
else
|
||||
{
|
||||
body = get_loop_body (loop);
|
||||
bool body_from_caller = true;
|
||||
if (!body)
|
||||
{
|
||||
body = get_loop_body (loop);
|
||||
body_from_caller = false;
|
||||
}
|
||||
for (i = 0; i < loop->num_nodes; i++)
|
||||
FOR_EACH_EDGE (e, ei, body[i]->succs)
|
||||
{
|
||||
if (!flow_bb_inside_loop_p (loop, e->dest))
|
||||
edges.safe_push (e);
|
||||
}
|
||||
free (body);
|
||||
if (!body_from_caller)
|
||||
free (body);
|
||||
}
|
||||
|
||||
return edges;
|
||||
|
|
|
@ -379,9 +379,9 @@ extern basic_block *get_loop_body_in_custom_order (const class loop *,
|
|||
extern basic_block *get_loop_body_in_custom_order (const class loop *, void *,
|
||||
int (*) (const void *, const void *, void *));
|
||||
|
||||
extern vec<edge> get_loop_exit_edges (const class loop *);
|
||||
extern vec<edge> get_loop_exit_edges (const class loop *, basic_block * = NULL);
|
||||
extern edge single_exit (const class loop *);
|
||||
extern edge single_likely_exit (class loop *loop);
|
||||
extern edge single_likely_exit (class loop *loop, vec<edge>);
|
||||
extern unsigned num_loop_branches (const class loop *);
|
||||
|
||||
extern edge loop_preheader_edge (const class loop *);
|
||||
|
|
|
@ -467,16 +467,14 @@ mark_loop_exit_edges (void)
|
|||
to noreturn call. */
|
||||
|
||||
edge
|
||||
single_likely_exit (class loop *loop)
|
||||
single_likely_exit (class loop *loop, vec<edge> exits)
|
||||
{
|
||||
edge found = single_exit (loop);
|
||||
vec<edge> exits;
|
||||
unsigned i;
|
||||
edge ex;
|
||||
|
||||
if (found)
|
||||
return found;
|
||||
exits = get_loop_exit_edges (loop);
|
||||
FOR_EACH_VEC_ELT (exits, i, ex)
|
||||
{
|
||||
if (probably_never_executed_edge_p (cfun, ex)
|
||||
|
@ -489,12 +487,8 @@ single_likely_exit (class loop *loop)
|
|||
if (!found)
|
||||
found = ex;
|
||||
else
|
||||
{
|
||||
exits.release ();
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
exits.release ();
|
||||
return found;
|
||||
}
|
||||
|
||||
|
|
|
@ -1222,8 +1222,10 @@ canonicalize_loop_induction_variables (class loop *loop,
|
|||
by find_loop_niter_by_eval. Be sure to keep it for future. */
|
||||
if (niter && TREE_CODE (niter) == INTEGER_CST)
|
||||
{
|
||||
vec<edge> exits = get_loop_exit_edges (loop);
|
||||
record_niter_bound (loop, wi::to_widest (niter),
|
||||
exit == single_likely_exit (loop), true);
|
||||
exit == single_likely_exit (loop, exits), true);
|
||||
exits.release ();
|
||||
}
|
||||
|
||||
/* Force re-computation of loop bounds so we can remove redundant exits. */
|
||||
|
|
|
@ -7977,7 +7977,8 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, class loop *loop,
|
|||
data->body_includes_call = loop_body_includes_call (body, loop->num_nodes);
|
||||
renumber_gimple_stmt_uids_in_blocks (body, loop->num_nodes);
|
||||
|
||||
data->loop_single_exit_p = exit != NULL && loop_only_exit_p (loop, exit);
|
||||
data->loop_single_exit_p
|
||||
= exit != NULL && loop_only_exit_p (loop, body, exit);
|
||||
|
||||
/* For each ssa name determines whether it behaves as an induction variable
|
||||
in some loop. */
|
||||
|
|
|
@ -2367,27 +2367,23 @@ simplify_using_outer_evolutions (class loop *loop, tree expr)
|
|||
/* Returns true if EXIT is the only possible exit from LOOP. */
|
||||
|
||||
bool
|
||||
loop_only_exit_p (const class loop *loop, const_edge exit)
|
||||
loop_only_exit_p (const class loop *loop, basic_block *body, const_edge exit)
|
||||
{
|
||||
basic_block *body;
|
||||
gimple_stmt_iterator bsi;
|
||||
unsigned i;
|
||||
|
||||
if (exit != single_exit (loop))
|
||||
return false;
|
||||
|
||||
body = get_loop_body (loop);
|
||||
for (i = 0; i < loop->num_nodes; i++)
|
||||
{
|
||||
for (bsi = gsi_start_bb (body[i]); !gsi_end_p (bsi); gsi_next (&bsi))
|
||||
if (stmt_can_terminate_bb_p (gsi_stmt (bsi)))
|
||||
{
|
||||
free (body);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
free (body);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2403,7 +2399,8 @@ loop_only_exit_p (const class loop *loop, const_edge exit)
|
|||
bool
|
||||
number_of_iterations_exit_assumptions (class loop *loop, edge exit,
|
||||
class tree_niter_desc *niter,
|
||||
gcond **at_stmt, bool every_iteration)
|
||||
gcond **at_stmt, bool every_iteration,
|
||||
basic_block *body)
|
||||
{
|
||||
gimple *last;
|
||||
gcond *stmt;
|
||||
|
@ -2477,8 +2474,17 @@ number_of_iterations_exit_assumptions (class loop *loop, edge exit,
|
|||
|
||||
iv0.base = expand_simple_operations (iv0.base);
|
||||
iv1.base = expand_simple_operations (iv1.base);
|
||||
bool body_from_caller = true;
|
||||
if (!body)
|
||||
{
|
||||
body = get_loop_body (loop);
|
||||
body_from_caller = false;
|
||||
}
|
||||
bool only_exit_p = loop_only_exit_p (loop, body, exit);
|
||||
if (!body_from_caller)
|
||||
free (body);
|
||||
if (!number_of_iterations_cond (loop, type, &iv0, code, &iv1, niter,
|
||||
loop_only_exit_p (loop, exit), safe))
|
||||
only_exit_p, safe))
|
||||
{
|
||||
fold_undefer_and_ignore_overflow_warnings ();
|
||||
return false;
|
||||
|
@ -2721,11 +2727,12 @@ number_of_iterations_popcount (loop_p loop, edge exit,
|
|||
bool
|
||||
number_of_iterations_exit (class loop *loop, edge exit,
|
||||
class tree_niter_desc *niter,
|
||||
bool warn, bool every_iteration)
|
||||
bool warn, bool every_iteration,
|
||||
basic_block *body)
|
||||
{
|
||||
gcond *stmt;
|
||||
if (!number_of_iterations_exit_assumptions (loop, exit, niter,
|
||||
&stmt, every_iteration))
|
||||
&stmt, every_iteration, body))
|
||||
return false;
|
||||
|
||||
if (integer_nonzerop (niter->assumptions))
|
||||
|
@ -3837,16 +3844,13 @@ infer_loop_bounds_from_signedness (class loop *loop, gimple *stmt)
|
|||
*/
|
||||
|
||||
static void
|
||||
infer_loop_bounds_from_undefined (class loop *loop)
|
||||
infer_loop_bounds_from_undefined (class loop *loop, basic_block *bbs)
|
||||
{
|
||||
unsigned i;
|
||||
basic_block *bbs;
|
||||
gimple_stmt_iterator bsi;
|
||||
basic_block bb;
|
||||
bool reliable;
|
||||
|
||||
bbs = get_loop_body (loop);
|
||||
|
||||
for (i = 0; i < loop->num_nodes; i++)
|
||||
{
|
||||
bb = bbs[i];
|
||||
|
@ -3871,8 +3875,6 @@ infer_loop_bounds_from_undefined (class loop *loop)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
free (bbs);
|
||||
}
|
||||
|
||||
/* Compare wide ints, callback for qsort. */
|
||||
|
@ -4275,8 +4277,9 @@ estimate_numbers_of_iterations (class loop *loop)
|
|||
diagnose those loops with -Waggressive-loop-optimizations. */
|
||||
number_of_latch_executions (loop);
|
||||
|
||||
exits = get_loop_exit_edges (loop);
|
||||
likely_exit = single_likely_exit (loop);
|
||||
basic_block *body = get_loop_body (loop);
|
||||
exits = get_loop_exit_edges (loop, body);
|
||||
likely_exit = single_likely_exit (loop, exits);
|
||||
FOR_EACH_VEC_ELT (exits, i, ex)
|
||||
{
|
||||
if (ex == likely_exit)
|
||||
|
@ -4296,7 +4299,8 @@ estimate_numbers_of_iterations (class loop *loop)
|
|||
}
|
||||
}
|
||||
|
||||
if (!number_of_iterations_exit (loop, ex, &niter_desc, false, false))
|
||||
if (!number_of_iterations_exit (loop, ex, &niter_desc,
|
||||
false, false, body))
|
||||
continue;
|
||||
|
||||
niter = niter_desc.niter;
|
||||
|
@ -4313,7 +4317,7 @@ estimate_numbers_of_iterations (class loop *loop)
|
|||
exits.release ();
|
||||
|
||||
if (flag_aggressive_loop_optimizations)
|
||||
infer_loop_bounds_from_undefined (loop);
|
||||
infer_loop_bounds_from_undefined (loop, body);
|
||||
|
||||
discover_iteration_bound_by_body_walk (loop);
|
||||
|
||||
|
|
|
@ -22,13 +22,16 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
extern tree expand_simple_operations (tree, tree = NULL);
|
||||
extern tree simplify_using_initial_conditions (class loop *, tree);
|
||||
extern bool loop_only_exit_p (const class loop *, const_edge);
|
||||
extern bool loop_only_exit_p (const class loop *, basic_block *body,
|
||||
const_edge);
|
||||
extern bool number_of_iterations_exit (class loop *, edge,
|
||||
class tree_niter_desc *niter, bool,
|
||||
bool every_iteration = true);
|
||||
bool every_iteration = true,
|
||||
basic_block * = NULL);
|
||||
extern bool number_of_iterations_exit_assumptions (class loop *, edge,
|
||||
class tree_niter_desc *,
|
||||
gcond **, bool = true);
|
||||
gcond **, bool = true,
|
||||
basic_block * = NULL);
|
||||
extern tree find_loop_niter (class loop *, edge *);
|
||||
extern bool finite_loop_p (class loop *);
|
||||
extern tree loop_niter_by_eval (class loop *, edge);
|
||||
|
|
Loading…
Add table
Reference in a new issue