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:
Martin Liska 2018-09-21 10:41:17 +02:00 committed by Martin Liska
parent 36ff254bf6
commit 512cc01512
21 changed files with 182 additions and 1215 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);

View File

@ -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[] =

View File

@ -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)

View 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)
{

View File

@ -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 = &lto_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)

View File

@ -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);

View File

@ -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",

View File

@ -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;

View File

@ -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;
}

View File

@ -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];

View File

@ -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 */

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}