opts.c (common_handle_option): Do not set flag_value_profile_transformations for -fprofile-generate.
* opts.c (common_handle_option): Do not set flag_value_profile_transformations for -fprofile-generate. * profile.c (instrument_values): Use COUNTER_FOR_HIST_TYPE. (BB_TO_GCOV_INDEX): Remove. (output_location): Don't use it. (branch_prob): Likewise. Don't fiddle with the index of ENTRY_BLOCK_PTR and EXIT_BLOCK_PTR. Use clear_aux_for_blocks. (find_spanning_tree): * gcov.c (struct function_info): Document that blocks 0 and 1 are the entry resp. exit blocks in gcov, too, like in GCC itself. (solve_flow_graph): Use ENTRY_BLOCK and EXIT_BLOCK for special blocks identification. (output_lines): Likewise. * value-prof.c (gimple_value_profile_transformations): Do not test flag_value_profile_transformations again. (gimple_ic_transform): Take a gimple_stmt_iterator like all other transformation functions. (gimple_values_to_profile): Don't test flag_value_profile_transformations * tree-profile.c (tree_profiling): Assert that the cgraph is in the CGRAPH_STATE_IPA_SSA state. Do not set, or look at, after_tree_profile. * function.h (struct function): Remove after_tree_profile bit. * omp-low.c (expand_omp_taskreg): Don't set after_tree_profile. * tree-inline.c (initialize_cfun): Don't copy it. * lto-streamer-out.c (output_struct_function_base): Don't stream it. * lto-streamer-in.c (input_struct_function_base): Likewise. From-SVN: r189778
This commit is contained in:
parent
678400b358
commit
9696c52909
|
@ -1,3 +1,33 @@
|
|||
2012-07-22 Steven Bosscher <steven@gcc.gnu.org>
|
||||
|
||||
* opts.c (common_handle_option): Do not set
|
||||
flag_value_profile_transformations for -fprofile-generate.
|
||||
* profile.c (instrument_values): Use COUNTER_FOR_HIST_TYPE.
|
||||
(BB_TO_GCOV_INDEX): Remove.
|
||||
(output_location): Don't use it.
|
||||
(branch_prob): Likewise. Don't fiddle with the index of
|
||||
ENTRY_BLOCK_PTR and EXIT_BLOCK_PTR. Use clear_aux_for_blocks.
|
||||
(find_spanning_tree):
|
||||
* gcov.c (struct function_info): Document that blocks 0 and 1
|
||||
are the entry resp. exit blocks in gcov, too, like in GCC itself.
|
||||
(solve_flow_graph): Use ENTRY_BLOCK and EXIT_BLOCK for special
|
||||
blocks identification.
|
||||
(output_lines): Likewise.
|
||||
* value-prof.c (gimple_value_profile_transformations): Do not
|
||||
test flag_value_profile_transformations again.
|
||||
(gimple_ic_transform): Take a gimple_stmt_iterator like all other
|
||||
transformation functions.
|
||||
(gimple_values_to_profile):
|
||||
Don't test flag_value_profile_transformations
|
||||
* tree-profile.c (tree_profiling): Assert that the cgraph is in
|
||||
the CGRAPH_STATE_IPA_SSA state.
|
||||
Do not set, or look at, after_tree_profile.
|
||||
* function.h (struct function): Remove after_tree_profile bit.
|
||||
* omp-low.c (expand_omp_taskreg): Don't set after_tree_profile.
|
||||
* tree-inline.c (initialize_cfun): Don't copy it.
|
||||
* lto-streamer-out.c (output_struct_function_base): Don't stream it.
|
||||
* lto-streamer-in.c (input_struct_function_base): Likewise.
|
||||
|
||||
2012-07-22 Oleg Endo <olegendo@gcc.gnu.org>
|
||||
|
||||
* config/sh/sh.h (TARGET_DYNSHIFT): New macro.
|
||||
|
|
|
@ -645,9 +645,6 @@ struct GTY(()) function {
|
|||
return the address of where it has put a structure value. */
|
||||
unsigned int returns_pcc_struct : 1;
|
||||
|
||||
/* Nonzero if pass_tree_profile was run on this function. */
|
||||
unsigned int after_tree_profile : 1;
|
||||
|
||||
/* Nonzero if this function has local DECL_HARD_REGISTER variables.
|
||||
In this case code motion has to be done more carefully. */
|
||||
unsigned int has_local_explicit_reg_vars : 1;
|
||||
|
|
30
gcc/gcov.c
30
gcc/gcov.c
|
@ -57,10 +57,10 @@ along with Gcov; see the file COPYING3. If not see
|
|||
|
||||
/* The code validates that the profile information read in corresponds
|
||||
to the code currently being compiled. Rather than checking for
|
||||
identical files, the code below computes a checksum on the CFG
|
||||
identical files, the code below compares a checksum on the CFG
|
||||
(based on the order of basic blocks and the arcs in the CFG). If
|
||||
the CFG checksum in the gcda file match the CFG checksum for the
|
||||
code currently being compiled, the profile data will be used. */
|
||||
the CFG checksum in the gcda file match the CFG checksum in the
|
||||
gcno file, the profile data will be used. */
|
||||
|
||||
/* This is the size of the buffer used to read in source file lines. */
|
||||
|
||||
|
@ -177,7 +177,10 @@ typedef struct function_info
|
|||
/* The graph contains at least one fake incoming edge. */
|
||||
unsigned has_catch : 1;
|
||||
|
||||
/* Array of basic blocks. */
|
||||
/* Array of basic blocks. Like in GCC, the entry block is
|
||||
at blocks[0] and the exit block is at blocks[1]. */
|
||||
#define ENTRY_BLOCK (0)
|
||||
#define EXIT_BLOCK (1)
|
||||
block_t *blocks;
|
||||
unsigned num_blocks;
|
||||
unsigned blocks_executed;
|
||||
|
@ -1363,21 +1366,21 @@ solve_flow_graph (function_t *fn)
|
|||
bbg_file_name, fn->name);
|
||||
else
|
||||
{
|
||||
if (fn->blocks[0].num_pred)
|
||||
if (fn->blocks[ENTRY_BLOCK].num_pred)
|
||||
fnotice (stderr, "%s:'%s' has arcs to entry block\n",
|
||||
bbg_file_name, fn->name);
|
||||
else
|
||||
/* We can't deduce the entry block counts from the lack of
|
||||
predecessors. */
|
||||
fn->blocks[0].num_pred = ~(unsigned)0;
|
||||
fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0;
|
||||
|
||||
if (fn->blocks[fn->num_blocks - 1].num_succ)
|
||||
if (fn->blocks[EXIT_BLOCK].num_succ)
|
||||
fnotice (stderr, "%s:'%s' has arcs from exit block\n",
|
||||
bbg_file_name, fn->name);
|
||||
else
|
||||
/* Likewise, we can't deduce exit block counts from the lack
|
||||
of its successors. */
|
||||
fn->blocks[fn->num_blocks - 1].num_succ = ~(unsigned)0;
|
||||
fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0;
|
||||
}
|
||||
|
||||
/* Propagate the measured counts, this must be done in the same
|
||||
|
@ -1637,7 +1640,7 @@ add_branch_counts (coverage_t *coverage, const arc_t *arc)
|
|||
}
|
||||
}
|
||||
|
||||
/* Format a HOST_WIDE_INT as either a percent ratio, or absolute
|
||||
/* Format a GCOV_TYPE integer as either a percent ratio, or absolute
|
||||
count. If dp >= 0, format TOP/BOTTOM * 100 to DP decimal places.
|
||||
If DP is zero, no decimal point is printed. Only print 100% when
|
||||
TOP==BOTTOM and only print 0% when TOP=0. If dp < 0, then simply
|
||||
|
@ -2266,8 +2269,9 @@ output_lines (FILE *gcov_file, const source_t *src)
|
|||
{
|
||||
for (; fn && fn->line == line_num; fn = fn->line_next)
|
||||
{
|
||||
arc_t *arc = fn->blocks[fn->num_blocks - 1].pred;
|
||||
gcov_type return_count = fn->blocks[fn->num_blocks - 1].count;
|
||||
arc_t *arc = fn->blocks[EXIT_BLOCK].pred;
|
||||
gcov_type return_count = fn->blocks[EXIT_BLOCK].count;
|
||||
gcov_type called_count = fn->blocks[ENTRY_BLOCK].count;
|
||||
|
||||
for (; arc; arc = arc->pred_next)
|
||||
if (arc->fake)
|
||||
|
@ -2275,9 +2279,9 @@ output_lines (FILE *gcov_file, const source_t *src)
|
|||
|
||||
fprintf (gcov_file, "function %s", fn->name);
|
||||
fprintf (gcov_file, " called %s",
|
||||
format_gcov (fn->blocks[0].count, 0, -1));
|
||||
format_gcov (called_count, 0, -1));
|
||||
fprintf (gcov_file, " returned %s",
|
||||
format_gcov (return_count, fn->blocks[0].count, 0));
|
||||
format_gcov (return_count, called_count, 0));
|
||||
fprintf (gcov_file, " blocks executed %s",
|
||||
format_gcov (fn->blocks_executed, fn->num_blocks - 2, 0));
|
||||
fprintf (gcov_file, "\n");
|
||||
|
|
|
@ -798,7 +798,6 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
|
|||
bp = streamer_read_bitpack (ib);
|
||||
fn->is_thunk = bp_unpack_value (&bp, 1);
|
||||
fn->has_local_explicit_reg_vars = bp_unpack_value (&bp, 1);
|
||||
fn->after_tree_profile = bp_unpack_value (&bp, 1);
|
||||
fn->returns_pcc_struct = bp_unpack_value (&bp, 1);
|
||||
fn->returns_struct = bp_unpack_value (&bp, 1);
|
||||
fn->can_throw_non_call_exceptions = bp_unpack_value (&bp, 1);
|
||||
|
|
|
@ -757,7 +757,6 @@ output_struct_function_base (struct output_block *ob, struct function *fn)
|
|||
bp = bitpack_create (ob->main_stream);
|
||||
bp_pack_value (&bp, fn->is_thunk, 1);
|
||||
bp_pack_value (&bp, fn->has_local_explicit_reg_vars, 1);
|
||||
bp_pack_value (&bp, fn->after_tree_profile, 1);
|
||||
bp_pack_value (&bp, fn->returns_pcc_struct, 1);
|
||||
bp_pack_value (&bp, fn->returns_struct, 1);
|
||||
bp_pack_value (&bp, fn->can_throw_non_call_exceptions, 1);
|
||||
|
|
|
@ -3398,9 +3398,6 @@ expand_omp_taskreg (struct omp_region *region)
|
|||
entry_stmt = last_stmt (region->entry);
|
||||
child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
|
||||
child_cfun = DECL_STRUCT_FUNCTION (child_fn);
|
||||
/* If this function has been already instrumented, make sure
|
||||
the child function isn't instrumented again. */
|
||||
child_cfun->after_tree_profile = cfun->after_tree_profile;
|
||||
|
||||
entry_bb = region->entry;
|
||||
exit_bb = region->exit;
|
||||
|
|
|
@ -1593,8 +1593,6 @@ common_handle_option (struct gcc_options *opts,
|
|||
opts->x_profile_arc_flag = value;
|
||||
if (!opts_set->x_flag_profile_values)
|
||||
opts->x_flag_profile_values = value;
|
||||
if (!opts_set->x_flag_value_profile_transformations)
|
||||
opts->x_flag_value_profile_transformations = value;
|
||||
if (!opts_set->x_flag_inline_functions)
|
||||
opts->x_flag_inline_functions = value;
|
||||
/* FIXME: Instrumentation we insert makes ipa-reference bitmaps
|
||||
|
|
|
@ -143,46 +143,15 @@ instrument_edges (struct edge_list *el)
|
|||
static void
|
||||
instrument_values (histogram_values values)
|
||||
{
|
||||
unsigned i, t;
|
||||
unsigned i;
|
||||
|
||||
/* Emit code to generate the histograms before the insns. */
|
||||
|
||||
for (i = 0; i < VEC_length (histogram_value, values); i++)
|
||||
{
|
||||
histogram_value hist = VEC_index (histogram_value, values, i);
|
||||
switch (hist->type)
|
||||
{
|
||||
case HIST_TYPE_INTERVAL:
|
||||
t = GCOV_COUNTER_V_INTERVAL;
|
||||
break;
|
||||
unsigned t = COUNTER_FOR_HIST_TYPE (hist->type);
|
||||
|
||||
case HIST_TYPE_POW2:
|
||||
t = GCOV_COUNTER_V_POW2;
|
||||
break;
|
||||
|
||||
case HIST_TYPE_SINGLE_VALUE:
|
||||
t = GCOV_COUNTER_V_SINGLE;
|
||||
break;
|
||||
|
||||
case HIST_TYPE_CONST_DELTA:
|
||||
t = GCOV_COUNTER_V_DELTA;
|
||||
break;
|
||||
|
||||
case HIST_TYPE_INDIR_CALL:
|
||||
t = GCOV_COUNTER_V_INDIR;
|
||||
break;
|
||||
|
||||
case HIST_TYPE_AVERAGE:
|
||||
t = GCOV_COUNTER_AVERAGE;
|
||||
break;
|
||||
|
||||
case HIST_TYPE_IOR:
|
||||
t = GCOV_COUNTER_IOR;
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
if (!coverage_counter_alloc (t, hist->n_counters))
|
||||
continue;
|
||||
|
||||
|
@ -870,9 +839,6 @@ compute_value_histograms (histogram_values values, unsigned cfg_checksum,
|
|||
free (histogram_counts[t]);
|
||||
}
|
||||
|
||||
/* The entry basic block will be moved around so that it has index=1,
|
||||
there is nothing at index 0 and the exit is at n_basic_block. */
|
||||
#define BB_TO_GCOV_INDEX(bb) ((bb)->index - 1)
|
||||
/* When passed NULL as file_name, initialize.
|
||||
When passed something else, output the necessary commands to change
|
||||
line to LINE and offset to FILE_NAME. */
|
||||
|
@ -899,7 +865,7 @@ output_location (char const *file_name, int line,
|
|||
if (!*offset)
|
||||
{
|
||||
*offset = gcov_write_tag (GCOV_TAG_LINES);
|
||||
gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
|
||||
gcov_write_unsigned (bb->index);
|
||||
name_differs = line_differs=true;
|
||||
}
|
||||
|
||||
|
@ -919,19 +885,22 @@ output_location (char const *file_name, int line,
|
|||
}
|
||||
}
|
||||
|
||||
/* Instrument and/or analyze program behavior based on program flow graph.
|
||||
In either case, this function builds a flow graph for the function being
|
||||
compiled. The flow graph is stored in BB_GRAPH.
|
||||
/* Instrument and/or analyze program behavior based on program the CFG.
|
||||
|
||||
This function creates a representation of the control flow graph (of
|
||||
the function being compiled) that is suitable for the instrumentation
|
||||
of edges and/or converting measured edge counts to counts on the
|
||||
complete CFG.
|
||||
|
||||
When FLAG_PROFILE_ARCS is nonzero, this function instruments the edges in
|
||||
the flow graph that are needed to reconstruct the dynamic behavior of the
|
||||
flow graph.
|
||||
flow graph. This data is written to the gcno file for gcov.
|
||||
|
||||
When FLAG_BRANCH_PROBABILITIES is nonzero, this function reads auxiliary
|
||||
information from a data file containing edge count information from previous
|
||||
executions of the function being compiled. In this case, the flow graph is
|
||||
annotated with actual execution counts, which are later propagated into the
|
||||
rtl for optimization purposes.
|
||||
information from the gcda file containing edge count information from
|
||||
previous executions of the function being compiled. In this case, the
|
||||
control flow graph is annotated with actual execution counts by
|
||||
compute_branch_probabilities().
|
||||
|
||||
Main entry point of this file. */
|
||||
|
||||
|
@ -1145,8 +1114,7 @@ branch_prob (void)
|
|||
lineno_checksum = coverage_compute_lineno_checksum ();
|
||||
|
||||
/* Write the data from which gcov can reconstruct the basic block
|
||||
graph and function line numbers */
|
||||
|
||||
graph and function line numbers (the gcno file). */
|
||||
if (coverage_begin_function (lineno_checksum, cfg_checksum))
|
||||
{
|
||||
gcov_position_t offset;
|
||||
|
@ -1157,12 +1125,6 @@ branch_prob (void)
|
|||
gcov_write_unsigned (0);
|
||||
gcov_write_length (offset);
|
||||
|
||||
/* Keep all basic block indexes nonnegative in the gcov output.
|
||||
Index 0 is used for entry block, last index is for exit
|
||||
block. */
|
||||
ENTRY_BLOCK_PTR->index = 1;
|
||||
EXIT_BLOCK_PTR->index = last_basic_block;
|
||||
|
||||
/* Arcs */
|
||||
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
|
||||
{
|
||||
|
@ -1170,7 +1132,7 @@ branch_prob (void)
|
|||
edge_iterator ei;
|
||||
|
||||
offset = gcov_write_tag (GCOV_TAG_ARCS);
|
||||
gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
|
||||
gcov_write_unsigned (bb->index);
|
||||
|
||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||
{
|
||||
|
@ -1191,7 +1153,7 @@ branch_prob (void)
|
|||
&& e->src->next_bb == e->dest)
|
||||
flag_bits |= GCOV_ARC_FALLTHROUGH;
|
||||
|
||||
gcov_write_unsigned (BB_TO_GCOV_INDEX (e->dest));
|
||||
gcov_write_unsigned (e->dest->index);
|
||||
gcov_write_unsigned (flag_bits);
|
||||
}
|
||||
}
|
||||
|
@ -1199,9 +1161,6 @@ branch_prob (void)
|
|||
gcov_write_length (offset);
|
||||
}
|
||||
|
||||
ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
|
||||
EXIT_BLOCK_PTR->index = EXIT_BLOCK;
|
||||
|
||||
/* Line numbers. */
|
||||
/* Initialize the output. */
|
||||
output_location (NULL, 0, NULL, NULL);
|
||||
|
@ -1247,8 +1206,6 @@ branch_prob (void)
|
|||
}
|
||||
}
|
||||
|
||||
#undef BB_TO_GCOV_INDEX
|
||||
|
||||
if (flag_profile_values)
|
||||
gimple_find_values_to_profile (&values);
|
||||
|
||||
|
@ -1391,8 +1348,7 @@ find_spanning_tree (struct edge_list *el)
|
|||
}
|
||||
}
|
||||
|
||||
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
|
||||
bb->aux = NULL;
|
||||
clear_aux_for_blocks ();
|
||||
}
|
||||
|
||||
/* Perform file-level initialization for branch-prob processing. */
|
||||
|
|
|
@ -2110,7 +2110,6 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
|
|||
cfun->can_delete_dead_exceptions = src_cfun->can_delete_dead_exceptions;
|
||||
cfun->returns_struct = src_cfun->returns_struct;
|
||||
cfun->returns_pcc_struct = src_cfun->returns_pcc_struct;
|
||||
cfun->after_tree_profile = src_cfun->after_tree_profile;
|
||||
|
||||
init_empty_tree_cfg ();
|
||||
|
||||
|
|
|
@ -100,6 +100,8 @@ init_ic_make_global_vars (void)
|
|||
varpool_finalize_decl (ic_gcov_type_ptr_var);
|
||||
}
|
||||
|
||||
/* Create the type and function decls for the interface with gcov. */
|
||||
|
||||
void
|
||||
gimple_init_edge_profiler (void)
|
||||
{
|
||||
|
@ -332,8 +334,9 @@ gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
|
|||
|
||||
/* Insert code:
|
||||
|
||||
__gcov_indirect_call_counters = get_relevant_counter_ptr ();
|
||||
__gcov_indirect_call_callee = (void *) indirect call argument;
|
||||
stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
|
||||
stmt2: tmp1 = (void *) (indirect call argument value)
|
||||
stmt3: __gcov_indirect_call_callee = tmp1;
|
||||
*/
|
||||
|
||||
tmp1 = create_tmp_reg (ptr_void, "PROF");
|
||||
|
@ -368,6 +371,13 @@ gimple_gen_ic_func_profiler (void)
|
|||
|
||||
gimple_init_edge_profiler ();
|
||||
|
||||
/* Insert code:
|
||||
|
||||
stmt1: __gcov_indirect_call_profiler (__gcov_indirect_call_counters,
|
||||
current_function_funcdef_no,
|
||||
¤t_function_decl,
|
||||
__gcov_indirect_call_callee);
|
||||
*/
|
||||
gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
|
||||
|
||||
cur_func = force_gimple_operand_gsi (&gsi,
|
||||
|
@ -461,12 +471,9 @@ tree_profiling (void)
|
|||
{
|
||||
struct cgraph_node *node;
|
||||
|
||||
/* Don't profile functions produced at destruction time, particularly
|
||||
the gcov datastructure initializer. Don't profile if it has been
|
||||
already instrumented either (when OpenMP expansion creates
|
||||
child function from already instrumented body). */
|
||||
if (cgraph_state == CGRAPH_STATE_FINISHED)
|
||||
return 0;
|
||||
/* This is a small-ipa pass that gets called only once, from
|
||||
cgraphunit.c:ipa_passes(). */
|
||||
gcc_assert (cgraph_state == CGRAPH_STATE_IPA_SSA);
|
||||
|
||||
init_node_map();
|
||||
|
||||
|
@ -476,8 +483,7 @@ tree_profiling (void)
|
|||
continue;
|
||||
|
||||
/* Don't profile functions produced for builtin stuff. */
|
||||
if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION
|
||||
|| DECL_STRUCT_FUNCTION (node->symbol.decl)->after_tree_profile)
|
||||
if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
|
||||
continue;
|
||||
|
||||
push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
|
||||
|
@ -489,6 +495,7 @@ tree_profiling (void)
|
|||
/* Local pure-const may imply need to fixup the cfg. */
|
||||
if (execute_fixup_cfg () & TODO_cleanup_cfg)
|
||||
cleanup_tree_cfg ();
|
||||
|
||||
branch_prob ();
|
||||
|
||||
if (! flag_branch_probabilities
|
||||
|
@ -519,8 +526,7 @@ tree_profiling (void)
|
|||
continue;
|
||||
|
||||
/* Don't profile functions produced for builtin stuff. */
|
||||
if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION
|
||||
|| DECL_STRUCT_FUNCTION (node->symbol.decl)->after_tree_profile)
|
||||
if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
|
||||
continue;
|
||||
|
||||
cgraph_set_const_flag (node, false, false);
|
||||
|
@ -538,8 +544,7 @@ tree_profiling (void)
|
|||
continue;
|
||||
|
||||
/* Don't profile functions produced for builtin stuff. */
|
||||
if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION
|
||||
|| DECL_STRUCT_FUNCTION (node->symbol.decl)->after_tree_profile)
|
||||
if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION)
|
||||
continue;
|
||||
|
||||
push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
|
||||
|
@ -556,7 +561,6 @@ tree_profiling (void)
|
|||
}
|
||||
}
|
||||
|
||||
cfun->after_tree_profile = 1;
|
||||
update_ssa (TODO_update_ssa);
|
||||
|
||||
rebuild_cgraph_edges ();
|
||||
|
|
|
@ -53,28 +53,63 @@ along with GCC; see the file COPYING3. If not see
|
|||
1) Division/modulo specialization. Provided that we can determine that the
|
||||
operands of the division have some special properties, we may use it to
|
||||
produce more effective code.
|
||||
2) Speculative prefetching. If we are able to determine that the difference
|
||||
|
||||
2) Indirect/virtual call specialization. If we can determine most
|
||||
common function callee in indirect/virtual call. We can use this
|
||||
information to improve code effectiveness (especially info for
|
||||
the inliner).
|
||||
|
||||
3) Speculative prefetching. If we are able to determine that the difference
|
||||
between addresses accessed by a memory reference is usually constant, we
|
||||
may add the prefetch instructions.
|
||||
FIXME: This transformation was removed together with RTL based value
|
||||
profiling.
|
||||
|
||||
3) Indirect/virtual call specialization. If we can determine most
|
||||
common function callee in indirect/virtual call. We can use this
|
||||
information to improve code effectiveness (especially info for
|
||||
inliner).
|
||||
|
||||
Every such optimization should add its requirements for profiled values to
|
||||
insn_values_to_profile function. This function is called from branch_prob
|
||||
in profile.c and the requested values are instrumented by it in the first
|
||||
compilation with -fprofile-arcs. The optimization may then read the
|
||||
gathered data in the second compilation with -fbranch-probabilities.
|
||||
Value profiling internals
|
||||
==========================
|
||||
|
||||
The measured data is pointed to from the histograms
|
||||
field of the statement annotation of the instrumented insns. It is
|
||||
kept as a linked list of struct histogram_value_t's, which contain the
|
||||
same information as above. */
|
||||
Every value profiling transformation starts with defining what values
|
||||
to profile. There are different histogram types (see HIST_TYPE_* in
|
||||
value-prof.h) and each transformation can request one or more histogram
|
||||
types per GIMPLE statement. The function gimple_find_values_to_profile()
|
||||
collects the values to profile in a VEC, and adds the number of counters
|
||||
required for the different histogram types.
|
||||
|
||||
For a -fprofile-generate run, the statements for which values should be
|
||||
recorded, are instrumented in instrument_values(). The instrumentation
|
||||
is done by helper functions that can be found in tree-profile.c, where
|
||||
new types of histograms can be added if necessary.
|
||||
|
||||
After a -fprofile-use, the value profiling data is read back in by
|
||||
compute_value_histograms() that translates the collected data to
|
||||
histograms and attaches them to the profiled statements via
|
||||
gimple_add_histogram_value(). Histograms are stored in a hash table
|
||||
that is attached to every intrumented function, see VALUE_HISTOGRAMS
|
||||
in function.h.
|
||||
|
||||
The value-profile transformations driver is the function
|
||||
gimple_value_profile_transformations(). It traverses all statements in
|
||||
the to-be-transformed function, and looks for statements with one or
|
||||
more histograms attached to it. If a statement has histograms, the
|
||||
transformation functions are called on the statement.
|
||||
|
||||
Limitations / FIXME / TODO:
|
||||
* Only one histogram of each type can be associated with a statement.
|
||||
* Currently, HIST_TYPE_CONST_DELTA is not implemented.
|
||||
(This type of histogram was originally used to implement a form of
|
||||
stride profiling based speculative prefetching to improve SPEC2000
|
||||
scores for memory-bound benchmarks, mcf and equake. However, this
|
||||
was an RTL value-profiling transformation, and those have all been
|
||||
removed.)
|
||||
* Some value profile transformations are done in builtins.c (?!)
|
||||
* Updating of histograms needs some TLC.
|
||||
* The value profiling code could be used to record analysis results
|
||||
from non-profiling (e.g. VRP).
|
||||
* Adding new profilers should be simplified, starting with a cleanup
|
||||
of what-happens-where andwith making gimple_find_values_to_profile
|
||||
and gimple_value_profile_transformations table-driven, perhaps...
|
||||
*/
|
||||
|
||||
static tree gimple_divmod_fixed_value (gimple, tree, int, gcov_type, gcov_type);
|
||||
static tree gimple_mod_pow2 (gimple, int, gcov_type, gcov_type);
|
||||
|
@ -84,7 +119,7 @@ static bool gimple_divmod_fixed_value_transform (gimple_stmt_iterator *);
|
|||
static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *);
|
||||
static bool gimple_mod_subtract_transform (gimple_stmt_iterator *);
|
||||
static bool gimple_stringops_transform (gimple_stmt_iterator *);
|
||||
static bool gimple_ic_transform (gimple);
|
||||
static bool gimple_ic_transform (gimple_stmt_iterator *);
|
||||
|
||||
/* Allocate histogram value. */
|
||||
|
||||
|
@ -309,7 +344,7 @@ dump_histograms_for_stmt (struct function *fun, FILE *dump_file, gimple stmt)
|
|||
{
|
||||
histogram_value hist;
|
||||
for (hist = gimple_histogram_value (fun, stmt); hist; hist = hist->hvalue.next)
|
||||
dump_histogram_value (dump_file, hist);
|
||||
dump_histogram_value (dump_file, hist);
|
||||
}
|
||||
|
||||
/* Remove all histograms associated with STMT. */
|
||||
|
@ -519,12 +554,11 @@ gimple_value_profile_transformations (void)
|
|||
will be added before the current statement, and that the
|
||||
current statement remain valid (although possibly
|
||||
modified) upon return. */
|
||||
if (flag_value_profile_transformations
|
||||
&& (gimple_mod_subtract_transform (&gsi)
|
||||
|| gimple_divmod_fixed_value_transform (&gsi)
|
||||
|| gimple_mod_pow2_value_transform (&gsi)
|
||||
|| gimple_stringops_transform (&gsi)
|
||||
|| gimple_ic_transform (stmt)))
|
||||
if (gimple_mod_subtract_transform (&gsi)
|
||||
|| gimple_divmod_fixed_value_transform (&gsi)
|
||||
|| gimple_mod_pow2_value_transform (&gsi)
|
||||
|| gimple_stringops_transform (&gsi)
|
||||
|| gimple_ic_transform (&gsi))
|
||||
{
|
||||
stmt = gsi_stmt (gsi);
|
||||
changed = true;
|
||||
|
@ -1283,8 +1317,9 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call,
|
|||
*/
|
||||
|
||||
static bool
|
||||
gimple_ic_transform (gimple stmt)
|
||||
gimple_ic_transform (gimple_stmt_iterator *gsi)
|
||||
{
|
||||
gimple stmt = gsi_stmt (*gsi);
|
||||
histogram_value histogram;
|
||||
gcov_type val, count, all, bb_all;
|
||||
gcov_type prob;
|
||||
|
@ -1749,12 +1784,9 @@ gimple_stringops_values_to_profile (gimple stmt, histogram_values *values)
|
|||
static void
|
||||
gimple_values_to_profile (gimple stmt, histogram_values *values)
|
||||
{
|
||||
if (flag_value_profile_transformations)
|
||||
{
|
||||
gimple_divmod_values_to_profile (stmt, values);
|
||||
gimple_stringops_values_to_profile (stmt, values);
|
||||
gimple_indirect_call_to_profile (stmt, values);
|
||||
}
|
||||
gimple_divmod_values_to_profile (stmt, values);
|
||||
gimple_stringops_values_to_profile (stmt, values);
|
||||
gimple_indirect_call_to_profile (stmt, values);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in New Issue