From 160576e1ac9bbee90af9e09e1507f64d58473358 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Tue, 13 Nov 2018 16:06:54 +0100 Subject: [PATCH] Improve -fprofile-report. 2018-11-13 Martin Liska PR tree-optimization/87885 * cfghooks.c (account_profile_record): Rename to ... (profile_record_check_consistency): ... this. Calculate missing num_mismatched_freq_in. (profile_record_account_profile): New function that calculates time and size of a function. * cfghooks.h (struct profile_record): Remove all tuples. (struct cfg_hooks): Remove after_pass flag. (account_profile_record): Rename to ... (profile_record_check_consistency): ... this. (profile_record_account_profile): New. * cfgrtl.c (rtl_account_profile_record): Remove after_pass flag. * passes.c (check_profile_consistency): Do only checking. (account_profile): Calculate size and time of function only. (pass_manager::dump_profile_report): Reformat output. (execute_one_ipa_transform_pass): Call consistency check before clean upand call account_profile after a clean up is done. (execute_one_pass): Call check_profile_consistency and account_profile instead of using after_pass flag.. * tree-cfg.c (gimple_account_profile_record): Likewise. From-SVN: r266074 --- gcc/ChangeLog | 30 +++++++ gcc/cfghooks.c | 38 +++++++-- gcc/cfghooks.h | 17 ++-- gcc/cfgrtl.c | 12 ++- gcc/passes.c | 207 ++++++++++++++++++++++++++----------------------- gcc/tree-cfg.c | 11 ++- 6 files changed, 191 insertions(+), 124 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fc809d395c6..0b82b956ee4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2018-11-13 Martin Liska + + PR tree-optimization/87885 + * cfghooks.c (account_profile_record): Rename + to ... + (profile_record_check_consistency): ... this. + Calculate missing num_mismatched_freq_in. + (profile_record_account_profile): New function + that calculates time and size of a function. + * cfghooks.h (struct profile_record): Remove + all tuples. + (struct cfg_hooks): Remove after_pass flag. + (account_profile_record): Rename to ... + (profile_record_check_consistency): ... this. + (profile_record_account_profile): New. + * cfgrtl.c (rtl_account_profile_record): Remove + after_pass flag. + * passes.c (check_profile_consistency): Do only + checking. + (account_profile): Calculate size and time of + function only. + (pass_manager::dump_profile_report): Reformat + output. + (execute_one_ipa_transform_pass): Call + consistency check before clean upand call account_profile + after a clean up is done. + (execute_one_pass): Call check_profile_consistency and + account_profile instead of using after_pass flag.. + * tree-cfg.c (gimple_account_profile_record): Likewise. + 2018-11-13 Martin Liska PR sanitizer/87930 diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c index ea106e0cb32..824ab25929a 100644 --- a/gcc/cfghooks.c +++ b/gcc/cfghooks.c @@ -1425,11 +1425,10 @@ split_block_before_cond_jump (basic_block bb) /* Work-horse for passes.c:check_profile_consistency. Do book-keeping of the CFG for the profile consistency checker. - If AFTER_PASS is 0, do pre-pass accounting, or if AFTER_PASS is 1 - then do post-pass accounting. Store the counting in RECORD. */ + Store the counting in RECORD. */ void -account_profile_record (struct profile_record *record, int after_pass) +profile_record_check_consistency (profile_record *record) { basic_block bb; edge_iterator ei; @@ -1445,26 +1444,49 @@ account_profile_record (struct profile_record *record, int after_pass) sum += e->probability; if (EDGE_COUNT (bb->succs) && sum.differs_from_p (profile_probability::always ())) - record->num_mismatched_freq_out[after_pass]++; + record->num_mismatched_freq_out++; profile_count lsum = profile_count::zero (); 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[after_pass]++; + record->num_mismatched_count_out++; } 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 (); + { + sum += e->probability; + lsum += e->count (); + } + 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[after_pass]++; + 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, after_pass, record); + cfg_hooks->account_profile_record (bb, record); + } +} + +/* Work-horse for passes.c:acount_profile. + Do book-keeping of the CFG for the profile accounting. + Store the counting in RECORD. */ + +void +profile_record_account_profile (profile_record *record) +{ + basic_block bb; + + FOR_ALL_BB_FN (bb, cfun) + { + gcc_assert (cfg_hooks->account_profile_record); + cfg_hooks->account_profile_record (bb, record); } } diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h index b5981da4a05..d1d2e70c3d4 100644 --- a/gcc/cfghooks.h +++ b/gcc/cfghooks.h @@ -38,18 +38,18 @@ struct profile_record { /* The number of basic blocks where sum(freq) of the block's predecessors doesn't match reasonably well with the incoming frequency. */ - int num_mismatched_freq_in[2]; + int num_mismatched_freq_in; /* Likewise for a basic block's successors. */ - int num_mismatched_freq_out[2]; + int num_mismatched_freq_out; /* The number of basic blocks where sum(count) of the block's predecessors doesn't match reasonably well with the incoming frequency. */ - int num_mismatched_count_in[2]; + int num_mismatched_count_in; /* Likewise for a basic block's successors. */ - int num_mismatched_count_out[2]; + int num_mismatched_count_out; /* A weighted cost of the run-time of the function body. */ - gcov_type time[2]; + gcov_type_unsigned time; /* A weighted cost of the size of the function body. */ - int size[2]; + int size; /* True iff this pass actually was run. */ bool run; }; @@ -182,7 +182,7 @@ struct cfg_hooks basic_block (*split_block_before_cond_jump) (basic_block); /* Do book-keeping of a basic block for the profile consistency checker. */ - void (*account_profile_record) (basic_block, int, struct profile_record *); + void (*account_profile_record) (basic_block, struct profile_record *); }; extern void verify_flow_info (void); @@ -254,7 +254,8 @@ extern void copy_bbs (basic_block *, unsigned, basic_block *, edge *, unsigned, edge *, struct loop *, basic_block, bool); -void account_profile_record (struct profile_record *, int); +void profile_record_check_consistency (profile_record *); +void profile_record_account_profile (profile_record *); /* Hooks containers. */ extern struct cfg_hooks gimple_cfg_hooks; diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 3b1931daeba..741a3120a97 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -5068,22 +5068,20 @@ rtl_duplicate_bb (basic_block bb) } /* Do book-keeping of basic block BB for the profile consistency checker. - If AFTER_PASS is 0, do pre-pass accounting, or if AFTER_PASS is 1 - then do post-pass accounting. Store the counting in RECORD. */ + Store the counting in RECORD. */ static void -rtl_account_profile_record (basic_block bb, int after_pass, - struct profile_record *record) +rtl_account_profile_record (basic_block bb, struct profile_record *record) { rtx_insn *insn; FOR_BB_INSNS (bb, insn) if (INSN_P (insn)) { - record->size[after_pass] += insn_cost (insn, false); + record->size += insn_cost (insn, false); if (bb->count.initialized_p ()) - record->time[after_pass] + record->time += insn_cost (insn, true) * bb->count.to_gcov_type (); else if (profile_status_for_fn (cfun) == PROFILE_GUESSED) - record->time[after_pass] + record->time += insn_cost (insn, true) * bb->count.to_frequency (cfun); } } diff --git a/gcc/passes.c b/gcc/passes.c index d838d909941..5d2372bac24 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1738,12 +1738,31 @@ emergency_dump_function () static struct profile_record *profile_record; /* Do profile consistency book-keeping for the pass with static number INDEX. - If SUBPASS is zero, we run _before_ the pass, and if SUBPASS is one, then - we run _after_ the pass. RUN is true if the pass really runs, or FALSE + RUN is true if the pass really runs, or FALSE if we are only book-keeping on passes that may have selectively disabled themselves on a given function. */ + +static void +check_profile_consistency (int index, bool run) +{ + pass_manager *passes = g->get_passes (); + if (index == -1) + return; + if (!profile_record) + profile_record = XCNEWVEC (struct profile_record, + passes->passes_by_id_size); + gcc_assert (index < passes->passes_by_id_size && index >= 0); + profile_record[index].run |= run; + profile_record_check_consistency (&profile_record[index]); +} + +/* Account profile the pass with static number INDEX. + RUN is true if the pass really runs, or FALSE + if we are only book-keeping on passes that may have selectively disabled + themselves on a given function. */ + static void -check_profile_consistency (int index, int subpass, bool run) +account_profile (int index, bool run) { pass_manager *passes = g->get_passes (); if (index == -1) @@ -1752,9 +1771,8 @@ check_profile_consistency (int index, int subpass, bool run) profile_record = XCNEWVEC (struct profile_record, passes->passes_by_id_size); gcc_assert (index < passes->passes_by_id_size && index >= 0); - gcc_assert (subpass < 2); profile_record[index].run |= run; - account_profile_record (&profile_record[index], subpass); + profile_record_account_profile (&profile_record[index]); } /* Output profile consistency. */ @@ -1768,7 +1786,6 @@ dump_profile_report (void) void pass_manager::dump_profile_report () const { - int i, j; int last_freq_in = 0, last_count_in = 0, last_freq_out = 0, last_count_out = 0; gcov_type last_time = 0, last_size = 0; double rel_time_change, rel_size_change; @@ -1777,86 +1794,86 @@ pass_manager::dump_profile_report () const if (!profile_record) return; fprintf (stderr, "\nProfile consistency report:\n\n"); - fprintf (stderr, "Pass name |mismatch in |mismated out|Overall\n"); - fprintf (stderr, " |freq count |freq count |size time\n"); + fprintf (stderr, " |mismatch |mismatch | |\n"); + fprintf (stderr, "Pass name |IN |IN |OUT |OUT |overall |\n"); + fprintf (stderr, " |freq |count |freq |count |size |time |\n"); - for (i = 0; i < passes_by_id_size; i++) - for (j = 0 ; j < 2; j++) - if (profile_record[i].run) - { - if (last_time) - rel_time_change = (profile_record[i].time[j] - - (double)last_time) * 100 / (double)last_time; - else - rel_time_change = 0; - if (last_size) - rel_size_change = (profile_record[i].size[j] - - (double)last_size) * 100 / (double)last_size; - else - rel_size_change = 0; - - if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in - || profile_record[i].num_mismatched_freq_out[j] != last_freq_out - || profile_record[i].num_mismatched_count_in[j] != last_count_in - || profile_record[i].num_mismatched_count_out[j] != last_count_out - || rel_time_change || rel_size_change) - { - last_reported = i; - fprintf (stderr, "%-20s %s", - passes_by_id [i]->name, - j ? "(after TODO)" : " "); - if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in) - fprintf (stderr, "| %+5i", - profile_record[i].num_mismatched_freq_in[j] - - last_freq_in); - else - fprintf (stderr, "| "); - if (profile_record[i].num_mismatched_count_in[j] != last_count_in) - fprintf (stderr, " %+5i", - profile_record[i].num_mismatched_count_in[j] - - last_count_in); - else - fprintf (stderr, " "); - if (profile_record[i].num_mismatched_freq_out[j] != last_freq_out) - fprintf (stderr, "| %+5i", - profile_record[i].num_mismatched_freq_out[j] - - last_freq_out); - else - fprintf (stderr, "| "); - if (profile_record[i].num_mismatched_count_out[j] != last_count_out) - fprintf (stderr, " %+5i", - profile_record[i].num_mismatched_count_out[j] - - last_count_out); - else - fprintf (stderr, " "); - - /* Size/time units change across gimple and RTL. */ - if (i == pass_expand_1->static_pass_number) - fprintf (stderr, "|----------"); - else - { - if (rel_size_change) - fprintf (stderr, "| %+8.4f%%", rel_size_change); - else - fprintf (stderr, "| "); - if (rel_time_change) - fprintf (stderr, " %+8.4f%%", rel_time_change); - } - fprintf (stderr, "\n"); - last_freq_in = profile_record[i].num_mismatched_freq_in[j]; - last_freq_out = profile_record[i].num_mismatched_freq_out[j]; - last_count_in = profile_record[i].num_mismatched_count_in[j]; - last_count_out = profile_record[i].num_mismatched_count_out[j]; - } - else if (j && last_reported != i) - { - last_reported = i; - fprintf (stderr, "%-20s ------------| | |\n", - passes_by_id [i]->name); - } - last_time = profile_record[i].time[j]; - last_size = profile_record[i].size[j]; - } + for (int i = 1; i < passes_by_id_size; i++) + if (profile_record[i].run) + { + if (last_time) + rel_time_change = (profile_record[i].time + - (double)last_time) * 100 / (double)last_time; + else + rel_time_change = 0; + if (last_size) + rel_size_change = (profile_record[i].size + - (double)last_size) * 100 / (double)last_size; + else + rel_size_change = 0; + + if (profile_record[i].num_mismatched_freq_in != last_freq_in + || profile_record[i].num_mismatched_freq_out != last_freq_out + || profile_record[i].num_mismatched_count_in != last_count_in + || profile_record[i].num_mismatched_count_out != last_count_out + || rel_time_change || rel_size_change) + { + last_reported = i; + fprintf (stderr, "%-33s", passes_by_id[i]->name); + if (profile_record[i].num_mismatched_freq_in != last_freq_in) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_freq_in + - last_freq_in); + else + fprintf (stderr, "| "); + if (profile_record[i].num_mismatched_count_in != last_count_in) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_count_in + - last_count_in); + else + fprintf (stderr, "| "); + if (profile_record[i].num_mismatched_freq_out != last_freq_out) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_freq_out + - last_freq_out); + else + fprintf (stderr, "| "); + if (profile_record[i].num_mismatched_count_out != last_count_out) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_count_out + - last_count_out); + else + fprintf (stderr, "| "); + + /* Size/time units change across gimple and RTL. */ + if (i == pass_expand_1->static_pass_number) + fprintf (stderr, "|----------|----------"); + else + { + if (rel_size_change) + fprintf (stderr, "| %+8.1f%%", rel_size_change); + else + fprintf (stderr, "| "); + if (rel_time_change) + fprintf (stderr, "| %+8.1f%%", rel_time_change); + else + fprintf (stderr, "| "); + } + fprintf (stderr, "|\n"); + last_freq_in = profile_record[i].num_mismatched_freq_in; + last_freq_out = profile_record[i].num_mismatched_freq_out; + last_count_in = profile_record[i].num_mismatched_count_in; + last_count_out = profile_record[i].num_mismatched_count_out; + } + else if (last_reported != i) + { + last_reported = i; + fprintf (stderr, "%-20s ------------| | | | | | |\n", + passes_by_id[i]->name); + } + last_time = profile_record[i].time; + last_size = profile_record[i].size; + } } /* Perform all TODO actions that ought to be done on each function. */ @@ -2163,20 +2180,20 @@ execute_one_ipa_transform_pass (struct cgraph_node *node, if (pass->tv_id != TV_NONE) timevar_push (pass->tv_id); + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + check_profile_consistency (pass->static_pass_number, true); + /* Run pre-pass verification. */ execute_todo (ipa_pass->function_transform_todo_flags_start); /* Do it! */ todo_after = ipa_pass->function_transform (node); - if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) - check_profile_consistency (pass->static_pass_number, 0, true); - /* Run post-pass cleanup and verification. */ execute_todo (todo_after); verify_interpass_invariants (); if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) - check_profile_consistency (pass->static_pass_number, 1, true); + account_profile (pass->static_pass_number, true); /* Stop timevar. */ if (pass->tv_id != TV_NONE) @@ -2387,8 +2404,8 @@ execute_one_pass (opt_pass *pass) are not miscounted. */ if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) { - check_profile_consistency (pass->static_pass_number, 0, false); - check_profile_consistency (pass->static_pass_number, 1, false); + check_profile_consistency (pass->static_pass_number, false); + account_profile (pass->static_pass_number, false); } current_pass = NULL; return false; @@ -2417,6 +2434,9 @@ execute_one_pass (opt_pass *pass) if (pass->tv_id != TV_NONE) timevar_push (pass->tv_id); + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + check_profile_consistency (pass->static_pass_number, true); + /* Run pre-pass verification. */ execute_todo (pass->todo_flags_start); @@ -2461,13 +2481,10 @@ execute_one_pass (opt_pass *pass) do_per_function (update_properties_after_pass, pass); - if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) - check_profile_consistency (pass->static_pass_number, 0, true); - /* Run post-pass cleanup and verification. */ execute_todo (todo_after | pass->todo_flags_finish | TODO_verify_il); if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) - check_profile_consistency (pass->static_pass_number, 1, true); + account_profile (pass->static_pass_number, true); verify_interpass_invariants (); diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 8db10898915..3b646f7149b 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -8798,23 +8798,22 @@ gimple_lv_add_condition_to_bb (basic_block first_head ATTRIBUTE_UNUSED, /* Do book-keeping of basic block BB for the profile consistency checker. - If AFTER_PASS is 0, do pre-pass accounting, or if AFTER_PASS is 1 - then do post-pass accounting. Store the counting in RECORD. */ + Store the counting in RECORD. */ static void -gimple_account_profile_record (basic_block bb, int after_pass, +gimple_account_profile_record (basic_block bb, struct profile_record *record) { gimple_stmt_iterator i; for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) { - record->size[after_pass] + record->size += estimate_num_insns (gsi_stmt (i), &eni_size_weights); if (bb->count.initialized_p ()) - record->time[after_pass] + record->time += estimate_num_insns (gsi_stmt (i), &eni_time_weights) * bb->count.to_gcov_type (); else if (profile_status_for_fn (cfun) == PROFILE_GUESSED) - record->time[after_pass] + record->time += estimate_num_insns (gsi_stmt (i), &eni_time_weights) * bb->count.to_frequency (cfun); } -- 2.30.2