Commit f10d2d85 by Richard Biener Committed by Richard Biener

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
parent 5a34952e
2019-11-25 Richard Biener <rguenther@suse.de> 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 * cfganal.c (pre_and_rev_post_order_compute_fn): Use an
auto_bb_flag instead of an sbitmap for visited handling. auto_bb_flag instead of an sbitmap for visited handling.
...@@ -1203,12 +1203,11 @@ release_recorded_exits (function *fn) ...@@ -1203,12 +1203,11 @@ release_recorded_exits (function *fn)
/* Returns the list of the exit edges of a LOOP. */ /* Returns the list of the exit edges of a LOOP. */
vec<edge> 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; vec<edge> edges = vNULL;
edge e; edge e;
unsigned i; unsigned i;
basic_block *body;
edge_iterator ei; edge_iterator ei;
struct loop_exit *exit; struct loop_exit *exit;
...@@ -1223,14 +1222,20 @@ get_loop_exit_edges (const class loop *loop) ...@@ -1223,14 +1222,20 @@ get_loop_exit_edges (const class loop *loop)
} }
else 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 (i = 0; i < loop->num_nodes; i++)
FOR_EACH_EDGE (e, ei, body[i]->succs) FOR_EACH_EDGE (e, ei, body[i]->succs)
{ {
if (!flow_bb_inside_loop_p (loop, e->dest)) if (!flow_bb_inside_loop_p (loop, e->dest))
edges.safe_push (e); edges.safe_push (e);
} }
free (body); if (!body_from_caller)
free (body);
} }
return edges; return edges;
......
...@@ -379,9 +379,9 @@ extern basic_block *get_loop_body_in_custom_order (const class loop *, ...@@ -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 *, extern basic_block *get_loop_body_in_custom_order (const class loop *, void *,
int (*) (const void *, const void *, 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_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 unsigned num_loop_branches (const class loop *);
extern edge loop_preheader_edge (const class loop *); extern edge loop_preheader_edge (const class loop *);
......
...@@ -467,16 +467,14 @@ mark_loop_exit_edges (void) ...@@ -467,16 +467,14 @@ mark_loop_exit_edges (void)
to noreturn call. */ to noreturn call. */
edge edge
single_likely_exit (class loop *loop) single_likely_exit (class loop *loop, vec<edge> exits)
{ {
edge found = single_exit (loop); edge found = single_exit (loop);
vec<edge> exits;
unsigned i; unsigned i;
edge ex; edge ex;
if (found) if (found)
return found; return found;
exits = get_loop_exit_edges (loop);
FOR_EACH_VEC_ELT (exits, i, ex) FOR_EACH_VEC_ELT (exits, i, ex)
{ {
if (probably_never_executed_edge_p (cfun, ex) if (probably_never_executed_edge_p (cfun, ex)
...@@ -489,12 +487,8 @@ single_likely_exit (class loop *loop) ...@@ -489,12 +487,8 @@ single_likely_exit (class loop *loop)
if (!found) if (!found)
found = ex; found = ex;
else else
{ return NULL;
exits.release ();
return NULL;
}
} }
exits.release ();
return found; return found;
} }
......
...@@ -1222,8 +1222,10 @@ canonicalize_loop_induction_variables (class loop *loop, ...@@ -1222,8 +1222,10 @@ canonicalize_loop_induction_variables (class loop *loop,
by find_loop_niter_by_eval. Be sure to keep it for future. */ by find_loop_niter_by_eval. Be sure to keep it for future. */
if (niter && TREE_CODE (niter) == INTEGER_CST) if (niter && TREE_CODE (niter) == INTEGER_CST)
{ {
vec<edge> exits = get_loop_exit_edges (loop);
record_niter_bound (loop, wi::to_widest (niter), 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. */ /* 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, ...@@ -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); data->body_includes_call = loop_body_includes_call (body, loop->num_nodes);
renumber_gimple_stmt_uids_in_blocks (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 /* For each ssa name determines whether it behaves as an induction variable
in some loop. */ in some loop. */
......
...@@ -2367,27 +2367,23 @@ simplify_using_outer_evolutions (class loop *loop, tree expr) ...@@ -2367,27 +2367,23 @@ simplify_using_outer_evolutions (class loop *loop, tree expr)
/* Returns true if EXIT is the only possible exit from LOOP. */ /* Returns true if EXIT is the only possible exit from LOOP. */
bool 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; gimple_stmt_iterator bsi;
unsigned i; unsigned i;
if (exit != single_exit (loop)) if (exit != single_exit (loop))
return false; return false;
body = get_loop_body (loop);
for (i = 0; i < loop->num_nodes; i++) for (i = 0; i < loop->num_nodes; i++)
{ {
for (bsi = gsi_start_bb (body[i]); !gsi_end_p (bsi); gsi_next (&bsi)) for (bsi = gsi_start_bb (body[i]); !gsi_end_p (bsi); gsi_next (&bsi))
if (stmt_can_terminate_bb_p (gsi_stmt (bsi))) if (stmt_can_terminate_bb_p (gsi_stmt (bsi)))
{ {
free (body);
return true; return true;
} }
} }
free (body);
return true; return true;
} }
...@@ -2403,7 +2399,8 @@ loop_only_exit_p (const class loop *loop, const_edge exit) ...@@ -2403,7 +2399,8 @@ loop_only_exit_p (const class loop *loop, const_edge exit)
bool bool
number_of_iterations_exit_assumptions (class loop *loop, edge exit, number_of_iterations_exit_assumptions (class loop *loop, edge exit,
class tree_niter_desc *niter, class tree_niter_desc *niter,
gcond **at_stmt, bool every_iteration) gcond **at_stmt, bool every_iteration,
basic_block *body)
{ {
gimple *last; gimple *last;
gcond *stmt; gcond *stmt;
...@@ -2477,8 +2474,17 @@ number_of_iterations_exit_assumptions (class loop *loop, edge exit, ...@@ -2477,8 +2474,17 @@ number_of_iterations_exit_assumptions (class loop *loop, edge exit,
iv0.base = expand_simple_operations (iv0.base); iv0.base = expand_simple_operations (iv0.base);
iv1.base = expand_simple_operations (iv1.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, 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 (); fold_undefer_and_ignore_overflow_warnings ();
return false; return false;
...@@ -2721,11 +2727,12 @@ number_of_iterations_popcount (loop_p loop, edge exit, ...@@ -2721,11 +2727,12 @@ number_of_iterations_popcount (loop_p loop, edge exit,
bool bool
number_of_iterations_exit (class loop *loop, edge exit, number_of_iterations_exit (class loop *loop, edge exit,
class tree_niter_desc *niter, class tree_niter_desc *niter,
bool warn, bool every_iteration) bool warn, bool every_iteration,
basic_block *body)
{ {
gcond *stmt; gcond *stmt;
if (!number_of_iterations_exit_assumptions (loop, exit, niter, if (!number_of_iterations_exit_assumptions (loop, exit, niter,
&stmt, every_iteration)) &stmt, every_iteration, body))
return false; return false;
if (integer_nonzerop (niter->assumptions)) if (integer_nonzerop (niter->assumptions))
...@@ -3837,16 +3844,13 @@ infer_loop_bounds_from_signedness (class loop *loop, gimple *stmt) ...@@ -3837,16 +3844,13 @@ infer_loop_bounds_from_signedness (class loop *loop, gimple *stmt)
*/ */
static void static void
infer_loop_bounds_from_undefined (class loop *loop) infer_loop_bounds_from_undefined (class loop *loop, basic_block *bbs)
{ {
unsigned i; unsigned i;
basic_block *bbs;
gimple_stmt_iterator bsi; gimple_stmt_iterator bsi;
basic_block bb; basic_block bb;
bool reliable; bool reliable;
bbs = get_loop_body (loop);
for (i = 0; i < loop->num_nodes; i++) for (i = 0; i < loop->num_nodes; i++)
{ {
bb = bbs[i]; bb = bbs[i];
...@@ -3871,8 +3875,6 @@ infer_loop_bounds_from_undefined (class loop *loop) ...@@ -3871,8 +3875,6 @@ infer_loop_bounds_from_undefined (class loop *loop)
} }
} }
free (bbs);
} }
/* Compare wide ints, callback for qsort. */ /* Compare wide ints, callback for qsort. */
...@@ -4275,8 +4277,9 @@ estimate_numbers_of_iterations (class loop *loop) ...@@ -4275,8 +4277,9 @@ estimate_numbers_of_iterations (class loop *loop)
diagnose those loops with -Waggressive-loop-optimizations. */ diagnose those loops with -Waggressive-loop-optimizations. */
number_of_latch_executions (loop); number_of_latch_executions (loop);
exits = get_loop_exit_edges (loop); basic_block *body = get_loop_body (loop);
likely_exit = single_likely_exit (loop); exits = get_loop_exit_edges (loop, body);
likely_exit = single_likely_exit (loop, exits);
FOR_EACH_VEC_ELT (exits, i, ex) FOR_EACH_VEC_ELT (exits, i, ex)
{ {
if (ex == likely_exit) if (ex == likely_exit)
...@@ -4296,7 +4299,8 @@ estimate_numbers_of_iterations (class loop *loop) ...@@ -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; continue;
niter = niter_desc.niter; niter = niter_desc.niter;
...@@ -4313,7 +4317,7 @@ estimate_numbers_of_iterations (class loop *loop) ...@@ -4313,7 +4317,7 @@ estimate_numbers_of_iterations (class loop *loop)
exits.release (); exits.release ();
if (flag_aggressive_loop_optimizations) 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); discover_iteration_bound_by_body_walk (loop);
......
...@@ -22,13 +22,16 @@ along with GCC; see the file COPYING3. If not see ...@@ -22,13 +22,16 @@ along with GCC; see the file COPYING3. If not see
extern tree expand_simple_operations (tree, tree = NULL); extern tree expand_simple_operations (tree, tree = NULL);
extern tree simplify_using_initial_conditions (class loop *, tree); 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, extern bool number_of_iterations_exit (class loop *, edge,
class tree_niter_desc *niter, bool, 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, extern bool number_of_iterations_exit_assumptions (class loop *, edge,
class tree_niter_desc *, class tree_niter_desc *,
gcond **, bool = true); gcond **, bool = true,
basic_block * = NULL);
extern tree find_loop_niter (class loop *, edge *); extern tree find_loop_niter (class loop *, edge *);
extern bool finite_loop_p (class loop *); extern bool finite_loop_p (class loop *);
extern tree loop_niter_by_eval (class loop *, edge); extern tree loop_niter_by_eval (class loop *, edge);
......
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