Remove arc profile histogram in non-LTO mode.
2018-09-21 Martin Liska <mliska@suse.cz> * auto-profile.c (autofdo_source_profile::read): Do not set sum_all. (read_profile): Do not add working sets. (read_autofdo_file): Remove sum_all. (afdo_callsite_hot_enough_for_early_inline): Remove const qualifier. * coverage.c (struct counts_entry): Remove gcov_summary. (read_counts_file): Read new GCOV_TAG_OBJECT_SUMMARY, do not support GCOV_TAG_PROGRAM_SUMMARY. (get_coverage_counts): Remove summary and expected arguments. * coverage.h (get_coverage_counts): Likewise. * doc/gcov-dump.texi: Remove -w option. * gcov-dump.c (dump_working_sets): Remove. (main): Do not support '-w' option. (print_usage): Likewise. (tag_summary): Likewise. * gcov-io.c (gcov_write_summary): Do not dump histogram. (gcov_read_summary): Likewise. (gcov_histo_index): Remove. (gcov_histogram_merge): Likewise. (compute_working_sets): Likewise. * gcov-io.h (GCOV_TAG_OBJECT_SUMMARY): Mark it not obsolete. (GCOV_TAG_PROGRAM_SUMMARY): Mark it obsolete. (GCOV_TAG_SUMMARY_LENGTH): Adjust. (GCOV_HISTOGRAM_SIZE): Remove. (GCOV_HISTOGRAM_BITVECTOR_SIZE): Likewise. (struct gcov_summary): Simplify rapidly just to runs and sum_max fields. (gcov_histo_index): Remove. (NUM_GCOV_WORKING_SETS): Likewise. (compute_working_sets): Likewise. * gcov-tool.c (print_overlap_usage_message): Remove trailing empty line. * gcov.c (read_count_file): Read GCOV_TAG_OBJECT_SUMMARY. (output_lines): Remove program related line. * ipa-profile.c (ipa_profile): Do not consider GCOV histogram. * lto-cgraph.c (output_profile_summary): Do not stream GCOV histogram. (input_profile_summary): Do not read it. (merge_profile_summaries): And do not merge it. (input_symtab): Do not call removed function. * modulo-sched.c (sms_schedule): Do not print sum_max. * params.def (HOT_BB_COUNT_FRACTION): Reincarnate param that was removed when histogram method was invented. (HOT_BB_COUNT_WS_PERMILLE): Mention that it's used only in LTO mode. * postreload-gcse.c (eliminate_partially_redundant_load): Fix GCOV coding style. * predict.c (get_hot_bb_threshold): Use HOT_BB_COUNT_FRACTION and dump selected value. * profile.c (add_working_set): Remove. (get_working_sets): Likewise. (find_working_set): Likewise. (get_exec_counts): Do not work with working sets. (read_profile_edge_counts): Do not inform as sum_max is removed. (compute_branch_probabilities): Likewise. (compute_value_histograms): Remove argument for call of get_coverage_counts. * profile.h: Do not make gcov_summary const. 2018-09-21 Martin Liska <mliska@suse.cz> * libgcov-driver.c (crc32_unsigned): Remove. (gcov_histogram_insert): Likewise. (gcov_compute_histogram): Likewise. (compute_summary): Simplify rapidly. (merge_one_data): Do not handle PROGRAM_SUMMARY tag. (merge_summary): Rapidly simplify. (dump_one_gcov): Ignore gcov_summary. (gcov_do_dump): Do not handle program summary, it's not used. * libgcov-util.c (tag_summary): Remove. (read_gcda_finalize): Fix coding style. (read_gcda_file): Initialize curr_object_summary. (compute_summary): Remove. (calculate_overlap): Remove settings of run_max. From-SVN: r264462
This commit is contained in:
parent
36ff254bf6
commit
512cc01512
@ -1,3 +1,68 @@
|
||||
2018-09-21 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* auto-profile.c (autofdo_source_profile::read): Do not
|
||||
set sum_all.
|
||||
(read_profile): Do not add working sets.
|
||||
(read_autofdo_file): Remove sum_all.
|
||||
(afdo_callsite_hot_enough_for_early_inline): Remove const
|
||||
qualifier.
|
||||
* coverage.c (struct counts_entry): Remove gcov_summary.
|
||||
(read_counts_file): Read new GCOV_TAG_OBJECT_SUMMARY,
|
||||
do not support GCOV_TAG_PROGRAM_SUMMARY.
|
||||
(get_coverage_counts): Remove summary and expected
|
||||
arguments.
|
||||
* coverage.h (get_coverage_counts): Likewise.
|
||||
* doc/gcov-dump.texi: Remove -w option.
|
||||
* gcov-dump.c (dump_working_sets): Remove.
|
||||
(main): Do not support '-w' option.
|
||||
(print_usage): Likewise.
|
||||
(tag_summary): Likewise.
|
||||
* gcov-io.c (gcov_write_summary): Do not dump
|
||||
histogram.
|
||||
(gcov_read_summary): Likewise.
|
||||
(gcov_histo_index): Remove.
|
||||
(gcov_histogram_merge): Likewise.
|
||||
(compute_working_sets): Likewise.
|
||||
* gcov-io.h (GCOV_TAG_OBJECT_SUMMARY): Mark
|
||||
it not obsolete.
|
||||
(GCOV_TAG_PROGRAM_SUMMARY): Mark it obsolete.
|
||||
(GCOV_TAG_SUMMARY_LENGTH): Adjust.
|
||||
(GCOV_HISTOGRAM_SIZE): Remove.
|
||||
(GCOV_HISTOGRAM_BITVECTOR_SIZE): Likewise.
|
||||
(struct gcov_summary): Simplify rapidly just
|
||||
to runs and sum_max fields.
|
||||
(gcov_histo_index): Remove.
|
||||
(NUM_GCOV_WORKING_SETS): Likewise.
|
||||
(compute_working_sets): Likewise.
|
||||
* gcov-tool.c (print_overlap_usage_message): Remove
|
||||
trailing empty line.
|
||||
* gcov.c (read_count_file): Read GCOV_TAG_OBJECT_SUMMARY.
|
||||
(output_lines): Remove program related line.
|
||||
* ipa-profile.c (ipa_profile): Do not consider GCOV histogram.
|
||||
* lto-cgraph.c (output_profile_summary): Do not stream GCOV
|
||||
histogram.
|
||||
(input_profile_summary): Do not read it.
|
||||
(merge_profile_summaries): And do not merge it.
|
||||
(input_symtab): Do not call removed function.
|
||||
* modulo-sched.c (sms_schedule): Do not print sum_max.
|
||||
* params.def (HOT_BB_COUNT_FRACTION): Reincarnate param that was
|
||||
removed when histogram method was invented.
|
||||
(HOT_BB_COUNT_WS_PERMILLE): Mention that it's used only in LTO
|
||||
mode.
|
||||
* postreload-gcse.c (eliminate_partially_redundant_load): Fix
|
||||
GCOV coding style.
|
||||
* predict.c (get_hot_bb_threshold): Use HOT_BB_COUNT_FRACTION
|
||||
and dump selected value.
|
||||
* profile.c (add_working_set): Remove.
|
||||
(get_working_sets): Likewise.
|
||||
(find_working_set): Likewise.
|
||||
(get_exec_counts): Do not work with working sets.
|
||||
(read_profile_edge_counts): Do not inform as sum_max is removed.
|
||||
(compute_branch_probabilities): Likewise.
|
||||
(compute_value_histograms): Remove argument for call of
|
||||
get_coverage_counts.
|
||||
* profile.h: Do not make gcov_summary const.
|
||||
|
||||
2018-09-21 Monk Chiang <sh.chiang04@gmail.com>
|
||||
|
||||
* config.gcc (nds32*-*-*): Set TARGET_DEFAULT_TLSDESC_TRAMPOLINE=0.
|
||||
|
@ -867,7 +867,6 @@ autofdo_source_profile::read ()
|
||||
function_instance::function_instance_stack stack;
|
||||
function_instance *s = function_instance::read_function_instance (
|
||||
&stack, gcov_read_counter ());
|
||||
afdo_profile_info->sum_all += s->total_count ();
|
||||
map_[s->name ()] = s;
|
||||
}
|
||||
return true;
|
||||
@ -958,23 +957,6 @@ read_profile (void)
|
||||
|
||||
/* autofdo_module_profile. */
|
||||
fake_read_autofdo_module_profile ();
|
||||
|
||||
/* Read in the working set. */
|
||||
if (gcov_read_unsigned () != GCOV_TAG_AFDO_WORKING_SET)
|
||||
{
|
||||
error ("cannot read working set from %s", auto_profile_file);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Skip the length of the section. */
|
||||
gcov_read_unsigned ();
|
||||
gcov_working_set_t set[128];
|
||||
for (unsigned i = 0; i < 128; i++)
|
||||
{
|
||||
set[i].num_counters = gcov_read_unsigned ();
|
||||
set[i].min_counter = gcov_read_counter ();
|
||||
}
|
||||
add_working_set (set);
|
||||
}
|
||||
|
||||
/* From AutoFDO profiles, find values inside STMT for that we want to measure
|
||||
@ -1685,7 +1667,6 @@ read_autofdo_file (void)
|
||||
autofdo::afdo_profile_info = XNEW (gcov_summary);
|
||||
autofdo::afdo_profile_info->runs = 1;
|
||||
autofdo::afdo_profile_info->sum_max = 0;
|
||||
autofdo::afdo_profile_info->sum_all = 0;
|
||||
|
||||
/* Read the profile from the profile file. */
|
||||
autofdo::read_profile ();
|
||||
@ -1712,7 +1693,7 @@ afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge *edge)
|
||||
if (count > 0)
|
||||
{
|
||||
bool is_hot;
|
||||
const gcov_summary *saved_profile_info = profile_info;
|
||||
gcov_summary *saved_profile_info = profile_info;
|
||||
/* At early inline stage, profile_info is not set yet. We need to
|
||||
temporarily set it to afdo_profile_info to calculate hotness. */
|
||||
profile_info = autofdo::afdo_profile_info;
|
||||
|
@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "intl.h"
|
||||
#include "params.h"
|
||||
#include "auto-profile.h"
|
||||
#include "profile.h"
|
||||
|
||||
#include "gcov-io.c"
|
||||
|
||||
@ -73,7 +74,6 @@ struct counts_entry : pointer_hash <counts_entry>
|
||||
unsigned lineno_checksum;
|
||||
unsigned cfg_checksum;
|
||||
gcov_type *counts;
|
||||
gcov_summary summary;
|
||||
|
||||
/* hash_table support. */
|
||||
static inline hashval_t hash (const counts_entry *);
|
||||
@ -185,8 +185,6 @@ static void
|
||||
read_counts_file (void)
|
||||
{
|
||||
gcov_unsigned_t fn_ident = 0;
|
||||
gcov_summary summary;
|
||||
unsigned new_summary = 1;
|
||||
gcov_unsigned_t tag;
|
||||
int is_error = 0;
|
||||
unsigned lineno_checksum = 0;
|
||||
@ -236,27 +234,12 @@ read_counts_file (void)
|
||||
}
|
||||
else
|
||||
fn_ident = lineno_checksum = cfg_checksum = 0;
|
||||
new_summary = 1;
|
||||
}
|
||||
else if (tag == GCOV_TAG_PROGRAM_SUMMARY)
|
||||
else if (tag == GCOV_TAG_OBJECT_SUMMARY)
|
||||
{
|
||||
struct gcov_summary sum;
|
||||
|
||||
if (new_summary)
|
||||
memset (&summary, 0, sizeof (summary));
|
||||
|
||||
gcov_read_summary (&sum);
|
||||
summary.runs += sum.runs;
|
||||
summary.sum_all += sum.sum_all;
|
||||
if (summary.run_max < sum.run_max)
|
||||
summary.run_max = sum.run_max;
|
||||
summary.sum_max += sum.sum_max;
|
||||
if (new_summary)
|
||||
memcpy (summary.histogram, sum.histogram,
|
||||
sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
|
||||
else
|
||||
gcov_histogram_merge (summary.histogram, sum.histogram);
|
||||
new_summary = 0;
|
||||
profile_info = XCNEW (gcov_summary);
|
||||
profile_info->runs = gcov_read_unsigned ();
|
||||
profile_info->sum_max = gcov_read_unsigned ();
|
||||
}
|
||||
else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident)
|
||||
{
|
||||
@ -276,9 +259,6 @@ read_counts_file (void)
|
||||
entry->ctr = elt.ctr;
|
||||
entry->lineno_checksum = lineno_checksum;
|
||||
entry->cfg_checksum = cfg_checksum;
|
||||
if (elt.ctr == GCOV_COUNTER_ARCS)
|
||||
entry->summary = summary;
|
||||
entry->summary.num = n_counts;
|
||||
entry->counts = XCNEWVEC (gcov_type, n_counts);
|
||||
}
|
||||
else if (entry->lineno_checksum != lineno_checksum
|
||||
@ -292,22 +272,6 @@ read_counts_file (void)
|
||||
counts_hash = NULL;
|
||||
break;
|
||||
}
|
||||
else if (entry->summary.num != n_counts)
|
||||
{
|
||||
error ("Profile data for function %u is corrupted", fn_ident);
|
||||
error ("number of counters is %d instead of %d", entry->summary.num, n_counts);
|
||||
delete counts_hash;
|
||||
counts_hash = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->summary.runs += summary.runs;
|
||||
entry->summary.sum_all += summary.sum_all;
|
||||
if (entry->summary.run_max < summary.run_max)
|
||||
entry->summary.run_max = summary.run_max;
|
||||
entry->summary.sum_max += summary.sum_max;
|
||||
}
|
||||
for (ix = 0; ix != n_counts; ix++)
|
||||
entry->counts[ix] += gcov_read_counter ();
|
||||
}
|
||||
@ -330,9 +294,8 @@ read_counts_file (void)
|
||||
/* Returns the counters for a particular tag. */
|
||||
|
||||
gcov_type *
|
||||
get_coverage_counts (unsigned counter, unsigned expected,
|
||||
unsigned cfg_checksum, unsigned lineno_checksum,
|
||||
const gcov_summary **summary)
|
||||
get_coverage_counts (unsigned counter, unsigned cfg_checksum,
|
||||
unsigned lineno_checksum)
|
||||
{
|
||||
counts_entry *entry, elt;
|
||||
|
||||
@ -363,14 +326,13 @@ get_coverage_counts (unsigned counter, unsigned expected,
|
||||
}
|
||||
elt.ctr = counter;
|
||||
entry = counts_hash->find (&elt);
|
||||
if (!entry || !entry->summary.num)
|
||||
if (!entry)
|
||||
/* The function was not emitted, or is weak and not chosen in the
|
||||
final executable. Silently fail, because there's nothing we
|
||||
can do about it. */
|
||||
return NULL;
|
||||
|
||||
if (entry->cfg_checksum != cfg_checksum
|
||||
|| entry->summary.num != expected)
|
||||
if (entry->cfg_checksum != cfg_checksum)
|
||||
{
|
||||
static int warned = 0;
|
||||
bool warning_printed = false;
|
||||
@ -414,9 +376,6 @@ get_coverage_counts (unsigned counter, unsigned expected,
|
||||
DECL_ASSEMBLER_NAME (current_function_decl));
|
||||
}
|
||||
|
||||
if (summary)
|
||||
*summary = &entry->summary;
|
||||
|
||||
return entry->counts;
|
||||
}
|
||||
|
||||
|
@ -51,10 +51,8 @@ extern tree tree_coverage_counter_addr (unsigned /*counter*/, unsigned/*num*/);
|
||||
|
||||
/* Get all the counters for the current function. */
|
||||
extern gcov_type *get_coverage_counts (unsigned /*counter*/,
|
||||
unsigned /*expected*/,
|
||||
unsigned /*cfg_checksum*/,
|
||||
unsigned /*lineno_checksum*/,
|
||||
const gcov_summary **);
|
||||
unsigned /*lineno_checksum*/);
|
||||
|
||||
extern tree get_gcov_type (void);
|
||||
extern bool coverage_node_map_initialized_p (void);
|
||||
|
@ -61,7 +61,7 @@ gcov-dump [@option{-v}|@option{--version}]
|
||||
[@option{-h}|@option{--help}]
|
||||
[@option{-l}|@option{--long}]
|
||||
[@option{-p}|@option{--positions}]
|
||||
[@option{-w}|@option{--working-sets}] @var{gcovfiles}
|
||||
@var{gcovfiles}
|
||||
@c man end
|
||||
@end ignore
|
||||
|
||||
@ -84,10 +84,6 @@ Dump positions of records.
|
||||
@itemx --version
|
||||
Display the @command{gcov-dump} version number (on the standard output),
|
||||
and exit without doing any further processing.
|
||||
|
||||
@item -w
|
||||
@itemx --working-sets
|
||||
Dump working set computed from summary.
|
||||
@end table
|
||||
|
||||
@c man end
|
||||
|
@ -38,9 +38,6 @@ static void tag_arcs (const char *, unsigned, unsigned, unsigned);
|
||||
static void tag_lines (const char *, unsigned, unsigned, unsigned);
|
||||
static void tag_counters (const char *, unsigned, unsigned, unsigned);
|
||||
static void tag_summary (const char *, unsigned, unsigned, unsigned);
|
||||
static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED,
|
||||
const gcov_summary *summary,
|
||||
unsigned depth);
|
||||
extern int main (int, char **);
|
||||
|
||||
typedef struct tag_format
|
||||
@ -52,7 +49,6 @@ typedef struct tag_format
|
||||
|
||||
static int flag_dump_contents = 0;
|
||||
static int flag_dump_positions = 0;
|
||||
static int flag_dump_working_sets = 0;
|
||||
|
||||
static const struct option options[] =
|
||||
{
|
||||
@ -60,7 +56,6 @@ static const struct option options[] =
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "long", no_argument, NULL, 'l' },
|
||||
{ "positions", no_argument, NULL, 'o' },
|
||||
{ "working-sets", no_argument, NULL, 'w' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@ -77,7 +72,6 @@ static const tag_format_t tag_table[] =
|
||||
{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}
|
||||
};
|
||||
|
||||
@ -117,9 +111,6 @@ main (int argc ATTRIBUTE_UNUSED, char **argv)
|
||||
case 'p':
|
||||
flag_dump_positions = 1;
|
||||
break;
|
||||
case 'w':
|
||||
flag_dump_working_sets = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "unknown flag `%c'\n", opt);
|
||||
}
|
||||
@ -139,7 +130,6 @@ print_usage (void)
|
||||
printf (" -l, --long Dump record contents too\n");
|
||||
printf (" -p, --positions Dump record positions\n");
|
||||
printf (" -v, --version Print version number\n");
|
||||
printf (" -w, --working-sets Dump working set computed from summary\n");
|
||||
printf ("\nFor bug reporting instructions, please see:\n%s.\n",
|
||||
bug_report_url);
|
||||
}
|
||||
@ -465,75 +455,10 @@ tag_counters (const char *filename ATTRIBUTE_UNUSED,
|
||||
static void
|
||||
tag_summary (const char *filename ATTRIBUTE_UNUSED,
|
||||
unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED,
|
||||
unsigned depth)
|
||||
unsigned depth ATTRIBUTE_UNUSED)
|
||||
{
|
||||
gcov_summary summary;
|
||||
unsigned h_ix;
|
||||
gcov_bucket_type *histo_bucket;
|
||||
|
||||
gcov_read_summary (&summary);
|
||||
printf (" checksum=0x%08x", summary.checksum);
|
||||
|
||||
printf ("\n");
|
||||
print_prefix (filename, depth, 0);
|
||||
printf (VALUE_PADDING_PREFIX "counts=%u, runs=%u",
|
||||
summary.num, summary.runs);
|
||||
|
||||
printf (", sum_all=%" PRId64,
|
||||
(int64_t)summary.sum_all);
|
||||
printf (", run_max=%" PRId64,
|
||||
(int64_t)summary.run_max);
|
||||
printf (", sum_max=%" PRId64,
|
||||
(int64_t)summary.sum_max);
|
||||
printf ("\n");
|
||||
print_prefix (filename, depth, 0);
|
||||
printf (VALUE_PADDING_PREFIX "counter histogram:");
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
{
|
||||
histo_bucket = &summary.histogram[h_ix];
|
||||
if (!histo_bucket->num_counters)
|
||||
continue;
|
||||
printf ("\n");
|
||||
print_prefix (filename, depth, 0);
|
||||
printf (VALUE_PADDING_PREFIX VALUE_PREFIX "num counts=%u, "
|
||||
"min counter=%" PRId64 ", cum_counter=%" PRId64,
|
||||
h_ix, histo_bucket->num_counters,
|
||||
(int64_t)histo_bucket->min_value,
|
||||
(int64_t)histo_bucket->cum_value);
|
||||
}
|
||||
if (flag_dump_working_sets)
|
||||
dump_working_sets (filename, &summary, depth);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_working_sets (const char *filename ATTRIBUTE_UNUSED,
|
||||
const gcov_summary *summary,
|
||||
unsigned depth)
|
||||
{
|
||||
gcov_working_set_t gcov_working_sets[NUM_GCOV_WORKING_SETS];
|
||||
unsigned ws_ix, pctinc, pct;
|
||||
gcov_working_set_t *ws_info;
|
||||
|
||||
compute_working_sets (summary, gcov_working_sets);
|
||||
|
||||
printf ("\n");
|
||||
print_prefix (filename, depth, 0);
|
||||
printf (VALUE_PADDING_PREFIX "counter working sets:");
|
||||
/* Multiply the percentage by 100 to avoid float. */
|
||||
pctinc = 100 * 100 / NUM_GCOV_WORKING_SETS;
|
||||
for (ws_ix = 0, pct = pctinc; ws_ix < NUM_GCOV_WORKING_SETS;
|
||||
ws_ix++, pct += pctinc)
|
||||
{
|
||||
if (ws_ix == NUM_GCOV_WORKING_SETS - 1)
|
||||
pct = 9990;
|
||||
ws_info = &gcov_working_sets[ws_ix];
|
||||
/* Print out the percentage using int arithmatic to avoid float. */
|
||||
printf ("\n");
|
||||
print_prefix (filename, depth + 1, 0);
|
||||
printf (VALUE_PADDING_PREFIX "%u.%02u%%: num counts=%u, min counter="
|
||||
"%" PRId64,
|
||||
pct / 100, pct - (pct / 100 * 100),
|
||||
ws_info->num_counters,
|
||||
(int64_t)ws_info->min_counter);
|
||||
}
|
||||
printf (" runs=%d, sum_max=%" PRId64,
|
||||
summary.runs, summary.sum_max);
|
||||
}
|
||||
|
398
gcc/gcov-io.c
398
gcc/gcov-io.c
@ -446,39 +446,11 @@ gcov_write_tag_length (gcov_unsigned_t tag, gcov_unsigned_t length)
|
||||
GCOV_LINKAGE void
|
||||
gcov_write_summary (gcov_unsigned_t tag, const struct gcov_summary *summary)
|
||||
{
|
||||
unsigned h_ix, bv_ix, h_cnt = 0;
|
||||
unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE];
|
||||
|
||||
/* Count number of non-zero histogram entries, and fill in a bit vector
|
||||
of non-zero indices. The histogram is only currently computed for arc
|
||||
counters. */
|
||||
for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
|
||||
histo_bitvector[bv_ix] = 0;
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
if (summary->histogram[h_ix].num_counters)
|
||||
{
|
||||
histo_bitvector[h_ix / 32] |= 1 << (h_ix % 32);
|
||||
h_cnt++;
|
||||
}
|
||||
gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH (h_cnt));
|
||||
gcov_write_unsigned (summary->checksum);
|
||||
|
||||
gcov_write_unsigned (summary->num);
|
||||
gcov_write_tag_length (tag, GCOV_TAG_SUMMARY_LENGTH);
|
||||
gcov_write_unsigned (summary->runs);
|
||||
gcov_write_counter (summary->sum_all);
|
||||
gcov_write_counter (summary->run_max);
|
||||
gcov_write_counter (summary->sum_max);
|
||||
for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
|
||||
gcov_write_unsigned (histo_bitvector[bv_ix]);
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
{
|
||||
if (!summary->histogram[h_ix].num_counters)
|
||||
continue;
|
||||
gcov_write_unsigned (summary->histogram[h_ix].num_counters);
|
||||
gcov_write_counter (summary->histogram[h_ix].min_value);
|
||||
gcov_write_counter (summary->histogram[h_ix].cum_value);
|
||||
}
|
||||
gcov_write_unsigned (summary->sum_max);
|
||||
}
|
||||
|
||||
#endif /* IN_LIBGCOV */
|
||||
|
||||
#endif /*!IN_GCOV */
|
||||
@ -637,65 +609,8 @@ gcov_read_string (void)
|
||||
GCOV_LINKAGE void
|
||||
gcov_read_summary (struct gcov_summary *summary)
|
||||
{
|
||||
unsigned h_ix, bv_ix, h_cnt = 0;
|
||||
unsigned histo_bitvector[GCOV_HISTOGRAM_BITVECTOR_SIZE];
|
||||
unsigned cur_bitvector;
|
||||
|
||||
summary->checksum = gcov_read_unsigned ();
|
||||
summary->num = gcov_read_unsigned ();
|
||||
summary->runs = gcov_read_unsigned ();
|
||||
summary->sum_all = gcov_read_counter ();
|
||||
summary->run_max = gcov_read_counter ();
|
||||
summary->sum_max = gcov_read_counter ();
|
||||
memset (summary->histogram, 0,
|
||||
sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
|
||||
for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
|
||||
{
|
||||
histo_bitvector[bv_ix] = gcov_read_unsigned ();
|
||||
#if IN_LIBGCOV
|
||||
/* When building libgcov we don't include system.h, which includes
|
||||
hwint.h (where popcount_hwi is declared). However, libgcov.a
|
||||
is built by the bootstrapped compiler and therefore the builtins
|
||||
are always available. */
|
||||
h_cnt += __builtin_popcount (histo_bitvector[bv_ix]);
|
||||
#else
|
||||
h_cnt += popcount_hwi (histo_bitvector[bv_ix]);
|
||||
#endif
|
||||
}
|
||||
bv_ix = 0;
|
||||
h_ix = 0;
|
||||
cur_bitvector = 0;
|
||||
while (h_cnt--)
|
||||
{
|
||||
/* Find the index corresponding to the next entry we will read in.
|
||||
First find the next non-zero bitvector and re-initialize
|
||||
the histogram index accordingly, then right shift and increment
|
||||
the index until we find a set bit. */
|
||||
while (!cur_bitvector)
|
||||
{
|
||||
h_ix = bv_ix * 32;
|
||||
if (bv_ix >= GCOV_HISTOGRAM_BITVECTOR_SIZE)
|
||||
gcov_error ("corrupted profile info: summary histogram "
|
||||
"bitvector is corrupt");
|
||||
cur_bitvector = histo_bitvector[bv_ix++];
|
||||
}
|
||||
while (!(cur_bitvector & 0x1))
|
||||
{
|
||||
h_ix++;
|
||||
cur_bitvector >>= 1;
|
||||
}
|
||||
if (h_ix >= GCOV_HISTOGRAM_SIZE)
|
||||
gcov_error ("corrupted profile info: summary histogram "
|
||||
"index is corrupt");
|
||||
|
||||
summary->histogram[h_ix].num_counters = gcov_read_unsigned ();
|
||||
summary->histogram[h_ix].min_value = gcov_read_counter ();
|
||||
summary->histogram[h_ix].cum_value = gcov_read_counter ();
|
||||
/* Shift off the index we are done with and increment to the
|
||||
corresponding next histogram entry. */
|
||||
cur_bitvector >>= 1;
|
||||
h_ix++;
|
||||
}
|
||||
summary->sum_max = gcov_read_unsigned ();
|
||||
}
|
||||
|
||||
/* We need to expose the below function when compiling for gcov-tool. */
|
||||
@ -747,308 +662,3 @@ gcov_time (void)
|
||||
return status.st_mtime;
|
||||
}
|
||||
#endif /* IN_GCOV */
|
||||
|
||||
#if !IN_GCOV
|
||||
/* Determine the index into histogram for VALUE. */
|
||||
|
||||
#if IN_LIBGCOV
|
||||
static unsigned
|
||||
#else
|
||||
GCOV_LINKAGE unsigned
|
||||
#endif
|
||||
gcov_histo_index (gcov_type value)
|
||||
{
|
||||
gcov_type_unsigned v = (gcov_type_unsigned)value;
|
||||
unsigned r = 0;
|
||||
unsigned prev2bits = 0;
|
||||
|
||||
/* Find index into log2 scale histogram, where each of the log2
|
||||
sized buckets is divided into 4 linear sub-buckets for better
|
||||
focus in the higher buckets. */
|
||||
|
||||
/* Find the place of the most-significant bit set. */
|
||||
if (v > 0)
|
||||
{
|
||||
#if IN_LIBGCOV
|
||||
/* When building libgcov we don't include system.h, which includes
|
||||
hwint.h (where floor_log2 is declared). However, libgcov.a
|
||||
is built by the bootstrapped compiler and therefore the builtins
|
||||
are always available. */
|
||||
r = sizeof (long long) * __CHAR_BIT__ - 1 - __builtin_clzll (v);
|
||||
#else
|
||||
/* We use floor_log2 from hwint.c, which takes a HOST_WIDE_INT
|
||||
that is 64 bits and gcov_type_unsigned is 64 bits. */
|
||||
r = floor_log2 (v);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If at most the 2 least significant bits are set (value is
|
||||
0 - 3) then that value is our index into the lowest set of
|
||||
four buckets. */
|
||||
if (r < 2)
|
||||
return (unsigned)value;
|
||||
|
||||
gcov_nonruntime_assert (r < 64);
|
||||
|
||||
/* Find the two next most significant bits to determine which
|
||||
of the four linear sub-buckets to select. */
|
||||
prev2bits = (v >> (r - 2)) & 0x3;
|
||||
/* Finally, compose the final bucket index from the log2 index and
|
||||
the next 2 bits. The minimum r value at this point is 2 since we
|
||||
returned above if r was 2 or more, so the minimum bucket at this
|
||||
point is 4. */
|
||||
return (r - 1) * 4 + prev2bits;
|
||||
}
|
||||
|
||||
/* Merge SRC_HISTO into TGT_HISTO. The counters are assumed to be in
|
||||
the same relative order in both histograms, and are matched up
|
||||
and merged in reverse order. Each counter is assigned an equal portion of
|
||||
its entry's original cumulative counter value when computing the
|
||||
new merged cum_value. */
|
||||
|
||||
static void gcov_histogram_merge (gcov_bucket_type *tgt_histo,
|
||||
gcov_bucket_type *src_histo)
|
||||
{
|
||||
int src_i, tgt_i, tmp_i = 0;
|
||||
unsigned src_num, tgt_num, merge_num;
|
||||
gcov_type src_cum, tgt_cum, merge_src_cum, merge_tgt_cum, merge_cum;
|
||||
gcov_type merge_min;
|
||||
gcov_bucket_type tmp_histo[GCOV_HISTOGRAM_SIZE];
|
||||
int src_done = 0;
|
||||
|
||||
memset (tmp_histo, 0, sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
|
||||
|
||||
/* Assume that the counters are in the same relative order in both
|
||||
histograms. Walk the histograms from largest to smallest entry,
|
||||
matching up and combining counters in order. */
|
||||
src_num = 0;
|
||||
src_cum = 0;
|
||||
src_i = GCOV_HISTOGRAM_SIZE - 1;
|
||||
for (tgt_i = GCOV_HISTOGRAM_SIZE - 1; tgt_i >= 0 && !src_done; tgt_i--)
|
||||
{
|
||||
tgt_num = tgt_histo[tgt_i].num_counters;
|
||||
tgt_cum = tgt_histo[tgt_i].cum_value;
|
||||
/* Keep going until all of the target histogram's counters at this
|
||||
position have been matched and merged with counters from the
|
||||
source histogram. */
|
||||
while (tgt_num > 0 && !src_done)
|
||||
{
|
||||
/* If this is either the first time through this loop or we just
|
||||
exhausted the previous non-zero source histogram entry, look
|
||||
for the next non-zero source histogram entry. */
|
||||
if (!src_num)
|
||||
{
|
||||
/* Locate the next non-zero entry. */
|
||||
while (src_i >= 0 && !src_histo[src_i].num_counters)
|
||||
src_i--;
|
||||
/* If source histogram has fewer counters, then just copy over the
|
||||
remaining target counters and quit. */
|
||||
if (src_i < 0)
|
||||
{
|
||||
tmp_histo[tgt_i].num_counters += tgt_num;
|
||||
tmp_histo[tgt_i].cum_value += tgt_cum;
|
||||
if (!tmp_histo[tgt_i].min_value ||
|
||||
tgt_histo[tgt_i].min_value < tmp_histo[tgt_i].min_value)
|
||||
tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value;
|
||||
while (--tgt_i >= 0)
|
||||
{
|
||||
tmp_histo[tgt_i].num_counters
|
||||
+= tgt_histo[tgt_i].num_counters;
|
||||
tmp_histo[tgt_i].cum_value += tgt_histo[tgt_i].cum_value;
|
||||
if (!tmp_histo[tgt_i].min_value ||
|
||||
tgt_histo[tgt_i].min_value
|
||||
< tmp_histo[tgt_i].min_value)
|
||||
tmp_histo[tgt_i].min_value = tgt_histo[tgt_i].min_value;
|
||||
}
|
||||
|
||||
src_done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
src_num = src_histo[src_i].num_counters;
|
||||
src_cum = src_histo[src_i].cum_value;
|
||||
}
|
||||
|
||||
/* The number of counters to merge on this pass is the minimum
|
||||
of the remaining counters from the current target and source
|
||||
histogram entries. */
|
||||
merge_num = tgt_num;
|
||||
if (src_num < merge_num)
|
||||
merge_num = src_num;
|
||||
|
||||
/* The merged min_value is the sum of the min_values from target
|
||||
and source. */
|
||||
merge_min = tgt_histo[tgt_i].min_value + src_histo[src_i].min_value;
|
||||
|
||||
/* Compute the portion of source and target entries' cum_value
|
||||
that will be apportioned to the counters being merged.
|
||||
The total remaining cum_value from each entry is divided
|
||||
equally among the counters from that histogram entry if we
|
||||
are not merging all of them. */
|
||||
merge_src_cum = src_cum;
|
||||
if (merge_num < src_num)
|
||||
merge_src_cum = merge_num * src_cum / src_num;
|
||||
merge_tgt_cum = tgt_cum;
|
||||
if (merge_num < tgt_num)
|
||||
merge_tgt_cum = merge_num * tgt_cum / tgt_num;
|
||||
/* The merged cum_value is the sum of the source and target
|
||||
components. */
|
||||
merge_cum = merge_src_cum + merge_tgt_cum;
|
||||
|
||||
/* Update the remaining number of counters and cum_value left
|
||||
to be merged from this source and target entry. */
|
||||
src_cum -= merge_src_cum;
|
||||
tgt_cum -= merge_tgt_cum;
|
||||
src_num -= merge_num;
|
||||
tgt_num -= merge_num;
|
||||
|
||||
/* The merged counters get placed in the new merged histogram
|
||||
at the entry for the merged min_value. */
|
||||
tmp_i = gcov_histo_index (merge_min);
|
||||
gcov_nonruntime_assert (tmp_i < GCOV_HISTOGRAM_SIZE);
|
||||
tmp_histo[tmp_i].num_counters += merge_num;
|
||||
tmp_histo[tmp_i].cum_value += merge_cum;
|
||||
if (!tmp_histo[tmp_i].min_value ||
|
||||
merge_min < tmp_histo[tmp_i].min_value)
|
||||
tmp_histo[tmp_i].min_value = merge_min;
|
||||
|
||||
/* Ensure the search for the next non-zero src_histo entry starts
|
||||
at the next smallest histogram bucket. */
|
||||
if (!src_num)
|
||||
src_i--;
|
||||
}
|
||||
}
|
||||
|
||||
gcov_nonruntime_assert (tgt_i < 0);
|
||||
|
||||
/* In the case where there were more counters in the source histogram,
|
||||
accumulate the remaining unmerged cumulative counter values. Add
|
||||
those to the smallest non-zero target histogram entry. Otherwise,
|
||||
the total cumulative counter values in the histogram will be smaller
|
||||
than the sum_all stored in the summary, which will complicate
|
||||
computing the working set information from the histogram later on. */
|
||||
if (src_num)
|
||||
src_i--;
|
||||
while (src_i >= 0)
|
||||
{
|
||||
src_cum += src_histo[src_i].cum_value;
|
||||
src_i--;
|
||||
}
|
||||
/* At this point, tmp_i should be the smallest non-zero entry in the
|
||||
tmp_histo. */
|
||||
gcov_nonruntime_assert (tmp_i >= 0 && tmp_i < GCOV_HISTOGRAM_SIZE
|
||||
&& tmp_histo[tmp_i].num_counters > 0);
|
||||
tmp_histo[tmp_i].cum_value += src_cum;
|
||||
|
||||
/* Finally, copy the merged histogram into tgt_histo. */
|
||||
memcpy (tgt_histo, tmp_histo,
|
||||
sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
|
||||
}
|
||||
#endif /* !IN_GCOV */
|
||||
|
||||
/* This is used by gcov-dump (IN_GCOV == -1) and in the compiler
|
||||
(!IN_GCOV && !IN_LIBGCOV). */
|
||||
#if IN_GCOV <= 0 && !IN_LIBGCOV
|
||||
/* Compute the working set information from the counter histogram in
|
||||
the profile summary. This is an array of information corresponding to a
|
||||
range of percentages of the total execution count (sum_all), and includes
|
||||
the number of counters required to cover that working set percentage and
|
||||
the minimum counter value in that working set. */
|
||||
|
||||
GCOV_LINKAGE void
|
||||
compute_working_sets (const gcov_summary *summary,
|
||||
gcov_working_set_t *gcov_working_sets)
|
||||
{
|
||||
gcov_type working_set_cum_values[NUM_GCOV_WORKING_SETS];
|
||||
gcov_type ws_cum_hotness_incr;
|
||||
gcov_type cum, tmp_cum;
|
||||
const gcov_bucket_type *histo_bucket;
|
||||
unsigned ws_ix, c_num, count;
|
||||
int h_ix;
|
||||
|
||||
/* Compute the amount of sum_all that the cumulative hotness grows
|
||||
by in each successive working set entry, which depends on the
|
||||
number of working set entries. */
|
||||
ws_cum_hotness_incr = summary->sum_all / NUM_GCOV_WORKING_SETS;
|
||||
|
||||
/* Next fill in an array of the cumulative hotness values corresponding
|
||||
to each working set summary entry we are going to compute below.
|
||||
Skip 0% statistics, which can be extrapolated from the
|
||||
rest of the summary data. */
|
||||
cum = ws_cum_hotness_incr;
|
||||
for (ws_ix = 0; ws_ix < NUM_GCOV_WORKING_SETS;
|
||||
ws_ix++, cum += ws_cum_hotness_incr)
|
||||
working_set_cum_values[ws_ix] = cum;
|
||||
/* The last summary entry is reserved for (roughly) 99.9% of the
|
||||
working set. Divide by 1024 so it becomes a shift, which gives
|
||||
almost exactly 99.9%. */
|
||||
working_set_cum_values[NUM_GCOV_WORKING_SETS-1]
|
||||
= summary->sum_all - summary->sum_all/1024;
|
||||
|
||||
/* Next, walk through the histogram in decending order of hotness
|
||||
and compute the statistics for the working set summary array.
|
||||
As histogram entries are accumulated, we check to see which
|
||||
working set entries have had their expected cum_value reached
|
||||
and fill them in, walking the working set entries in increasing
|
||||
size of cum_value. */
|
||||
ws_ix = 0; /* The current entry into the working set array. */
|
||||
cum = 0; /* The current accumulated counter sum. */
|
||||
count = 0; /* The current accumulated count of block counters. */
|
||||
for (h_ix = GCOV_HISTOGRAM_SIZE - 1;
|
||||
h_ix >= 0 && ws_ix < NUM_GCOV_WORKING_SETS; h_ix--)
|
||||
{
|
||||
histo_bucket = &summary->histogram[h_ix];
|
||||
|
||||
/* If we haven't reached the required cumulative counter value for
|
||||
the current working set percentage, simply accumulate this histogram
|
||||
entry into the running sums and continue to the next histogram
|
||||
entry. */
|
||||
if (cum + histo_bucket->cum_value < working_set_cum_values[ws_ix])
|
||||
{
|
||||
cum += histo_bucket->cum_value;
|
||||
count += histo_bucket->num_counters;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If adding the current histogram entry's cumulative counter value
|
||||
causes us to exceed the current working set size, then estimate
|
||||
how many of this histogram entry's counter values are required to
|
||||
reach the working set size, and fill in working set entries
|
||||
as we reach their expected cumulative value. */
|
||||
for (c_num = 0, tmp_cum = cum;
|
||||
c_num < histo_bucket->num_counters && ws_ix < NUM_GCOV_WORKING_SETS;
|
||||
c_num++)
|
||||
{
|
||||
count++;
|
||||
/* If we haven't reached the last histogram entry counter, add
|
||||
in the minimum value again. This will underestimate the
|
||||
cumulative sum so far, because many of the counter values in this
|
||||
entry may have been larger than the minimum. We could add in the
|
||||
average value every time, but that would require an expensive
|
||||
divide operation. */
|
||||
if (c_num + 1 < histo_bucket->num_counters)
|
||||
tmp_cum += histo_bucket->min_value;
|
||||
/* If we have reached the last histogram entry counter, then add
|
||||
in the entire cumulative value. */
|
||||
else
|
||||
tmp_cum = cum + histo_bucket->cum_value;
|
||||
|
||||
/* Next walk through successive working set entries and fill in
|
||||
the statistics for any whose size we have reached by accumulating
|
||||
this histogram counter. */
|
||||
while (ws_ix < NUM_GCOV_WORKING_SETS
|
||||
&& tmp_cum >= working_set_cum_values[ws_ix])
|
||||
{
|
||||
gcov_working_sets[ws_ix].num_counters = count;
|
||||
gcov_working_sets[ws_ix].min_counter
|
||||
= histo_bucket->min_value;
|
||||
ws_ix++;
|
||||
}
|
||||
}
|
||||
/* Finally, update the running cumulative value since we were
|
||||
using a temporary above. */
|
||||
cum += histo_bucket->cum_value;
|
||||
}
|
||||
gcov_nonruntime_assert (ws_ix == NUM_GCOV_WORKING_SETS);
|
||||
}
|
||||
#endif /* IN_GCOV <= 0 && !IN_LIBGCOV */
|
||||
|
@ -133,17 +133,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
blocks they are for.
|
||||
|
||||
The data file contains the following records.
|
||||
data: {unit summary:object summary:program* function-data*}*
|
||||
data: {unit summary:object function-data*}*
|
||||
unit: header int32:checksum
|
||||
function-data: announce_function present counts
|
||||
function-data: announce_function present counts
|
||||
announce_function: header int32:ident
|
||||
int32:lineno_checksum int32:cfg_checksum
|
||||
present: header int32:present
|
||||
counts: header int64:count*
|
||||
summary: int32:checksum int32:num int32:runs int64:sum
|
||||
int64:max int64:sum_max histogram
|
||||
histogram: {int32:bitvector}8 histogram-buckets*
|
||||
histogram-buckets: int32:num int64:min int64:sum
|
||||
summary: int32:checksum int32:runs int32:sum_max
|
||||
|
||||
The ANNOUNCE_FUNCTION record is the same as that in the note file,
|
||||
but without the source location. The COUNTS gives the
|
||||
@ -190,7 +187,7 @@ typedef uint64_t gcov_type_unsigned;
|
||||
|
||||
#define ATTRIBUTE_HIDDEN
|
||||
|
||||
#endif /* !IN_LIBGOCV */
|
||||
#endif /* !IN_LIBGCOV */
|
||||
|
||||
#ifndef GCOV_LINKAGE
|
||||
#define GCOV_LINKAGE extern
|
||||
@ -240,9 +237,9 @@ typedef uint64_t gcov_type_unsigned;
|
||||
#define GCOV_TAG_COUNTER_BASE ((gcov_unsigned_t)0x01a10000)
|
||||
#define GCOV_TAG_COUNTER_LENGTH(NUM) ((NUM) * 2)
|
||||
#define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2)
|
||||
#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */
|
||||
#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000)
|
||||
#define GCOV_TAG_SUMMARY_LENGTH(NUM) (1 + (10 + 3 * 2) + (NUM) * 5)
|
||||
#define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000)
|
||||
#define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) /* Obsolete */
|
||||
#define GCOV_TAG_SUMMARY_LENGTH (2)
|
||||
#define GCOV_TAG_AFDO_FILE_NAMES ((gcov_unsigned_t)0xaa000000)
|
||||
#define GCOV_TAG_AFDO_FUNCTION ((gcov_unsigned_t)0xac000000)
|
||||
#define GCOV_TAG_AFDO_WORKING_SET ((gcov_unsigned_t)0xaf000000)
|
||||
@ -307,43 +304,12 @@ GCOV_COUNTERS
|
||||
#define GCOV_ARC_FAKE (1 << 1)
|
||||
#define GCOV_ARC_FALLTHROUGH (1 << 2)
|
||||
|
||||
/* Structured records. */
|
||||
|
||||
/* Structure used for each bucket of the log2 histogram of counter values. */
|
||||
typedef struct
|
||||
{
|
||||
/* Number of counters whose profile count falls within the bucket. */
|
||||
gcov_unsigned_t num_counters;
|
||||
/* Smallest profile count included in this bucket. */
|
||||
gcov_type min_value;
|
||||
/* Cumulative value of the profile counts in this bucket. */
|
||||
gcov_type cum_value;
|
||||
} gcov_bucket_type;
|
||||
|
||||
/* For a log2 scale histogram with each range split into 4
|
||||
linear sub-ranges, there will be at most 64 (max gcov_type bit size) - 1 log2
|
||||
ranges since the lowest 2 log2 values share the lowest 4 linear
|
||||
sub-range (values 0 - 3). This is 252 total entries (63*4). */
|
||||
|
||||
#define GCOV_HISTOGRAM_SIZE 252
|
||||
|
||||
/* How many unsigned ints are required to hold a bit vector of non-zero
|
||||
histogram entries when the histogram is written to the gcov file.
|
||||
This is essentially a ceiling divide by 32 bits. */
|
||||
#define GCOV_HISTOGRAM_BITVECTOR_SIZE (GCOV_HISTOGRAM_SIZE + 31) / 32
|
||||
|
||||
/* Object & program summary record. */
|
||||
|
||||
struct gcov_summary
|
||||
{
|
||||
gcov_unsigned_t checksum; /* Checksum of program. */
|
||||
gcov_unsigned_t num; /* Number of counters. */
|
||||
gcov_unsigned_t runs; /* Number of program runs. */
|
||||
gcov_type sum_all; /* Sum of all counters accumulated. */
|
||||
gcov_type run_max; /* Maximum value on a single run. */
|
||||
gcov_type sum_max; /* Sum of individual run max values. */
|
||||
gcov_bucket_type histogram[GCOV_HISTOGRAM_SIZE]; /* Histogram of
|
||||
counter values. */
|
||||
};
|
||||
|
||||
#if !defined(inhibit_libc)
|
||||
@ -380,35 +346,12 @@ GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN;
|
||||
|
||||
#if !IN_GCOV && !IN_LIBGCOV
|
||||
/* Available only in compiler */
|
||||
GCOV_LINKAGE unsigned gcov_histo_index (gcov_type value);
|
||||
GCOV_LINKAGE void gcov_write_string (const char *);
|
||||
GCOV_LINKAGE void gcov_write_filename (const char *);
|
||||
GCOV_LINKAGE gcov_position_t gcov_write_tag (gcov_unsigned_t);
|
||||
GCOV_LINKAGE void gcov_write_length (gcov_position_t /*position*/);
|
||||
#endif
|
||||
|
||||
#if IN_GCOV <= 0 && !IN_LIBGCOV
|
||||
/* Available in gcov-dump and the compiler. */
|
||||
|
||||
/* Number of data points in the working set summary array. Using 128
|
||||
provides information for at least every 1% increment of the total
|
||||
profile size. The last entry is hardwired to 99.9% of the total. */
|
||||
#define NUM_GCOV_WORKING_SETS 128
|
||||
|
||||
/* Working set size statistics for a given percentage of the entire
|
||||
profile (sum_all from the counter summary). */
|
||||
typedef struct gcov_working_set_info
|
||||
{
|
||||
/* Number of hot counters included in this working set. */
|
||||
unsigned num_counters;
|
||||
/* Smallest counter included in this working set. */
|
||||
gcov_type min_counter;
|
||||
} gcov_working_set_t;
|
||||
|
||||
GCOV_LINKAGE void compute_working_sets (const gcov_summary *summary,
|
||||
gcov_working_set_t *gcov_working_sets);
|
||||
#endif
|
||||
|
||||
#if IN_GCOV > 0
|
||||
/* Available in gcov */
|
||||
GCOV_LINKAGE time_t gcov_time (void);
|
||||
|
@ -423,7 +423,6 @@ print_overlap_usage_message (int error_p)
|
||||
fnotice (file, " -o, --object Print object level info\n");
|
||||
fnotice (file, " -t <float>, --hot_threshold <float> Set the threshold for hotness\n");
|
||||
fnotice (file, " -v, --verbose Verbose mode\n");
|
||||
|
||||
}
|
||||
|
||||
static const struct option overlap_options[] =
|
||||
|
@ -418,7 +418,6 @@ static vector<char *> processed_files;
|
||||
/* This holds data summary information. */
|
||||
|
||||
static unsigned object_runs;
|
||||
static unsigned program_count;
|
||||
|
||||
static unsigned total_lines;
|
||||
static unsigned total_executed;
|
||||
@ -1829,12 +1828,11 @@ read_count_file (void)
|
||||
unsigned length = gcov_read_unsigned ();
|
||||
unsigned long base = gcov_position ();
|
||||
|
||||
if (tag == GCOV_TAG_PROGRAM_SUMMARY)
|
||||
if (tag == GCOV_TAG_OBJECT_SUMMARY)
|
||||
{
|
||||
struct gcov_summary summary;
|
||||
gcov_read_summary (&summary);
|
||||
object_runs += summary.runs;
|
||||
program_count++;
|
||||
object_runs = summary.runs;
|
||||
}
|
||||
else if (tag == GCOV_TAG_FUNCTION && !length)
|
||||
; /* placeholder */
|
||||
@ -2952,7 +2950,6 @@ output_lines (FILE *gcov_file, const source_info *src)
|
||||
no_data_file ? "-" : da_file_name);
|
||||
fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs);
|
||||
}
|
||||
fprintf (gcov_file, DEFAULT_LINE_START "Programs:%u\n", program_count);
|
||||
|
||||
source_file = fopen (src->name, "r");
|
||||
if (!source_file)
|
||||
|
@ -25,13 +25,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
from profile feedback. This histogram is complete only with LTO,
|
||||
otherwise it contains information only about the current unit.
|
||||
|
||||
Similar histogram is also estimated by coverage runtime. This histogram
|
||||
is not dependent on LTO, but it suffers from various defects; first
|
||||
gcov runtime is not weighting individual basic block by estimated execution
|
||||
time and second the merging of multiple runs makes assumption that the
|
||||
histogram distribution did not change. Consequentely histogram constructed
|
||||
here may be more precise.
|
||||
|
||||
The information is used to set hot/cold thresholds.
|
||||
- Next speculative indirect call resolution is performed: the local
|
||||
profile pass assigns profile-id to each function and provide us with a
|
||||
@ -512,25 +505,7 @@ ipa_profile (void)
|
||||
gcov_type threshold;
|
||||
|
||||
gcc_assert (overall_size);
|
||||
if (dump_file)
|
||||
{
|
||||
gcov_type min, cumulated_time = 0, cumulated_size = 0;
|
||||
|
||||
fprintf (dump_file, "Overall time: %" PRId64"\n",
|
||||
(int64_t)overall_time);
|
||||
min = get_hot_bb_threshold ();
|
||||
for (i = 0; i < (int)histogram.length () && histogram[i]->count >= min;
|
||||
i++)
|
||||
{
|
||||
cumulated_time += histogram[i]->count * histogram[i]->time;
|
||||
cumulated_size += histogram[i]->size;
|
||||
}
|
||||
fprintf (dump_file, "GCOV min count: %" PRId64
|
||||
" Time:%3.2f%% Size:%3.2f%%\n",
|
||||
(int64_t)min,
|
||||
cumulated_time * 100.0 / overall_time,
|
||||
cumulated_size * 100.0 / overall_size);
|
||||
}
|
||||
cutoff = (overall_time * PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE) + 500) / 1000;
|
||||
threshold = 0;
|
||||
for (i = 0; cumulated < cutoff; i++)
|
||||
@ -557,6 +532,7 @@ ipa_profile (void)
|
||||
cumulated_time * 100.0 / overall_time,
|
||||
cumulated_size * 100.0 / overall_size);
|
||||
}
|
||||
|
||||
if (threshold > get_hot_bb_threshold ()
|
||||
|| in_lto_p)
|
||||
{
|
||||
|
134
gcc/lto-cgraph.c
134
gcc/lto-cgraph.c
@ -693,39 +693,14 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref,
|
||||
static void
|
||||
output_profile_summary (struct lto_simple_output_block *ob)
|
||||
{
|
||||
unsigned h_ix;
|
||||
struct bitpack_d bp;
|
||||
|
||||
if (profile_info)
|
||||
{
|
||||
/* We do not output num and run_max, they are not used by
|
||||
GCC profile feedback and they are difficult to merge from multiple
|
||||
units. */
|
||||
gcc_assert (profile_info->runs);
|
||||
streamer_write_uhwi_stream (ob->main_stream, profile_info->runs);
|
||||
streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_max);
|
||||
unsigned runs = (profile_info->runs);
|
||||
streamer_write_uhwi_stream (ob->main_stream, runs);
|
||||
|
||||
/* sum_all is needed for computing the working set with the
|
||||
histogram. */
|
||||
streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_all);
|
||||
|
||||
/* Create and output a bitpack of non-zero histogram entries indices. */
|
||||
bp = bitpack_create (ob->main_stream);
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
bp_pack_value (&bp, profile_info->histogram[h_ix].num_counters > 0, 1);
|
||||
streamer_write_bitpack (&bp);
|
||||
/* Now stream out only those non-zero entries. */
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
{
|
||||
if (!profile_info->histogram[h_ix].num_counters)
|
||||
continue;
|
||||
streamer_write_gcov_count_stream (ob->main_stream,
|
||||
profile_info->histogram[h_ix].num_counters);
|
||||
streamer_write_gcov_count_stream (ob->main_stream,
|
||||
profile_info->histogram[h_ix].min_value);
|
||||
streamer_write_gcov_count_stream (ob->main_stream,
|
||||
profile_info->histogram[h_ix].cum_value);
|
||||
}
|
||||
/* IPA-profile computes hot bb threshold based on cumulated
|
||||
whole program profile. We need to stream it down to ltrans. */
|
||||
if (flag_wpa)
|
||||
@ -1591,46 +1566,16 @@ input_refs (struct lto_input_block *ib,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gcov_summary lto_gcov_summary;
|
||||
|
||||
/* Input profile_info from IB. */
|
||||
static void
|
||||
input_profile_summary (struct lto_input_block *ib,
|
||||
struct lto_file_decl_data *file_data)
|
||||
{
|
||||
unsigned h_ix;
|
||||
struct bitpack_d bp;
|
||||
unsigned int runs = streamer_read_uhwi (ib);
|
||||
if (runs)
|
||||
{
|
||||
file_data->profile_info.runs = runs;
|
||||
file_data->profile_info.sum_max = streamer_read_gcov_count (ib);
|
||||
file_data->profile_info.sum_all = streamer_read_gcov_count (ib);
|
||||
|
||||
memset (file_data->profile_info.histogram, 0,
|
||||
sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
|
||||
/* Input the bitpack of non-zero histogram indices. */
|
||||
bp = streamer_read_bitpack (ib);
|
||||
/* Read in and unpack the full bitpack, flagging non-zero
|
||||
histogram entries by setting the num_counters non-zero. */
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
{
|
||||
file_data->profile_info.histogram[h_ix].num_counters
|
||||
= bp_unpack_value (&bp, 1);
|
||||
}
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
{
|
||||
if (!file_data->profile_info.histogram[h_ix].num_counters)
|
||||
continue;
|
||||
|
||||
file_data->profile_info.histogram[h_ix].num_counters
|
||||
= streamer_read_gcov_count (ib);
|
||||
file_data->profile_info.histogram[h_ix].min_value
|
||||
= streamer_read_gcov_count (ib);
|
||||
file_data->profile_info.histogram[h_ix].cum_value
|
||||
= streamer_read_gcov_count (ib);
|
||||
}
|
||||
/* IPA-profile computes hot bb threshold based on cumulated
|
||||
whole program profile. We need to stream it down to ltrans. */
|
||||
if (flag_ltrans)
|
||||
@ -1645,13 +1590,10 @@ static void
|
||||
merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
|
||||
{
|
||||
struct lto_file_decl_data *file_data;
|
||||
unsigned int j, h_ix;
|
||||
unsigned int j;
|
||||
gcov_unsigned_t max_runs = 0;
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *edge;
|
||||
gcov_type saved_sum_all = 0;
|
||||
gcov_summary *saved_profile_info = 0;
|
||||
int saved_scale = 0;
|
||||
|
||||
/* Find unit with maximal number of runs. If we ever get serious about
|
||||
roundoff errors, we might also consider computing smallest common
|
||||
@ -1672,70 +1614,8 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
|
||||
return;
|
||||
}
|
||||
|
||||
profile_info = <o_gcov_summary;
|
||||
lto_gcov_summary.runs = max_runs;
|
||||
lto_gcov_summary.sum_max = 0;
|
||||
memset (lto_gcov_summary.histogram, 0,
|
||||
sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
|
||||
|
||||
/* Rescale all units to the maximal number of runs.
|
||||
sum_max can not be easily merged, as we have no idea what files come from
|
||||
the same run. We do not use the info anyway, so leave it 0. */
|
||||
for (j = 0; (file_data = file_data_vec[j]) != NULL; j++)
|
||||
if (file_data->profile_info.runs)
|
||||
{
|
||||
int scale = GCOV_COMPUTE_SCALE (max_runs,
|
||||
file_data->profile_info.runs);
|
||||
lto_gcov_summary.sum_max
|
||||
= MAX (lto_gcov_summary.sum_max,
|
||||
apply_scale (file_data->profile_info.sum_max, scale));
|
||||
lto_gcov_summary.sum_all
|
||||
= MAX (lto_gcov_summary.sum_all,
|
||||
apply_scale (file_data->profile_info.sum_all, scale));
|
||||
/* Save a pointer to the profile_info with the largest
|
||||
scaled sum_all and the scale for use in merging the
|
||||
histogram. */
|
||||
if (!saved_profile_info
|
||||
|| lto_gcov_summary.sum_all > saved_sum_all)
|
||||
{
|
||||
saved_profile_info = &file_data->profile_info;
|
||||
saved_sum_all = lto_gcov_summary.sum_all;
|
||||
saved_scale = scale;
|
||||
}
|
||||
}
|
||||
|
||||
gcc_assert (saved_profile_info);
|
||||
|
||||
/* Scale up the histogram from the profile that had the largest
|
||||
scaled sum_all above. */
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
{
|
||||
/* Scale up the min value as we did the corresponding sum_all
|
||||
above. Use that to find the new histogram index. */
|
||||
gcov_type scaled_min
|
||||
= apply_scale (saved_profile_info->histogram[h_ix].min_value,
|
||||
saved_scale);
|
||||
/* The new index may be shared with another scaled histogram entry,
|
||||
so we need to account for a non-zero histogram entry at new_ix. */
|
||||
unsigned new_ix = gcov_histo_index (scaled_min);
|
||||
lto_gcov_summary.histogram[new_ix].min_value
|
||||
= (lto_gcov_summary.histogram[new_ix].num_counters
|
||||
? MIN (lto_gcov_summary.histogram[new_ix].min_value, scaled_min)
|
||||
: scaled_min);
|
||||
/* Some of the scaled counter values would ostensibly need to be placed
|
||||
into different (larger) histogram buckets, but we keep things simple
|
||||
here and place the scaled cumulative counter value in the bucket
|
||||
corresponding to the scaled minimum counter value. */
|
||||
lto_gcov_summary.histogram[new_ix].cum_value
|
||||
+= apply_scale (saved_profile_info->histogram[h_ix].cum_value,
|
||||
saved_scale);
|
||||
lto_gcov_summary.histogram[new_ix].num_counters
|
||||
+= saved_profile_info->histogram[h_ix].num_counters;
|
||||
}
|
||||
|
||||
/* Watch roundoff errors. */
|
||||
if (lto_gcov_summary.sum_max < max_runs)
|
||||
lto_gcov_summary.sum_max = max_runs;
|
||||
profile_info = XCNEW (gcov_summary);
|
||||
profile_info->runs = max_runs;
|
||||
|
||||
/* If merging already happent at WPA time, we are done. */
|
||||
if (flag_ltrans)
|
||||
@ -1814,10 +1694,6 @@ input_symtab (void)
|
||||
|
||||
merge_profile_summaries (file_data_vec);
|
||||
|
||||
if (!flag_auto_profile)
|
||||
get_working_sets ();
|
||||
|
||||
|
||||
/* Clear out the aux field that was used to store enough state to
|
||||
tell which nodes should be overwritten. */
|
||||
FOR_EACH_FUNCTION (node)
|
||||
|
@ -1449,10 +1449,6 @@ sms_schedule (void)
|
||||
fprintf (dump_file, "%" PRId64 "max %" PRId64,
|
||||
(int64_t) trip_count, (int64_t) max_trip_count);
|
||||
fprintf (dump_file, "\n");
|
||||
fprintf (dump_file, "SMS profile-sum-max ");
|
||||
fprintf (dump_file, "%" PRId64,
|
||||
(int64_t) profile_info->sum_max);
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@ -1567,10 +1563,6 @@ sms_schedule (void)
|
||||
fprintf (dump_file, "%" PRId64,
|
||||
(int64_t) bb->count.to_gcov_type ());
|
||||
fprintf (dump_file, "\n");
|
||||
fprintf (dump_file, "SMS profile-sum-max ");
|
||||
fprintf (dump_file, "%" PRId64,
|
||||
(int64_t) profile_info->sum_max);
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
fprintf (dump_file, "SMS doloop\n");
|
||||
fprintf (dump_file, "SMS built-ddg %d\n", g->num_nodes);
|
||||
|
@ -393,10 +393,15 @@ DEFPARAM(PARAM_SMS_LOOP_AVERAGE_COUNT_THRESHOLD,
|
||||
"A threshold on the average loop count considered by the swing modulo scheduler.",
|
||||
0, 0, 0)
|
||||
|
||||
DEFPARAM(HOT_BB_COUNT_FRACTION,
|
||||
"hot-bb-count-fraction",
|
||||
"Select fraction of the maximal count of repetitions of basic block in program given basic "
|
||||
"block needs to have to be considered hot (used in non-LTO mode)",
|
||||
10000, 0, 0)
|
||||
DEFPARAM(HOT_BB_COUNT_WS_PERMILLE,
|
||||
"hot-bb-count-ws-permille",
|
||||
"A basic block profile count is considered hot if it contributes to "
|
||||
"the given permillage of the entire profiled execution.",
|
||||
"the given permillage of the entire profiled execution (used in LTO mode).",
|
||||
999, 0, 1000)
|
||||
DEFPARAM(HOT_BB_FREQUENCY_FRACTION,
|
||||
"hot-bb-frequency-fraction",
|
||||
|
@ -1161,7 +1161,7 @@ eliminate_partially_redundant_load (basic_block bb, rtx_insn *insn,
|
||||
|| (optimize_bb_for_size_p (bb) && npred_ok > 1)
|
||||
/* If we don't have profile information we cannot tell if splitting
|
||||
a critical edge is profitable or not so don't do it. */
|
||||
|| ((! profile_info || profile_status_for_fn (cfun) != PROFILE_READ
|
||||
|| ((!profile_info || profile_status_for_fn (cfun) != PROFILE_READ
|
||||
|| targetm.cannot_modify_jumps_p ())
|
||||
&& critical_edge_split))
|
||||
goto cleanup;
|
||||
|
@ -129,12 +129,13 @@ static gcov_type min_count = -1;
|
||||
gcov_type
|
||||
get_hot_bb_threshold ()
|
||||
{
|
||||
gcov_working_set_t *ws;
|
||||
if (min_count == -1)
|
||||
{
|
||||
ws = find_working_set (PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE));
|
||||
gcc_assert (ws);
|
||||
min_count = ws->min_counter;
|
||||
min_count
|
||||
= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION);
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Setting hotness threshold to %" PRId64 ".\n",
|
||||
min_count);
|
||||
}
|
||||
return min_count;
|
||||
}
|
||||
|
116
gcc/profile.c
116
gcc/profile.c
@ -84,11 +84,7 @@ struct bb_profile_info {
|
||||
|
||||
/* Counter summary from the last set of coverage counts read. */
|
||||
|
||||
const gcov_summary *profile_info;
|
||||
|
||||
/* Counter working set information computed from the current counter
|
||||
summary. Not initialized unless profile_info summary is non-NULL. */
|
||||
static gcov_working_set_t gcov_working_sets[NUM_GCOV_WORKING_SETS];
|
||||
gcov_summary *profile_info;
|
||||
|
||||
/* Collect statistics on the performance of this pass for the entire source
|
||||
file. */
|
||||
@ -103,14 +99,6 @@ static int total_num_times_called;
|
||||
static int total_hist_br_prob[20];
|
||||
static int total_num_branches;
|
||||
|
||||
/* Helper function to update gcov_working_sets. */
|
||||
|
||||
void add_working_set (gcov_working_set_t *set) {
|
||||
int i = 0;
|
||||
for (; i < NUM_GCOV_WORKING_SETS; i++)
|
||||
gcov_working_sets[i] = set[i];
|
||||
}
|
||||
|
||||
/* Forward declarations. */
|
||||
static void find_spanning_tree (struct edge_list *);
|
||||
|
||||
@ -207,60 +195,6 @@ instrument_values (histogram_values values)
|
||||
}
|
||||
|
||||
|
||||
/* Fill the working set information into the profile_info structure. */
|
||||
|
||||
void
|
||||
get_working_sets (void)
|
||||
{
|
||||
unsigned ws_ix, pctinc, pct;
|
||||
gcov_working_set_t *ws_info;
|
||||
|
||||
if (!profile_info)
|
||||
return;
|
||||
|
||||
compute_working_sets (profile_info, gcov_working_sets);
|
||||
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (dump_file, "Counter working sets:\n");
|
||||
/* Multiply the percentage by 100 to avoid float. */
|
||||
pctinc = 100 * 100 / NUM_GCOV_WORKING_SETS;
|
||||
for (ws_ix = 0, pct = pctinc; ws_ix < NUM_GCOV_WORKING_SETS;
|
||||
ws_ix++, pct += pctinc)
|
||||
{
|
||||
if (ws_ix == NUM_GCOV_WORKING_SETS - 1)
|
||||
pct = 9990;
|
||||
ws_info = &gcov_working_sets[ws_ix];
|
||||
/* Print out the percentage using int arithmatic to avoid float. */
|
||||
fprintf (dump_file, "\t\t%u.%02u%%: num counts=%u, min counter="
|
||||
"%" PRId64 "\n",
|
||||
pct / 100, pct - (pct / 100 * 100),
|
||||
ws_info->num_counters,
|
||||
(int64_t)ws_info->min_counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a the desired percentage of the full profile (sum_all from the
|
||||
summary), multiplied by 10 to avoid float in PCT_TIMES_10, returns
|
||||
the corresponding working set information. If an exact match for
|
||||
the percentage isn't found, the closest value is used. */
|
||||
|
||||
gcov_working_set_t *
|
||||
find_working_set (unsigned pct_times_10)
|
||||
{
|
||||
unsigned i;
|
||||
if (!profile_info)
|
||||
return NULL;
|
||||
gcc_assert (pct_times_10 <= 1000);
|
||||
if (pct_times_10 >= 999)
|
||||
return &gcov_working_sets[NUM_GCOV_WORKING_SETS - 1];
|
||||
i = pct_times_10 * NUM_GCOV_WORKING_SETS / 1000;
|
||||
if (!i)
|
||||
return &gcov_working_sets[0];
|
||||
return &gcov_working_sets[i - 1];
|
||||
}
|
||||
|
||||
/* Computes hybrid profile for all matching entries in da_file.
|
||||
|
||||
CFG_CHECKSUM is the precomputed checksum for the CFG. */
|
||||
@ -283,21 +217,14 @@ get_exec_counts (unsigned cfg_checksum, unsigned lineno_checksum)
|
||||
num_edges++;
|
||||
}
|
||||
|
||||
counts = get_coverage_counts (GCOV_COUNTER_ARCS, num_edges, cfg_checksum,
|
||||
lineno_checksum, &profile_info);
|
||||
counts = get_coverage_counts (GCOV_COUNTER_ARCS, cfg_checksum,
|
||||
lineno_checksum);
|
||||
if (!counts)
|
||||
return NULL;
|
||||
|
||||
get_working_sets ();
|
||||
|
||||
if (dump_file && profile_info)
|
||||
fprintf (dump_file, "Merged %u profiles with maximal count %u.\n",
|
||||
profile_info->runs, (unsigned) profile_info->sum_max);
|
||||
|
||||
return counts;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
is_edge_inconsistent (vec<edge, va_gc> *edges)
|
||||
{
|
||||
@ -439,29 +366,7 @@ read_profile_edge_counts (gcov_type *exec_counts)
|
||||
{
|
||||
num_edges++;
|
||||
if (exec_counts)
|
||||
{
|
||||
edge_gcov_count (e) = exec_counts[exec_counts_pos++];
|
||||
if (edge_gcov_count (e) > profile_info->sum_max)
|
||||
{
|
||||
if (flag_profile_correction)
|
||||
{
|
||||
static bool informed = 0;
|
||||
if (dump_enabled_p () && !informed)
|
||||
{
|
||||
dump_location_t loc
|
||||
= dump_location_t::from_location_t
|
||||
(input_location);
|
||||
dump_printf_loc (MSG_NOTE, loc,
|
||||
"corrupted profile info: edge count"
|
||||
" exceeds maximal count\n");
|
||||
}
|
||||
informed = 1;
|
||||
}
|
||||
else
|
||||
error ("corrupted profile info: edge from %i to %i exceeds maximal count",
|
||||
bb->index, e->dest->index);
|
||||
}
|
||||
}
|
||||
edge_gcov_count (e) = exec_counts[exec_counts_pos++];
|
||||
else
|
||||
edge_gcov_count (e) = 0;
|
||||
|
||||
@ -511,12 +416,6 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
|
||||
bb_gcov_counts.safe_grow_cleared (last_basic_block_for_fn (cfun));
|
||||
edge_gcov_counts = new hash_map<edge,gcov_type>;
|
||||
|
||||
if (profile_info->sum_all < profile_info->sum_max)
|
||||
{
|
||||
error ("corrupted profile info: sum_all is smaller than sum_max");
|
||||
exec_counts = NULL;
|
||||
}
|
||||
|
||||
/* Attach extra info block to each bb. */
|
||||
alloc_aux_for_blocks (sizeof (struct bb_profile_info));
|
||||
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
|
||||
@ -871,10 +770,9 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
|
||||
continue;
|
||||
}
|
||||
|
||||
histogram_counts[t] =
|
||||
get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
|
||||
n_histogram_counters[t], cfg_checksum,
|
||||
lineno_checksum, NULL);
|
||||
histogram_counts[t] = get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
|
||||
cfg_checksum,
|
||||
lineno_checksum);
|
||||
if (histogram_counts[t])
|
||||
any = 1;
|
||||
act_count[t] = histogram_counts[t];
|
||||
|
@ -75,6 +75,6 @@ extern void get_working_sets (void);
|
||||
|
||||
/* Counter summary from the last set of coverage counts read by
|
||||
profile.c. */
|
||||
extern const struct gcov_summary *profile_info;
|
||||
extern struct gcov_summary *profile_info;
|
||||
|
||||
#endif /* PROFILE_H */
|
||||
|
@ -1,3 +1,20 @@
|
||||
2018-09-21 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* libgcov-driver.c (crc32_unsigned): Remove.
|
||||
(gcov_histogram_insert): Likewise.
|
||||
(gcov_compute_histogram): Likewise.
|
||||
(compute_summary): Simplify rapidly.
|
||||
(merge_one_data): Do not handle PROGRAM_SUMMARY tag.
|
||||
(merge_summary): Rapidly simplify.
|
||||
(dump_one_gcov): Ignore gcov_summary.
|
||||
(gcov_do_dump): Do not handle program summary, it's not
|
||||
used.
|
||||
* libgcov-util.c (tag_summary): Remove.
|
||||
(read_gcda_finalize): Fix coding style.
|
||||
(read_gcda_file): Initialize curr_object_summary.
|
||||
(compute_summary): Remove.
|
||||
(calculate_overlap): Remove settings of run_max.
|
||||
|
||||
2018-09-21 Monk Chiang <sh.chiang04@gmail.com>
|
||||
|
||||
* config/nds32/linux-unwind.h (struct _rt_sigframe): Use struct
|
||||
|
@ -24,6 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "libgcov.h"
|
||||
#include "gcov-io.h"
|
||||
|
||||
#if defined(inhibit_libc)
|
||||
/* If libc and its header files are not available, provide dummy functions. */
|
||||
@ -156,25 +157,6 @@ fail:
|
||||
return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
|
||||
}
|
||||
|
||||
/* Add an unsigned value to the current crc */
|
||||
|
||||
static gcov_unsigned_t
|
||||
crc32_unsigned (gcov_unsigned_t crc32, gcov_unsigned_t value)
|
||||
{
|
||||
unsigned ix;
|
||||
|
||||
for (ix = 32; ix--; value <<= 1)
|
||||
{
|
||||
unsigned feedback;
|
||||
|
||||
feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
|
||||
crc32 <<= 1;
|
||||
crc32 ^= feedback;
|
||||
}
|
||||
|
||||
return crc32;
|
||||
}
|
||||
|
||||
/* Check if VERSION of the info block PTR matches libgcov one.
|
||||
Return 1 on success, or zero in case of versions mismatch.
|
||||
If FILENAME is not NULL, its value used for reporting purposes
|
||||
@ -198,117 +180,8 @@ gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Insert counter VALUE into HISTOGRAM. */
|
||||
|
||||
static void
|
||||
gcov_histogram_insert(gcov_bucket_type *histogram, gcov_type value)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
i = gcov_histo_index(value);
|
||||
histogram[i].num_counters++;
|
||||
histogram[i].cum_value += value;
|
||||
if (value < histogram[i].min_value)
|
||||
histogram[i].min_value = value;
|
||||
}
|
||||
|
||||
/* Computes a histogram of the arc counters to place in the summary SUM. */
|
||||
|
||||
static void
|
||||
gcov_compute_histogram (struct gcov_info *list, struct gcov_summary *sum)
|
||||
{
|
||||
struct gcov_info *gi_ptr;
|
||||
const struct gcov_fn_info *gfi_ptr;
|
||||
const struct gcov_ctr_info *ci_ptr;
|
||||
unsigned f_ix, ix;
|
||||
int h_ix;
|
||||
|
||||
/* First check if there are any counts recorded for this counter. */
|
||||
if (!sum->num)
|
||||
return;
|
||||
|
||||
for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
|
||||
{
|
||||
sum->histogram[h_ix].num_counters = 0;
|
||||
sum->histogram[h_ix].min_value = sum->run_max;
|
||||
sum->histogram[h_ix].cum_value = 0;
|
||||
}
|
||||
|
||||
/* Walk through all the per-object structures and record each of
|
||||
the count values in histogram. */
|
||||
for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
|
||||
{
|
||||
for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
|
||||
{
|
||||
gfi_ptr = gi_ptr->functions[f_ix];
|
||||
|
||||
if (!gfi_ptr || gfi_ptr->key != gi_ptr)
|
||||
continue;
|
||||
|
||||
ci_ptr = &gfi_ptr->ctrs[0];
|
||||
for (ix = 0; ix < ci_ptr->num; ix++)
|
||||
gcov_histogram_insert (sum->histogram, ci_ptr->values[ix]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* buffer for the fn_data from another program. */
|
||||
static struct gcov_fn_buffer *fn_buffer;
|
||||
/* buffer for summary from other programs to be written out. */
|
||||
static struct gcov_summary_buffer *sum_buffer;
|
||||
|
||||
/* This function computes the program level summary and the histo-gram.
|
||||
It computes and returns CRC32 and stored summary in THIS_PRG. */
|
||||
|
||||
#if !IN_GCOV_TOOL
|
||||
static
|
||||
#endif
|
||||
gcov_unsigned_t
|
||||
compute_summary (struct gcov_info *list, struct gcov_summary *this_prg)
|
||||
{
|
||||
struct gcov_info *gi_ptr;
|
||||
const struct gcov_fn_info *gfi_ptr;
|
||||
const struct gcov_ctr_info *ci_ptr;
|
||||
int f_ix;
|
||||
gcov_unsigned_t c_num;
|
||||
gcov_unsigned_t crc32 = 0;
|
||||
|
||||
/* Find the totals for this execution. */
|
||||
memset (this_prg, 0, sizeof (*this_prg));
|
||||
for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
|
||||
{
|
||||
crc32 = crc32_unsigned (crc32, gi_ptr->stamp);
|
||||
crc32 = crc32_unsigned (crc32, gi_ptr->n_functions);
|
||||
|
||||
for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
|
||||
{
|
||||
gfi_ptr = gi_ptr->functions[f_ix];
|
||||
|
||||
if (gfi_ptr && gfi_ptr->key != gi_ptr)
|
||||
gfi_ptr = 0;
|
||||
|
||||
crc32 = crc32_unsigned (crc32, gfi_ptr ? gfi_ptr->cfg_checksum : 0);
|
||||
crc32 = crc32_unsigned (crc32,
|
||||
gfi_ptr ? gfi_ptr->lineno_checksum : 0);
|
||||
if (!gfi_ptr)
|
||||
continue;
|
||||
|
||||
ci_ptr = gfi_ptr->ctrs;
|
||||
this_prg->num += ci_ptr->num;
|
||||
crc32 = crc32_unsigned (crc32, ci_ptr->num);
|
||||
|
||||
for (c_num = 0; c_num < ci_ptr->num; c_num++)
|
||||
{
|
||||
this_prg->sum_all += ci_ptr->values[c_num];
|
||||
if (this_prg->run_max < ci_ptr->values[c_num])
|
||||
this_prg->run_max = ci_ptr->values[c_num];
|
||||
}
|
||||
ci_ptr++;
|
||||
}
|
||||
}
|
||||
gcov_compute_histogram (list, this_prg);
|
||||
return crc32;
|
||||
}
|
||||
|
||||
/* Including system dependent components. */
|
||||
#include "libgcov-driver-system.c"
|
||||
@ -320,18 +193,13 @@ compute_summary (struct gcov_info *list, struct gcov_summary *this_prg)
|
||||
static int
|
||||
merge_one_data (const char *filename,
|
||||
struct gcov_info *gi_ptr,
|
||||
struct gcov_summary *prg_p,
|
||||
struct gcov_summary *this_prg,
|
||||
gcov_position_t *summary_pos_p,
|
||||
gcov_position_t *eof_pos_p,
|
||||
gcov_unsigned_t crc32)
|
||||
struct gcov_summary *summary)
|
||||
{
|
||||
gcov_unsigned_t tag, length;
|
||||
unsigned t_ix;
|
||||
int f_ix;
|
||||
int f_ix = -1;
|
||||
int error = 0;
|
||||
struct gcov_fn_buffer **fn_tail = &fn_buffer;
|
||||
struct gcov_summary_buffer **sum_tail = &sum_buffer;
|
||||
|
||||
length = gcov_read_unsigned ();
|
||||
if (!gcov_version (gi_ptr, length, filename))
|
||||
@ -346,46 +214,14 @@ merge_one_data (const char *filename,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look for program summary. */
|
||||
for (f_ix = 0;;)
|
||||
{
|
||||
struct gcov_summary tmp;
|
||||
|
||||
*eof_pos_p = gcov_position ();
|
||||
tag = gcov_read_unsigned ();
|
||||
if (tag != GCOV_TAG_PROGRAM_SUMMARY)
|
||||
break;
|
||||
|
||||
f_ix--;
|
||||
length = gcov_read_unsigned ();
|
||||
gcov_read_summary (&tmp);
|
||||
if ((error = gcov_is_error ()))
|
||||
goto read_error;
|
||||
if (*summary_pos_p)
|
||||
{
|
||||
/* Save all summaries after the one that will be
|
||||
merged into below. These will need to be rewritten
|
||||
as histogram merging may change the number of non-zero
|
||||
histogram entries that will be emitted, and thus the
|
||||
size of the merged summary. */
|
||||
(*sum_tail) = (struct gcov_summary_buffer *)
|
||||
xmalloc (sizeof(struct gcov_summary_buffer));
|
||||
(*sum_tail)->summary = tmp;
|
||||
(*sum_tail)->next = 0;
|
||||
sum_tail = &((*sum_tail)->next);
|
||||
goto next_summary;
|
||||
}
|
||||
if (tmp.checksum != crc32)
|
||||
goto next_summary;
|
||||
|
||||
if (tmp.num != this_prg->num)
|
||||
goto next_summary;
|
||||
*prg_p = tmp;
|
||||
*summary_pos_p = *eof_pos_p;
|
||||
|
||||
next_summary:;
|
||||
}
|
||||
tag = gcov_read_unsigned ();
|
||||
if (tag != GCOV_TAG_OBJECT_SUMMARY)
|
||||
goto read_mismatch;
|
||||
length = gcov_read_unsigned ();
|
||||
gcc_assert (length > 0);
|
||||
gcov_read_summary (summary);
|
||||
|
||||
tag = gcov_read_unsigned ();
|
||||
/* Merge execution counts for each function. */
|
||||
for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
|
||||
f_ix++, tag = gcov_read_unsigned ())
|
||||
@ -472,38 +308,15 @@ read_error:
|
||||
|
||||
static void
|
||||
write_one_data (const struct gcov_info *gi_ptr,
|
||||
const struct gcov_summary *prg_p,
|
||||
const gcov_position_t eof_pos,
|
||||
const gcov_position_t summary_pos)
|
||||
const struct gcov_summary *prg_p)
|
||||
{
|
||||
unsigned f_ix;
|
||||
struct gcov_summary_buffer *next_sum_buffer;
|
||||
|
||||
/* Write out the data. */
|
||||
if (!eof_pos)
|
||||
{
|
||||
gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
|
||||
gcov_write_unsigned (gi_ptr->stamp);
|
||||
}
|
||||
|
||||
if (summary_pos)
|
||||
gcov_seek (summary_pos);
|
||||
gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
|
||||
gcov_write_unsigned (gi_ptr->stamp);
|
||||
|
||||
/* Generate whole program statistics. */
|
||||
gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, prg_p);
|
||||
|
||||
/* Rewrite all the summaries that were after the summary we merged
|
||||
into. This is necessary as the merged summary may have a different
|
||||
size due to the number of non-zero histogram entries changing after
|
||||
merging. */
|
||||
|
||||
while (sum_buffer)
|
||||
{
|
||||
gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &sum_buffer->summary);
|
||||
next_sum_buffer = sum_buffer->next;
|
||||
free (sum_buffer);
|
||||
sum_buffer = next_sum_buffer;
|
||||
}
|
||||
gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, prg_p);
|
||||
|
||||
/* Write execution counts for each function. */
|
||||
for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
|
||||
@ -562,70 +375,19 @@ write_one_data (const struct gcov_info *gi_ptr,
|
||||
gcov_write_unsigned (0);
|
||||
}
|
||||
|
||||
/* Helper function for merging summary.
|
||||
Return -1 on error. Return 0 on success. */
|
||||
/* Helper function for merging summary. */
|
||||
|
||||
static int
|
||||
merge_summary (const char *filename __attribute__ ((unused)), int run_counted,
|
||||
struct gcov_summary *prg,
|
||||
struct gcov_summary *this_prg, gcov_unsigned_t crc32,
|
||||
struct gcov_summary *all_prg __attribute__ ((unused)))
|
||||
static void
|
||||
merge_summary (int run_counted, struct gcov_summary *summary,
|
||||
gcov_type run_max)
|
||||
{
|
||||
#if !GCOV_LOCKED
|
||||
/* summary for all instances of program. */
|
||||
struct gcov_summary *all;
|
||||
#endif
|
||||
|
||||
/* Merge the summary. */
|
||||
int first = !prg->runs;
|
||||
|
||||
if (!run_counted)
|
||||
prg->runs++;
|
||||
if (first)
|
||||
prg->num = this_prg->num;
|
||||
prg->sum_all += this_prg->sum_all;
|
||||
if (prg->run_max < this_prg->run_max)
|
||||
prg->run_max = this_prg->run_max;
|
||||
prg->sum_max += this_prg->run_max;
|
||||
if (first)
|
||||
memcpy (prg->histogram, this_prg->histogram,
|
||||
sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
|
||||
else
|
||||
gcov_histogram_merge (prg->histogram, this_prg->histogram);
|
||||
#if !GCOV_LOCKED
|
||||
all = all_prg;
|
||||
if (!all->runs && prg->runs)
|
||||
{
|
||||
all->num = prg->num;
|
||||
all->runs = prg->runs;
|
||||
all->sum_all = prg->sum_all;
|
||||
all->run_max = prg->run_max;
|
||||
all->sum_max = prg->sum_max;
|
||||
summary->runs++;
|
||||
summary->sum_max += run_max;
|
||||
}
|
||||
else if (!all_prg->checksum
|
||||
/* Don't compare the histograms, which may have slight
|
||||
variations depending on the order they were updated
|
||||
due to the truncating integer divides used in the
|
||||
merge. */
|
||||
&& (all->num != prg->num
|
||||
|| all->runs != prg->runs
|
||||
|| all->sum_all != prg->sum_all
|
||||
|| all->run_max != prg->run_max
|
||||
|| all->sum_max != prg->sum_max))
|
||||
{
|
||||
gcov_error ("profiling:%s:Data file mismatch - some "
|
||||
"data files may have been concurrently "
|
||||
"updated without locking support\n", filename);
|
||||
all_prg->checksum = ~0u;
|
||||
}
|
||||
#endif
|
||||
|
||||
prg->checksum = crc32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Sort N entries in VALUE_ARRAY in descending order.
|
||||
Each entry in VALUE_ARRAY has two values. The sorting
|
||||
is based on the second value. */
|
||||
@ -713,18 +475,13 @@ gcov_sort_topn_counter_arrays (const struct gcov_info *gi_ptr)
|
||||
|
||||
static void
|
||||
dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
|
||||
unsigned run_counted,
|
||||
gcov_unsigned_t crc32, struct gcov_summary *all_prg,
|
||||
struct gcov_summary *this_prg)
|
||||
unsigned run_counted, gcov_type run_max)
|
||||
{
|
||||
struct gcov_summary prg; /* summary for this object over all program. */
|
||||
struct gcov_summary summary = {};
|
||||
int error;
|
||||
gcov_unsigned_t tag;
|
||||
gcov_position_t summary_pos = 0;
|
||||
gcov_position_t eof_pos = 0;
|
||||
|
||||
fn_buffer = 0;
|
||||
sum_buffer = 0;
|
||||
|
||||
gcov_sort_topn_counter_arrays (gi_ptr);
|
||||
|
||||
@ -741,26 +498,16 @@ dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
|
||||
gcov_error ("profiling:%s:Not a gcov data file\n", gf->filename);
|
||||
goto read_fatal;
|
||||
}
|
||||
error = merge_one_data (gf->filename, gi_ptr, &prg, this_prg,
|
||||
&summary_pos, &eof_pos, crc32);
|
||||
error = merge_one_data (gf->filename, gi_ptr, &summary);
|
||||
if (error == -1)
|
||||
goto read_fatal;
|
||||
}
|
||||
|
||||
gcov_rewrite ();
|
||||
|
||||
if (!summary_pos)
|
||||
{
|
||||
memset (&prg, 0, sizeof (prg));
|
||||
summary_pos = eof_pos;
|
||||
}
|
||||
merge_summary (run_counted, &summary, run_max);
|
||||
|
||||
error = merge_summary (gf->filename, run_counted, &prg, this_prg,
|
||||
crc32, all_prg);
|
||||
if (error == -1)
|
||||
goto read_fatal;
|
||||
|
||||
write_one_data (gi_ptr, &prg, eof_pos, summary_pos);
|
||||
write_one_data (gi_ptr, &summary);
|
||||
/* fall through */
|
||||
|
||||
read_fatal:;
|
||||
@ -787,21 +534,26 @@ gcov_do_dump (struct gcov_info *list, int run_counted)
|
||||
{
|
||||
struct gcov_info *gi_ptr;
|
||||
struct gcov_filename gf;
|
||||
gcov_unsigned_t crc32;
|
||||
struct gcov_summary all_prg;
|
||||
struct gcov_summary this_prg;
|
||||
|
||||
crc32 = compute_summary (list, &this_prg);
|
||||
/* Compute run_max of this program run. */
|
||||
gcov_type run_max = 0;
|
||||
for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
|
||||
for (unsigned f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
|
||||
{
|
||||
const struct gcov_ctr_info *cinfo
|
||||
= &gi_ptr->functions[f_ix]->ctrs[GCOV_COUNTER_ARCS];
|
||||
|
||||
for (unsigned i = 0; i < cinfo->num; i++)
|
||||
if (run_max < cinfo->values[i])
|
||||
run_max = cinfo->values[i];
|
||||
}
|
||||
|
||||
allocate_filename_struct (&gf);
|
||||
#if !GCOV_LOCKED
|
||||
memset (&all_prg, 0, sizeof (all_prg));
|
||||
#endif
|
||||
|
||||
/* Now merge each file. */
|
||||
for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
|
||||
{
|
||||
dump_one_gcov (gi_ptr, &gf, run_counted, crc32, &all_prg, &this_prg);
|
||||
dump_one_gcov (gi_ptr, &gf, run_counted, run_max);
|
||||
free (gf.filename);
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
#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))
|
||||
@ -79,6 +80,8 @@ static int k_ctrs_mask[GCOV_COUNTERS];
|
||||
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,
|
||||
@ -131,7 +134,6 @@ static const tag_format_t tag_table[] =
|
||||
{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}
|
||||
};
|
||||
|
||||
@ -223,9 +225,8 @@ tag_counters (unsigned tag, unsigned length)
|
||||
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.
|
||||
@ -239,7 +240,8 @@ read_gcda_finalize (struct gcov_info *obj_info)
|
||||
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);
|
||||
|
||||
@ -299,6 +301,7 @@ read_gcda_file (const char *filename)
|
||||
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);
|
||||
@ -892,8 +895,6 @@ calculate_2_entries (const unsigned long v1, const unsigned long v2,
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
@ -1048,12 +1049,6 @@ struct overlap_t {
|
||||
/* 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];
|
||||
|
||||
@ -1200,10 +1195,6 @@ matched_gcov_info (const struct gcov_info *info1, const struct gcov_info *info2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Defined in libgcov-driver.c. */
|
||||
extern gcov_unsigned_t compute_summary (struct gcov_info *,
|
||||
struct gcov_summary *);
|
||||
|
||||
/* 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. */
|
||||
@ -1212,21 +1203,11 @@ static double
|
||||
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;
|
||||
const struct gcov_info *gi_ptr;
|
||||
struct overlap_t *all_infos;
|
||||
|
||||
compute_summary (gcov_list1, &this_prg);
|
||||
overlap_sum_1 = (double) (this_prg.sum_all);
|
||||
p1_sum_all = this_prg.sum_all;
|
||||
p1_run_max = this_prg.run_max;
|
||||
compute_summary (gcov_list2, &this_prg);
|
||||
overlap_sum_2 = (double) (this_prg.sum_all);
|
||||
p2_sum_all = this_prg.sum_all;
|
||||
p2_run_max = this_prg.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)
|
||||
@ -1334,10 +1315,6 @@ calculate_overlap (struct gcov_info *gcov_list1,
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user