diff mbox series

[2/3] Add get_loop_body_in_rpo

Message ID 20240405131314.DEC1A139F1@imap2.dmz-prg2.suse.org
State New
Headers show
Series [1/3] Pass reliable down to infer_loop_bounds_from_array | expand

Commit Message

Richard Biener April 5, 2024, 1:13 p.m. UTC
The following adds another get_loop_body variant, one to get blocks
in RPO.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

	* cfgloop.h (get_loop_body_in_rpo): Declare.
	* cfgloop.cc (get_loop_body_in_rpo): Compute loop body in RPO.
---
 gcc/cfgloop.cc | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/cfgloop.h  |  1 +
 2 files changed, 69 insertions(+)
diff mbox series

Patch

diff --git a/gcc/cfgloop.cc b/gcc/cfgloop.cc
index 5202c3865d1..d79a006554f 100644
--- a/gcc/cfgloop.cc
+++ b/gcc/cfgloop.cc
@@ -1021,6 +1021,74 @@  get_loop_body_in_bfs_order (const class loop *loop)
   return blocks;
 }
 
+/* Get the body of LOOP in FN in reverse post order.  */
+
+basic_block *
+get_loop_body_in_rpo (function *fn, const class loop *loop)
+{
+  auto_vec<edge_iterator, 20> stack (loop->num_nodes + 1);
+  auto_bb_flag visited (fn);
+
+  basic_block *blocks = XNEWVEC (basic_block, loop->num_nodes);
+  int rev_post_order_num = loop->num_nodes - 1;
+
+  /* Find a block leading to the loop header.  */
+  edge_iterator ei;
+  edge e;
+  FOR_EACH_EDGE (e, ei, loop->header->preds)
+    if (!flow_bb_inside_loop_p (loop, e->src))
+      break;
+  basic_block preheader = e->src;
+
+  stack.quick_push (ei_start (preheader->succs));
+
+  while (!stack.is_empty ())
+    {
+      basic_block src;
+      basic_block dest;
+
+      /* Look at the edge on the top of the stack.  */
+      edge_iterator ei = stack.last ();
+      src = ei_edge (ei)->src;
+      dest = ei_edge (ei)->dest;
+
+      /* Check if the edge destination has been visited yet.  */
+      if (flow_bb_inside_loop_p (loop, dest)
+	  && ! (dest->flags & visited))
+	{
+	  /* Mark that we have visited the destination.  */
+	  dest->flags |= visited;
+
+	  if (EDGE_COUNT (dest->succs) > 0)
+	    /* Since the DEST node has been visited for the first
+	       time, check its successors.  */
+	    stack.quick_push (ei_start (dest->succs));
+	  else
+	    /* There are no successors for the DEST node so record
+	       the block.  */
+	    blocks[rev_post_order_num--] = dest;
+	}
+      else
+	{
+	  if (ei_one_before_end_p (ei)
+	      && src != preheader)
+	    /* There are no more successors for the SRC node
+	       so record the block.  */
+	    blocks[rev_post_order_num--] = src;
+
+	  if (!ei_one_before_end_p (ei))
+	    ei_next (&stack.last ());
+	  else
+	    stack.pop ();
+	}
+    }
+
+  for (int i = rev_post_order_num + 1; i < (int) loop->num_nodes; ++i)
+    blocks[i]->flags &= ~visited;
+
+  return blocks;
+}
+
 /* Hash function for struct loop_exit.  */
 
 hashval_t
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 30b5e40d0d9..42f3079102d 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -385,6 +385,7 @@  extern basic_block *get_loop_body_in_custom_order (const class loop *,
 			       int (*) (const void *, const void *));
 extern basic_block *get_loop_body_in_custom_order (const class loop *, void *,
 			       int (*) (const void *, const void *, void *));
+extern basic_block *get_loop_body_in_rpo (function *, const class loop *);
 
 extern auto_vec<edge> get_loop_exit_edges (const class loop *, basic_block * = NULL);
 extern edge single_exit (const class loop *);