aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgcc/libgcov-merge.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libgcc/libgcov-merge.c')
-rw-r--r--gcc-4.9/libgcc/libgcov-merge.c145
1 files changed, 135 insertions, 10 deletions
diff --git a/gcc-4.9/libgcc/libgcov-merge.c b/gcc-4.9/libgcc/libgcov-merge.c
index 488d5426c..09d5769ff 100644
--- a/gcc-4.9/libgcc/libgcov-merge.c
+++ b/gcc-4.9/libgcc/libgcov-merge.c
@@ -53,7 +53,7 @@ void
__gcov_merge_add (gcov_type *counters, unsigned n_counters)
{
for (; n_counters; counters++, n_counters--)
- *counters += gcov_read_counter ();
+ *counters += gcov_get_counter ();
}
#endif /* L_gcov_merge_add */
@@ -65,10 +65,135 @@ void
__gcov_merge_ior (gcov_type *counters, unsigned n_counters)
{
for (; n_counters; counters++, n_counters--)
- *counters |= gcov_read_counter ();
+ *counters |= gcov_get_counter_target ();
}
#endif
+
+#ifdef L_gcov_merge_dc
+
+/* Returns 1 if the function global id GID is not valid. */
+
+static int
+__gcov_is_gid_insane (gcov_type gid)
+{
+ if (EXTRACT_MODULE_ID_FROM_GLOBAL_ID (gid) == 0
+ || EXTRACT_FUNC_ID_FROM_GLOBAL_ID (gid) == 0)
+ return 1;
+ return 0;
+}
+
+/* The profile merging function used for merging direct call counts
+ This function is given array COUNTERS of N_COUNTERS old counters and it
+ reads the same number of counters from the gcov file. */
+
+void
+__gcov_merge_dc (gcov_type *counters, unsigned n_counters)
+{
+ unsigned i;
+
+ gcc_assert (!(n_counters % 2));
+ for (i = 0; i < n_counters; i += 2)
+ {
+ gcov_type global_id = gcov_read_counter ();
+ gcov_type call_count = gcov_read_counter ();
+
+ /* Note that global id counter may never have been set if no calls were
+ made from this call-site. */
+ if (counters[i] && global_id)
+ {
+ /* TODO race condition requires us do the following correction. */
+ if (__gcov_is_gid_insane (counters[i]))
+ counters[i] = global_id;
+ else if (__gcov_is_gid_insane (global_id))
+ global_id = counters[i];
+
+ gcc_assert (counters[i] == global_id);
+ }
+ else if (global_id)
+ counters[i] = global_id;
+
+ counters[i + 1] += call_count;
+
+ /* Reset. */
+ if (__gcov_is_gid_insane (counters[i]))
+ counters[i] = counters[i + 1] = 0;
+
+ /* Assert that the invariant (global_id == 0) <==> (call_count == 0)
+ holds true after merging. */
+ if (counters[i] == 0)
+ counters[i+1] = 0;
+ if (counters[i + 1] == 0)
+ counters[i] = 0;
+ }
+}
+#endif
+
+
+#ifdef L_gcov_merge_icall_topn
+/* The profile merging function used for merging indirect call counts
+ This function is given array COUNTERS of N_COUNTERS old counters and it
+ reads the same number of counters from the gcov file. */
+
+void
+__gcov_merge_icall_topn (gcov_type *counters, unsigned n_counters)
+{
+ unsigned i, j, k, m;
+
+ gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS));
+ for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS)
+ {
+ gcov_type *value_array = &counters[i + 1];
+ unsigned tmp_size = 2 * (GCOV_ICALL_TOPN_NCOUNTS - 1);
+ gcov_type *tmp_array
+ = (gcov_type *) alloca (tmp_size * sizeof (gcov_type));
+
+ for (j = 0; j < tmp_size; j++)
+ tmp_array[j] = 0;
+
+ for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2)
+ {
+ tmp_array[j] = value_array[j];
+ tmp_array[j + 1] = value_array [j + 1];
+ }
+
+ /* Skip the number_of_eviction entry. */
+ gcov_read_counter ();
+ for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
+ {
+ int found = 0;
+ gcov_type global_id = gcov_read_counter ();
+ gcov_type call_count = gcov_read_counter ();
+ for (m = 0; m < j; m += 2)
+ {
+ if (tmp_array[m] == global_id)
+ {
+ found = 1;
+ tmp_array[m + 1] += call_count;
+ break;
+ }
+ }
+ if (!found)
+ {
+ tmp_array[j] = global_id;
+ tmp_array[j + 1] = call_count;
+ j += 2;
+ }
+ }
+ /* Now sort the temp array */
+ gcov_sort_n_vals (tmp_array, j);
+
+ /* Now copy back the top half of the temp array */
+ for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
+ {
+ value_array[k] = tmp_array[k];
+ value_array[k + 1] = tmp_array[k + 1];
+ }
+ }
+}
+#endif
+
+
#ifdef L_gcov_merge_time_profile
/* Time profiles are merged so that minimum from all valid (greater than zero)
is stored. There could be a fork that creates new counters. To have
@@ -81,7 +206,7 @@ __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
for (i = 0; i < n_counters; i++)
{
- value = gcov_read_counter ();
+ value = gcov_get_counter_target ();
if (value && (!counters[i] || value < counters[i]))
counters[i] = value;
@@ -109,9 +234,9 @@ __gcov_merge_single (gcov_type *counters, unsigned n_counters)
n_measures = n_counters / 3;
for (i = 0; i < n_measures; i++, counters += 3)
{
- value = gcov_read_counter ();
- counter = gcov_read_counter ();
- all = gcov_read_counter ();
+ value = gcov_get_counter_target ();
+ counter = gcov_get_counter ();
+ all = gcov_get_counter ();
if (counters[0] == value)
counters[1] += counter;
@@ -148,10 +273,10 @@ __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
n_measures = n_counters / 4;
for (i = 0; i < n_measures; i++, counters += 4)
{
- /* last = */ gcov_read_counter ();
- value = gcov_read_counter ();
- counter = gcov_read_counter ();
- all = gcov_read_counter ();
+ /* last = */ gcov_get_counter ();
+ value = gcov_get_counter_target ();
+ counter = gcov_get_counter ();
+ all = gcov_get_counter ();
if (counters[1] == value)
counters[2] += counter;