* 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
+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
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
{
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);
}
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. */
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. */
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;