cfgloop.h (get_loop_exit_edges): Add extra parameter denoting loop body, defaulted...
authorRichard Biener <rguenther@suse.de>
Mon, 25 Nov 2019 07:51:38 +0000 (07:51 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 25 Nov 2019 07:51:38 +0000 (07:51 +0000)
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

gcc/ChangeLog
gcc/cfgloop.c
gcc/cfgloop.h
gcc/cfgloopanal.c
gcc/tree-ssa-loop-ivcanon.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-loop-niter.c
gcc/tree-ssa-loop-niter.h

index a385d20617d39fae33dd32c9dabb12f38b838f15..f4d0ee5db7b58e49ac6f234eda53e176a661cad7 100644 (file)
@@ -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
index 308ed7d18d0ba01f9ee5492475f0ed4ee4216885..c766471aa09720f3d259bee900903cc1be558412 100644 (file)
@@ -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;
index e3590d712b0f543c08ed5142bd6dc84f811c8ef9..2979febe2e07b11e1257ba262164777528c9dd22 100644 (file)
@@ -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 *);
index 199c20b1423418d99ceee10bf032b355e3c831f6..d78bfc66f4b30138d71e7cc4522957fbd498a2cc 100644 (file)
@@ -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;
 }
 
index 63c2c6bdb083f340c0da52dd53db7acab9831d04..979b250e83e017139ced476453085ab58646bf64 100644 (file)
@@ -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.  */
index ab52cbe7afa1ca4315cddcf5c0647040deaf757f..3b2a493dcb94b53d80f3a992f69e304b2029f723 100644 (file)
@@ -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.  */
index d5c1b5b925f9fdd49356e578529735bb3d6ff77e..f0dd9a0b36345e245b915db3dab33a2228421fee 100644 (file)
@@ -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);
 
index aec6225125ce42ab0e4dbc930fc1a93862e6e267..742d3b8e140ef593f3ef8b9c9a7eaecc2bee2b91 100644 (file)
@@ -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);