aboutsummaryrefslogtreecommitdiff
path: root/libgcc/libgcov-merge.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2020-01-31 13:10:14 +0100
committerMartin Liska <mliska@suse.cz>2020-06-02 12:11:02 +0200
commit871e5ada6d53d5eb495cc9f323983f347487c1b2 (patch)
tree15075fc87b2c7817e72f0b26b065a91e7963d0e6 /libgcc/libgcov-merge.c
parent23438370f768802fefd732529177fcea074c493b (diff)
downloadgcc-871e5ada6d53d5eb495cc9f323983f347487c1b2.zip
gcc-871e5ada6d53d5eb495cc9f323983f347487c1b2.tar.gz
gcc-871e5ada6d53d5eb495cc9f323983f347487c1b2.tar.bz2
Make TOPN counter dynamically allocated.
gcc/ChangeLog: * coverage.c (get_coverage_counts): Skip sanity check for TOP N counters as they have variable number of counters. * gcov-dump.c (main): Add new option -r. (print_usage): Likewise. (tag_counters): All new raw format. * gcov-io.h (struct gcov_kvp): New. (GCOV_TOPN_VALUES): Remove. (GCOV_TOPN_VALUES_COUNTERS): Likewise. (GCOV_TOPN_MEM_COUNTERS): New. (GCOV_TOPN_DISK_COUNTERS): Likewise. (GCOV_TOPN_MAXIMUM_TRACKED_VALUES): Likewise. * ipa-profile.c (ipa_profile_generate_summary): Use GCOV_TOPN_MAXIMUM_TRACKED_VALUES. (ipa_profile_write_edge_summary): Likewise. (ipa_profile_read_edge_summary): Likewise. (ipa_profile): Remove usage of GCOV_TOPN_VALUES. * profile.c (sort_hist_values): Sort variable number of counters. (compute_value_histograms): Special case for TOP N counters that have dynamic number of key-value pairs. * value-prof.c (dump_histogram_value): Dump variable number of key-value pairs. (stream_in_histogram_value): Stream in variable number of key-value pairs for TOP N counter. (get_nth_most_common_value): Deal with variable number of key-value pairs. (dump_ic_profile): Use GCOV_TOPN_MAXIMUM_TRACKED_VALUES for loop iteration. (gimple_find_values_to_profile): Set GCOV_TOPN_MEM_COUNTERS to n_counters. * doc/gcov-dump.texi: Document new -r option. libgcc/ChangeLog: * libgcov-driver.c (prune_topn_counter): Remove. (prune_counters): Likewise. (merge_one_data): Special case TOP N counters as they have variable length. (write_top_counters): New. (write_one_data): Special case TOP N. (dump_one_gcov): Do not prune TOP N counters. * libgcov-merge.c (merge_topn_values_set): Remove. (__gcov_merge_topn): Use gcov_topn_add_value. * libgcov-profiler.c (__gcov_topn_values_profiler_body): Likewise here. * libgcov.h (gcov_counter_add): New. (gcov_counter_set_if_null): Likewise. (gcov_topn_add_value): New.
Diffstat (limited to 'libgcc/libgcov-merge.c')
-rw-r--r--libgcc/libgcov-merge.c103
1 files changed, 20 insertions, 83 deletions
diff --git a/libgcc/libgcov-merge.c b/libgcc/libgcov-merge.c
index c0785b0..1acdaa0 100644
--- a/libgcc/libgcov-merge.c
+++ b/libgcc/libgcov-merge.c
@@ -86,86 +86,6 @@ __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
#ifdef L_gcov_merge_topn
-/* To merging of TOPN profiles.
- counters[0] is the number of executions
- for i in 0 ... TOPN-1
- counters[2 * i + 1] is target
- counters[2 * i + 2] is corresponding hitrate counter.
-
- Because we prune counters only those with probability >= 1/TOPN are
- present now.
-
- We use sign of counters[0] to track whether the number of different
- targets exceeds TOPN. */
-
-static void
-merge_topn_values_set (gcov_type *counters)
-{
- /* First value is number of total executions of the profiler. */
- gcov_type all = gcov_get_counter ();
- gcov_type *total = &counters[0];
- ++counters;
-
- /* Negative value means that counter is missing some of values. */
- if (all < 0)
- *total = -(*total);
-
- *total += all;
-
- /* Read all part values. */
- gcov_type read_counters[2 * GCOV_TOPN_VALUES];
- for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
- {
- read_counters[2 * i] = gcov_get_counter_target ();
- read_counters[2 * i + 1] = gcov_get_counter_ignore_scaling (-1);
- }
-
- for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
- {
- if (read_counters[2 * i + 1] == 0)
- continue;
-
- unsigned j;
- int slot = 0;
-
- for (j = 0; j < GCOV_TOPN_VALUES; j++)
- {
- if (counters[2 * j] == read_counters[2 * i])
- {
- counters[2 * j + 1] += read_counters[2 * i + 1];
- break;
- }
- else if (counters[2 * j + 1] < counters[2 * slot + 1])
- slot = j;
- }
-
- if (j == GCOV_TOPN_VALUES)
- {
- gcov_type slot_count = counters[2 * slot + 1];
- /* We found an empty slot. */
- if (slot_count == 0)
- {
- /* If we found empty slot, add the value. */
- counters[2 * slot] = read_counters[2 * i];
- counters[2 * slot + 1] = read_counters[2 * i + 1];
- }
- else
- {
- /* Here we are loosing some values. */
- if (*total >= 0)
- *total = -(*total);
- if (read_counters[2 * i + 1] > slot_count)
- {
- counters[2 * slot] = read_counters[2 * i];
- counters[2 * slot + 1] = read_counters[2 * i + 1];
- }
- else
- counters[2 * slot + 1] -= read_counters[2 * i + 1];
- }
- }
- }
-}
-
/* The profile merging function for choosing the most common value.
It is given an array COUNTERS of N_COUNTERS old counters and it
reads the same number of counters from the gcov file. The counters
@@ -175,13 +95,30 @@ merge_topn_values_set (gcov_type *counters)
-- the stored candidate on the most common value of the measured entity
-- counter
*/
+
void
__gcov_merge_topn (gcov_type *counters, unsigned n_counters)
{
- gcc_assert (!(n_counters % GCOV_TOPN_VALUES_COUNTERS));
+ gcc_assert (!(n_counters % GCOV_TOPN_MEM_COUNTERS));
- for (unsigned i = 0; i < (n_counters / GCOV_TOPN_VALUES_COUNTERS); i++)
- merge_topn_values_set (counters + (i * GCOV_TOPN_VALUES_COUNTERS));
+ for (unsigned i = 0; i < (n_counters / GCOV_TOPN_MEM_COUNTERS); i++)
+ {
+ /* First value is number of total executions of the profiler. */
+ gcov_type all = gcov_get_counter_ignore_scaling (-1);
+ gcov_type n = gcov_get_counter_ignore_scaling (-1);
+
+ counters[GCOV_TOPN_MEM_COUNTERS * i] += all;
+
+ for (unsigned j = 0; j < n; j++)
+ {
+ gcov_type value = gcov_get_counter_target ();
+ gcov_type count = gcov_get_counter_ignore_scaling (-1);
+
+ // TODO: we should use atomic here
+ gcov_topn_add_value (counters + GCOV_TOPN_MEM_COUNTERS * i, value,
+ count, 0, 0);
+ }
+ }
}
#endif /* L_gcov_merge_topn */