From b5db8b44e55b6d95865c59e92779dc7dc2e3c273 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Mon, 3 Jul 2017 14:42:07 +0200 Subject: [PATCH] tree-cfgcleanup.c (want_merge_blocks_p): New function. * 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 | 8 ++++++++ gcc/profile-count.h | 25 +++++++++++++++++++++++++ gcc/tree-cfg.c | 2 +- gcc/tree-cfgcleanup.c | 17 +++++++++++++++-- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 19c6c29070b..3d0826ae6c9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-07-02 Jan Hubicka + + * 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 PR bootstrap/81285 diff --git a/gcc/profile-count.h b/gcc/profile-count.h index 73bc8ed0506..e63b964413a 100644 --- a/gcc/profile-count.h +++ b/gcc/profile-count.h @@ -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 { diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 6add0402080..e0cee12a69e 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -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); } diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index b4127f968ff..c6e5c8da03c 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -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; -- 2.30.2