Hi, > gcc/ChangeLog: > > PR tree-optimization/117790 > * cfgloopmanip.cc (can_flow_scale_loop_freqs_p): New. > (flow_scale_loop_freqs): New. > (scale_loop_freqs_with_exit_counts): New. > (scale_loop_freqs_hold_exit_counts): New. > (scale_loop_profile): Refactor to use the newly-added > scale_loop_profile_1, and use scale_loop_freqs_hold_exit_counts to > correctly handle reducing the expected niters for loops with multiple > exits. > (scale_loop_freqs_with_new_exit_count): New. > (scale_loop_profile_1): New. > (scale_loop_profile_hold_exit_counts): New. > * cfgloopmanip.h (scale_loop_profile_hold_exit_counts): New. > (scale_loop_freqs_with_new_exit_count): New. +template<typename ExitCountFn> +static bool +can_flow_scale_loop_freqs_p (class loop *loop, + ExitCountFn get_exit_count) +{ + basic_block bb = loop->header; + + const profile_count count_in = loop_count_in (loop); + profile_count exit_count = profile_count::zero (); + + while (bb != loop->latch) + { + /* Punt if any of the BB counts are uninitialized. */ + if (!bb->count.initialized_p ()) + return false; + + bool found_exit = false; + edge internal_edge = nullptr; + for (auto e : bb->succs) + if (flow_bb_inside_loop_p (loop, e->dest)) + { + if (internal_edge) + return false; + internal_edge = e;
This assumes that there are at most 2 edges out which is not always the case (i.e. for EH and switch). I suppose vectorizer never calls it there but probably you want to test that there are precisely two edges in can_flow_scale_loop_freqs and if not drop message to dump file, so in case we encounter such loops we notice. + } + else + { + if (found_exit) + return false; + found_exit = true; + exit_count += get_exit_count (e); + } + + bb = internal_edge->dest; + } + + /* Punt if any exit edge had an uninitialized count. */ + if (!exit_count.initialized_p ()) + return false; You already early rturn once you hit bb with uninitialized count, so perhaps you can move this check just after call of get_exit_count? + const profile_count new_exit_count = get_exit_count (exit_edge); + profile_probability new_exit_prob; + if (new_block_count.nonzero_p ()) + new_exit_prob = new_exit_count.probability_in (new_block_count); If new_exit_count > new_block_count probability_in will return 1. I guess there is not much to do, but pehraps logging inconsistency into dump is not a bad idea here. + else + { + /* NEW_BLOCK_COUNT is zero, so the only way we can make the profile + consistent is if NEW_EXIT_COUNT is zero too. */ + if (dump_file && new_exit_count.nonzero_p ()) + fprintf (dump_file, + ";; flow_scale_loop_freqs wants non-zero exit count " + "but bb count is zero/uninit: profile is inconsistent\n"); + + /* Arbitrarily set the exit probability to 0. */ + new_exit_prob = profile_probability::never (); never is kind of strong hint to optimize the other patch (it has RELIABLE reliability). Since we have no info I would just keep the probability which was there before. + } Patch is OK with these changes. Honza