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]

Do not merge blocks when profile would be lost


Hi,
consider function

test ()
{
  do_something_that_will_call_exit ();
  report_catastrophic_failure ();
}

No while profile estimation we know that do_something_that_will_call_exit may
end execution and thus split BBs and introduce fake edges.  After fake edges
are removed we however merge BBs and in htat case report_catastrophic_failure
gets non-zero profile.

Theresa added code to drop poroflies when sum of counts is non-zero and we also
keep preporting profile inconsistencies. The following patch fixes it by not
merging the BBs during the tree optimization.  After RTL expansion we merge them
but I think that is quite OK.

Bootstrapped/regtested x86_64-linux, plan to commit it later today.

Honza

	* tree-cfgcleanup.c (want_merge_blocks_p): New function.
        (cleanup_tree_cfg_bb): Use it.
	* profile-count.h (profile_count::of_for_merging, profile_count::merge):
	New functions.
	* tree-cfg.c (gimple_merge_blocks): Use profile_count::merge.

Index: tree-cfgcleanup.c
===================================================================
--- tree-cfgcleanup.c	(revision 249885)
+++ tree-cfgcleanup.c	(working copy)
@@ -636,6 +636,19 @@ fixup_noreturn_call (gimple *stmt)
   return changed;
 }
 
+/* Return true if we want to merge BB1 and BB2 into a single block.  */
+
+static bool
+want_merge_blocks_p (basic_block bb1, basic_block bb2)
+{
+  if (!can_merge_blocks_p (bb1, bb2))
+    return false;
+  gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb1);
+  if (gsi_end_p (gsi) || !stmt_can_terminate_bb_p (gsi_stmt (gsi)))
+    return true;
+  return bb1->count.ok_for_merging (bb2->count);
+}
+
 
 /* Tries to cleanup cfg in basic block BB.  Returns true if anything
    changes.  */
@@ -652,7 +665,7 @@ cleanup_tree_cfg_bb (basic_block bb)
      This happens when we visit BBs in a non-optimal order and
      avoids quadratic behavior with adjusting stmts BB pointer.  */
   if (single_pred_p (bb)
-      && can_merge_blocks_p (single_pred (bb), bb))
+      && want_merge_blocks_p (single_pred (bb), bb))
     /* But make sure we _do_ visit it.  When we remove unreachable paths
        ending in a backedge we fail to mark the destinations predecessors
        as changed.  */
@@ -662,7 +675,7 @@ cleanup_tree_cfg_bb (basic_block bb)
      conditional branches (due to the elimination of single-valued PHI
      nodes).  */
   else if (single_succ_p (bb)
-	   && can_merge_blocks_p (bb, single_succ (bb)))
+	   && want_merge_blocks_p (bb, single_succ (bb)))
     {
       merge_blocks (bb, single_succ (bb));
       return true;
Index: profile-count.h
===================================================================
--- profile-count.h	(revision 249885)
+++ profile-count.h	(working copy)
@@ -565,6 +565,31 @@ public:
       return initialized_p ();
     }
 
+  /* When merging basic blocks, the two different profile counts are unified.
+     Return true if this can be done without losing info about profile.
+     The only case we care about here is when first BB contains something
+     that makes it terminate in a way not visible in CFG.  */
+  bool ok_for_merging (profile_count other) const
+    {
+      if (m_quality < profile_adjusted
+	  || other.m_quality < profile_adjusted)
+	return true;
+      return !(other < *this);
+    }
+
+  /* When merging two BBs with different counts, pick common count that looks
+     most representative.  */
+  profile_count merge (profile_count other) const
+    {
+      if (*this == other || !other.initialized_p ()
+	  || m_quality > other.m_quality)
+	return *this;
+      if (other.m_quality > m_quality
+	  || other > *this)
+	return other;
+      return *this;
+    }
+
   /* Basic operations.  */
   bool operator== (const profile_count &other) const
     {
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 249887)
+++ tree-cfg.c	(working copy)
@@ -2076,7 +2081,7 @@ gimple_merge_blocks (basic_block a, basi
      profiles.  */
   if (a->loop_father == b->loop_father)
     {
-      a->count = MAX (a->count, b->count);
+      a->count = a->count.merge (b->count);
       a->frequency = MAX (a->frequency, b->frequency);
     }
 


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