diff options
author | Martin Liska <mliska@suse.cz> | 2021-09-09 13:02:24 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-10-13 15:26:58 +0200 |
commit | 72e0c742bd01f8e7e6dcca64042b9ad7e75979de (patch) | |
tree | b902a8580178ec7ed6d4dc9416679a4d92f81e78 /gcc/coverage.c | |
parent | 489c8f27296362dcfbc967aecef17ba7c5cab0f2 (diff) | |
download | gcc-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.c | 50 |
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); |