/* Forward declarations. */
static void find_spanning_tree (struct edge_list *);
-static unsigned instrument_edges (struct edge_list *);
-static void instrument_values (histogram_values);
-static void compute_branch_probabilities (void);
-static void compute_value_histograms (histogram_values);
-static gcov_type * get_exec_counts (void);
-static basic_block find_group (basic_block);
-static void union_groups (basic_block, basic_block);
/* Add edge instrumentation code to the entire insn chain.
}
\f
-/* Computes hybrid profile for all matching entries in da_file. */
+/* Computes hybrid profile for all matching entries in da_file.
+
+ CFG_CHECKSUM is the precomputed checksum for the CFG. */
static gcov_type *
-get_exec_counts (void)
+get_exec_counts (unsigned cfg_checksum, unsigned lineno_checksum)
{
unsigned num_edges = 0;
basic_block bb;
num_edges++;
}
- counts = get_coverage_counts (GCOV_COUNTER_ARCS, num_edges, &profile_info);
+ counts = get_coverage_counts (GCOV_COUNTER_ARCS, num_edges, cfg_checksum,
+ lineno_checksum, &profile_info);
if (!counts)
return NULL;
return num_edges;
}
+#define OVERLAP_BASE 10000
+
+/* Compare the static estimated profile to the actual profile, and
+ return the "degree of overlap" measure between them.
+
+ Degree of overlap is a number between 0 and OVERLAP_BASE. It is
+ the sum of each basic block's minimum relative weights between
+ two profiles. And overlap of OVERLAP_BASE means two profiles are
+ identical. */
+
+static int
+compute_frequency_overlap (void)
+{
+ gcov_type count_total = 0, freq_total = 0;
+ int overlap = 0;
+ basic_block bb;
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ {
+ count_total += bb->count;
+ freq_total += bb->frequency;
+ }
+
+ if (count_total == 0 || freq_total == 0)
+ return 0;
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ overlap += MIN (bb->count * OVERLAP_BASE / count_total,
+ bb->frequency * OVERLAP_BASE / freq_total);
+
+ return overlap;
+}
+
/* Compute the branch probabilities for the various branches.
- Annotate them accordingly. */
+ Annotate them accordingly.
+
+ CFG_CHECKSUM is the precomputed checksum for the CFG. */
static void
-compute_branch_probabilities (void)
+compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
{
basic_block bb;
int i;
int passes;
int hist_br_prob[20];
int num_branches;
- gcov_type *exec_counts = get_exec_counts ();
+ gcov_type *exec_counts = get_exec_counts (cfg_checksum, lineno_checksum);
int inconsistent = 0;
/* Very simple sanity checks so we catch bugs in our profiling code. */
}
}
if (dump_file)
- dump_flow_info (dump_file, dump_flags);
+ {
+ int overlap = compute_frequency_overlap ();
+ dump_flow_info (dump_file, dump_flags);
+ fprintf (dump_file, "Static profile overlap: %d.%d%%\n",
+ overlap / (OVERLAP_BASE / 100),
+ overlap % (OVERLAP_BASE / 100));
+ }
total_num_passes += passes;
if (dump_file)
}
counts_to_freqs ();
profile_status = PROFILE_READ;
+ compute_function_frequency ();
if (dump_file)
{
}
/* Load value histograms values whose description is stored in VALUES array
- from .gcda file. */
+ from .gcda file.
+
+ CFG_CHECKSUM is the precomputed checksum for the CFG. */
static void
-compute_value_histograms (histogram_values values)
+compute_value_histograms (histogram_values values, unsigned cfg_checksum,
+ unsigned lineno_checksum)
{
unsigned i, j, t, any;
unsigned n_histogram_counters[GCOV_N_VALUE_COUNTERS];
histogram_counts[t] =
get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
- n_histogram_counters[t], NULL);
+ n_histogram_counters[t], cfg_checksum,
+ lineno_checksum, NULL);
if (histogram_counts[t])
any = 1;
act_count[t] = histogram_counts[t];
}
for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
- if (histogram_counts[t])
- free (histogram_counts[t]);
+ free (histogram_counts[t]);
}
/* The entry basic block will be moved around so that it has index=1,
unsigned num_instrumented;
struct edge_list *el;
histogram_values values = NULL;
+ unsigned cfg_checksum, lineno_checksum;
total_num_times_called++;
if (dump_file)
fprintf (dump_file, "%d ignored edges\n", ignored_edges);
+
+ /* Compute two different checksums. Note that we want to compute
+ the checksum in only once place, since it depends on the shape
+ of the control flow which can change during
+ various transformations. */
+ cfg_checksum = coverage_compute_cfg_checksum ();
+ lineno_checksum = coverage_compute_lineno_checksum ();
+
/* Write the data from which gcov can reconstruct the basic block
graph. */
/* Basic block flags */
- if (coverage_begin_output ())
+ if (coverage_begin_output (lineno_checksum, cfg_checksum))
{
gcov_position_t offset;
EXIT_BLOCK_PTR->index = last_basic_block;
/* Arcs */
- if (coverage_begin_output ())
+ if (coverage_begin_output (lineno_checksum, cfg_checksum))
{
gcov_position_t offset;
}
/* Line numbers. */
- if (coverage_begin_output ())
+ if (coverage_begin_output (lineno_checksum, cfg_checksum))
{
- gcov_position_t offset;
-
/* Initialize the output. */
output_location (NULL, 0, NULL, NULL);
FOR_EACH_BB (bb)
{
gimple_stmt_iterator gsi;
-
- offset = 0;
+ gcov_position_t offset = 0;
if (bb == ENTRY_BLOCK_PTR->next_bb)
{
&offset, bb);
}
- /* Notice GOTO expressions we eliminated while constructing the
- CFG. */
+ /* Notice GOTO expressions eliminated while constructing the CFG. */
if (single_succ_p (bb)
&& single_succ_edge (bb)->goto_locus != UNKNOWN_LOCATION)
{
- location_t curr_location = single_succ_edge (bb)->goto_locus;
- /* ??? The FILE/LINE API is inconsistent for these cases. */
- output_location (LOCATION_FILE (curr_location),
- LOCATION_LINE (curr_location), &offset, bb);
+ expanded_location curr_location
+ = expand_location (single_succ_edge (bb)->goto_locus);
+ output_location (curr_location.file, curr_location.line,
+ &offset, bb);
}
if (offset)
if (flag_branch_probabilities)
{
- compute_branch_probabilities ();
+ compute_branch_probabilities (cfg_checksum, lineno_checksum);
if (flag_profile_values)
- compute_value_histograms (values);
+ compute_value_histograms (values, cfg_checksum, lineno_checksum);
}
remove_fake_edges ();
VEC_free (histogram_value, heap, values);
free_edge_list (el);
- coverage_end_function ();
+ coverage_end_function (lineno_checksum, cfg_checksum);
}
\f
/* Union find algorithm implementation for the basic blocks using
}
}
}
-