diff options
author | Jan Hubicka <jh@suse.cz> | 2021-11-28 19:25:33 +0100 |
---|---|---|
committer | Jan Hubicka <jh@suse.cz> | 2021-11-28 19:25:33 +0100 |
commit | d1471457fcda26cd24e0053b82f8eed35ddb8727 (patch) | |
tree | ccb130300fe101af002265cb1efebb51938b17a1 /gcc/cfghooks.c | |
parent | 7393fa8b1d21eeeb37e59ff8efaebf178fd891e5 (diff) | |
download | gcc-d1471457fcda26cd24e0053b82f8eed35ddb8727.zip gcc-d1471457fcda26cd24e0053b82f8eed35ddb8727.tar.gz gcc-d1471457fcda26cd24e0053b82f8eed35ddb8727.tar.bz2 |
Improve -fprofile-report
Profile-report was never properly updated after switch to new profile
representation. This patch fixes the way profile mismatches are calculated:
we used to collect separately count and freq mismatches, while now we have
only counts & probabilities. So we verify
- in count: that total count of incomming edges is close to acutal count of
the BB
- out prob: that total sum of outgoing edge edge probabilities is close
to 1 (except for BB containing noreturn calls or EH).
Moreover I added dumping of absolute data which is useful to plot them: with
Martin Liska we plan to setup regular testing so we keep optimizers profie
updates bit under control.
Finally I added both static and dynamic stats about mismatches - static one is
simply number of inconsistencies in the cfg while dynamic is scaled by the
profile - I think in order to keep eye on optimizers the first number is quite
relevant. WHile when tracking why code quality regressed the second number
matters more.
2021-11-28 Jan Hubicka <hubicka@ucw.cz>
* cfghooks.c: Include sreal.h, profile.h.
(profile_record_check_consistency): Fix checking of count counsistency;
record also dynamic mismatches.
* cfgrtl.c (rtl_account_profile_record): Similarly.
* tree-cfg.c (gimple_account_profile_record): Likewise.
* cfghooks.h (struct profile_record): Remove num_mismatched_freq_in,
num_mismatched_freq_out, turn time to double, add
dyn_mismatched_prob_out, dyn_mismatched_count_in,
num_mismatched_prob_out; remove num_mismatched_count_out.
* passes.c (account_profile_1): New function.
(account_profile_in_list): New function.
(pass_manager::dump_profile_report): Rewrite.
(execute_one_ipa_transform_pass): Check profile consistency after
running all passes.
(execute_all_ipa_transforms): Remove cfun test; record all transform
methods.
(execute_one_pass): Fix collecting of profile stats.
Diffstat (limited to 'gcc/cfghooks.c')
-rw-r--r-- | gcc/cfghooks.c | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c index fa2dae2..550dc4a 100644 --- a/gcc/cfghooks.c +++ b/gcc/cfghooks.c @@ -31,6 +31,8 @@ along with GCC; see the file COPYING3. If not see #include "cfganal.h" #include "tree-ssa.h" #include "cfgloop.h" +#include "sreal.h" +#include "profile.h" /* Disable warnings about missing quoting in GCC diagnostics. */ #if __GNUC__ >= 10 @@ -1467,41 +1469,73 @@ profile_record_check_consistency (profile_record *record) FOR_ALL_BB_FN (bb, cfun) { if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun) - && profile_status_for_fn (cfun) != PROFILE_ABSENT) + && profile_status_for_fn (cfun) != PROFILE_ABSENT + && EDGE_COUNT (bb->succs)) { - profile_probability sum = profile_probability::never (); - FOR_EACH_EDGE (e, ei, bb->succs) - sum += e->probability; - if (EDGE_COUNT (bb->succs) - && sum.differs_from_p (profile_probability::always ())) - record->num_mismatched_freq_out++; - profile_count lsum = profile_count::zero (); + sreal sum = 0; + bool found = false; FOR_EACH_EDGE (e, ei, bb->succs) - lsum += e->count (); - if (EDGE_COUNT (bb->succs) && (lsum.differs_from_p (bb->count))) - record->num_mismatched_count_out++; + { + if (!(e->flags & (EDGE_EH | EDGE_FAKE))) + found = true; + if (e->probability.initialized_p ()) + sum += e->probability.to_sreal (); + } + double dsum = sum.to_double (); + if (found && (dsum < 0.9 || dsum > 1.1) + && !(bb->count == profile_count::zero ())) + { + record->num_mismatched_prob_out++; + dsum = dsum > 1 ? dsum - 1 : 1 - dsum; + if (profile_info) + { + if (ENTRY_BLOCK_PTR_FOR_FN + (cfun)->count.ipa ().initialized_p () + && ENTRY_BLOCK_PTR_FOR_FN + (cfun)->count.ipa ().nonzero_p () + && bb->count.ipa ().initialized_p ()) + record->dyn_mismatched_prob_out + += dsum * bb->count.ipa ().to_gcov_type (); + } + else if (bb->count.initialized_p ()) + record->dyn_mismatched_prob_out + += dsum * bb->count.to_sreal_scale + (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count).to_double (); + } } if (bb != ENTRY_BLOCK_PTR_FOR_FN (cfun) && profile_status_for_fn (cfun) != PROFILE_ABSENT) { - profile_probability sum = profile_probability::never (); profile_count lsum = profile_count::zero (); FOR_EACH_EDGE (e, ei, bb->preds) + lsum += e->count (); + if (lsum.differs_from_p (bb->count)) { - sum += e->probability; - lsum += e->count (); + record->num_mismatched_count_in++; + profile_count max; + if (lsum < bb->count) + max = bb->count; + else + max = lsum; + if (profile_info) + { + if (ENTRY_BLOCK_PTR_FOR_FN + (cfun)->count.ipa ().initialized_p () + && ENTRY_BLOCK_PTR_FOR_FN + (cfun)->count.ipa ().nonzero_p () + && max.ipa ().initialized_p ()) + record->dyn_mismatched_count_in + += max.ipa ().to_gcov_type (); + } + else if (bb->count.initialized_p ()) + record->dyn_mismatched_prob_out + += max.to_sreal_scale + (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count).to_double (); } - if (EDGE_COUNT (bb->preds) - && sum.differs_from_p (profile_probability::always ())) - record->num_mismatched_freq_in++; - if (lsum.differs_from_p (bb->count)) - record->num_mismatched_count_in++; } if (bb == ENTRY_BLOCK_PTR_FOR_FN (cfun) || bb == EXIT_BLOCK_PTR_FOR_FN (cfun)) continue; - gcc_assert (cfg_hooks->account_profile_record); - cfg_hooks->account_profile_record (bb, record); } } |