> > libgcc/ChangeLog: > > PR gcov-profile/99105 > * libgcov-driver.c (write_top_counters): Rename to ... > (write_topn_counters): ... this. > (write_one_data): Pre-allocate buffer for number of items > in the corresponding linked lists. > * libgcov-merge.c (__gcov_merge_topn): Use renamed function. > > gcc/testsuite/ChangeLog: > > PR gcov-profile/99105 > * gcc.dg/tree-prof/indir-call-prof-malloc.c: Use profile > correction as the wrapped malloc is called one more time > from libgcov.
> for (unsigned i = 0; i < counters; i++) > { > - gcov_type pair_count = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 1]; > gcov_write_counter (ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i]); > - gcov_write_counter (pair_count); > + gcov_write_counter (list_sizes[i]); > gcov_type start = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 2]; > + > + unsigned j = 0; > for (struct gcov_kvp *node = (struct gcov_kvp *)(intptr_t)start; > - node != NULL; node = node->next) > + node != NULL; node = node->next, j++) > { > gcov_write_counter (node->value); > gcov_write_counter (node->count); > + > + /* Stop when we reach expected number of items. */ > + if (j + 1 == list_sizes[i]) > + break; Since you counted number of entries earlier, I would expect loop to always terminate here and thus the node != NULL condition in for loop above to be unnecesary. > } > } > + > + free (list_sizes); We already have our own mmap allocator, so I wonder if we don't want to avoid malloc/free pair here. The counters are per-function, right? I wonder if they happen to be large on some bigger project, but it may reduct risk of user messing this up with his own malloc/free implementation if we used alloca for counts of reasonable size. > } > > /* Write counters in GI_PTR and the summary in PRG to a gcda file. In > @@ -425,7 +446,7 @@ write_one_data (const struct gcov_info *gi_ptr, > n_counts = ci_ptr->num; > > if (t_ix == GCOV_COUNTER_V_TOPN || t_ix == GCOV_COUNTER_V_INDIR) > - write_top_counters (ci_ptr, t_ix, n_counts); > + write_topn_counters (ci_ptr, t_ix, n_counts); > else > { > /* Do not stream when all counters are zero. */ > diff --git a/libgcc/libgcov-merge.c b/libgcc/libgcov-merge.c > index 7db188a4f4c..3379b688128 100644 > --- a/libgcc/libgcov-merge.c > +++ b/libgcc/libgcov-merge.c > @@ -109,6 +109,7 @@ __gcov_merge_topn (gcov_type *counters, unsigned > n_counters) > /* 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); > + gcc_assert (n <= GCOV_TOPN_MAXIMUM_TRACKED_VALUES); I think in the runtime we do not want to have asserts checking implementation correctness since it bloats it up. So I would leave it out. I wonder if we can have some testcase for parallel updating/streaming in testsuite? Otherwise the patch looks good to me. Honza > > unsigned full = all < 0; > gcov_type *total = &counters[GCOV_TOPN_MEM_COUNTERS * i]; > -- > 2.30.0 >