mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-15 07:50:29 +08:00
Smart relaxation of TOP N counter.
PR tree-optimization/92924 * profile.c (compute_value_histograms): Divide all counter values. PR tree-optimization/92924 * libgcov-driver.c (prune_topn_counter): New. (prune_counters): Likewise. (dump_one_gcov): Prune a run-time counter. * libgcov-profiler.c (__gcov_topn_values_profiler_body): For a known value, add GCOV_TOPN_VALUES to value. Otherwise, decrement all counters by one.
This commit is contained in:
parent
f96af171be
commit
5f32f9cf13
@ -1,3 +1,9 @@
|
||||
2020-01-22 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR tree-optimization/92924
|
||||
* profile.c (compute_value_histograms): Divide
|
||||
all counter values.
|
||||
|
||||
2020-01-22 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/91298
|
||||
|
@ -863,7 +863,15 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
|
||||
|
||||
if (hist->type == HIST_TYPE_TOPN_VALUES
|
||||
|| hist->type == HIST_TYPE_INDIR_CALL)
|
||||
sort_hist_values (hist);
|
||||
{
|
||||
/* Each count value is multiplied by GCOV_TOPN_VALUES. */
|
||||
if (hist->hvalue.counters[2] != -1)
|
||||
for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
|
||||
hist->hvalue.counters[2 * i + 2]
|
||||
= RDIV (hist->hvalue.counters[2 * i + 2], GCOV_TOPN_VALUES);
|
||||
|
||||
sort_hist_values (hist);
|
||||
}
|
||||
|
||||
/* Time profiler counter is not related to any statement,
|
||||
so that we have to read the counter and set the value to
|
||||
|
@ -1,3 +1,13 @@
|
||||
2020-01-22 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR tree-optimization/92924
|
||||
* libgcov-driver.c (prune_topn_counter): New.
|
||||
(prune_counters): Likewise.
|
||||
(dump_one_gcov): Prune a run-time counter.
|
||||
* libgcov-profiler.c (__gcov_topn_values_profiler_body):
|
||||
For a known value, add GCOV_TOPN_VALUES to value.
|
||||
Otherwise, decrement all counters by one.
|
||||
|
||||
2020-01-18 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
* config/cris/arit.c (DS): Apply attribute __fallthrough__.
|
||||
|
@ -213,6 +213,56 @@ static struct gcov_fn_buffer *fn_buffer;
|
||||
/* Including system dependent components. */
|
||||
#include "libgcov-driver-system.c"
|
||||
|
||||
/* Prune TOP N value COUNTERS. It's needed in order to preserve
|
||||
reproducibility of builds. */
|
||||
|
||||
static void
|
||||
prune_topn_counter (gcov_type *counters, gcov_type all)
|
||||
{
|
||||
if (counters[1] == -1)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
|
||||
{
|
||||
if (counters[2 * i + 1] < all)
|
||||
{
|
||||
counters[2 * i] = 0;
|
||||
counters[2 * i + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Prune counters so that they are ready to store or merge. */
|
||||
|
||||
static void
|
||||
prune_counters (struct gcov_info *gi)
|
||||
{
|
||||
for (unsigned i = 0; i < gi->n_functions; i++)
|
||||
{
|
||||
const struct gcov_fn_info *gfi = gi->functions[i];
|
||||
const struct gcov_ctr_info *ci = gfi->ctrs;
|
||||
|
||||
for (unsigned j = 0; j < GCOV_COUNTERS; j++)
|
||||
{
|
||||
if (gi->merge[j] == NULL)
|
||||
continue;
|
||||
|
||||
if (gi->merge[j] == __gcov_merge_topn)
|
||||
{
|
||||
gcc_assert (!(ci->num % GCOV_TOPN_VALUES_COUNTERS));
|
||||
for (unsigned k = 0; k < (ci->num / GCOV_TOPN_VALUES_COUNTERS);
|
||||
k++)
|
||||
{
|
||||
gcov_type *counters
|
||||
= ci->values + (k * GCOV_TOPN_VALUES_COUNTERS);
|
||||
prune_topn_counter (counters + 1, *counters);
|
||||
}
|
||||
}
|
||||
ci++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function merges counters in GI_PTR to an existing gcda file.
|
||||
Return 0 on success.
|
||||
Return -1 on error. In this case, caller will goto read_fatal. */
|
||||
@ -429,9 +479,11 @@ dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
|
||||
struct gcov_summary summary = {};
|
||||
int error;
|
||||
gcov_unsigned_t tag;
|
||||
|
||||
fn_buffer = 0;
|
||||
|
||||
/* Prune current counters before we merge them. */
|
||||
prune_counters (gi_ptr);
|
||||
|
||||
error = gcov_exit_open_gcda_file (gi_ptr, gf);
|
||||
if (error == -1)
|
||||
return;
|
||||
|
@ -119,37 +119,35 @@ __gcov_topn_values_profiler_body (gcov_type *counters, gcov_type value,
|
||||
|
||||
++counters;
|
||||
|
||||
/* We have GCOV_TOPN_VALUES as we can keep multiple values
|
||||
next to each other. */
|
||||
unsigned sindex = 0;
|
||||
|
||||
for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
|
||||
{
|
||||
if (value == counters[2 * i])
|
||||
{
|
||||
if (use_atomic)
|
||||
__atomic_fetch_add (&counters[2 * i + 1], 1, __ATOMIC_RELAXED);
|
||||
__atomic_fetch_add (&counters[2 * i + 1], GCOV_TOPN_VALUES,
|
||||
__ATOMIC_RELAXED);
|
||||
else
|
||||
counters[2 * i + 1]++;
|
||||
counters[2 * i + 1] += GCOV_TOPN_VALUES;
|
||||
return;
|
||||
}
|
||||
else if (counters[2 * i + 1] == 0)
|
||||
else if (counters[2 * i + 1] <= 0)
|
||||
{
|
||||
/* We found an empty slot. */
|
||||
counters[2 * i] = value;
|
||||
counters[2 * i + 1] = 1;
|
||||
counters[2 * i + 1] = GCOV_TOPN_VALUES;
|
||||
return;
|
||||
}
|
||||
|
||||
if (counters[2 * i + 1] < counters[2 * sindex + 1])
|
||||
sindex = i;
|
||||
}
|
||||
|
||||
/* We haven't found an empty slot, then decrement the smallest. */
|
||||
if (use_atomic)
|
||||
__atomic_fetch_sub (&counters[2 * sindex + 1], 1, __ATOMIC_RELAXED);
|
||||
else
|
||||
counters[2 * sindex + 1]--;
|
||||
/* We haven't found an empty slot, then decrement all
|
||||
counter values by one. */
|
||||
for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
|
||||
{
|
||||
if (use_atomic)
|
||||
__atomic_fetch_sub (&counters[2 * i + 1], 1, __ATOMIC_RELAXED);
|
||||
else
|
||||
counters[2 * i + 1]--;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef L_gcov_topn_values_profiler
|
||||
|
Loading…
x
Reference in New Issue
Block a user