From 92d417175b9f7b41d5ebe3ceb723f808917ed964 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 10 Jun 2019 09:38:59 +0200 Subject: Implement N disk counters for single value and indirect call counters. 2019-06-10 Martin Liska * gcov-io.h (GCOV_DISK_SINGLE_VALUES): New. (GCOV_SINGLE_VALUE_COUNTERS): Likewise. * ipa-profile.c (ipa_profile_generate_summary): Use get_most_common_single_value. * tree-profile.c (gimple_init_gcov_profiler): Instrument with __gcov_one_value_profiler_v2 and __gcov_indirect_call_profiler_v4. * value-prof.c (dump_histogram_value): Print all values for HIST_TYPE_SINGLE_VALUE. (stream_out_histogram_value): Update assert for N values. (stream_in_histogram_value): Set number of counters for HIST_TYPE_SINGLE_VALUE. (get_most_common_single_value): New. (gimple_divmod_fixed_value_transform): Use get_most_common_single_value. (gimple_ic_transform): Likewise. (gimple_stringops_transform): Likewise. (gimple_find_values_to_profile): Set number of counters for HIST_TYPE_SINGLE_VALUE. * value-prof.h (get_most_common_single_value): New. 2019-06-10 Martin Liska * Makefile.in: Add __gcov_one_value_profiler_v2, __gcov_one_value_profiler_v2_atomic and __gcov_indirect_call_profiler_v4. * libgcov-merge.c (__gcov_merge_single): Change function signature. (merge_single_value_set): New. * libgcov-profiler.c (__gcov_one_value_profiler_body): Update functionality. (__gcov_one_value_profiler): Remove. (__gcov_one_value_profiler_v2): ... this. (__gcov_one_value_profiler_atomic): Rename to ... (__gcov_one_value_profiler_v2_atomic): this. (__gcov_indirect_call_profiler_v3): Rename to ... (__gcov_indirect_call_profiler_v4): ... this. * libgcov.h (__gcov_one_value_profiler): Remove. (__gcov_one_value_profiler_atomic): Remove. (__gcov_one_value_profiler_v2_atomic): New. (__gcov_indirect_call_profiler_v3): Remove. (__gcov_one_value_profiler_v2): New. (__gcov_indirect_call_profiler_v4): New. (gcov_get_counter_ignore_scaling): New function. From-SVN: r272106 --- gcc/value-prof.c | 136 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 58 deletions(-) (limited to 'gcc/value-prof.c') diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 1e14e53..b95bf85 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -259,15 +259,22 @@ dump_histogram_value (FILE *dump_file, histogram_value hist) break; case HIST_TYPE_SINGLE_VALUE: - fprintf (dump_file, "Single value "); + case HIST_TYPE_INDIR_CALL: + fprintf (dump_file, + (hist->type == HIST_TYPE_SINGLE_VALUE + ? "Single value counter " : "Indirect call counter")); if (hist->hvalue.counters) { - fprintf (dump_file, "value:%" PRId64 - " match:%" PRId64 - " wrong:%" PRId64, - (int64_t) hist->hvalue.counters[0], - (int64_t) hist->hvalue.counters[1], - (int64_t) hist->hvalue.counters[2]); + fprintf (dump_file, "all: %" PRId64 ", values: ", + (int64_t) hist->hvalue.counters[0]); + for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++) + { + fprintf (dump_file, "[%" PRId64 ":%" PRId64 "]", + (int64_t) hist->hvalue.counters[2 * i + 1], + (int64_t) hist->hvalue.counters[2 * i + 2]); + if (i != GCOV_DISK_SINGLE_VALUES - 1) + fprintf (dump_file, ", "); + } } fprintf (dump_file, ".\n"); break; @@ -294,19 +301,6 @@ dump_histogram_value (FILE *dump_file, histogram_value hist) fprintf (dump_file, ".\n"); break; - case HIST_TYPE_INDIR_CALL: - fprintf (dump_file, "Indirect call "); - if (hist->hvalue.counters) - { - fprintf (dump_file, "value:%" PRId64 - " match:%" PRId64 - " all:%" PRId64, - (int64_t) hist->hvalue.counters[0], - (int64_t) hist->hvalue.counters[1], - (int64_t) hist->hvalue.counters[2]); - } - fprintf (dump_file, ".\n"); - break; case HIST_TYPE_TIME_PROFILE: fprintf (dump_file, "Time profile "); if (hist->hvalue.counters) @@ -347,7 +341,7 @@ stream_out_histogram_value (struct output_block *ob, histogram_value hist) /* When user uses an unsigned type with a big value, constant converted to gcov_type (a signed type) can be negative. */ gcov_type value = hist->hvalue.counters[i]; - if (hist->type == HIST_TYPE_SINGLE_VALUE && i == 0) + if (hist->type == HIST_TYPE_SINGLE_VALUE && (i > 0 && ((i - 1) % 2) == 0)) ; else gcc_assert (value >= 0); @@ -392,7 +386,7 @@ stream_in_histogram_value (struct lto_input_block *ib, gimple *stmt) case HIST_TYPE_SINGLE_VALUE: case HIST_TYPE_INDIR_CALL: - ncounters = 3; + ncounters = GCOV_SINGLE_VALUE_COUNTERS; break; case HIST_TYPE_IOR: @@ -729,6 +723,48 @@ gimple_divmod_fixed_value (gassign *stmt, tree value, profile_probability prob, return tmp2; } +/* Return most common value of SINGLE_VALUE histogram. If + there's a unique value, return true and set VALUE and COUNT + arguments. */ + +bool +get_most_common_single_value (gimple *stmt, const char *counter_type, + histogram_value hist, + gcov_type *value, gcov_type *count, + gcov_type *all) +{ + if (hist->hvalue.counters[2] == -1) + return false; + + *count = 0; + *value = 0; + + gcov_type read_all = hist->hvalue.counters[0]; + + for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++) + { + gcov_type v = hist->hvalue.counters[2 * i + 1]; + gcov_type c = hist->hvalue.counters[2 * i + 2]; + + /* Indirect calls can't be vereified. */ + if (stmt && check_counter (stmt, counter_type, &c, &read_all, + gimple_bb (stmt)->count)) + return false; + + *all = read_all; + + if (c > *count) + { + *value = v; + *count = c; + } + else if (c == *count && v > *value) + *value = v; + } + + return true; +} + /* Do transform 1) on INSN if applicable. */ static bool @@ -758,23 +794,19 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si) if (!histogram) return false; + if (!get_most_common_single_value (stmt, "divmod", histogram, &val, &count, + &all)) + return false; + value = histogram->hvalue.value; - val = histogram->hvalue.counters[0]; - count = histogram->hvalue.counters[1]; - all = histogram->hvalue.counters[2]; gimple_remove_histogram_value (cfun, stmt, histogram); - /* We require that count is at least half of all; this means - that for the transformation to fire the value must be constant - at least 50% of time (and 75% gives the guarantee of usage). */ + /* We require that count is at least half of all. */ if (simple_cst_equal (gimple_assign_rhs2 (stmt), value) != 1 || 2 * count < all || optimize_bb_for_size_p (gimple_bb (stmt))) return false; - if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count)) - return false; - /* Compute probability of taking the optimal path. */ if (all > 0) prob = profile_probability::probability_in_gcov_type (count, all); @@ -1401,7 +1433,7 @@ gimple_ic_transform (gimple_stmt_iterator *gsi) { gcall *stmt; histogram_value histogram; - gcov_type val, count, all, bb_all; + gcov_type val, count, all; struct cgraph_node *direct_call; stmt = dyn_cast (gsi_stmt (*gsi)); @@ -1418,21 +1450,9 @@ gimple_ic_transform (gimple_stmt_iterator *gsi) if (!histogram) return false; - val = histogram->hvalue.counters [0]; - count = histogram->hvalue.counters [1]; - all = histogram->hvalue.counters [2]; - - bb_all = gimple_bb (stmt)->count.ipa ().to_gcov_type (); - /* The order of CHECK_COUNTER calls is important - - since check_counter can correct the third parameter - and we want to make count <= all <= bb_all. */ - if (check_counter (stmt, "ic", &all, &bb_all, gimple_bb (stmt)->count) - || check_counter (stmt, "ic", &count, &all, - profile_count::from_gcov_type (all))) - { - gimple_remove_histogram_value (cfun, stmt, histogram); - return false; - } + if (!get_most_common_single_value (NULL, "indirect call", histogram, &val, + &count, &all)) + return false; if (4 * count <= 3 * all) return false; @@ -1644,19 +1664,19 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi) if (TREE_CODE (blck_size) == INTEGER_CST) return false; - histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE); + histogram = gimple_histogram_value_of_type (cfun, stmt, + HIST_TYPE_SINGLE_VALUE); if (!histogram) return false; - val = histogram->hvalue.counters[0]; - count = histogram->hvalue.counters[1]; - all = histogram->hvalue.counters[2]; + if (!get_most_common_single_value (stmt, "stringops", histogram, &val, + &count, &all)) + return false; + gimple_remove_histogram_value (cfun, stmt, histogram); - /* We require that count is at least half of all; this means - that for the transformation to fire the value must be constant - at least 80% of time. */ - if ((6 * count / 5) < all || optimize_bb_for_size_p (gimple_bb (stmt))) + /* We require that count is at least half of all. */ + if (2 * count < all || optimize_bb_for_size_p (gimple_bb (stmt))) return false; if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count)) return false; @@ -1928,11 +1948,11 @@ gimple_find_values_to_profile (histogram_values *values) break; case HIST_TYPE_SINGLE_VALUE: - hist->n_counters = 3; + hist->n_counters = GCOV_SINGLE_VALUE_COUNTERS; break; - case HIST_TYPE_INDIR_CALL: - hist->n_counters = 3; + case HIST_TYPE_INDIR_CALL: + hist->n_counters = GCOV_SINGLE_VALUE_COUNTERS; break; case HIST_TYPE_TIME_PROFILE: -- cgit v1.1