diff options
author | Giuliano Belinassi <giuliano.belinassi@usp.br> | 2020-08-22 17:43:43 -0300 |
---|---|---|
committer | Giuliano Belinassi <giuliano.belinassi@usp.br> | 2020-08-22 17:43:43 -0300 |
commit | a926878ddbd5a98b272c22171ce58663fc04c3e0 (patch) | |
tree | 86af256e5d9a9c06263c00adc90e5fe348008c43 /libgcc/libgcov-driver.c | |
parent | 542730f087133690b47e036dfd43eb0db8a650ce (diff) | |
parent | 07cbaed8ba7d1b6e4ab3a9f44175502a4e1ecdb1 (diff) | |
download | gcc-devel/autopar_devel.zip gcc-devel/autopar_devel.tar.gz gcc-devel/autopar_devel.tar.bz2 |
Merge branch 'autopar_rebase2' into autopar_develdevel/autopar_devel
Quickly commit changes in the rebase branch.
Diffstat (limited to 'libgcc/libgcov-driver.c')
-rw-r--r-- | libgcc/libgcov-driver.c | 178 |
1 files changed, 94 insertions, 84 deletions
diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c index fb32073..5891426 100644 --- a/libgcc/libgcov-driver.c +++ b/libgcc/libgcov-driver.c @@ -213,51 +213,6 @@ static struct gcov_fn_buffer *fn_buffer; /* Including system dependent components. */ #include "libgcov-driver-system.c" -/* Prune TOP N value COUNTERS. It's needed in order to preserve - reproducibility of builds. */ - -static void -prune_topn_counter (gcov_type *counters, gcov_type all) -{ - for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++) - if (counters[2 * i + 1] < all) - { - counters[2 * i] = 0; - counters[2 * i + 1] = 0; - } -} - -/* Prune counters so that they are ready to store or merge. */ - -static void -prune_counters (struct gcov_info *gi) -{ - for (unsigned i = 0; i < gi->n_functions; i++) - { - const struct gcov_fn_info *gfi = gi->functions[i]; - const struct gcov_ctr_info *ci = gfi->ctrs; - - for (unsigned j = 0; j < GCOV_COUNTERS; j++) - { - if (gi->merge[j] == NULL) - continue; - - if (gi->merge[j] == __gcov_merge_topn) - { - gcc_assert (!(ci->num % GCOV_TOPN_VALUES_COUNTERS)); - for (unsigned k = 0; k < (ci->num / GCOV_TOPN_VALUES_COUNTERS); - k++) - { - gcov_type *counters - = ci->values + (k * GCOV_TOPN_VALUES_COUNTERS); - prune_topn_counter (counters + 1, *counters); - } - } - ci++; - } - } -} - /* This function merges counters in GI_PTR to an existing gcda file. Return 0 on success. Return -1 on error. In this case, caller will goto read_fatal. */ @@ -346,16 +301,21 @@ merge_one_data (const char *filename, if (!merge) continue; - tag = gcov_read_unsigned (); - length = gcov_read_unsigned (); - if (tag != GCOV_TAG_FOR_COUNTER (t_ix) - || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) - goto read_mismatch; - (*merge) (ci_ptr->values, ci_ptr->num); - ci_ptr++; - } + tag = gcov_read_unsigned (); + int read_length = (int)gcov_read_unsigned (); + length = abs (read_length); + if (tag != GCOV_TAG_FOR_COUNTER (t_ix) + || (length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num) + && t_ix != GCOV_COUNTER_V_TOPN + && t_ix != GCOV_COUNTER_V_INDIR)) + goto read_mismatch; + /* Merging with all zero counters does not make sense. */ + if (read_length > 0) + (*merge) (ci_ptr->values, ci_ptr->num); + ci_ptr++; + } if ((error = gcov_is_error ())) - goto read_error; + goto read_error; } if (tag) @@ -374,6 +334,37 @@ read_error: return -1; } +/* Store all TOP N counters where each has a dynamic length. */ + +static void +write_top_counters (const struct gcov_ctr_info *ci_ptr, + unsigned t_ix, + gcov_unsigned_t n_counts) +{ + unsigned counters = n_counts / GCOV_TOPN_MEM_COUNTERS; + gcc_assert (n_counts % GCOV_TOPN_MEM_COUNTERS == 0); + unsigned pair_total = 0; + for (unsigned i = 0; i < counters; i++) + pair_total += ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 1]; + unsigned disk_size = GCOV_TOPN_DISK_COUNTERS * counters + 2 * pair_total; + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (disk_size)); + + for (unsigned i = 0; i < counters; i++) + { + gcov_type pair_count = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 1]; + gcov_write_counter (ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i]); + gcov_write_counter (pair_count); + gcov_type start = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 2]; + for (struct gcov_kvp *node = (struct gcov_kvp *)(intptr_t)start; + node != NULL; node = node->next) + { + gcov_write_counter (node->value); + gcov_write_counter (node->count); + } + } +} + /* Write counters in GI_PTR and the summary in PRG to a gcda file. In the case of appending to an existing file, SUMMARY_POS will be non-zero. We will write the file starting from SUMMAY_POS. */ @@ -426,20 +417,40 @@ write_one_data (const struct gcov_info *gi_ptr, ci_ptr = gfi_ptr->ctrs; for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) { - gcov_unsigned_t n_counts; - gcov_type *c_ptr; + gcov_position_t n_counts; - if (!gi_ptr->merge[t_ix]) - continue; + if (!gi_ptr->merge[t_ix]) + continue; - n_counts = ci_ptr->num; - gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), - GCOV_TAG_COUNTER_LENGTH (n_counts)); - c_ptr = ci_ptr->values; - while (n_counts--) - gcov_write_counter (*c_ptr++); - ci_ptr++; - } + n_counts = ci_ptr->num; + + if (gi_ptr->merge[t_ix] == __gcov_merge_topn) + write_top_counters (ci_ptr, t_ix, n_counts); + else + { + /* Do not stream when all counters are zero. */ + int all_zeros = 1; + for (unsigned i = 0; i < n_counts; i++) + if (ci_ptr->values[i] != 0) + { + all_zeros = 0; + break; + } + + if (all_zeros) + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (-n_counts)); + else + { + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (n_counts)); + for (unsigned i = 0; i < n_counts; i++) + gcov_write_counter (ci_ptr->values[i]); + } + } + + ci_ptr++; + } if (buffered) fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); } @@ -447,19 +458,6 @@ write_one_data (const struct gcov_info *gi_ptr, gcov_write_unsigned (0); } -/* Helper function for merging summary. */ - -static void -merge_summary (int run_counted, struct gcov_summary *summary, - gcov_type run_max) -{ - if (!run_counted) - { - summary->runs++; - summary->sum_max += run_max; - } -} - /* 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 @@ -469,16 +467,14 @@ merge_summary (int run_counted, struct gcov_summary *summary, static void dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf, - unsigned run_counted, gcov_type run_max) + unsigned run_counted ATTRIBUTE_UNUSED, + gcov_type run_max ATTRIBUTE_UNUSED) { struct gcov_summary summary = {}; int error; gcov_unsigned_t tag; fn_buffer = 0; - /* Prune current counters before we merge them. */ - prune_counters (gi_ptr); - error = gcov_exit_open_gcda_file (gi_ptr, gf); if (error == -1) return; @@ -500,7 +496,15 @@ dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf, gcov_rewrite (); - merge_summary (run_counted, &summary, run_max); +#if !IN_GCOV_TOOL + if (!run_counted) + { + summary.runs++; + summary.sum_max += run_max; + } +#else + summary = gi_ptr->summary; +#endif write_one_data (gi_ptr, &summary); /* fall through */ @@ -584,6 +588,12 @@ struct gcov_root __gcov_root; struct gcov_master __gcov_master = {GCOV_VERSION, 0}; +/* Pool of pre-allocated gcov_kvp strutures. */ +struct gcov_kvp __gcov_kvp_pool[GCOV_PREALLOCATED_KVP]; + +/* Index to first free gcov_kvp in the pool. */ +unsigned __gcov_kvp_pool_index; + void __gcov_exit (void) { |