aboutsummaryrefslogtreecommitdiff
path: root/libgcc/libgcov-merge.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2019-06-10 07:38:59 +0000
committerMartin Liska <mliska@suse.cz>2019-06-10 07:38:59 +0000
commit1470f5c9ea8aa736539abb5e9d48832fe3aac649 (patch)
tree68db0aeb3fb07bf5bb068e205d5a3cb895a45a01 /libgcc/libgcov-merge.c
parent234c7d3ec9d1875ecd7cb577e696017be2f6c954 (diff)
Implement N disk counters for single value and indirect call counters.
2019-06-10 Martin Liska <mliska@suse.cz> * 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 <mliska@suse.cz> * 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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@272106 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc/libgcov-merge.c')
-rw-r--r--libgcc/libgcov-merge.c83
1 files changed, 58 insertions, 25 deletions
diff --git a/libgcc/libgcov-merge.c b/libgcc/libgcov-merge.c
index 702a69f8349..42416341b4d 100644
--- a/libgcc/libgcov-merge.c
+++ b/libgcc/libgcov-merge.c
@@ -34,8 +34,9 @@ void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)),
#endif
#ifdef L_gcov_merge_single
-void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)),
- unsigned n_counters __attribute__ ((unused))) {}
+void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)))
+{
+}
#endif
#else
@@ -85,40 +86,72 @@ __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
#endif /* L_gcov_merge_time_profile */
#ifdef L_gcov_merge_single
+
+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;
+
+ for (unsigned i = 0; i < GCOV_DISK_SINGLE_VALUES; i++)
+ {
+ value = gcov_get_counter_target ();
+ counter = 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;
+ }
+
+ for (j = 0; j < GCOV_DISK_SINGLE_VALUES; j++)
+ {
+ if (counters[2 * j] == value)
+ {
+ counters[2 * j + 1] += counter;
+ break;
+ }
+ else if (counters[2 * j + 1] == 0)
+ {
+ counters[2 * j] = value;
+ counters[2 * j + 1] = counter;
+ break;
+ }
+ }
+
+ /* We haven't found a free slot for the value, mark overflow. */
+ if (j == GCOV_DISK_SINGLE_VALUES)
+ counters[1] = -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
- are split into 3-tuples where the members of the tuple have
+ are split into pairs where the members of the tuple have
meanings:
-- the stored candidate on the most common value of the measured entity
-- counter
- -- total number of evaluations of the value */
+ */
void
__gcov_merge_single (gcov_type *counters, unsigned n_counters)
{
- unsigned i, n_measures;
- gcov_type value, counter, all;
+ gcc_assert (!(n_counters % GCOV_SINGLE_VALUE_COUNTERS));
- gcc_assert (!(n_counters % 3));
- n_measures = n_counters / 3;
- for (i = 0; i < n_measures; i++, counters += 3)
- {
- value = gcov_get_counter_target ();
- counter = gcov_get_counter ();
- all = gcov_get_counter ();
-
- if (counters[0] == value)
- counters[1] += counter;
- else if (counter > counters[1])
- {
- counters[0] = value;
- counters[1] = counter - counters[1];
- }
- else
- counters[1] -= counter;
- counters[2] += all;
- }
+ for (unsigned i = 0; i < (n_counters / GCOV_SINGLE_VALUE_COUNTERS); i++)
+ merge_single_value_set (counters + (i * GCOV_SINGLE_VALUE_COUNTERS));
}
#endif /* L_gcov_merge_single */