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); }