This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix profile updating in cfgbuild


Hi
the following patch makes cfgbuild to preserve profile when loops are
introduced at RTL level (not very well, but at least do not throw it all
away) and also avoids re-computing probabilities when there are no
changes to CFG.

Bootstrapped/regtested x86_64-linux. Comitted.

Honza

Index: cfgbuild.c
===================================================================
--- cfgbuild.c	(revision 248915)
+++ cfgbuild.c	(working copy)
@@ -475,6 +475,10 @@ find_bb_boundaries (basic_block bb)
 
 	  bb = fallthru->dest;
 	  remove_edge (fallthru);
+	  /* BB is unreachable at this point - we need to determine its profile
+	     once edges are built.  */
+	  bb->frequency = 0;
+	  bb->count = profile_count::uninitialized ();
 	  flow_transfer_insn = NULL;
 	  if (code == CODE_LABEL && LABEL_ALT_ENTRY_P (insn))
 	    make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, 0);
@@ -577,7 +581,7 @@ compute_outgoing_frequencies (basic_bloc
         guess_outgoing_edge_probabilities (b);
     }
 
-  if (b->count > profile_count::zero ())
+  if (b->count.initialized_p ())
     FOR_EACH_EDGE (e, ei, b->succs)
       e->count = b->count.apply_probability (e->probability);
 }
@@ -590,6 +594,9 @@ void
 find_many_sub_basic_blocks (sbitmap blocks)
 {
   basic_block bb, min, max;
+  bool found = false;
+  auto_vec<unsigned int> n_succs;
+  n_succs.safe_grow_cleared (last_basic_block_for_fn (cfun));
 
   FOR_EACH_BB_FN (bb, cfun)
     SET_STATE (bb,
@@ -597,11 +604,24 @@ find_many_sub_basic_blocks (sbitmap bloc
 
   FOR_EACH_BB_FN (bb, cfun)
     if (STATE (bb) == BLOCK_TO_SPLIT)
-      find_bb_boundaries (bb);
+      {
+	int n = last_basic_block_for_fn (cfun);
+	unsigned int ns = EDGE_COUNT (bb->succs);
+
+        find_bb_boundaries (bb);
+	if (n == last_basic_block_for_fn (cfun) && ns == EDGE_COUNT (bb->succs))
+	  n_succs[bb->index] = EDGE_COUNT (bb->succs);
+      }
 
   FOR_EACH_BB_FN (bb, cfun)
     if (STATE (bb) != BLOCK_ORIGINAL)
-      break;
+      {
+	found = true;
+        break;
+      }
+
+  if (!found)
+    return;
 
   min = max = bb;
   for (; bb != EXIT_BLOCK_PTR_FOR_FN (cfun); bb = bb->next_bb)
@@ -624,14 +644,37 @@ find_many_sub_basic_blocks (sbitmap bloc
 	  continue;
 	if (STATE (bb) == BLOCK_NEW)
 	  {
+	    bool initialized_src = false, uninitialized_src = false;
 	    bb->count = profile_count::zero ();
 	    bb->frequency = 0;
 	    FOR_EACH_EDGE (e, ei, bb->preds)
 	      {
-		bb->count += e->count;
+		if (e->count.initialized_p ())
+		  {
+		    bb->count += e->count;
+		    initialized_src = true;
+		  }
+		else
+		  uninitialized_src = false;
 		bb->frequency += EDGE_FREQUENCY (e);
 	      }
+	    /* When some edges are missing with read profile, this is
+	       most likely because RTL expansion introduced loop.
+	       When profile is guessed we may have BB that is reachable
+	       from unlikely path as well as from normal path.
+
+	       TODO: We should handle loops created during BB expansion
+	       correctly here.  For now we assume all those loop to cycle
+	       precisely once.  */
+	    if (!initialized_src
+		|| (uninitialized_src
+		     && profile_status_for_fn (cfun) != PROFILE_READ))
+	      bb->count = profile_count::uninitialized ();
 	  }
+	else
+	  /* If nothing changed, there is no need to create new BBs.  */
+	  if (EDGE_COUNT (bb->succs) == n_succs[bb->index])
+	    continue;
 
 	compute_outgoing_frequencies (bb);
       }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]