On 6/19/19 10:56 AM, Martin Liška wrote: > Thank you very much for the numbers. Today, I'm going to prepare the > generalization of single-value counter to track N values.
Ok, here's a patch candidate that does tracking of most common N values. For your test-case I can see: pr69678.gcda: 01a90000: 18:COUNTERS indirect_call 9 counts pr69678.gcda: 0: 350000000 1868707024 175000000 969338501 175000000 0 0 0 pr69678.gcda: 8: 0 So for now, you'll need to generalize get_most_common_single_value to return N most common values. Eventually we'll need to renamed the counter as it won't be tracking just a single value any longer. I can take care of it. Can you please verify that the patch candidate works for you? Thanks, Martin
>From 93175b20aa794baf1795ff1ccb3ac0391c326ada Mon Sep 17 00:00:00 2001 From: Martin Liska <mli...@suse.cz> Date: Wed, 19 Jun 2019 14:15:14 +0200 Subject: [PATCH] Support N values in libgcov for single value counter type. --- libgcc/libgcov-merge.c | 48 +++++++++++++++++++++------------------ libgcc/libgcov-profiler.c | 38 +++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 32 deletions(-) diff --git a/libgcc/libgcov-merge.c b/libgcc/libgcov-merge.c index f778cc4b6b7..84367005663 100644 --- a/libgcc/libgcov-merge.c +++ b/libgcc/libgcov-merge.c @@ -89,49 +89,53 @@ __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters) static void merge_single_value_set (gcov_type *counters) { - unsigned j; - gcov_type value, counter; - /* First value is number of total executions of the profiler. */ gcov_type all = gcov_get_counter_ignore_scaling (-1); counters[0] += all; ++counters; + /* Read all part values. */ + gcov_type read_counters[2 * GCOV_DISK_SINGLE_VALUES]; + for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++) { - value = gcov_get_counter_target (); - counter = gcov_get_counter_ignore_scaling (-1); + read_counters[2 * i] = gcov_get_counter_target (); + read_counters[2 * i + 1] = gcov_get_counter_ignore_scaling (-1); + } - if (counter == -1) - { - counters[1] = -1; - /* We can't return as we need to read all counters. */ - continue; - } - else if (counter == 0 || counters[1] == -1) - { - /* We can't return as we need to read all counters. */ - continue; - } + if (read_counters[1] == -1) + { + counters[1] = -1; + return; + } + + for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++) + { + if (read_counters[2 * i + 1] == 0) + return; + unsigned j; for (j = 0; j < GCOV_DISK_SINGLE_VALUES; j++) { - if (counters[2 * j] == value) + if (counters[2 * j] == read_counters[2 * i]) { - counters[2 * j + 1] += counter; + counters[2 * j + 1] += read_counters[2 * i + 1]; break; } else if (counters[2 * j + 1] == 0) { - counters[2 * j] = value; - counters[2 * j + 1] = counter; + counters[2 * j] += read_counters[2 * i]; + counters[2 * j + 1] += read_counters[2 * i + 1]; break; } } - /* We haven't found a free slot for the value, mark overflow. */ + /* We haven't found a slot, bail out. */ if (j == GCOV_DISK_SINGLE_VALUES) - counters[1] = -1; + { + counters[1] = -1; + return; + } } } diff --git a/libgcc/libgcov-profiler.c b/libgcc/libgcov-profiler.c index 9ba65b90df3..0ef400bdda7 100644 --- a/libgcc/libgcov-profiler.c +++ b/libgcc/libgcov-profiler.c @@ -118,20 +118,38 @@ static inline void __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value, int use_atomic) { - if (value == counters[1]) - counters[2]++; - else if (counters[2] == 0) - { - counters[2] = 1; - counters[1] = value; - } - else - counters[2]--; - if (use_atomic) __atomic_fetch_add (&counters[0], 1, __ATOMIC_RELAXED); else counters[0]++; + + ++counters; + + /* We have GCOV_DISK_SINGLE_VALUES as we can keep multiple values + next to each other. */ + unsigned sindex = 0; + + for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++) + { + if (value == counters[2 * i]) + { + counters[2 * i + 1]++; + return; + } + else if (counters[2 * i + 1] == 0) + { + /* We found an empty slot. */ + counters[2 * i] = value; + counters[2 * i + 1] = 1; + return; + } + + if (counters[2 * i + 1] < counters[2 * sindex + 1]) + sindex = i; + } + + /* We haven't found an empty slot, then decrement the smallest. */ + counters[2 * sindex + 1]--; } #ifdef L_gcov_one_value_profiler_v2 -- 2.21.0