Patchwork add find_fallthru_edge function

login
register
mail settings
Submitter Nathan Froyd
Date Oct. 9, 2010, 3:13 a.m.
Message ID <20101009031336.GW17388@nightcrawler>
Download mbox | patch
Permalink /patch/67312/
State New
Headers show

Comments

Nathan Froyd - Oct. 9, 2010, 3:13 a.m.
The patch below creates a helper function for the common act of finding
the fallthru edge in an edge list and uses the new function in a number
of places.

The only complication is that the scheduler infrastructure already had a
find_fallthru_edge function that worked slightly differently.  I have
renamed said function to find_fallthru_edge_from and updated uses
appropriately.

A find_edge_with_flags function would not be out of place, but that will
have to wait for a later cleanup.

Bootstrapped on x86_64-unknown-linux-gnu.  OK to commit?

-Nathan

	* basic-block.h (find_fallthru_edge): Declare.
	* cfganal.c (find_fallthru_edge): New function.
	* cfgcleanup.c (merge_blocks_move): Use it.
	(try_crossjump_bb): Likewise.
	* cfglayout.c (fixup_reorder_chains): Likewise.
	(fixup_fallthru_exit_predecessor): Likewise.
	* cfgrtl.c (rtl_split_edge): Likewise.
	(rtl_verify_flow_info): Likewise.
	* function.c (thread_prologue_and_epilogue_insns): Likewise.
	* gimple-pretty-print.c (dump_implicit_edges): Likewise.
	* ifcvt.c (block_fallthru): Likewise.
	* reload1.c (fixup_abnormal_edges): Likewise.
	* sched-ebb.c (being_schedule_ready): Likewise.
	(schedule_ebb): Likwise.
	* sched-rgn.c (find_single_block_region): Likewise.
	* sel-sched-ir.c (bb_ends_ebb_p): Likewise.
	* tree-complex.c (expand_complex_move): Likewise.
	* sched-int.h (find_fallthru_edge): Rename to...
	(find_fallthru_edge_from): ...this.
	* haifa-sched.c (find_fallthru_edge): Rename to...
	(find_fallthru_edge_from): ...this.  Use new find_fallthru_edge.
	(init_before_recovery): Call find_fallthru_edge_from.
	* sel-sched-ir.c (merge_fences): Likewise.
	* sel-sched.c (in_fallthru_bb_p): Likewise.
	(move_cond_jump): Likewise.
Eric Botcazou - Oct. 9, 2010, 9:10 a.m.
> 	* basic-block.h (find_fallthru_edge): Declare.
> 	* cfganal.c (find_fallthru_edge): New function.

We have similar helpers inlined in basic-block.h:

static inline bool
bb_has_eh_pred (basic_block bb)
{
  edge e;
  edge_iterator ei;

  FOR_EACH_EDGE (e, ei, bb->preds)
    {
      if (e->flags & EDGE_EH)
	return true;
    }
  return false;
}

static inline bool
bb_has_abnormal_pred (basic_block bb)
{
  edge e;
  edge_iterator ei;

  FOR_EACH_EDGE (e, ei, bb->preds)
    {
      if (e->flags & EDGE_ABNORMAL)
	return true;
    }
  return false;
}

so it might make sense to do the same for find_fallthru_edge.
Mark Mitchell - Oct. 12, 2010, 6:10 p.m.
On 10/8/2010 8:13 PM, Nathan Froyd wrote:

> 	* basic-block.h (find_fallthru_edge): Declare.

OK.

If you want to do as Eric B. suggests and put this inline in
basic-block.h, that's pre-approved as well.  But, I'm not sure if that's
a useful optimization or not; I have no idea as to what the profile of
these functions might be.

Thanks,
Nathan Froyd - Oct. 21, 2010, 2:33 a.m.
On Tue, Oct 12, 2010 at 11:10:14AM -0700, Mark Mitchell wrote:
> On 10/8/2010 8:13 PM, Nathan Froyd wrote:
> > 	* basic-block.h (find_fallthru_edge): Declare.
> 
> OK.
> 
> If you want to do as Eric B. suggests and put this inline in
> basic-block.h, that's pre-approved as well.  But, I'm not sure if that's
> a useful optimization or not; I have no idea as to what the profile of
> these functions might be.

I've committed this with Eric's suggestion.

Thanks,
-Nathan

Patch

diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index e274d6c..5568eb0 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -803,6 +803,7 @@  extern bool can_fallthru (basic_block, basic_block);
 extern bool could_fall_through (basic_block, basic_block);
 extern void flow_nodes_print (const char *, const_sbitmap, FILE *);
 extern void flow_edge_list_print (const char *, const edge *, int, FILE *);
+extern edge find_fallthru_edge (VEC(edge,gc) *);
 
 /* In cfgrtl.c  */
 extern basic_block force_nonfallthru (edge);
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index b4cc86c..e058848 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -104,6 +104,21 @@  forwarder_block_p (const_basic_block bb)
 	  || !flow_active_insn_p (insn));
 }
 
+/* Return the fallthru edge in EDGES if it exists, NULL otherwise.  */
+
+edge
+find_fallthru_edge (VEC(edge,gc) *edges)
+{
+  edge e;
+  edge_iterator ei;
+
+  FOR_EACH_EDGE (e, ei, edges)
+    if (e->flags & EDGE_FALLTHRU)
+      break;
+
+  return e;
+}
+
 /* Return nonzero if we can reach target from src by falling through.  */
 
 bool
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index d28ae6f..9563e3f 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -793,7 +793,6 @@  merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
       edge tmp_edge, b_fallthru_edge;
       bool c_has_outgoing_fallthru;
       bool b_has_incoming_fallthru;
-      edge_iterator ei;
 
       /* Avoid overactive code motion, as the forwarder blocks should be
 	 eliminated by edge redirection instead.  One exception might have
@@ -806,16 +805,10 @@  merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
 	 and loop notes.  This is done by squeezing out all the notes
 	 and leaving them there to lie.  Not ideal, but functional.  */
 
-      FOR_EACH_EDGE (tmp_edge, ei, c->succs)
-	if (tmp_edge->flags & EDGE_FALLTHRU)
-	  break;
-
+      tmp_edge = find_fallthru_edge (c->succs);
       c_has_outgoing_fallthru = (tmp_edge != NULL);
 
-      FOR_EACH_EDGE (tmp_edge, ei, b->preds)
-	if (tmp_edge->flags & EDGE_FALLTHRU)
-	  break;
-
+      tmp_edge = find_fallthru_edge (b->preds);
       b_has_incoming_fallthru = (tmp_edge != NULL);
       b_fallthru_edge = tmp_edge;
       next = b->prev_bb;
@@ -1801,7 +1794,6 @@  try_crossjump_bb (int mode, basic_block bb)
   bool changed;
   unsigned max, ix, ix2;
   basic_block ev, ev2;
-  edge_iterator ei;
 
   /* Nothing to do if there is not at least two incoming edges.  */
   if (EDGE_COUNT (bb->preds) < 2)
@@ -1838,14 +1830,7 @@  try_crossjump_bb (int mode, basic_block bb)
   if (EDGE_COUNT (bb->preds) > max)
     return false;
 
-  FOR_EACH_EDGE (e, ei, bb->preds)
-    {
-      if (e->flags & EDGE_FALLTHRU)
-	{
-	  fallthru = e;
-	  break;
-	}
-    }
+  fallthru = find_fallthru_edge (bb->preds);
 
   changed = false;
   for (ix = 0, ev = bb; ix < EDGE_COUNT (ev->preds); )
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index e93e407..9fc05fe 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -927,12 +927,7 @@  fixup_reorder_chain (void)
   /* Annoying special case - jump around dead jumptables left in the code.  */
   FOR_EACH_BB (bb)
     {
-      edge e;
-      edge_iterator ei;
-
-      FOR_EACH_EDGE (e, ei, bb->succs)
-	if (e->flags & EDGE_FALLTHRU)
-	  break;
+      edge e = find_fallthru_edge (bb->succs);
 
       if (e && !can_fallthru (e->src, e->dest))
 	force_nonfallthru (e);
@@ -1019,7 +1014,6 @@  static void
 fixup_fallthru_exit_predecessor (void)
 {
   edge e;
-  edge_iterator ei;
   basic_block bb = NULL;
 
   /* This transformation is not valid before reload, because we might
@@ -1027,9 +1021,9 @@  fixup_fallthru_exit_predecessor (void)
      value.  */
   gcc_assert (reload_completed);
 
-  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
-    if (e->flags & EDGE_FALLTHRU)
-      bb = e->src;
+  e = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
+  if (e)
+    bb = e->src;
 
   if (bb && bb->aux)
     {
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index f7ce558..e46050d 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -1370,12 +1370,7 @@  rtl_split_edge (edge edge_in)
      Avoid existence of fallthru predecessors.  */
   if ((edge_in->flags & EDGE_FALLTHRU) == 0)
     {
-      edge e;
-      edge_iterator ei;
-
-      FOR_EACH_EDGE (e, ei, edge_in->dest->preds)
-	if (e->flags & EDGE_FALLTHRU)
-	  break;
+      edge e = find_fallthru_edge (edge_in->dest->preds);
 
       if (e)
 	force_nonfallthru (e);
@@ -2068,7 +2063,6 @@  rtl_verify_flow_info (void)
   FOR_EACH_BB_REVERSE (bb)
     {
       edge e;
-      edge_iterator ei;
       rtx head = BB_HEAD (bb);
       rtx end = BB_END (bb);
 
@@ -2122,9 +2116,7 @@  rtl_verify_flow_info (void)
 
       last_head = PREV_INSN (x);
 
-      FOR_EACH_EDGE (e, ei, bb->succs)
-	if (e->flags & EDGE_FALLTHRU)
-	  break;
+      e = find_fallthru_edge (bb->succs);
       if (!e)
 	{
 	  rtx insn;
diff --git a/gcc/function.c b/gcc/function.c
index 21f8537..d0da7dc 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5311,9 +5311,7 @@  thread_prologue_and_epilogue_insns (void)
       basic_block last;
       rtx label;
 
-      FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
-	if (e->flags & EDGE_FALLTHRU)
-	  break;
+      e = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
       if (e == NULL)
 	goto epilogue_done;
       last = e->src;
@@ -5434,9 +5432,7 @@  thread_prologue_and_epilogue_insns (void)
      There really shouldn't be a mixture -- either all should have
      been converted or none, however...  */
 
-  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
-    if (e->flags & EDGE_FALLTHRU)
-      break;
+  e = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
   if (e == NULL)
     goto epilogue_done;
 
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 941d323..c74dd0e 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1976,7 +1976,6 @@  dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent,
 		     int flags)
 {
   edge e;
-  edge_iterator ei;
   gimple stmt;
 
   stmt = last_stmt (bb);
@@ -2004,9 +2003,7 @@  dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent,
 
   /* If there is a fallthru edge, we may need to add an artificial
      goto to the dump.  */
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    if (e->flags & EDGE_FALLTHRU)
-      break;
+  e = find_fallthru_edge (bb->succs);
 
   if (e && e->dest != bb->next_bb)
     {
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 5b5459f..015f8b9 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -4247,10 +4247,9 @@  xrecalloc (void *p, size_t new_nmemb, size_t old_nmemb, size_t size)
 /* Helper function.
    Find fallthru edge from PRED.  */
 edge
-find_fallthru_edge (basic_block pred)
+find_fallthru_edge_from (basic_block pred)
 {
   edge e;
-  edge_iterator ei;
   basic_block succ;
 
   succ = pred->next_bb;
@@ -4258,21 +4257,23 @@  find_fallthru_edge (basic_block pred)
 
   if (EDGE_COUNT (pred->succs) <= EDGE_COUNT (succ->preds))
     {
-      FOR_EACH_EDGE (e, ei, pred->succs)
-	if (e->flags & EDGE_FALLTHRU)
-	  {
-	    gcc_assert (e->dest == succ);
-	    return e;
-	  }
+      e = find_fallthru_edge (pred->succs);
+
+      if (e)
+	{
+	  gcc_assert (e->dest == succ);
+	  return e;
+	}
     }
   else
     {
-      FOR_EACH_EDGE (e, ei, succ->preds)
-	if (e->flags & EDGE_FALLTHRU)
-	  {
-	    gcc_assert (e->src == pred);
-	    return e;
-	  }
+      e = find_fallthru_edge (succ->preds);
+
+      if (e)
+	{
+	  gcc_assert (e->src == pred);
+	  return e;
+	}
     }
 
   return NULL;
@@ -4314,7 +4315,7 @@  init_before_recovery (basic_block *before_recovery_ptr)
   edge e;
 
   last = EXIT_BLOCK_PTR->prev_bb;
-  e = find_fallthru_edge (last);
+  e = find_fallthru_edge_from (last);
 
   if (e)
     {
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 4e3a685..3b05b37 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -234,12 +234,7 @@  last_active_insn (basic_block bb, int skip_use_p)
 static basic_block
 block_fallthru (basic_block bb)
 {
-  edge e;
-  edge_iterator ei;
-
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    if (e->flags & EDGE_FALLTHRU)
-      break;
+  edge e = find_fallthru_edge (bb->succs);
 
   return (e) ? e->dest : NULL_BLOCK;
 }
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 40098b3..3bb6ce1 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -9161,9 +9161,7 @@  fixup_abnormal_edges (void)
 	      BB_END (bb) = insn;
 	      insn = NEXT_INSN (insn);
 
-	      FOR_EACH_EDGE (e, ei, bb->succs)
-		if (e->flags & EDGE_FALLTHRU)
-		  break;
+	      e = find_fallthru_edge (bb->succs);
 
 	      while (insn && insn != stop)
 		{
diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c
index 2e797b1..8e69215 100644
--- a/gcc/sched-ebb.c
+++ b/gcc/sched-ebb.c
@@ -138,7 +138,6 @@  begin_schedule_ready (rtx insn, rtx last)
       && last != PREV_INSN (insn))
     {
       edge e;
-      edge_iterator ei;
       basic_block bb;
 
       /* An obscure special case, where we do have partially dead
@@ -146,9 +145,7 @@  begin_schedule_ready (rtx insn, rtx last)
 	 In this case we can create new basic block.  It is
 	 always exactly one basic block last in the sequence.  */
 
-      FOR_EACH_EDGE (e, ei, last_bb->succs)
-	if (e->flags & EDGE_FALLTHRU)
-	  break;
+      e = find_fallthru_edge (last_bb->succs);
 
 #ifdef ENABLE_CHECKING
       gcc_assert (!e || !(e->flags & EDGE_COMPLEX));
@@ -589,14 +586,11 @@  schedule_ebbs (void)
       for (;;)
 	{
 	  edge e;
-	  edge_iterator ei;
 	  tail = BB_END (bb);
 	  if (bb->next_bb == EXIT_BLOCK_PTR
 	      || LABEL_P (BB_HEAD (bb->next_bb)))
 	    break;
-	  FOR_EACH_EDGE (e, ei, bb->succs)
-	    if ((e->flags & EDGE_FALLTHRU) != 0)
-	      break;
+	  e = find_fallthru_edge (bb->succs);
 	  if (! e)
 	    break;
 	  if (e->probability <= probability_cutoff)
diff --git a/gcc/sched-int.h b/gcc/sched-int.h
index fd2e15d..bea5aab 100644
--- a/gcc/sched-int.h
+++ b/gcc/sched-int.h
@@ -199,7 +199,7 @@  extern int max_issue (struct ready_list *, int, state_t, int *);
 
 extern void ebb_compute_jump_reg_dependencies (rtx, regset, regset, regset);
 
-extern edge find_fallthru_edge (basic_block);
+extern edge find_fallthru_edge_from (basic_block);
 
 extern void (* sched_init_only_bb) (basic_block, basic_block);
 extern basic_block (* sched_split_block) (basic_block, rtx);
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index adae839..7e971e1 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -487,7 +487,6 @@  find_single_block_region (bool ebbs_p)
         for (bb = ebb_start; ; bb = bb->next_bb)
           {
             edge e;
-            edge_iterator ei;
 
             rgn_bb_table[i] = bb->index;
             RGN_NR_BLOCKS (nr_regions)++;
@@ -499,9 +498,7 @@  find_single_block_region (bool ebbs_p)
                 || LABEL_P (BB_HEAD (bb->next_bb)))
               break;
 
-            FOR_EACH_EDGE (e, ei, bb->succs)
-             if ((e->flags & EDGE_FALLTHRU) != 0)
-               break;
+	    e = find_fallthru_edge (bb->succs);
             if (! e)
               break;
             if (e->probability <= probability_cutoff)
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index a9d7ccf..7884980 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -688,7 +688,7 @@  merge_fences (fence_t f, insn_t insn,
 
       /* Find fallthrough edge.  */
       gcc_assert (BLOCK_FOR_INSN (insn)->prev_bb);
-      candidate = find_fallthru_edge (BLOCK_FOR_INSN (insn)->prev_bb);
+      candidate = find_fallthru_edge_from (BLOCK_FOR_INSN (insn)->prev_bb);
 
       if (!candidate
           || (candidate->src != BLOCK_FOR_INSN (last_scheduled_insn)
@@ -4643,7 +4643,6 @@  bb_ends_ebb_p (basic_block bb)
 {
   basic_block next_bb = bb_next_bb (bb);
   edge e;
-  edge_iterator ei;
 
   if (next_bb == EXIT_BLOCK_PTR
       || bitmap_bit_p (forced_ebb_heads, next_bb->index)
@@ -4656,13 +4655,13 @@  bb_ends_ebb_p (basic_block bb)
   if (!in_current_region_p (next_bb))
     return true;
 
-  FOR_EACH_EDGE (e, ei, bb->succs)
-    if ((e->flags & EDGE_FALLTHRU) != 0)
-      {
-	gcc_assert (e->dest == next_bb);
-
-	return false;
-      }
+  e = find_fallthru_edge (bb->succs);
+  if (e)
+    {
+      gcc_assert (e->dest == next_bb);
+      
+      return false;
+    }
 
   return true;
 }
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 0e0c7c8..106c090 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -612,12 +612,14 @@  static bool
 in_fallthru_bb_p (rtx insn, rtx succ)
 {
   basic_block bb = BLOCK_FOR_INSN (insn);
+  edge e;
 
   if (bb == BLOCK_FOR_INSN (succ))
     return true;
 
-  if (find_fallthru_edge (bb))
-    bb = find_fallthru_edge (bb)->dest;
+  e = find_fallthru_edge_from (bb);
+  if (e)
+    bb = e->dest;
   else
     return false;
 
@@ -4907,7 +4909,7 @@  move_cond_jump (rtx insn, bnd_t bnd)
   next = PREV_INSN (insn);
   BND_TO (bnd) = insn;
 
-  ft_edge = find_fallthru_edge (block_from);
+  ft_edge = find_fallthru_edge_from (block_from);
   block_next = ft_edge->dest;
   /* There must be a fallthrough block (or where should go
   control flow in case of false jump predicate otherwise?).  */
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index af85644..ec2b438 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -782,17 +782,14 @@  expand_complex_move (gimple_stmt_iterator *gsi, tree type)
     {
       if (is_ctrl_altering_stmt (stmt))
 	{
-	  edge_iterator ei;
 	  edge e;
 
 	  /* The value is not assigned on the exception edges, so we need not
 	     concern ourselves there.  We do need to update on the fallthru
 	     edge.  Find it.  */
-	  FOR_EACH_EDGE (e, ei, gsi_bb (*gsi)->succs)
-	    if (e->flags & EDGE_FALLTHRU)
-	      goto found_fallthru;
-	  gcc_unreachable ();
-	found_fallthru:
+	  e = find_fallthru_edge (gsi_bb (*gsi)->succs);
+	  if (!e)
+	    gcc_unreachable ();
 
 	  r = build1 (REALPART_EXPR, inner_type, lhs);
 	  i = build1 (IMAGPART_EXPR, inner_type, lhs);