Hi, this patch fixes infrastructure used by branch prediction code to collect information about prediction hitrates that is needed to verify their performance.
We used to read profile first and then do profile estimation, nowdays passes are run in the opposite order. Because dumping happens during estimation, we no longer get the information. This patch simply re-runs the branch prediction w/o modifying the profile when -fdump-ipa-profile is used. Profile estimation and maintenance code was not very actively developed in recent years and there are some dead ends. This stage 1 I would like to fix them, update the APIs to be more robust and use sreals instaed of fixedpoint arithmetics. Bootstrapped/regtested x86_64-linux, comitted. Honza * predict.c (combine_predictions_for_bb): Add dry_run parmaeter. (tree_estimate_probability): Likewise. (pass_profile::execute): Update. (report_predictor_hitrates): New function. * profile.c (compute_branch_probabilities): Use it. * predict.h (report_predictor_hitrates): Declare. * analyze_brprob: Update comment. Index: predict.c =================================================================== --- predict.c (revision 234877) +++ predict.c (working copy) @@ -842,10 +842,11 @@ combine_predictions_for_insn (rtx_insn * } /* Combine predictions into single probability and store them into CFG. - Remove now useless prediction entries. */ + Remove now useless prediction entries. + If DRY_RUN is set, only produce dumps and do not modify profile. */ static void -combine_predictions_for_bb (basic_block bb) +combine_predictions_for_bb (basic_block bb, bool dry_run) { int best_probability = PROB_EVEN; enum br_predictor best_predictor = END_PREDICTORS; @@ -876,7 +877,7 @@ combine_predictions_for_bb (basic_block this later. */ if (nedges != 2) { - if (!bb->count) + if (!bb->count && !dry_run) set_even_probabilities (bb); clear_bb_predictions (bb); if (dump_file) @@ -982,7 +983,7 @@ combine_predictions_for_bb (basic_block } clear_bb_predictions (bb); - if (!bb->count) + if (!bb->count && !dry_run) { first->probability = combined_probability; second->probability = REG_BR_PROB_BASE - combined_probability; @@ -2327,10 +2328,11 @@ tree_estimate_probability_bb (basic_bloc /* Predict branch probabilities and estimate profile of the tree CFG. This function can be called from the loop optimizers to recompute - the profile information. */ + the profile information. + If DRY_RUN is set, do not modify CFG and only produce dump files. */ void -tree_estimate_probability (void) +tree_estimate_probability (bool dry_run) { basic_block bb; @@ -2352,7 +2354,7 @@ tree_estimate_probability (void) tree_estimate_probability_bb (bb); FOR_EACH_BB_FN (bb, cfun) - combine_predictions_for_bb (bb); + combine_predictions_for_bb (bb, dry_run); if (flag_checking) bb_predictions->traverse<void *, assert_is_empty> (NULL); @@ -2360,7 +2362,8 @@ tree_estimate_probability (void) delete bb_predictions; bb_predictions = NULL; - estimate_bb_frequencies (false); + if (!dry_run) + estimate_bb_frequencies (false); free_dominance_info (CDI_POST_DOMINATORS); remove_fake_exit_edges (); } @@ -3040,7 +3043,7 @@ pass_profile::execute (function *fun) if (nb_loops > 1) scev_initialize (); - tree_estimate_probability (); + tree_estimate_probability (false); if (nb_loops > 1) scev_finalize (); @@ -3191,3 +3194,30 @@ rebuild_frequencies (void) gcc_unreachable (); timevar_pop (TV_REBUILD_FREQUENCIES); } + +/* Perform a dry run of the branch prediction pass and report comparsion of + the predicted and real profile into the dump file. */ + +void +report_predictor_hitrates (void) +{ + unsigned nb_loops; + + loop_optimizer_init (LOOPS_NORMAL); + if (dump_file && (dump_flags & TDF_DETAILS)) + flow_loops_dump (dump_file, NULL, 0); + + mark_irreducible_loops (); + + nb_loops = number_of_loops (cfun); + if (nb_loops > 1) + scev_initialize (); + + tree_estimate_probability (true); + + if (nb_loops > 1) + scev_finalize (); + + loop_optimizer_finalize (); +} + Index: profile.c =================================================================== --- profile.c (revision 234877) +++ profile.c (working copy) @@ -845,6 +845,8 @@ compute_branch_probabilities (unsigned c fputc ('\n', dump_file); fputc ('\n', dump_file); } + if (dump_file && (dump_flags & TDF_DETAILS)) + report_predictor_hitrates (); free_aux_for_blocks (); } Index: predict.h =================================================================== --- predict.h (revision 234877) +++ predict.h (working copy) @@ -90,5 +90,6 @@ extern void compute_function_frequency ( extern tree build_predict_expr (enum br_predictor, enum prediction); extern const char *predictor_name (enum br_predictor); extern void rebuild_frequencies (void); +extern void report_predictor_hitrates (void); #endif /* GCC_PREDICT_H */ Index: contrib/analyze_brprob =================================================================== --- contrib/analyze_brprob (revision 235039) +++ contrib/analyze_brprob (working copy) @@ -33,11 +33,12 @@ # Step 1: Compile and profile your program. You need to use -fprofile-arcs # flag to get the profiles # Step 2: Generate log files. The information about given heuristics are -# saved into *.bp dumps. You need to pass the -db switch to the compiler as well +# saved into ipa-profile dumps. You need to pass the -fdimp-ipa-profile switch +# to the compiler as well # as -fbranch-probabilities to get the results of profiling noted in the dumps. # Ensure that there are no "Arc profiling: some edge counts were bad." warnings. -# Step 3: Run this script to concatenate all *.life files: -# analyze_brprob `find . -name *.life` +# Step 3: Run this script to concatenate all *.profile files: +# analyze_brprob `find . -name *.profile` # the information is collected and print once all files are parsed. This # may take a while. # Note that the script does use bc to perform long arithmetic.