aboutsummaryrefslogtreecommitdiff
path: root/gcc/coverage.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2021-09-09 13:02:24 +0200
committerMartin Liska <mliska@suse.cz>2021-10-13 15:26:58 +0200
commit72e0c742bd01f8e7e6dcca64042b9ad7e75979de (patch)
treeb902a8580178ec7ed6d4dc9416679a4d92f81e78 /gcc/coverage.c
parent489c8f27296362dcfbc967aecef17ba7c5cab0f2 (diff)
downloadgcc-72e0c742bd01f8e7e6dcca64042b9ad7e75979de.zip
gcc-72e0c742bd01f8e7e6dcca64042b9ad7e75979de.tar.gz
gcc-72e0c742bd01f8e7e6dcca64042b9ad7e75979de.tar.bz2
gcov: make profile merging smarter
Support merging of profiles that are built from a different .o files but belong to the same source file. Moreover, a checksum is verified during profile merging and so we can safely combine such profile. PR gcov-profile/90364 gcc/ChangeLog: * coverage.c (build_info): Emit checksum to the global variable. (build_info_type): Add new field for checksum. (coverage_obj_finish): Pass object_checksum. (coverage_init): Use 0 as checksum for .gcno files. * gcov-dump.c (dump_gcov_file): Dump also new checksum field. * gcov.c (read_graph_file): Read also checksum. * doc/invoke.texi: Document the behaviour change. libgcc/ChangeLog: * libgcov-driver.c (merge_one_data): Skip timestamp and verify checksums. (write_one_data): Write also checksum. * libgcov-util.c (read_gcda_file): Read also checksum field. * libgcov.h (struct gcov_info): Add new field.
Diffstat (limited to 'gcc/coverage.c')
-rw-r--r--gcc/coverage.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 10d7f83..4467f1e 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -129,16 +129,7 @@ static const char *const ctr_names[GCOV_COUNTERS] = {
#undef DEF_GCOV_COUNTER
/* Forward declarations. */
-static void read_counts_file (void);
static tree build_var (tree, tree, int);
-static void build_fn_info_type (tree, unsigned, tree);
-static void build_info_type (tree, tree);
-static tree build_fn_info (const struct coverage_data *, tree, tree);
-static tree build_info (tree, tree);
-static bool coverage_obj_init (void);
-static vec<constructor_elt, va_gc> *coverage_obj_fn
-(vec<constructor_elt, va_gc> *, tree, struct coverage_data const *);
-static void coverage_obj_finish (vec<constructor_elt, va_gc> *);
/* Return the type node for gcov_type. */
@@ -218,6 +209,9 @@ read_counts_file (void)
tag = gcov_read_unsigned ();
bbg_file_stamp = crc32_unsigned (bbg_file_stamp, tag);
+ /* Read checksum. */
+ gcov_read_unsigned ();
+
counts_hash = new hash_table<counts_entry> (10);
while ((tag = gcov_read_unsigned ()))
{
@@ -935,6 +929,12 @@ build_info_type (tree type, tree fn_info_ptr_type)
DECL_CHAIN (field) = fields;
fields = field;
+ /* Checksum. */
+ field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
+ get_gcov_unsigned_t ());
+ DECL_CHAIN (field) = fields;
+ fields = field;
+
/* Filename */
field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
build_pointer_type (build_qualified_type
@@ -977,7 +977,7 @@ build_info_type (tree type, tree fn_info_ptr_type)
function info objects. */
static tree
-build_info (tree info_type, tree fn_ary)
+build_info (tree info_type, tree fn_ary, unsigned object_checksum)
{
tree info_fields = TYPE_FIELDS (info_type);
tree merge_fn_type, n_funcs;
@@ -996,13 +996,19 @@ build_info (tree info_type, tree fn_ary)
/* next -- NULL */
CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node);
info_fields = DECL_CHAIN (info_fields);
-
+
/* stamp */
CONSTRUCTOR_APPEND_ELT (v1, info_fields,
build_int_cstu (TREE_TYPE (info_fields),
bbg_file_stamp));
info_fields = DECL_CHAIN (info_fields);
+ /* Checksum. */
+ CONSTRUCTOR_APPEND_ELT (v1, info_fields,
+ build_int_cstu (TREE_TYPE (info_fields),
+ object_checksum));
+ info_fields = DECL_CHAIN (info_fields);
+
/* Filename */
da_file_name_len = strlen (da_file_name);
filename_string = build_string (da_file_name_len + 1, da_file_name);
@@ -1214,7 +1220,8 @@ coverage_obj_fn (vec<constructor_elt, va_gc> *ctor, tree fn,
function objects from CTOR. Generate the gcov_info initializer. */
static void
-coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
+coverage_obj_finish (vec<constructor_elt, va_gc> *ctor,
+ unsigned object_checksum)
{
unsigned n_functions = vec_safe_length (ctor);
tree fn_info_ary_type = build_array_type
@@ -1231,7 +1238,7 @@ coverage_obj_finish (vec<constructor_elt, va_gc> *ctor)
varpool_node::finalize_decl (fn_info_ary);
DECL_INITIAL (gcov_info_var)
- = build_info (TREE_TYPE (gcov_info_var), fn_info_ary);
+ = build_info (TREE_TYPE (gcov_info_var), fn_info_ary, object_checksum);
varpool_node::finalize_decl (gcov_info_var);
}
@@ -1300,7 +1307,6 @@ coverage_init (const char *filename)
strcpy (da_file_name + prefix_len + len, GCOV_DATA_SUFFIX);
bbg_file_stamp = local_tick;
-
if (flag_auto_profile)
read_autofdo_file ();
else if (flag_branch_probabilities)
@@ -1328,6 +1334,8 @@ coverage_init (const char *filename)
gcov_write_unsigned (GCOV_NOTE_MAGIC);
gcov_write_unsigned (GCOV_VERSION);
gcov_write_unsigned (bbg_file_stamp);
+ /* Use an arbitrary checksum */
+ gcov_write_unsigned (0);
gcov_write_string (getpwd ());
/* Do not support has_unexecuted_blocks for Ada. */
@@ -1353,14 +1361,24 @@ coverage_finish (void)
cannot uniquely stamp it. If we can stamp it, libgcov will DTRT. */
unlink (da_file_name);
+ /* Global GCDA checksum that aggregates all functions. */
+ unsigned object_checksum = 0;
+
if (coverage_obj_init ())
{
vec<constructor_elt, va_gc> *fn_ctor = NULL;
struct coverage_data *fn;
for (fn = functions_head; fn; fn = fn->next)
- fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
- coverage_obj_finish (fn_ctor);
+ {
+ fn_ctor = coverage_obj_fn (fn_ctor, fn->fn_decl, fn);
+
+ object_checksum = crc32_unsigned (object_checksum, fn->ident);
+ object_checksum = crc32_unsigned (object_checksum,
+ fn->lineno_checksum);
+ object_checksum = crc32_unsigned (object_checksum, fn->cfg_checksum);
+ }
+ coverage_obj_finish (fn_ctor, object_checksum);
}
XDELETEVEC (da_file_name);