Hi the following patch makes cfgbuild to preserve profile when loops are introduced at RTL level (not very well, but at least do not throw it all away) and also avoids re-computing probabilities when there are no changes to CFG.
Bootstrapped/regtested x86_64-linux. Comitted. Honza Index: cfgbuild.c =================================================================== --- cfgbuild.c (revision 248915) +++ cfgbuild.c (working copy) @@ -475,6 +475,10 @@ find_bb_boundaries (basic_block bb) bb = fallthru->dest; remove_edge (fallthru); + /* BB is unreachable at this point - we need to determine its profile + once edges are built. */ + bb->frequency = 0; + bb->count = profile_count::uninitialized (); flow_transfer_insn = NULL; if (code == CODE_LABEL && LABEL_ALT_ENTRY_P (insn)) make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun), bb, 0); @@ -577,7 +581,7 @@ compute_outgoing_frequencies (basic_bloc guess_outgoing_edge_probabilities (b); } - if (b->count > profile_count::zero ()) + if (b->count.initialized_p ()) FOR_EACH_EDGE (e, ei, b->succs) e->count = b->count.apply_probability (e->probability); } @@ -590,6 +594,9 @@ void find_many_sub_basic_blocks (sbitmap blocks) { basic_block bb, min, max; + bool found = false; + auto_vec<unsigned int> n_succs; + n_succs.safe_grow_cleared (last_basic_block_for_fn (cfun)); FOR_EACH_BB_FN (bb, cfun) SET_STATE (bb, @@ -597,11 +604,24 @@ find_many_sub_basic_blocks (sbitmap bloc FOR_EACH_BB_FN (bb, cfun) if (STATE (bb) == BLOCK_TO_SPLIT) - find_bb_boundaries (bb); + { + int n = last_basic_block_for_fn (cfun); + unsigned int ns = EDGE_COUNT (bb->succs); + + find_bb_boundaries (bb); + if (n == last_basic_block_for_fn (cfun) && ns == EDGE_COUNT (bb->succs)) + n_succs[bb->index] = EDGE_COUNT (bb->succs); + } FOR_EACH_BB_FN (bb, cfun) if (STATE (bb) != BLOCK_ORIGINAL) - break; + { + found = true; + break; + } + + if (!found) + return; min = max = bb; for (; bb != EXIT_BLOCK_PTR_FOR_FN (cfun); bb = bb->next_bb) @@ -624,14 +644,37 @@ find_many_sub_basic_blocks (sbitmap bloc continue; if (STATE (bb) == BLOCK_NEW) { + bool initialized_src = false, uninitialized_src = false; bb->count = profile_count::zero (); bb->frequency = 0; FOR_EACH_EDGE (e, ei, bb->preds) { - bb->count += e->count; + if (e->count.initialized_p ()) + { + bb->count += e->count; + initialized_src = true; + } + else + uninitialized_src = false; bb->frequency += EDGE_FREQUENCY (e); } + /* When some edges are missing with read profile, this is + most likely because RTL expansion introduced loop. + When profile is guessed we may have BB that is reachable + from unlikely path as well as from normal path. + + TODO: We should handle loops created during BB expansion + correctly here. For now we assume all those loop to cycle + precisely once. */ + if (!initialized_src + || (uninitialized_src + && profile_status_for_fn (cfun) != PROFILE_READ)) + bb->count = profile_count::uninitialized (); } + else + /* If nothing changed, there is no need to create new BBs. */ + if (EDGE_COUNT (bb->succs) == n_succs[bb->index]) + continue; compute_outgoing_frequencies (bb); }