aboutsummaryrefslogtreecommitdiff
path: root/libgcc/libgcov-driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/libgcov-driver.c')
-rw-r--r--libgcc/libgcov-driver.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c
index 7bde526..754584d 100644
--- a/libgcc/libgcov-driver.c
+++ b/libgcc/libgcov-driver.c
@@ -665,6 +665,85 @@ merge_summary (const char *filename, int run_counted,
return 0;
}
+
+/* Sort N entries in VALUE_ARRAY in descending order.
+ Each entry in VALUE_ARRAY has two values. The sorting
+ is based on the second value. */
+
+GCOV_LINKAGE void
+gcov_sort_n_vals (gcov_type *value_array, int n)
+{
+ int j, k;
+
+ for (j = 2; j < n; j += 2)
+ {
+ gcov_type cur_ent[2];
+
+ cur_ent[0] = value_array[j];
+ cur_ent[1] = value_array[j + 1];
+ k = j - 2;
+ while (k >= 0 && value_array[k + 1] < cur_ent[1])
+ {
+ value_array[k + 2] = value_array[k];
+ value_array[k + 3] = value_array[k+1];
+ k -= 2;
+ }
+ value_array[k + 2] = cur_ent[0];
+ value_array[k + 3] = cur_ent[1];
+ }
+}
+
+/* Sort the profile counters for all indirect call sites. Counters
+ for each call site are allocated in array COUNTERS. */
+
+static void
+gcov_sort_icall_topn_counter (const struct gcov_ctr_info *counters)
+{
+ int i;
+ gcov_type *values;
+ int n = counters->num;
+
+ gcc_assert (!(n % GCOV_ICALL_TOPN_NCOUNTS));
+ values = counters->values;
+
+ for (i = 0; i < n; i += GCOV_ICALL_TOPN_NCOUNTS)
+ {
+ gcov_type *value_array = &values[i + 1];
+ gcov_sort_n_vals (value_array, GCOV_ICALL_TOPN_NCOUNTS - 1);
+ }
+}
+
+/* Sort topn indirect_call profile counters in GI_PTR. */
+
+static void
+gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
+{
+ unsigned int i;
+ int f_ix;
+ const struct gcov_fn_info *gfi_ptr;
+ const struct gcov_ctr_info *ci_ptr;
+
+ if (!gi_ptr->merge[GCOV_COUNTER_ICALL_TOPNV])
+ return;
+
+ for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
+ {
+ gfi_ptr = gi_ptr->functions[f_ix];
+ ci_ptr = gfi_ptr->ctrs;
+ for (i = 0; i < GCOV_COUNTERS; i++)
+ {
+ if (!gi_ptr->merge[i])
+ continue;
+ if (i == GCOV_COUNTER_ICALL_TOPNV)
+ {
+ gcov_sort_icall_topn_counter (ci_ptr);
+ break;
+ }
+ ci_ptr++;
+ }
+ }
+}
+
/* Dump the coverage counts for one gcov_info object. We merge with existing
counts when possible, to avoid growing the .da files ad infinitum. We use
this program's checksum to make sure we only accumulate whole program
@@ -687,6 +766,8 @@ dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
fn_buffer = 0;
sum_buffer = 0;
+ gcov_sort_topn_counter_arrays (gi_ptr);
+
error = gcov_exit_open_gcda_file (gi_ptr, gf);
if (error == -1)
return;