From 512cc0151207de4c7ff3a84f040f730fe0d52458 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Fri, 21 Sep 2018 10:41:17 +0200 Subject: [PATCH] Remove arc profile histogram in non-LTO mode. 2018-09-21 Martin Liska * auto-profile.c (autofdo_source_profile::read): Do not set sum_all. (read_profile): Do not add working sets. (read_autofdo_file): Remove sum_all. (afdo_callsite_hot_enough_for_early_inline): Remove const qualifier. * coverage.c (struct counts_entry): Remove gcov_summary. (read_counts_file): Read new GCOV_TAG_OBJECT_SUMMARY, do not support GCOV_TAG_PROGRAM_SUMMARY. (get_coverage_counts): Remove summary and expected arguments. * coverage.h (get_coverage_counts): Likewise. * doc/gcov-dump.texi: Remove -w option. * gcov-dump.c (dump_working_sets): Remove. (main): Do not support '-w' option. (print_usage): Likewise. (tag_summary): Likewise. * gcov-io.c (gcov_write_summary): Do not dump histogram. (gcov_read_summary): Likewise. (gcov_histo_index): Remove. (gcov_histogram_merge): Likewise. (compute_working_sets): Likewise. * gcov-io.h (GCOV_TAG_OBJECT_SUMMARY): Mark it not obsolete. (GCOV_TAG_PROGRAM_SUMMARY): Mark it obsolete. (GCOV_TAG_SUMMARY_LENGTH): Adjust. (GCOV_HISTOGRAM_SIZE): Remove. (GCOV_HISTOGRAM_BITVECTOR_SIZE): Likewise. (struct gcov_summary): Simplify rapidly just to runs and sum_max fields. (gcov_histo_index): Remove. (NUM_GCOV_WORKING_SETS): Likewise. (compute_working_sets): Likewise. * gcov-tool.c (print_overlap_usage_message): Remove trailing empty line. * gcov.c (read_count_file): Read GCOV_TAG_OBJECT_SUMMARY. (output_lines): Remove program related line. * ipa-profile.c (ipa_profile): Do not consider GCOV histogram. * lto-cgraph.c (output_profile_summary): Do not stream GCOV histogram. (input_profile_summary): Do not read it. (merge_profile_summaries): And do not merge it. (input_symtab): Do not call removed function. * modulo-sched.c (sms_schedule): Do not print sum_max. * params.def (HOT_BB_COUNT_FRACTION): Reincarnate param that was removed when histogram method was invented. (HOT_BB_COUNT_WS_PERMILLE): Mention that it's used only in LTO mode. * postreload-gcse.c (eliminate_partially_redundant_load): Fix GCOV coding style. * predict.c (get_hot_bb_threshold): Use HOT_BB_COUNT_FRACTION and dump selected value. * profile.c (add_working_set): Remove. (get_working_sets): Likewise. (find_working_set): Likewise. (get_exec_counts): Do not work with working sets. (read_profile_edge_counts): Do not inform as sum_max is removed. (compute_branch_probabilities): Likewise. (compute_value_histograms): Remove argument for call of get_coverage_counts. * profile.h: Do not make gcov_summary const. 2018-09-21 Martin Liska * libgcov-driver.c (crc32_unsigned): Remove. (gcov_histogram_insert): Likewise. (gcov_compute_histogram): Likewise. (compute_summary): Simplify rapidly. (merge_one_data): Do not handle PROGRAM_SUMMARY tag. (merge_summary): Rapidly simplify. (dump_one_gcov): Ignore gcov_summary. (gcov_do_dump): Do not handle program summary, it's not used. * libgcov-util.c (tag_summary): Remove. (read_gcda_finalize): Fix coding style. (read_gcda_file): Initialize curr_object_summary. (compute_summary): Remove. (calculate_overlap): Remove settings of run_max. From-SVN: r264462 --- gcc/ChangeLog | 65 +++++++ gcc/auto-profile.c | 21 +-- gcc/coverage.c | 59 +----- gcc/coverage.h | 4 +- gcc/doc/gcov-dump.texi | 6 +- gcc/gcov-dump.c | 81 +------- gcc/gcov-io.c | 398 +--------------------------------------- gcc/gcov-io.h | 71 +------ gcc/gcov-tool.c | 1 - gcc/gcov.c | 7 +- gcc/ipa-profile.c | 26 +-- gcc/lto-cgraph.c | 134 +------------- gcc/modulo-sched.c | 8 - gcc/params.def | 7 +- gcc/postreload-gcse.c | 2 +- gcc/predict.c | 9 +- gcc/profile.c | 116 +----------- gcc/profile.h | 2 +- libgcc/ChangeLog | 17 ++ libgcc/libgcov-driver.c | 324 ++++---------------------------- libgcc/libgcov-util.c | 39 +--- 21 files changed, 182 insertions(+), 1215 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2070b59742b..97e75ec34b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,68 @@ +2018-09-21 Martin Liska + + * auto-profile.c (autofdo_source_profile::read): Do not + set sum_all. + (read_profile): Do not add working sets. + (read_autofdo_file): Remove sum_all. + (afdo_callsite_hot_enough_for_early_inline): Remove const + qualifier. + * coverage.c (struct counts_entry): Remove gcov_summary. + (read_counts_file): Read new GCOV_TAG_OBJECT_SUMMARY, + do not support GCOV_TAG_PROGRAM_SUMMARY. + (get_coverage_counts): Remove summary and expected + arguments. + * coverage.h (get_coverage_counts): Likewise. + * doc/gcov-dump.texi: Remove -w option. + * gcov-dump.c (dump_working_sets): Remove. + (main): Do not support '-w' option. + (print_usage): Likewise. + (tag_summary): Likewise. + * gcov-io.c (gcov_write_summary): Do not dump + histogram. + (gcov_read_summary): Likewise. + (gcov_histo_index): Remove. + (gcov_histogram_merge): Likewise. + (compute_working_sets): Likewise. + * gcov-io.h (GCOV_TAG_OBJECT_SUMMARY): Mark + it not obsolete. + (GCOV_TAG_PROGRAM_SUMMARY): Mark it obsolete. + (GCOV_TAG_SUMMARY_LENGTH): Adjust. + (GCOV_HISTOGRAM_SIZE): Remove. + (GCOV_HISTOGRAM_BITVECTOR_SIZE): Likewise. + (struct gcov_summary): Simplify rapidly just + to runs and sum_max fields. + (gcov_histo_index): Remove. + (NUM_GCOV_WORKING_SETS): Likewise. + (compute_working_sets): Likewise. + * gcov-tool.c (print_overlap_usage_message): Remove + trailing empty line. + * gcov.c (read_count_file): Read GCOV_TAG_OBJECT_SUMMARY. + (output_lines): Remove program related line. + * ipa-profile.c (ipa_profile): Do not consider GCOV histogram. + * lto-cgraph.c (output_profile_summary): Do not stream GCOV + histogram. + (input_profile_summary): Do not read it. + (merge_profile_summaries): And do not merge it. + (input_symtab): Do not call removed function. + * modulo-sched.c (sms_schedule): Do not print sum_max. + * params.def (HOT_BB_COUNT_FRACTION): Reincarnate param that was + removed when histogram method was invented. + (HOT_BB_COUNT_WS_PERMILLE): Mention that it's used only in LTO + mode. + * postreload-gcse.c (eliminate_partially_redundant_load): Fix + GCOV coding style. + * predict.c (get_hot_bb_threshold): Use HOT_BB_COUNT_FRACTION + and dump selected value. + * profile.c (add_working_set): Remove. + (get_working_sets): Likewise. + (find_working_set): Likewise. + (get_exec_counts): Do not work with working sets. + (read_profile_edge_counts): Do not inform as sum_max is removed. + (compute_branch_probabilities): Likewise. + (compute_value_histograms): Remove argument for call of + get_coverage_counts. + * profile.h: Do not make gcov_summary const. + 2018-09-21 Monk Chiang * config.gcc (nds32*-*-*): Set TARGET_DEFAULT_TLSDESC_TRAMPOLINE=0. diff --git a/gcc/auto-profile.c b/gcc/auto-profile.c index 197fa10e08c..68abe327cce 100644 --- a/gcc/auto-profile.c +++ b/gcc/auto-profile.c @@ -867,7 +867,6 @@ autofdo_source_profile::read () function_instance::function_instance_stack stack; function_instance *s = function_instance::read_function_instance ( &stack, gcov_read_counter ()); - afdo_profile_info->sum_all += s->total_count (); map_[s->name ()] = s; } return true; @@ -958,23 +957,6 @@ read_profile (void) /* autofdo_module_profile. */ fake_read_autofdo_module_profile (); - - /* Read in the working set. */ - if (gcov_read_unsigned () != GCOV_TAG_AFDO_WORKING_SET) - { - error ("cannot read working set from %s", auto_profile_file); - return; - } - - /* Skip the length of the section. */ - gcov_read_unsigned (); - gcov_working_set_t set[128]; - for (unsigned i = 0; i < 128; i++) - { - set[i].num_counters = gcov_read_unsigned (); - set[i].min_counter = gcov_read_counter (); - } - add_working_set (set); } /* From AutoFDO profiles, find values inside STMT for that we want to measure @@ -1685,7 +1667,6 @@ read_autofdo_file (void) autofdo::afdo_profile_info = XNEW (gcov_summary); autofdo::afdo_profile_info->runs = 1; autofdo::afdo_profile_info->sum_max = 0; - autofdo::afdo_profile_info->sum_all = 0; /* Read the profile from the profile file. */ autofdo::read_profile (); @@ -1712,7 +1693,7 @@ afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge *edge) if (count > 0) { bool is_hot; - const gcov_summary *saved_profile_info = profile_info; + gcov_summary *saved_profile_info = profile_info; /* At early inline stage, profile_info is not set yet. We need to temporarily set it to afdo_profile_info to calculate hotness. */ profile_info = autofdo::afdo_profile_info; diff --git a/gcc/coverage.c b/gcc/coverage.c index bae6f5cafac..26cce2bc63a 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "params.h" #include "auto-profile.h" +#include "profile.h" #include "gcov-io.c" @@ -73,7 +74,6 @@ struct counts_entry : pointer_hash unsigned lineno_checksum; unsigned cfg_checksum; gcov_type *counts; - gcov_summary summary; /* hash_table support. */ static inline hashval_t hash (const counts_entry *); @@ -185,8 +185,6 @@ static void read_counts_file (void) { gcov_unsigned_t fn_ident = 0; - gcov_summary summary; - unsigned new_summary = 1; gcov_unsigned_t tag; int is_error = 0; unsigned lineno_checksum = 0; @@ -236,27 +234,12 @@ read_counts_file (void) } else fn_ident = lineno_checksum = cfg_checksum = 0; - new_summary = 1; } - else if (tag == GCOV_TAG_PROGRAM_SUMMARY) + else if (tag == GCOV_TAG_OBJECT_SUMMARY) { - struct gcov_summary sum; - - if (new_summary) - memset (&summary, 0, sizeof (summary)); - - gcov_read_summary (&sum); - summary.runs += sum.runs; - summary.sum_all += sum.sum_all; - if (summary.run_max < sum.run_max) - summary.run_max = sum.run_max; - summary.sum_max += sum.sum_max; - if (new_summary) - memcpy (summary.histogram, sum.histogram, - sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); - else - gcov_histogram_merge (summary.histogram, sum.histogram); - new_summary = 0; + profile_info = XCNEW (gcov_summary); + profile_info->runs = gcov_read_unsigned (); + profile_info->sum_max = gcov_read_unsigned (); } else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident) { @@ -276,9 +259,6 @@ read_counts_file (void) entry->ctr = elt.ctr; entry->lineno_checksum = lineno_checksum; entry->cfg_checksum = cfg_checksum; - if (elt.ctr == GCOV_COUNTER_ARCS) - entry->summary = summary; - entry->summary.num = n_counts; entry->counts = XCNEWVEC (gcov_type, n_counts); } else if (entry->lineno_checksum != lineno_checksum @@ -292,22 +272,6 @@ read_counts_file (void) counts_hash = NULL; break; } - else if (entry->summary.num != n_counts) - { - error ("Profile data for function %u is corrupted", fn_ident); - error ("number of counters is %d instead of %d", entry->summary.num, n_counts); - delete counts_hash; - counts_hash = NULL; - break; - } - else - { - entry->summary.runs += summary.runs; - entry->summary.sum_all += summary.sum_all; - if (entry->summary.run_max < summary.run_max) - entry->summary.run_max = summary.run_max; - entry->summary.sum_max += summary.sum_max; - } for (ix = 0; ix != n_counts; ix++) entry->counts[ix] += gcov_read_counter (); } @@ -330,9 +294,8 @@ read_counts_file (void) /* Returns the counters for a particular tag. */ gcov_type * -get_coverage_counts (unsigned counter, unsigned expected, - unsigned cfg_checksum, unsigned lineno_checksum, - const gcov_summary **summary) +get_coverage_counts (unsigned counter, unsigned cfg_checksum, + unsigned lineno_checksum) { counts_entry *entry, elt; @@ -363,14 +326,13 @@ get_coverage_counts (unsigned counter, unsigned expected, } elt.ctr = counter; entry = counts_hash->find (&elt); - if (!entry || !entry->summary.num) + if (!entry) /* The function was not emitted, or is weak and not chosen in the final executable. Silently fail, because there's nothing we can do about it. */ return NULL; - if (entry->cfg_checksum != cfg_checksum - || entry->summary.num != expected) + if (entry->cfg_checksum != cfg_checksum) { static int warned = 0; bool warning_printed = false; @@ -414,9 +376,6 @@ get_coverage_counts (unsigned counter, unsigned expected, DECL_ASSEMBLER_NAME (current_function_decl)); } - if (summary) - *summary = &entry->summary; - return entry->counts; } diff --git a/gcc/coverage.h b/gcc/coverage.h index 842d6952c16..d612c38d159 100644 --- a/gcc/coverage.h +++ b/gcc/coverage.h @@ -51,10 +51,8 @@ extern tree tree_coverage_counter_addr (unsigned /*counter*/, unsigned/*num*/); /* Get all the counters for the current function. */ extern gcov_type *get_coverage_counts (unsigned /*counter*/, - unsigned /*expected*/, unsigned /*cfg_checksum*/, - unsigned /*lineno_checksum*/, - const gcov_summary **); + unsigned /*lineno_checksum*/); extern tree get_gcov_type (void); extern bool coverage_node_map_initialized_p (void); diff --git a/gcc/doc/gcov-dump.texi b/gcc/doc/gcov-dump.texi index e526bdeb858..0313358cdb0 100644 --- a/gcc/doc/gcov-dump.texi +++ b/gcc/doc/gcov-dump.texi @@ -61,7 +61,7 @@ gcov-dump [@option{-v}|@option{--version}] [@option{-h}|@option{--help}] [@option{-l}|@option{--long}] [@option{-p}|@option{--positions}] - [@option{-w}|@option{--working-sets}] @var{gcovfiles} + @var{gcovfiles} @c man end @end ignore @@ -84,10 +84,6 @@ Dump positions of records. @itemx --version Display the @command{gcov-dump} version number (on the standard output), and exit without doing any further processing. - -@item -w -@itemx --working-sets -Dump working set computed from summary. @end table @c man end diff --git a/gcc/gcov-dump.c b/gcc/gcov-dump.c index 3ff11a6aa0b..7762e4e8190 100644 --- a/gcc/gcov-dump.c +++ b/gcc/gcov-dump.c @@ -38,9 +38,6 @@ static void tag_arcs (const char *, unsigned, unsigned, unsigned); static void tag_lines (const char *, unsigned, unsigned, unsigned); static void tag_counters (const char *, unsigned, unsigned, unsigned); static void tag_summary (const char *, unsigned, unsigned, unsigned); -static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED, - const gcov_summary *summary, - unsigned depth); extern int main (int, char **); typedef struct tag_format @@ -52,7 +49,6 @@ typedef struct tag_format static int flag_dump_contents = 0; static int flag_dump_positions = 0; -static int flag_dump_working_sets = 0; static const struct option options[] = { @@ -60,7 +56,6 @@ static const struct option options[] = { "version", no_argument, NULL, 'v' }, { "long", no_argument, NULL, 'l' }, { "positions", no_argument, NULL, 'o' }, - { "working-sets", no_argument, NULL, 'w' }, { 0, 0, 0, 0 } }; @@ -77,7 +72,6 @@ static const tag_format_t tag_table[] = {GCOV_TAG_ARCS, "ARCS", tag_arcs}, {GCOV_TAG_LINES, "LINES", tag_lines}, {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary}, - {GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary}, {0, NULL, NULL} }; @@ -117,9 +111,6 @@ main (int argc ATTRIBUTE_UNUSED, char **argv) case 'p': flag_dump_positions = 1; break; - case 'w': - flag_dump_working_sets = 1; - break; default: fprintf (stderr, "unknown flag `%c'\n", opt); } @@ -139,7 +130,6 @@ print_usage (void) printf (" -l, --long Dump record contents too\n"); printf (" -p, --positions Dump record positions\n"); printf (" -v, --version Print version number\n"); - printf (" -w, --working-sets Dump working set computed from summary\n"); printf ("\nFor bug reporting instructions, please see:\n%s.\n", bug_report_url); } @@ -465,75 +455,10 @@ tag_counters (const char *filename ATTRIBUTE_UNUSED, static void tag_summary (const char *filename ATTRIBUTE_UNUSED, unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED, - unsigned depth) + unsigned depth ATTRIBUTE_UNUSED) { gcov_summary summary; - unsigned h_ix; - gcov_bucket_type *histo_bucket; - gcov_read_summary (&summary); - printf (" checksum=0x%08x", summary.checksum); - - printf ("\n"); - print_prefix (filename, depth, 0); - printf (VALUE_PADDING_PREFIX "counts=%u, runs=%u", - summary.num, summary.runs); - - printf (", sum_all=%" PRId64, - (int64_t)summary.sum_all); - printf (", run_max=%" PRId64, - (int64_t)summary.run_max); - printf (", sum_max=%" PRId64, - (int64_t)summary.sum_max); - printf ("\n"); - print_prefix (filename, depth, 0); - printf (VALUE_PADDING_PREFIX "counter histogram:"); - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - { - histo_bucket = &summary.histogram[h_ix]; - if (!histo_bucket->num_counters) - continue; - printf ("\n"); - print_prefix (filename, depth, 0); - printf (VALUE_PADDING_PREFIX VALUE_PREFIX "num counts=%u, " - "min counter=%" PRId64 ", cum_counter=%" PRId64, - h_ix, histo_bucket->num_counters, - (int64_t)histo_bucket->min_value, - (int64_t)histo_bucket->cum_value); - } - if (flag_dump_working_sets) - dump_working_sets (filename, &summary, depth); -} - -static void -dump_working_sets (const char *filename ATTRIBUTE_UNUSED, - const gcov_summary *summary, - unsigned depth) -{ - gcov_working_set_t gcov_working_sets[NUM_GCOV_WORKING_SETS]; - unsigned ws_ix, pctinc, pct; - gcov_working_set_t *ws_info; - - compute_working_sets (summary, gcov_working_sets); - - printf ("\n"); - print_prefix (filename, depth, 0); - printf (VALUE_PADDING_PREFIX "counter working sets:"); - /* Multiply the percentage by 100 to avoid float. */ - pctinc = 100 * 100 / NUM_GCOV_WORKING_SETS; - for (ws_ix = 0, pct = pctinc; ws_ix < NUM_GCOV_WORKING_SETS; - ws_ix++, pct += pctinc) - { - if (ws_ix == NUM_GCOV_WORKING_SETS - 1) - pct = 9990; - ws_info = &gcov_working_sets[ws_ix]; - /* Print out the percentage using int arithmatic to avoid float. */ - printf ("\n"); - print_prefix (filename, depth + 1, 0); - printf (VALUE_PADDING_PREFIX "%u.%02u%%: num counts=%u, min counter=" - "%" PRId64, - pct / 100, pct - (pct / 100 * 100), - ws_info->num_counters, - (int64_t)ws_info->min_counter); - } + printf (" runs=%d, sum_max=%" PRId64, + summary.runs, summary.sum_max); } diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c index 311e4d014bf..63cc7fcb048 100644 --- a/gcc/gcov-io.c +++ b/gcc/gcov-io.c @@ -446,39 +446,11 @@ gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length) GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary) { - unsigned h_ix, bv_ix, h_cnt = 0; - unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE]; - - /* Count number of non-zero histogram entries, and fill in a bit vector - of non-zero indices. The histogram is only currently computed for arc - counters. */ - for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) - histo_bitvector[bv_ix] = 0; - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - if (summary->histogram[h_ix].num_counters) - { - histo_bitvector[h_ix / 32] |= 1 << (h_ix % 32); - h_cnt++; - } - gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH (h_cnt)); - gcov_write_unsigned (summary->checksum); - - gcov_write_unsigned (summary->num); + gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH); gcov_write_unsigned (summary->runs); - gcov_write_counter (summary->sum_all); - gcov_write_counter (summary->run_max); - gcov_write_counter (summary->sum_max); - for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) - gcov_write_unsigned (histo_bitvector[bv_ix]); - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - { - if (!summary->histogram[h_ix].num_counters) - continue; - gcov_write_unsigned (summary->histogram[h_ix].num_counters); - gcov_write_counter (summary->histogram[h_ix].min_value); - gcov_write_counter (summary->histogram[h_ix].cum_value); - } + gcov_write_unsigned (summary->sum_max); } + #endif /* IN_LIBGCOV */ #endif /*!IN_GCOV */ @@ -637,65 +609,8 @@ gcov_read_string (void) GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *summary) { - unsigned h_ix, bv_ix, h_cnt = 0; - unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE]; - unsigned cur_bitvector; - - summary->checksum = gcov_read_unsigned (); - summary->num = gcov_read_unsigned (); summary->runs = gcov_read_unsigned (); - summary->sum_all = gcov_read_counter (); - summary->run_max = gcov_read_counter (); - summary->sum_max = gcov_read_counter (); - memset (summary->histogram, 0, - sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); - for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++) - { - histo_bitvector[bv_ix] = gcov_read_unsigned (); -#if IN_LIBGCOV - /* When building libgcov we don't include system.h, which includes - hwint.h (where popcount_hwi is declared). However, libgcov.a - is built by the bootstrapped compiler and therefore the builtins - are always available. */ - h_cnt += __builtin_popcount (histo_bitvector[bv_ix]); -#else - h_cnt += popcount_hwi (histo_bitvector[bv_ix]); -#endif - } - bv_ix = 0; - h_ix = 0; - cur_bitvector = 0; - while (h_cnt--) - { - /* Find the index corresponding to the next entry we will read in. - First find the next non-zero bitvector and re-initialize - the histogram index accordingly, then right shift and increment - the index until we find a set bit. */ - while (!cur_bitvector) - { - h_ix = bv_ix * 32; - if (bv_ix >= GCOV_HISTOGRAM_BITVECTOR_SIZE) - gcov_error ("corrupted profile info: summary histogram " - "bitvector is corrupt"); - cur_bitvector = histo_bitvector[bv_ix++]; - } - while (!(cur_bitvector & 0x1)) - { - h_ix++; - cur_bitvector >>= 1; - } - if (h_ix >= GCOV_HISTOGRAM_SIZE) - gcov_error ("corrupted profile info: summary histogram " - "index is corrupt"); - - summary->histogram[h_ix].num_counters = gcov_read_unsigned (); - summary->histogram[h_ix].min_value = gcov_read_counter (); - summary->histogram[h_ix].cum_value = gcov_read_counter (); - /* Shift off the index we are done with and increment to the - corresponding next histogram entry. */ - cur_bitvector >>= 1; - h_ix++; - } + summary->sum_max = gcov_read_unsigned (); } /* We need to expose the below function when compiling for gcov-tool. */ @@ -747,308 +662,3 @@ gcov_time (void) return status.st_mtime; } #endif /* IN_GCOV */ - -#if !IN_GCOV -/* Determine the index into histogram for VALUE. */ - -#if IN_LIBGCOV -static unsigned -#else -GCOV_LINKAGE unsigned -#endif -gcov_histo_index (gcov_type value) -{ - gcov_type_unsigned v = (gcov_type_unsigned)value; - unsigned r = 0; - unsigned prev2bits = 0; - - /* Find index into log2 scale histogram, where each of the log2 - sized buckets is divided into 4 linear sub-buckets for better - focus in the higher buckets. */ - - /* Find the place of the most-significant bit set. */ - if (v > 0) - { -#if IN_LIBGCOV - /* When building libgcov we don't include system.h, which includes - hwint.h (where floor_log2 is declared). However, libgcov.a - is built by the bootstrapped compiler and therefore the builtins - are always available. */ - r = sizeof (long long) * __CHAR_BIT__ - 1 - __builtin_clzll (v); -#else - /* We use floor_log2 from hwint.c, which takes a HOST_WIDE_INT - that is 64 bits and gcov_type_unsigned is 64 bits. */ - r = floor_log2 (v); -#endif - } - - /* If at most the 2 least significant bits are set (value is - 0 - 3) then that value is our index into the lowest set of - four buckets. */ - if (r < 2) - return (unsigned)value; - - gcov_nonruntime_assert (r < 64); - - /* Find the two next most significant bits to determine which - of the four linear sub-buckets to select. */ - prev2bits = (v >> (r - 2)) & 0x3; - /* Finally, compose the final bucket index from the log2 index and - the next 2 bits. The minimum r value at this point is 2 since we - returned above if r was 2 or more, so the minimum bucket at this - point is 4. */ - return (r - 1) * 4 + prev2bits; -} - -/* Merge SRC_HISTO into TGT_HISTO. The counters are assumed to be in - the same relative order in both histograms, and are matched up - and merged in reverse order. Each counter is assigned an equal portion of - its entry's original cumulative counter value when computing the - new merged cum_value. */ - -static void gcov_histogram_merge (gcov_bucket_type *tgt_histo, - gcov_bucket_type *src_histo) -{ - int src_i, tgt_i, tmp_i = 0; - unsigned src_num, tgt_num, merge_num; - gcov_type src_cum, tgt_cum, merge_src_cum, merge_tgt_cum, merge_cum; - gcov_type merge_min; - gcov_bucket_type tmp_histo[GCOV_HISTOGRAM_SIZE]; - int src_done = 0; - - memset (tmp_histo, 0, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); - - /* Assume that the counters are in the same relative order in both - histograms. Walk the histograms from largest to smallest entry, - matching up and combining counters in order. */ - src_num = 0; - src_cum = 0; - src_i = GCOV_HISTOGRAM_SIZE - 1; - for (tgt_i = GCOV_HISTOGRAM_SIZE - 1; tgt_i >= 0 && !src_done; tgt_i--) - { - tgt_num = tgt_histo[tgt_i].num_counters; - tgt_cum = tgt_histo[tgt_i].cum_value; - /* Keep going until all of the target histogram's counters at this - position have been matched and merged with counters from the - source histogram. */ - while (tgt_num > 0 && !src_done) - { - /* If this is either the first time through this loop or we just - exhausted the previous non-zero source histogram entry, look - for the next non-zero source histogram entry. */ - if (!src_num) - { - /* Locate the next non-zero entry. */ - while (src_i >= 0 && !src_histo[src_i].num_counters) - src_i--; - /* If source histogram has fewer counters, then just copy over the - remaining target counters and quit. */ - if (src_i < 0) - { - tmp_histo[tgt_i].num_counters += tgt_num; - tmp_histo[tgt_i].cum_value += tgt_cum; - if (!tmp_histo[tgt_i].min_value || - tgt_histo[tgt_i].min_value < tmp_histo[tgt_i].min_value) - tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value; - while (--tgt_i >= 0) - { - tmp_histo[tgt_i].num_counters - += tgt_histo[tgt_i].num_counters; - tmp_histo[tgt_i].cum_value += tgt_histo[tgt_i].cum_value; - if (!tmp_histo[tgt_i].min_value || - tgt_histo[tgt_i].min_value - < tmp_histo[tgt_i].min_value) - tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value; - } - - src_done = 1; - break; - } - - src_num = src_histo[src_i].num_counters; - src_cum = src_histo[src_i].cum_value; - } - - /* The number of counters to merge on this pass is the minimum - of the remaining counters from the current target and source - histogram entries. */ - merge_num = tgt_num; - if (src_num < merge_num) - merge_num = src_num; - - /* The merged min_value is the sum of the min_values from target - and source. */ - merge_min = tgt_histo[tgt_i].min_value + src_histo[src_i].min_value; - - /* Compute the portion of source and target entries' cum_value - that will be apportioned to the counters being merged. - The total remaining cum_value from each entry is divided - equally among the counters from that histogram entry if we - are not merging all of them. */ - merge_src_cum = src_cum; - if (merge_num < src_num) - merge_src_cum = merge_num * src_cum / src_num; - merge_tgt_cum = tgt_cum; - if (merge_num < tgt_num) - merge_tgt_cum = merge_num * tgt_cum / tgt_num; - /* The merged cum_value is the sum of the source and target - components. */ - merge_cum = merge_src_cum + merge_tgt_cum; - - /* Update the remaining number of counters and cum_value left - to be merged from this source and target entry. */ - src_cum -= merge_src_cum; - tgt_cum -= merge_tgt_cum; - src_num -= merge_num; - tgt_num -= merge_num; - - /* The merged counters get placed in the new merged histogram - at the entry for the merged min_value. */ - tmp_i = gcov_histo_index (merge_min); - gcov_nonruntime_assert (tmp_i < GCOV_HISTOGRAM_SIZE); - tmp_histo[tmp_i].num_counters += merge_num; - tmp_histo[tmp_i].cum_value += merge_cum; - if (!tmp_histo[tmp_i].min_value || - merge_min < tmp_histo[tmp_i].min_value) - tmp_histo[tmp_i].min_value = merge_min; - - /* Ensure the search for the next non-zero src_histo entry starts - at the next smallest histogram bucket. */ - if (!src_num) - src_i--; - } - } - - gcov_nonruntime_assert (tgt_i < 0); - - /* In the case where there were more counters in the source histogram, - accumulate the remaining unmerged cumulative counter values. Add - those to the smallest non-zero target histogram entry. Otherwise, - the total cumulative counter values in the histogram will be smaller - than the sum_all stored in the summary, which will complicate - computing the working set information from the histogram later on. */ - if (src_num) - src_i--; - while (src_i >= 0) - { - src_cum += src_histo[src_i].cum_value; - src_i--; - } - /* At this point, tmp_i should be the smallest non-zero entry in the - tmp_histo. */ - gcov_nonruntime_assert (tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE - && tmp_histo[tmp_i].num_counters > 0); - tmp_histo[tmp_i].cum_value += src_cum; - - /* Finally, copy the merged histogram into tgt_histo. */ - memcpy (tgt_histo, tmp_histo, - sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); -} -#endif /* !IN_GCOV */ - -/* This is used by gcov-dump (IN_GCOV == -1) and in the compiler - (!IN_GCOV && !IN_LIBGCOV). */ -#if IN_GCOV <= 0 && !IN_LIBGCOV -/* Compute the working set information from the counter histogram in - the profile summary. This is an array of information corresponding to a - range of percentages of the total execution count (sum_all), and includes - the number of counters required to cover that working set percentage and - the minimum counter value in that working set. */ - -GCOV_LINKAGE void -compute_working_sets (const gcov_summary *summary, - gcov_working_set_t *gcov_working_sets) -{ - gcov_type working_set_cum_values[NUM_GCOV_WORKING_SETS]; - gcov_type ws_cum_hotness_incr; - gcov_type cum, tmp_cum; - const gcov_bucket_type *histo_bucket; - unsigned ws_ix, c_num, count; - int h_ix; - - /* Compute the amount of sum_all that the cumulative hotness grows - by in each successive working set entry, which depends on the - number of working set entries. */ - ws_cum_hotness_incr = summary->sum_all / NUM_GCOV_WORKING_SETS; - - /* Next fill in an array of the cumulative hotness values corresponding - to each working set summary entry we are going to compute below. - Skip 0% statistics, which can be extrapolated from the - rest of the summary data. */ - cum = ws_cum_hotness_incr; - for (ws_ix = 0; ws_ix < NUM_GCOV_WORKING_SETS; - ws_ix++, cum += ws_cum_hotness_incr) - working_set_cum_values[ws_ix] = cum; - /* The last summary entry is reserved for (roughly) 99.9% of the - working set. Divide by 1024 so it becomes a shift, which gives - almost exactly 99.9%. */ - working_set_cum_values[NUM_GCOV_WORKING_SETS-1] - = summary->sum_all - summary->sum_all/1024; - - /* Next, walk through the histogram in decending order of hotness - and compute the statistics for the working set summary array. - As histogram entries are accumulated, we check to see which - working set entries have had their expected cum_value reached - and fill them in, walking the working set entries in increasing - size of cum_value. */ - ws_ix = 0; /* The current entry into the working set array. */ - cum = 0; /* The current accumulated counter sum. */ - count = 0; /* The current accumulated count of block counters. */ - for (h_ix = GCOV_HISTOGRAM_SIZE - 1; - h_ix >= 0 && ws_ix < NUM_GCOV_WORKING_SETS; h_ix--) - { - histo_bucket = &summary->histogram[h_ix]; - - /* If we haven't reached the required cumulative counter value for - the current working set percentage, simply accumulate this histogram - entry into the running sums and continue to the next histogram - entry. */ - if (cum + histo_bucket->cum_value < working_set_cum_values[ws_ix]) - { - cum += histo_bucket->cum_value; - count += histo_bucket->num_counters; - continue; - } - - /* If adding the current histogram entry's cumulative counter value - causes us to exceed the current working set size, then estimate - how many of this histogram entry's counter values are required to - reach the working set size, and fill in working set entries - as we reach their expected cumulative value. */ - for (c_num = 0, tmp_cum = cum; - c_num < histo_bucket->num_counters && ws_ix < NUM_GCOV_WORKING_SETS; - c_num++) - { - count++; - /* If we haven't reached the last histogram entry counter, add - in the minimum value again. This will underestimate the - cumulative sum so far, because many of the counter values in this - entry may have been larger than the minimum. We could add in the - average value every time, but that would require an expensive - divide operation. */ - if (c_num + 1 < histo_bucket->num_counters) - tmp_cum += histo_bucket->min_value; - /* If we have reached the last histogram entry counter, then add - in the entire cumulative value. */ - else - tmp_cum = cum + histo_bucket->cum_value; - - /* Next walk through successive working set entries and fill in - the statistics for any whose size we have reached by accumulating - this histogram counter. */ - while (ws_ix < NUM_GCOV_WORKING_SETS - && tmp_cum >= working_set_cum_values[ws_ix]) - { - gcov_working_sets[ws_ix].num_counters = count; - gcov_working_sets[ws_ix].min_counter - = histo_bucket->min_value; - ws_ix++; - } - } - /* Finally, update the running cumulative value since we were - using a temporary above. */ - cum += histo_bucket->cum_value; - } - gcov_nonruntime_assert (ws_ix == NUM_GCOV_WORKING_SETS); -} -#endif /* IN_GCOV <= 0 && !IN_LIBGCOV */ diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h index 7a11f0aec7f..1fc31f52eee 100644 --- a/gcc/gcov-io.h +++ b/gcc/gcov-io.h @@ -133,17 +133,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see blocks they are for. The data file contains the following records. - data: {unit summary:object summary:program* function-data*}* + data: {unit summary:object function-data*}* unit: header int32:checksum - function-data: announce_function present counts + function-data: announce_function present counts announce_function: header int32:ident int32:lineno_checksum int32:cfg_checksum present: header int32:present counts: header int64:count* - summary: int32:checksum int32:num int32:runs int64:sum - int64:max int64:sum_max histogram - histogram: {int32:bitvector}8 histogram-buckets* - histogram-buckets: int32:num int64:min int64:sum + summary: int32:checksum int32:runs int32:sum_max The ANNOUNCE_FUNCTION record is the same as that in the note file, but without the source location. The COUNTS gives the @@ -190,7 +187,7 @@ typedef uint64_t gcov_type_unsigned; #define ATTRIBUTE_HIDDEN -#endif /* !IN_LIBGOCV */ +#endif /* !IN_LIBGCOV */ #ifndef GCOV_LINKAGE #define GCOV_LINKAGE extern @@ -240,9 +237,9 @@ typedef uint64_t gcov_type_unsigned; #define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000) #define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2) #define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) -#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */ -#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) -#define GCOV_TAG_SUMMARY_LENGTH(NUM) (1 + (10 + 3 * 2) + (NUM) * 5) +#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) +#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) /* Obsolete */ +#define GCOV_TAG_SUMMARY_LENGTH (2) #define GCOV_TAG_AFDO_FILE_NAMES ((gcov_unsigned_t)0xaa000000) #define GCOV_TAG_AFDO_FUNCTION ((gcov_unsigned_t)0xac000000) #define GCOV_TAG_AFDO_WORKING_SET ((gcov_unsigned_t)0xaf000000) @@ -307,43 +304,12 @@ GCOV_COUNTERS #define GCOV_ARC_FAKE (1 << 1) #define GCOV_ARC_FALLTHROUGH (1 << 2) -/* Structured records. */ - -/* Structure used for each bucket of the log2 histogram of counter values. */ -typedef struct -{ - /* Number of counters whose profile count falls within the bucket. */ - gcov_unsigned_t num_counters; - /* Smallest profile count included in this bucket. */ - gcov_type min_value; - /* Cumulative value of the profile counts in this bucket. */ - gcov_type cum_value; -} gcov_bucket_type; - -/* For a log2 scale histogram with each range split into 4 - linear sub-ranges, there will be at most 64 (max gcov_type bit size) - 1 log2 - ranges since the lowest 2 log2 values share the lowest 4 linear - sub-range (values 0 - 3). This is 252 total entries (63*4). */ - -#define GCOV_HISTOGRAM_SIZE 252 - -/* How many unsigned ints are required to hold a bit vector of non-zero - histogram entries when the histogram is written to the gcov file. - This is essentially a ceiling divide by 32 bits. */ -#define GCOV_HISTOGRAM_BITVECTOR_SIZE (GCOV_HISTOGRAM_SIZE + 31) / 32 - /* Object & program summary record. */ struct gcov_summary { - gcov_unsigned_t checksum; /* Checksum of program. */ - gcov_unsigned_t num; /* Number of counters. */ gcov_unsigned_t runs; /* Number of program runs. */ - gcov_type sum_all; /* Sum of all counters accumulated. */ - gcov_type run_max; /* Maximum value on a single run. */ gcov_type sum_max; /* Sum of individual run max values. */ - gcov_bucket_type histogram[GCOV_HISTOGRAM_SIZE]; /* Histogram of - counter values. */ }; #if !defined(inhibit_libc) @@ -380,35 +346,12 @@ GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN; #if !IN_GCOV && !IN_LIBGCOV /* Available only in compiler */ -GCOV_LINKAGE unsigned gcov_histo_index (gcov_type value); GCOV_LINKAGE void gcov_write_string (const char *); GCOV_LINKAGE void gcov_write_filename (const char *); GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t); GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/); #endif -#if IN_GCOV <= 0 && !IN_LIBGCOV -/* Available in gcov-dump and the compiler. */ - -/* Number of data points in the working set summary array. Using 128 - provides information for at least every 1% increment of the total - profile size. The last entry is hardwired to 99.9% of the total. */ -#define NUM_GCOV_WORKING_SETS 128 - -/* Working set size statistics for a given percentage of the entire - profile (sum_all from the counter summary). */ -typedef struct gcov_working_set_info -{ - /* Number of hot counters included in this working set. */ - unsigned num_counters; - /* Smallest counter included in this working set. */ - gcov_type min_counter; -} gcov_working_set_t; - -GCOV_LINKAGE void compute_working_sets (const gcov_summary *summary, - gcov_working_set_t *gcov_working_sets); -#endif - #if IN_GCOV > 0 /* Available in gcov */ GCOV_LINKAGE time_t gcov_time (void); diff --git a/gcc/gcov-tool.c b/gcc/gcov-tool.c index 15fd710b18c..88539f9647f 100644 --- a/gcc/gcov-tool.c +++ b/gcc/gcov-tool.c @@ -423,7 +423,6 @@ print_overlap_usage_message (int error_p) fnotice (file, " -o, --object Print object level info\n"); fnotice (file, " -t , --hot_threshold Set the threshold for hotness\n"); fnotice (file, " -v, --verbose Verbose mode\n"); - } static const struct option overlap_options[] = diff --git a/gcc/gcov.c b/gcc/gcov.c index c09d5060053..922e2de2646 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -418,7 +418,6 @@ static vector processed_files; /* This holds data summary information. */ static unsigned object_runs; -static unsigned program_count; static unsigned total_lines; static unsigned total_executed; @@ -1829,12 +1828,11 @@ read_count_file (void) unsigned length = gcov_read_unsigned (); unsigned long base = gcov_position (); - if (tag == GCOV_TAG_PROGRAM_SUMMARY) + if (tag == GCOV_TAG_OBJECT_SUMMARY) { struct gcov_summary summary; gcov_read_summary (&summary); - object_runs += summary.runs; - program_count++; + object_runs = summary.runs; } else if (tag == GCOV_TAG_FUNCTION && !length) ; /* placeholder */ @@ -2952,7 +2950,6 @@ output_lines (FILE *gcov_file, const source_info *src) no_data_file ? "-" : da_file_name); fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs); } - fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count); source_file = fopen (src->name, "r"); if (!source_file) diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index f921d1bb6f4..c74f4a4a41d 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -25,13 +25,6 @@ along with GCC; see the file COPYING3. If not see from profile feedback. This histogram is complete only with LTO, otherwise it contains information only about the current unit. - Similar histogram is also estimated by coverage runtime. This histogram - is not dependent on LTO, but it suffers from various defects; first - gcov runtime is not weighting individual basic block by estimated execution - time and second the merging of multiple runs makes assumption that the - histogram distribution did not change. Consequentely histogram constructed - here may be more precise. - The information is used to set hot/cold thresholds. - Next speculative indirect call resolution is performed: the local profile pass assigns profile-id to each function and provide us with a @@ -512,25 +505,7 @@ ipa_profile (void) gcov_type threshold; gcc_assert (overall_size); - if (dump_file) - { - gcov_type min, cumulated_time = 0, cumulated_size = 0; - fprintf (dump_file, "Overall time: %" PRId64"\n", - (int64_t)overall_time); - min = get_hot_bb_threshold (); - for (i = 0; i < (int)histogram.length () && histogram[i]->count >= min; - i++) - { - cumulated_time += histogram[i]->count * histogram[i]->time; - cumulated_size += histogram[i]->size; - } - fprintf (dump_file, "GCOV min count: %" PRId64 - " Time:%3.2f%% Size:%3.2f%%\n", - (int64_t)min, - cumulated_time * 100.0 / overall_time, - cumulated_size * 100.0 / overall_size); - } cutoff = (overall_time * PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE) + 500) / 1000; threshold = 0; for (i = 0; cumulated < cutoff; i++) @@ -557,6 +532,7 @@ ipa_profile (void) cumulated_time * 100.0 / overall_time, cumulated_size * 100.0 / overall_size); } + if (threshold > get_hot_bb_threshold () || in_lto_p) { diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 1e6a7adeaa2..6d9eea13f22 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -693,39 +693,14 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref, static void output_profile_summary (struct lto_simple_output_block *ob) { - unsigned h_ix; - struct bitpack_d bp; - if (profile_info) { /* We do not output num and run_max, they are not used by GCC profile feedback and they are difficult to merge from multiple units. */ - gcc_assert (profile_info->runs); - streamer_write_uhwi_stream (ob->main_stream, profile_info->runs); - streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_max); + unsigned runs = (profile_info->runs); + streamer_write_uhwi_stream (ob->main_stream, runs); - /* sum_all is needed for computing the working set with the - histogram. */ - streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_all); - - /* Create and output a bitpack of non-zero histogram entries indices. */ - bp = bitpack_create (ob->main_stream); - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - bp_pack_value (&bp, profile_info->histogram[h_ix].num_counters > 0, 1); - streamer_write_bitpack (&bp); - /* Now stream out only those non-zero entries. */ - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - { - if (!profile_info->histogram[h_ix].num_counters) - continue; - streamer_write_gcov_count_stream (ob->main_stream, - profile_info->histogram[h_ix].num_counters); - streamer_write_gcov_count_stream (ob->main_stream, - profile_info->histogram[h_ix].min_value); - streamer_write_gcov_count_stream (ob->main_stream, - profile_info->histogram[h_ix].cum_value); - } /* IPA-profile computes hot bb threshold based on cumulated whole program profile. We need to stream it down to ltrans. */ if (flag_wpa) @@ -1591,46 +1566,16 @@ input_refs (struct lto_input_block *ib, } } - -static gcov_summary lto_gcov_summary; - /* Input profile_info from IB. */ static void input_profile_summary (struct lto_input_block *ib, struct lto_file_decl_data *file_data) { - unsigned h_ix; - struct bitpack_d bp; unsigned int runs = streamer_read_uhwi (ib); if (runs) { file_data->profile_info.runs = runs; - file_data->profile_info.sum_max = streamer_read_gcov_count (ib); - file_data->profile_info.sum_all = streamer_read_gcov_count (ib); - memset (file_data->profile_info.histogram, 0, - sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); - /* Input the bitpack of non-zero histogram indices. */ - bp = streamer_read_bitpack (ib); - /* Read in and unpack the full bitpack, flagging non-zero - histogram entries by setting the num_counters non-zero. */ - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - { - file_data->profile_info.histogram[h_ix].num_counters - = bp_unpack_value (&bp, 1); - } - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - { - if (!file_data->profile_info.histogram[h_ix].num_counters) - continue; - - file_data->profile_info.histogram[h_ix].num_counters - = streamer_read_gcov_count (ib); - file_data->profile_info.histogram[h_ix].min_value - = streamer_read_gcov_count (ib); - file_data->profile_info.histogram[h_ix].cum_value - = streamer_read_gcov_count (ib); - } /* IPA-profile computes hot bb threshold based on cumulated whole program profile. We need to stream it down to ltrans. */ if (flag_ltrans) @@ -1645,13 +1590,10 @@ static void merge_profile_summaries (struct lto_file_decl_data **file_data_vec) { struct lto_file_decl_data *file_data; - unsigned int j, h_ix; + unsigned int j; gcov_unsigned_t max_runs = 0; struct cgraph_node *node; struct cgraph_edge *edge; - gcov_type saved_sum_all = 0; - gcov_summary *saved_profile_info = 0; - int saved_scale = 0; /* Find unit with maximal number of runs. If we ever get serious about roundoff errors, we might also consider computing smallest common @@ -1672,70 +1614,8 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec) return; } - profile_info = <o_gcov_summary; - lto_gcov_summary.runs = max_runs; - lto_gcov_summary.sum_max = 0; - memset (lto_gcov_summary.histogram, 0, - sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); - - /* Rescale all units to the maximal number of runs. - sum_max can not be easily merged, as we have no idea what files come from - the same run. We do not use the info anyway, so leave it 0. */ - for (j = 0; (file_data = file_data_vec[j]) != NULL; j++) - if (file_data->profile_info.runs) - { - int scale = GCOV_COMPUTE_SCALE (max_runs, - file_data->profile_info.runs); - lto_gcov_summary.sum_max - = MAX (lto_gcov_summary.sum_max, - apply_scale (file_data->profile_info.sum_max, scale)); - lto_gcov_summary.sum_all - = MAX (lto_gcov_summary.sum_all, - apply_scale (file_data->profile_info.sum_all, scale)); - /* Save a pointer to the profile_info with the largest - scaled sum_all and the scale for use in merging the - histogram. */ - if (!saved_profile_info - || lto_gcov_summary.sum_all > saved_sum_all) - { - saved_profile_info = &file_data->profile_info; - saved_sum_all = lto_gcov_summary.sum_all; - saved_scale = scale; - } - } - - gcc_assert (saved_profile_info); - - /* Scale up the histogram from the profile that had the largest - scaled sum_all above. */ - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - { - /* Scale up the min value as we did the corresponding sum_all - above. Use that to find the new histogram index. */ - gcov_type scaled_min - = apply_scale (saved_profile_info->histogram[h_ix].min_value, - saved_scale); - /* The new index may be shared with another scaled histogram entry, - so we need to account for a non-zero histogram entry at new_ix. */ - unsigned new_ix = gcov_histo_index (scaled_min); - lto_gcov_summary.histogram[new_ix].min_value - = (lto_gcov_summary.histogram[new_ix].num_counters - ? MIN (lto_gcov_summary.histogram[new_ix].min_value, scaled_min) - : scaled_min); - /* Some of the scaled counter values would ostensibly need to be placed - into different (larger) histogram buckets, but we keep things simple - here and place the scaled cumulative counter value in the bucket - corresponding to the scaled minimum counter value. */ - lto_gcov_summary.histogram[new_ix].cum_value - += apply_scale (saved_profile_info->histogram[h_ix].cum_value, - saved_scale); - lto_gcov_summary.histogram[new_ix].num_counters - += saved_profile_info->histogram[h_ix].num_counters; - } - - /* Watch roundoff errors. */ - if (lto_gcov_summary.sum_max < max_runs) - lto_gcov_summary.sum_max = max_runs; + profile_info = XCNEW (gcov_summary); + profile_info->runs = max_runs; /* If merging already happent at WPA time, we are done. */ if (flag_ltrans) @@ -1814,10 +1694,6 @@ input_symtab (void) merge_profile_summaries (file_data_vec); - if (!flag_auto_profile) - get_working_sets (); - - /* Clear out the aux field that was used to store enough state to tell which nodes should be overwritten. */ FOR_EACH_FUNCTION (node) diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index 9a27365bfbc..121e6191afd 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -1449,10 +1449,6 @@ sms_schedule (void) fprintf (dump_file, "%" PRId64 "max %" PRId64, (int64_t) trip_count, (int64_t) max_trip_count); fprintf (dump_file, "\n"); - fprintf (dump_file, "SMS profile-sum-max "); - fprintf (dump_file, "%" PRId64, - (int64_t) profile_info->sum_max); - fprintf (dump_file, "\n"); } } continue; @@ -1567,10 +1563,6 @@ sms_schedule (void) fprintf (dump_file, "%" PRId64, (int64_t) bb->count.to_gcov_type ()); fprintf (dump_file, "\n"); - fprintf (dump_file, "SMS profile-sum-max "); - fprintf (dump_file, "%" PRId64, - (int64_t) profile_info->sum_max); - fprintf (dump_file, "\n"); } fprintf (dump_file, "SMS doloop\n"); fprintf (dump_file, "SMS built-ddg %d\n", g->num_nodes); diff --git a/gcc/params.def b/gcc/params.def index a0ad3ecdad6..9f0697327d4 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -393,10 +393,15 @@ DEFPARAM(PARAM_SMS_LOOP_AVERAGE_COUNT_THRESHOLD, "A threshold on the average loop count considered by the swing modulo scheduler.", 0, 0, 0) +DEFPARAM(HOT_BB_COUNT_FRACTION, + "hot-bb-count-fraction", + "Select fraction of the maximal count of repetitions of basic block in program given basic " + "block needs to have to be considered hot (used in non-LTO mode)", + 10000, 0, 0) DEFPARAM(HOT_BB_COUNT_WS_PERMILLE, "hot-bb-count-ws-permille", "A basic block profile count is considered hot if it contributes to " - "the given permillage of the entire profiled execution.", + "the given permillage of the entire profiled execution (used in LTO mode).", 999, 0, 1000) DEFPARAM(HOT_BB_FREQUENCY_FRACTION, "hot-bb-frequency-fraction", diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c index afa61dcede6..b56993183d0 100644 --- a/gcc/postreload-gcse.c +++ b/gcc/postreload-gcse.c @@ -1161,7 +1161,7 @@ eliminate_partially_redundant_load (basic_block bb, rtx_insn *insn, || (optimize_bb_for_size_p (bb) && npred_ok > 1) /* If we don't have profile information we cannot tell if splitting a critical edge is profitable or not so don't do it. */ - || ((! profile_info || profile_status_for_fn (cfun) != PROFILE_READ + || ((!profile_info || profile_status_for_fn (cfun) != PROFILE_READ || targetm.cannot_modify_jumps_p ()) && critical_edge_split)) goto cleanup; diff --git a/gcc/predict.c b/gcc/predict.c index 51145526d2a..ab2dc8ed031 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -129,12 +129,13 @@ static gcov_type min_count = -1; gcov_type get_hot_bb_threshold () { - gcov_working_set_t *ws; if (min_count == -1) { - ws = find_working_set (PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE)); - gcc_assert (ws); - min_count = ws->min_counter; + min_count + = profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION); + if (dump_file) + fprintf (dump_file, "Setting hotness threshold to %" PRId64 ".\n", + min_count); } return min_count; } diff --git a/gcc/profile.c b/gcc/profile.c index cb51e0d4c51..2130319b081 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -84,11 +84,7 @@ struct bb_profile_info { /* Counter summary from the last set of coverage counts read. */ -const gcov_summary *profile_info; - -/* Counter working set information computed from the current counter - summary. Not initialized unless profile_info summary is non-NULL. */ -static gcov_working_set_t gcov_working_sets[NUM_GCOV_WORKING_SETS]; +gcov_summary *profile_info; /* Collect statistics on the performance of this pass for the entire source file. */ @@ -103,14 +99,6 @@ static int total_num_times_called; static int total_hist_br_prob[20]; static int total_num_branches; -/* Helper function to update gcov_working_sets. */ - -void add_working_set (gcov_working_set_t *set) { - int i = 0; - for (; i < NUM_GCOV_WORKING_SETS; i++) - gcov_working_sets[i] = set[i]; -} - /* Forward declarations. */ static void find_spanning_tree (struct edge_list *); @@ -207,60 +195,6 @@ instrument_values (histogram_values values) } -/* Fill the working set information into the profile_info structure. */ - -void -get_working_sets (void) -{ - unsigned ws_ix, pctinc, pct; - gcov_working_set_t *ws_info; - - if (!profile_info) - return; - - compute_working_sets (profile_info, gcov_working_sets); - - if (dump_file) - { - fprintf (dump_file, "Counter working sets:\n"); - /* Multiply the percentage by 100 to avoid float. */ - pctinc = 100 * 100 / NUM_GCOV_WORKING_SETS; - for (ws_ix = 0, pct = pctinc; ws_ix < NUM_GCOV_WORKING_SETS; - ws_ix++, pct += pctinc) - { - if (ws_ix == NUM_GCOV_WORKING_SETS - 1) - pct = 9990; - ws_info = &gcov_working_sets[ws_ix]; - /* Print out the percentage using int arithmatic to avoid float. */ - fprintf (dump_file, "\t\t%u.%02u%%: num counts=%u, min counter=" - "%" PRId64 "\n", - pct / 100, pct - (pct / 100 * 100), - ws_info->num_counters, - (int64_t)ws_info->min_counter); - } - } -} - -/* Given a the desired percentage of the full profile (sum_all from the - summary), multiplied by 10 to avoid float in PCT_TIMES_10, returns - the corresponding working set information. If an exact match for - the percentage isn't found, the closest value is used. */ - -gcov_working_set_t * -find_working_set (unsigned pct_times_10) -{ - unsigned i; - if (!profile_info) - return NULL; - gcc_assert (pct_times_10 <= 1000); - if (pct_times_10 >= 999) - return &gcov_working_sets[NUM_GCOV_WORKING_SETS - 1]; - i = pct_times_10 * NUM_GCOV_WORKING_SETS / 1000; - if (!i) - return &gcov_working_sets[0]; - return &gcov_working_sets[i - 1]; -} - /* Computes hybrid profile for all matching entries in da_file. CFG_CHECKSUM is the precomputed checksum for the CFG. */ @@ -283,21 +217,14 @@ get_exec_counts (unsigned cfg_checksum, unsigned lineno_checksum) num_edges++; } - counts = get_coverage_counts (GCOV_COUNTER_ARCS, num_edges, cfg_checksum, - lineno_checksum, &profile_info); + counts = get_coverage_counts (GCOV_COUNTER_ARCS, cfg_checksum, + lineno_checksum); if (!counts) return NULL; - get_working_sets (); - - if (dump_file && profile_info) - fprintf (dump_file, "Merged %u profiles with maximal count %u.\n", - profile_info->runs, (unsigned) profile_info->sum_max); - return counts; } - static bool is_edge_inconsistent (vec *edges) { @@ -439,29 +366,7 @@ read_profile_edge_counts (gcov_type *exec_counts) { num_edges++; if (exec_counts) - { - edge_gcov_count (e) = exec_counts[exec_counts_pos++]; - if (edge_gcov_count (e) > profile_info->sum_max) - { - if (flag_profile_correction) - { - static bool informed = 0; - if (dump_enabled_p () && !informed) - { - dump_location_t loc - = dump_location_t::from_location_t - (input_location); - dump_printf_loc (MSG_NOTE, loc, - "corrupted profile info: edge count" - " exceeds maximal count\n"); - } - informed = 1; - } - else - error ("corrupted profile info: edge from %i to %i exceeds maximal count", - bb->index, e->dest->index); - } - } + edge_gcov_count (e) = exec_counts[exec_counts_pos++]; else edge_gcov_count (e) = 0; @@ -511,12 +416,6 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum) bb_gcov_counts.safe_grow_cleared (last_basic_block_for_fn (cfun)); edge_gcov_counts = new hash_map; - if (profile_info->sum_all < profile_info->sum_max) - { - error ("corrupted profile info: sum_all is smaller than sum_max"); - exec_counts = NULL; - } - /* Attach extra info block to each bb. */ alloc_aux_for_blocks (sizeof (struct bb_profile_info)); FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb) @@ -871,10 +770,9 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum, continue; } - histogram_counts[t] = - get_coverage_counts (COUNTER_FOR_HIST_TYPE (t), - n_histogram_counters[t], cfg_checksum, - lineno_checksum, NULL); + histogram_counts[t] = get_coverage_counts (COUNTER_FOR_HIST_TYPE (t), + cfg_checksum, + lineno_checksum); if (histogram_counts[t]) any = 1; act_count[t] = histogram_counts[t]; diff --git a/gcc/profile.h b/gcc/profile.h index 6b37bb6f3df..183e8d83b65 100644 --- a/gcc/profile.h +++ b/gcc/profile.h @@ -75,6 +75,6 @@ extern void get_working_sets (void); /* Counter summary from the last set of coverage counts read by profile.c. */ -extern const struct gcov_summary *profile_info; +extern struct gcov_summary *profile_info; #endif /* PROFILE_H */ diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 8d3f440a994..b172d714851 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,20 @@ +2018-09-21 Martin Liska + + * libgcov-driver.c (crc32_unsigned): Remove. + (gcov_histogram_insert): Likewise. + (gcov_compute_histogram): Likewise. + (compute_summary): Simplify rapidly. + (merge_one_data): Do not handle PROGRAM_SUMMARY tag. + (merge_summary): Rapidly simplify. + (dump_one_gcov): Ignore gcov_summary. + (gcov_do_dump): Do not handle program summary, it's not + used. + * libgcov-util.c (tag_summary): Remove. + (read_gcda_finalize): Fix coding style. + (read_gcda_file): Initialize curr_object_summary. + (compute_summary): Remove. + (calculate_overlap): Remove settings of run_max. + 2018-09-21 Monk Chiang * config/nds32/linux-unwind.h (struct _rt_sigframe): Use struct diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c index 1f2c4a74298..cdebb747326 100644 --- a/libgcc/libgcov-driver.c +++ b/libgcc/libgcov-driver.c @@ -24,6 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include "libgcov.h" +#include "gcov-io.h" #if defined(inhibit_libc) /* If libc and its header files are not available, provide dummy functions. */ @@ -156,25 +157,6 @@ fail: return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix); } -/* Add an unsigned value to the current crc */ - -static gcov_unsigned_t -crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value) -{ - unsigned ix; - - for (ix = 32; ix--; value <<= 1) - { - unsigned feedback; - - feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; - crc32 <<= 1; - crc32 ^= feedback; - } - - return crc32; -} - /* Check if VERSION of the info block PTR matches libgcov one. Return 1 on success, or zero in case of versions mismatch. If FILENAME is not NULL, its value used for reporting purposes @@ -198,117 +180,8 @@ gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, return 1; } -/* Insert counter VALUE into HISTOGRAM. */ - -static void -gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value) -{ - unsigned i; - - i = gcov_histo_index(value); - histogram[i].num_counters++; - histogram[i].cum_value += value; - if (value < histogram[i].min_value) - histogram[i].min_value = value; -} - -/* Computes a histogram of the arc counters to place in the summary SUM. */ - -static void -gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum) -{ - struct gcov_info *gi_ptr; - const struct gcov_fn_info *gfi_ptr; - const struct gcov_ctr_info *ci_ptr; - unsigned f_ix, ix; - int h_ix; - - /* First check if there are any counts recorded for this counter. */ - if (!sum->num) - return; - - for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) - { - sum->histogram[h_ix].num_counters = 0; - sum->histogram[h_ix].min_value = sum->run_max; - sum->histogram[h_ix].cum_value = 0; - } - - /* Walk through all the per-object structures and record each of - the count values in histogram. */ - for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next) - { - for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++) - { - gfi_ptr = gi_ptr->functions[f_ix]; - - if (!gfi_ptr || gfi_ptr->key != gi_ptr) - continue; - - ci_ptr = &gfi_ptr->ctrs[0]; - for (ix = 0; ix < ci_ptr->num; ix++) - gcov_histogram_insert (sum->histogram, ci_ptr->values[ix]); - } - } -} - /* buffer for the fn_data from another program. */ static struct gcov_fn_buffer *fn_buffer; -/* buffer for summary from other programs to be written out. */ -static struct gcov_summary_buffer *sum_buffer; - -/* This function computes the program level summary and the histo-gram. - It computes and returns CRC32 and stored summary in THIS_PRG. */ - -#if !IN_GCOV_TOOL -static -#endif -gcov_unsigned_t -compute_summary (struct gcov_info *list, struct gcov_summary *this_prg) -{ - struct gcov_info *gi_ptr; - const struct gcov_fn_info *gfi_ptr; - const struct gcov_ctr_info *ci_ptr; - int f_ix; - gcov_unsigned_t c_num; - gcov_unsigned_t crc32 = 0; - - /* Find the totals for this execution. */ - memset (this_prg, 0, sizeof (*this_prg)); - for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next) - { - crc32 = crc32_unsigned (crc32, gi_ptr->stamp); - crc32 = crc32_unsigned (crc32, gi_ptr->n_functions); - - for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) - { - gfi_ptr = gi_ptr->functions[f_ix]; - - if (gfi_ptr && gfi_ptr->key != gi_ptr) - gfi_ptr = 0; - - crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0); - crc32 = crc32_unsigned (crc32, - gfi_ptr ? gfi_ptr->lineno_checksum : 0); - if (!gfi_ptr) - continue; - - ci_ptr = gfi_ptr->ctrs; - this_prg->num += ci_ptr->num; - crc32 = crc32_unsigned (crc32, ci_ptr->num); - - for (c_num = 0; c_num < ci_ptr->num; c_num++) - { - this_prg->sum_all += ci_ptr->values[c_num]; - if (this_prg->run_max < ci_ptr->values[c_num]) - this_prg->run_max = ci_ptr->values[c_num]; - } - ci_ptr++; - } - } - gcov_compute_histogram (list, this_prg); - return crc32; -} /* Including system dependent components. */ #include "libgcov-driver-system.c" @@ -320,18 +193,13 @@ compute_summary (struct gcov_info *list, struct gcov_summary *this_prg) static int merge_one_data (const char *filename, struct gcov_info *gi_ptr, - struct gcov_summary *prg_p, - struct gcov_summary *this_prg, - gcov_position_t *summary_pos_p, - gcov_position_t *eof_pos_p, - gcov_unsigned_t crc32) + struct gcov_summary *summary) { gcov_unsigned_t tag, length; unsigned t_ix; - int f_ix; + int f_ix = -1; int error = 0; struct gcov_fn_buffer **fn_tail = &fn_buffer; - struct gcov_summary_buffer **sum_tail = &sum_buffer; length = gcov_read_unsigned (); if (!gcov_version (gi_ptr, length, filename)) @@ -346,46 +214,14 @@ merge_one_data (const char *filename, return 0; } - /* Look for program summary. */ - for (f_ix = 0;;) - { - struct gcov_summary tmp; - - *eof_pos_p = gcov_position (); - tag = gcov_read_unsigned (); - if (tag != GCOV_TAG_PROGRAM_SUMMARY) - break; - - f_ix--; - length = gcov_read_unsigned (); - gcov_read_summary (&tmp); - if ((error = gcov_is_error ())) - goto read_error; - if (*summary_pos_p) - { - /* Save all summaries after the one that will be - merged into below. These will need to be rewritten - as histogram merging may change the number of non-zero - histogram entries that will be emitted, and thus the - size of the merged summary. */ - (*sum_tail) = (struct gcov_summary_buffer *) - xmalloc (sizeof(struct gcov_summary_buffer)); - (*sum_tail)->summary = tmp; - (*sum_tail)->next = 0; - sum_tail = &((*sum_tail)->next); - goto next_summary; - } - if (tmp.checksum != crc32) - goto next_summary; - - if (tmp.num != this_prg->num) - goto next_summary; - *prg_p = tmp; - *summary_pos_p = *eof_pos_p; - - next_summary:; - } + tag = gcov_read_unsigned (); + if (tag != GCOV_TAG_OBJECT_SUMMARY) + goto read_mismatch; + length = gcov_read_unsigned (); + gcc_assert (length > 0); + gcov_read_summary (summary); + tag = gcov_read_unsigned (); /* Merge execution counts for each function. */ for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++, tag = gcov_read_unsigned ()) @@ -472,38 +308,15 @@ read_error: static void write_one_data (const struct gcov_info *gi_ptr, - const struct gcov_summary *prg_p, - const gcov_position_t eof_pos, - const gcov_position_t summary_pos) + const struct gcov_summary *prg_p) { unsigned f_ix; - struct gcov_summary_buffer *next_sum_buffer; - /* Write out the data. */ - if (!eof_pos) - { - gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); - gcov_write_unsigned (gi_ptr->stamp); - } - - if (summary_pos) - gcov_seek (summary_pos); + gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); + gcov_write_unsigned (gi_ptr->stamp); /* Generate whole program statistics. */ - gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p); - - /* Rewrite all the summaries that were after the summary we merged - into. This is necessary as the merged summary may have a different - size due to the number of non-zero histogram entries changing after - merging. */ - - while (sum_buffer) - { - gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary); - next_sum_buffer = sum_buffer->next; - free (sum_buffer); - sum_buffer = next_sum_buffer; - } + gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, prg_p); /* Write execution counts for each function. */ for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++) @@ -562,70 +375,19 @@ write_one_data (const struct gcov_info *gi_ptr, gcov_write_unsigned (0); } -/* Helper function for merging summary. - Return -1 on error. Return 0 on success. */ +/* Helper function for merging summary. */ -static int -merge_summary (const char *filename __attribute__ ((unused)), int run_counted, - struct gcov_summary *prg, - struct gcov_summary *this_prg, gcov_unsigned_t crc32, - struct gcov_summary *all_prg __attribute__ ((unused))) +static void +merge_summary (int run_counted, struct gcov_summary *summary, + gcov_type run_max) { -#if !GCOV_LOCKED - /* summary for all instances of program. */ - struct gcov_summary *all; -#endif - - /* Merge the summary. */ - int first = !prg->runs; - if (!run_counted) - prg->runs++; - if (first) - prg->num = this_prg->num; - prg->sum_all += this_prg->sum_all; - if (prg->run_max < this_prg->run_max) - prg->run_max = this_prg->run_max; - prg->sum_max += this_prg->run_max; - if (first) - memcpy (prg->histogram, this_prg->histogram, - sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE); - else - gcov_histogram_merge (prg->histogram, this_prg->histogram); -#if !GCOV_LOCKED - all = all_prg; - if (!all->runs && prg->runs) { - all->num = prg->num; - all->runs = prg->runs; - all->sum_all = prg->sum_all; - all->run_max = prg->run_max; - all->sum_max = prg->sum_max; + summary->runs++; + summary->sum_max += run_max; } - else if (!all_prg->checksum - /* Don't compare the histograms, which may have slight - variations depending on the order they were updated - due to the truncating integer divides used in the - merge. */ - && (all->num != prg->num - || all->runs != prg->runs - || all->sum_all != prg->sum_all - || all->run_max != prg->run_max - || all->sum_max != prg->sum_max)) - { - gcov_error ("profiling:%s:Data file mismatch - some " - "data files may have been concurrently " - "updated without locking support\n", filename); - all_prg->checksum = ~0u; - } -#endif - - prg->checksum = crc32; - - return 0; } - /* Sort N entries in VALUE_ARRAY in descending order. Each entry in VALUE_ARRAY has two values. The sorting is based on the second value. */ @@ -713,18 +475,13 @@ gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr) static void dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf, - unsigned run_counted, - gcov_unsigned_t crc32, struct gcov_summary *all_prg, - struct gcov_summary *this_prg) + unsigned run_counted, gcov_type run_max) { - struct gcov_summary prg; /* summary for this object over all program. */ + struct gcov_summary summary = {}; int error; gcov_unsigned_t tag; - gcov_position_t summary_pos = 0; - gcov_position_t eof_pos = 0; fn_buffer = 0; - sum_buffer = 0; gcov_sort_topn_counter_arrays (gi_ptr); @@ -741,26 +498,16 @@ dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf, gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename); goto read_fatal; } - error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg, - &summary_pos, &eof_pos, crc32); + error = merge_one_data (gf->filename, gi_ptr, &summary); if (error == -1) goto read_fatal; } gcov_rewrite (); - if (!summary_pos) - { - memset (&prg, 0, sizeof (prg)); - summary_pos = eof_pos; - } + merge_summary (run_counted, &summary, run_max); - error = merge_summary (gf->filename, run_counted, &prg, this_prg, - crc32, all_prg); - if (error == -1) - goto read_fatal; - - write_one_data (gi_ptr, &prg, eof_pos, summary_pos); + write_one_data (gi_ptr, &summary); /* fall through */ read_fatal:; @@ -787,21 +534,26 @@ gcov_do_dump (struct gcov_info *list, int run_counted) { struct gcov_info *gi_ptr; struct gcov_filename gf; - gcov_unsigned_t crc32; - struct gcov_summary all_prg; - struct gcov_summary this_prg; - crc32 = compute_summary (list, &this_prg); + /* Compute run_max of this program run. */ + gcov_type run_max = 0; + for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next) + for (unsigned f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++) + { + const struct gcov_ctr_info *cinfo + = &gi_ptr->functions[f_ix]->ctrs[GCOV_COUNTER_ARCS]; + + for (unsigned i = 0; i < cinfo->num; i++) + if (run_max < cinfo->values[i]) + run_max = cinfo->values[i]; + } allocate_filename_struct (&gf); -#if !GCOV_LOCKED - memset (&all_prg, 0, sizeof (all_prg)); -#endif /* Now merge each file. */ for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next) { - dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg); + dump_one_gcov (gi_ptr, &gf, run_counted, run_max); free (gf.filename); } diff --git a/libgcc/libgcov-util.c b/libgcc/libgcov-util.c index 37dd186beaa..408bda82236 100644 --- a/libgcc/libgcov-util.c +++ b/libgcc/libgcov-util.c @@ -32,6 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "diagnostic.h" #include "version.h" #include "demangle.h" +#include "gcov-io.h" /* Borrowed from basic-block.h. */ #define RDIV(X,Y) (((X) + (Y) / 2) / (Y)) @@ -79,6 +80,8 @@ static int k_ctrs_mask[GCOV_COUNTERS]; static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS]; /* Number of kind of counters that have been seen. */ static int k_ctrs_types; +/* The object summary being processed. */ +static struct gcov_summary *curr_object_summary; /* Merge functions for counters. */ #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE, @@ -131,7 +134,6 @@ static const tag_format_t tag_table[] = {GCOV_TAG_ARCS, "ARCS", tag_arcs}, {GCOV_TAG_LINES, "LINES", tag_lines}, {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary}, - {GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary}, {0, NULL, NULL} }; @@ -223,9 +225,8 @@ tag_counters (unsigned tag, unsigned length) static void tag_summary (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) { - struct gcov_summary summary; - - gcov_read_summary (&summary); + curr_object_summary = (gcov_summary *) xcalloc (sizeof (gcov_summary), 1); + gcov_read_summary (curr_object_summary); } /* This function is called at the end of reading a gcda file. @@ -239,7 +240,8 @@ read_gcda_finalize (struct gcov_info *obj_info) set_fn_ctrs (curr_fn_info); obstack_ptr_grow (&fn_info, curr_fn_info); - /* We set the following fields: merge, n_functions, and functions. */ + /* We set the following fields: merge, n_functions, functions + and summary. */ obj_info->n_functions = num_fn_info; obj_info->functions = (const struct gcov_fn_info**) obstack_finish (&fn_info); @@ -299,6 +301,7 @@ read_gcda_file (const char *filename) obstack_init (&fn_info); num_fn_info = 0; curr_fn_info = 0; + curr_object_summary = NULL; { size_t len = strlen (filename) + 1; char *str_dup = (char*) xmalloc (len); @@ -892,8 +895,6 @@ calculate_2_entries (const unsigned long v1, const unsigned long v2, } /* Compute the overlap score between GCOV_INFO1 and GCOV_INFO2. - SUM_1 is the sum_all for profile1 where GCOV_INFO1 belongs. - SUM_2 is the sum_all for profile2 where GCOV_INFO2 belongs. This function also updates cumulative score CUM_1_RESULT and CUM_2_RESULT. */ @@ -1048,12 +1049,6 @@ struct overlap_t { /* Cumlative overlap dscore for profile1 and profile2. */ static double overlap_sum_1, overlap_sum_2; -/* sum_all for profile1 and profile2. */ -static gcov_type p1_sum_all, p2_sum_all; - -/* run_max for profile1 and profile2. */ -static gcov_type p1_run_max, p2_run_max; - /* The number of gcda files in the profiles. */ static unsigned gcda_files[2]; @@ -1200,10 +1195,6 @@ matched_gcov_info (const struct gcov_info *info1, const struct gcov_info *info2) return 1; } -/* Defined in libgcov-driver.c. */ -extern gcov_unsigned_t compute_summary (struct gcov_info *, - struct gcov_summary *); - /* Compute the overlap score of two profiles with the head of GCOV_LIST1 and GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no match and 1.0 meaning a perfect match. */ @@ -1212,21 +1203,11 @@ static double calculate_overlap (struct gcov_info *gcov_list1, struct gcov_info *gcov_list2) { - struct gcov_summary this_prg; unsigned list1_cnt = 0, list2_cnt= 0, all_cnt; unsigned int i, j; const struct gcov_info *gi_ptr; struct overlap_t *all_infos; - compute_summary (gcov_list1, &this_prg); - overlap_sum_1 = (double) (this_prg.sum_all); - p1_sum_all = this_prg.sum_all; - p1_run_max = this_prg.run_max; - compute_summary (gcov_list2, &this_prg); - overlap_sum_2 = (double) (this_prg.sum_all); - p2_sum_all = this_prg.sum_all; - p2_run_max = this_prg.run_max; - for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next) list1_cnt++; for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next) @@ -1334,10 +1315,6 @@ calculate_overlap (struct gcov_info *gcov_list1, cold_gcda_files[1], both_cold_cnt); printf (" zero files: %12u\t%12u\t%12u\n", zero_gcda_files[0], zero_gcda_files[1], both_zero_cnt); - printf (" sum_all: %12" PRId64 "\t%12" PRId64 "\n", - p1_sum_all, p2_sum_all); - printf (" run_max: %12" PRId64 "\t%12" PRId64 "\n", - p1_run_max, p2_run_max); return prg_val; }