From f10d2d85c90c9c649675c248cd5a99f66288f81f Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Mon, 25 Nov 2019 07:51:38 +0000 Subject: [PATCH] cfgloop.h (get_loop_exit_edges): Add extra parameter denoting loop body, defaulted to NULL. 2019-11-25 Richard Biener * 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 --- gcc/ChangeLog | 23 ++++++++++++++++++++ gcc/cfgloop.c | 13 ++++++++---- gcc/cfgloop.h | 4 ++-- gcc/cfgloopanal.c | 10 ++------- gcc/tree-ssa-loop-ivcanon.c | 4 +++- gcc/tree-ssa-loop-ivopts.c | 3 ++- gcc/tree-ssa-loop-niter.c | 42 ++++++++++++++++++++----------------- gcc/tree-ssa-loop-niter.h | 9 +++++--- 8 files changed, 70 insertions(+), 38 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a385d20617d..f4d0ee5db7b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2019-11-25 Richard Biener + + * 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 * cfganal.c (pre_and_rev_post_order_compute_fn): Use an diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 308ed7d18d0..c766471aa09 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -1203,12 +1203,11 @@ release_recorded_exits (function *fn) /* Returns the list of the exit edges of a LOOP. */ vec -get_loop_exit_edges (const class loop *loop) +get_loop_exit_edges (const class loop *loop, basic_block *body) { vec 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; diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index e3590d712b0..2979febe2e0 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -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 get_loop_exit_edges (const class loop *); +extern vec 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); extern unsigned num_loop_branches (const class loop *); extern edge loop_preheader_edge (const class loop *); diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index 199c20b1423..d78bfc66f4b 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -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 exits) { edge found = single_exit (loop); - vec 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; } diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 63c2c6bdb08..979b250e83e 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -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 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. */ diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index ab52cbe7afa..3b2a493dcb9 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -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. */ diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index d5c1b5b925f..f0dd9a0b363 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -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); diff --git a/gcc/tree-ssa-loop-niter.h b/gcc/tree-ssa-loop-niter.h index aec6225125c..742d3b8e140 100644 --- a/gcc/tree-ssa-loop-niter.h +++ b/gcc/tree-ssa-loop-niter.h @@ -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); -- 2.30.2