/* Utility functions for reading gcda files into in-memory
gcov_info structures and offline profile processing. */
-/* Copyright (C) 2014-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
Contributed by Rong Xu <xur@google.com>.
This file is part of GCC.
#include "diagnostic.h"
#include "version.h"
#include "demangle.h"
+#include "gcov-io.h"
/* Borrowed from basic-block.h. */
#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS];
/* Number of kind of counters that have been seen. */
static int k_ctrs_types;
+/* The object summary being processed. */
+static struct gcov_summary *curr_object_summary;
/* Merge functions for counters. */
#define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE,
{GCOV_TAG_ARCS, "ARCS", tag_arcs},
{GCOV_TAG_LINES, "LINES", tag_lines},
{GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
- {GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary},
{0, NULL, NULL}
};
static void
tag_summary (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED)
{
- struct gcov_summary summary;
-
- gcov_read_summary (&summary);
+ curr_object_summary = (gcov_summary *) xcalloc (sizeof (gcov_summary), 1);
+ gcov_read_summary (curr_object_summary);
}
/* This function is called at the end of reading a gcda file.
set_fn_ctrs (curr_fn_info);
obstack_ptr_grow (&fn_info, curr_fn_info);
- /* We set the following fields: merge, n_functions, and functions. */
+ /* We set the following fields: merge, n_functions, functions
+ and summary. */
obj_info->n_functions = num_fn_info;
obj_info->functions = (const struct gcov_fn_info**) obstack_finish (&fn_info);
obstack_init (&fn_info);
num_fn_info = 0;
curr_fn_info = 0;
+ curr_object_summary = NULL;
{
size_t len = strlen (filename) + 1;
char *str_dup = (char*) xmalloc (len);
{
if (((mask & 0xff) != 0xff))
{
- warning (0, "%s:tag `%x' is invalid\n", filename, tag);
+ warning (0, "%s:tag %qx is invalid", filename, tag);
break;
}
tag_depth--;
if (depth && depth < tag_depth)
{
if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag))
- warning (0, "%s:tag `%x' is incorrectly nested\n",
+ warning (0, "%s:tag %qx is incorrectly nested",
filename, tag);
}
depth = tag_depth;
actual_length = gcov_position () - base;
if (actual_length > length)
- warning (0, "%s:record size mismatch %lu bytes overread\n",
+ warning (0, "%s:record size mismatch %lu bytes overread",
filename, actual_length - length);
else if (length > actual_length)
- warning (0, "%s:record size mismatch %lu bytes unread\n",
+ warning (0, "%s:record size mismatch %lu bytes unread",
filename, length - actual_length);
}
gcov_sync (base, length);
if ((error = gcov_is_error ()))
{
- warning (0, error < 0 ? "%s:counter overflow at %lu\n" :
- "%s:read error at %lu\n", filename,
+ warning (0, error < 0 ? "%s:counter overflow at %lu" :
+ "%s:read error at %lu", filename,
(long unsigned) gcov_position ());
break;
}
#ifdef HAVE_FTW_H
ftw (".", ftw_read_file, 50);
#endif
- ret = chdir (pwd);
+ chdir (pwd);
free (pwd);
-
return gcov_info_head;;
}
tgt_tail = gi_ptr;
}
+ free (in_src_not_tgt);
+ free (tgt_infos);
+
return 0;
}
/* Do nothing. */
}
-/* Performing FN upon single counters. */
+/* Performing FN upon TOP N counters. */
static void
-__gcov_single_counter_op (gcov_type *counters, unsigned n_counters,
- counter_op_fn fn, void *data1, void *data2)
+__gcov_topn_counter_op (gcov_type *counters, unsigned n_counters,
+ counter_op_fn fn, void *data1, void *data2)
{
unsigned i, n_measures;
}
}
-/* Performing FN upon indirect-call profile counters. */
-
-static void
-__gcov_icall_topn_counter_op (gcov_type *counters, unsigned n_counters,
- counter_op_fn fn, void *data1, void *data2)
-{
- unsigned i;
-
- gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS));
- for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS)
- {
- unsigned j;
- gcov_type *value_array = &counters[i + 1];
-
- for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2)
- value_array[j + 1] = fn (value_array[j + 1], data1, data2);
- }
-}
-
/* Scaling the counter value V by multiplying *(float*) DATA1. */
static gcov_type
}
/* Compute the overlap score between GCOV_INFO1 and GCOV_INFO2.
- SUM_1 is the sum_all for profile1 where GCOV_INFO1 belongs.
- SUM_2 is the sum_all for profile2 where GCOV_INFO2 belongs.
This function also updates cumulative score CUM_1_RESULT and
CUM_2_RESULT. */
{
for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
{
- unsigned t_ix;
const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
if (!gfi_ptr || gfi_ptr->key != gcov_info)
continue;
const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
- for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
- {
- unsigned c_num;
-
- if (!gcov_info->merge[t_ix])
- continue;
-
- for (c_num = 0; c_num < ci_ptr->num; c_num++)
- {
- cum_1 += ci_ptr->values[c_num] / sum;
- }
- ci_ptr++;
- }
+ unsigned c_num;
+ for (c_num = 0; c_num < ci_ptr->num; c_num++)
+ cum_1 += ci_ptr->values[c_num] / sum;
}
*cum_p = cum_1;
return 0.0;
for (f_ix = 0; f_ix < gcov_info1->n_functions; f_ix++)
{
- unsigned t_ix;
double func_cum_1 = 0.0;
double func_cum_2 = 0.0;
double func_val = 0.0;
const struct gcov_ctr_info *ci_ptr1 = gfi_ptr1->ctrs;
const struct gcov_ctr_info *ci_ptr2 = gfi_ptr2->ctrs;
- for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
- {
- unsigned c_num;
+ unsigned c_num;
+ for (c_num = 0; c_num < ci_ptr1->num; c_num++)
+ {
+ if (ci_ptr1->values[c_num] | ci_ptr2->values[c_num])
+ {
+ func_val += calculate_2_entries (ci_ptr1->values[c_num],
+ ci_ptr2->values[c_num],
+ sum_1, sum_2);
+
+ func_cum_1 += ci_ptr1->values[c_num] / sum_1;
+ func_cum_2 += ci_ptr2->values[c_num] / sum_2;
+ nonzero = 1;
+ if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold
+ || ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
+ hot = 1;
+ }
+ }
- if (!gcov_info1->merge[t_ix])
- continue;
-
- for (c_num = 0; c_num < ci_ptr1->num; c_num++)
- {
- if (ci_ptr1->values[c_num] | ci_ptr2->values[c_num])
- {
- func_val += calculate_2_entries (ci_ptr1->values[c_num],
- ci_ptr2->values[c_num],
- sum_1, sum_2);
-
- func_cum_1 += ci_ptr1->values[c_num] / sum_1;
- func_cum_2 += ci_ptr2->values[c_num] / sum_2;
- nonzero = 1;
- if (ci_ptr1->values[c_num] / sum_1 >= overlap_hot_threshold ||
- ci_ptr2->values[c_num] / sum_2 >= overlap_hot_threshold)
- hot = 1;
- }
- }
- ci_ptr1++;
- ci_ptr2++;
- }
ret += func_val;
cum_1 += func_cum_1;
cum_2 += func_cum_2;
for (f_ix = 0; f_ix < gcov_info->n_functions; f_ix++)
{
- unsigned t_ix;
const struct gcov_fn_info *gfi_ptr = gcov_info->functions[f_ix];
if (!gfi_ptr || gfi_ptr->key != gcov_info)
continue;
const struct gcov_ctr_info *ci_ptr = gfi_ptr->ctrs;
- for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
- {
- unsigned c_num;
-
- if (!gcov_info->merge[t_ix])
- continue;
-
- for (c_num = 0; c_num < ci_ptr->num; c_num++)
- {
- if (ci_ptr->values[c_num] > threshold)
- return false;
- }
- ci_ptr++;
- }
+ for (unsigned c_num = 0; c_num < ci_ptr->num; c_num++)
+ if (ci_ptr->values[c_num] > threshold)
+ return false;
}
return true;
/* Cumlative overlap dscore for profile1 and profile2. */
static double overlap_sum_1, overlap_sum_2;
-/* sum_all for profile1 and profile2. */
-static gcov_type p1_sum_all, p2_sum_all;
-
-/* run_max for profile1 and profile2. */
-static gcov_type p1_run_max, p2_run_max;
-
/* The number of gcda files in the profiles. */
static unsigned gcda_files[2];
return 1;
}
-/* Defined in libgcov-driver.c. */
-extern gcov_unsigned_t compute_summary (struct gcov_info *,
- struct gcov_summary *, size_t *);
-
/* Compute the overlap score of two profiles with the head of GCOV_LIST1 and
GCOV_LIST1. Return a number ranging from [0.0, 1.0], with 0.0 meaning no
match and 1.0 meaning a perfect match. */
calculate_overlap (struct gcov_info *gcov_list1,
struct gcov_info *gcov_list2)
{
- struct gcov_summary this_prg;
unsigned list1_cnt = 0, list2_cnt= 0, all_cnt;
unsigned int i, j;
- size_t max_length;
const struct gcov_info *gi_ptr;
struct overlap_t *all_infos;
- compute_summary (gcov_list1, &this_prg, &max_length);
- overlap_sum_1 = (double) (this_prg.ctrs[0].sum_all);
- p1_sum_all = this_prg.ctrs[0].sum_all;
- p1_run_max = this_prg.ctrs[0].run_max;
- compute_summary (gcov_list2, &this_prg, &max_length);
- overlap_sum_2 = (double) (this_prg.ctrs[0].sum_all);
- p2_sum_all = this_prg.ctrs[0].sum_all;
- p2_run_max = this_prg.ctrs[0].run_max;
-
for (gi_ptr = gcov_list1; gi_ptr; gi_ptr = gi_ptr->next)
list1_cnt++;
for (gi_ptr = gcov_list2; gi_ptr; gi_ptr = gi_ptr->next)
}
+ free (all_infos);
+
if (overlap_obj_level)
printf(" SUM:%36s overlap = %6.2f%% (%5.2f%% %5.2f%%)\n",
"", sum_val*100, sum_cum_1*100, sum_cum_2*100);
cold_gcda_files[1], both_cold_cnt);
printf (" zero files: %12u\t%12u\t%12u\n", zero_gcda_files[0],
zero_gcda_files[1], both_zero_cnt);
- printf (" sum_all: %12" PRId64 "\t%12" PRId64 "\n",
- p1_sum_all, p2_sum_all);
- printf (" run_max: %12" PRId64 "\t%12" PRId64 "\n",
- p1_run_max, p2_run_max);
return prg_val;
}