tree-cfgcleanup.c (want_merge_blocks_p): New function.
authorJan Hubicka <hubicka@ucw.cz>
Mon, 3 Jul 2017 12:42:07 +0000 (14:42 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Mon, 3 Jul 2017 12:42:07 +0000 (12:42 +0000)
* 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.

From-SVN: r249907

gcc/ChangeLog
gcc/profile-count.h
gcc/tree-cfg.c
gcc/tree-cfgcleanup.c

index 19c6c29070bda8d013f99f1d84a68f1baa1ca05b..3d0826ae6c9ee4e05c777528199993b0b879b716 100644 (file)
@@ -1,3 +1,11 @@
+2017-07-02  Jan Hubicka  <hubicka@ucw.cz>
+
+       * 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.
+
 2017-07-02  Jan Hubicka  <hubicka@ucw.cz>
 
        PR bootstrap/81285
index 73bc8ed0506bcd7e138185071efb6193b356936d..e63b964413a9215e0f4adc0e47c96b6c090100c5 100644 (file)
@@ -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 6add0402080e62b2c93d54ece324ef58faf1cb95..e0cee12a69ebf12d0ffd756f3c586fd8c2963ae5 100644 (file)
@@ -2076,7 +2076,7 @@ gimple_merge_blocks (basic_block a, basic_block b)
      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 b4127f968ff353a97b1eba8c5326827fce8b4b0f..c6e5c8da03c3391e1da693281d6ebf8ff2f2b3b2 100644 (file)
@@ -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;