From 9696c52909efcdb631f5fd7e8a8261656a25cc1b Mon Sep 17 00:00:00 2001 From: Steven Bosscher Date: Mon, 23 Jul 2012 09:24:21 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 30 ++++++++++++++ gcc/function.h | 3 -- gcc/gcov.c | 30 ++++++++------ gcc/lto-streamer-in.c | 1 - gcc/lto-streamer-out.c | 1 - gcc/omp-low.c | 3 -- gcc/opts.c | 2 - gcc/profile.c | 80 ++++++++--------------------------- gcc/tree-inline.c | 1 - gcc/tree-profile.c | 34 ++++++++------- gcc/value-prof.c | 94 ++++++++++++++++++++++++++++-------------- 11 files changed, 147 insertions(+), 132 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2b04ab700c4..68800a66400 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2012-07-22 Steven Bosscher + + * 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 * config/sh/sh.h (TARGET_DYNSHIFT): New macro. diff --git a/gcc/function.h b/gcc/function.h index a7d8b44a5d0..3d3313fc9b3 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -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; diff --git a/gcc/gcov.c b/gcc/gcov.c index d4823991d14..318ce6046ba 100644 --- a/gcc/gcov.c +++ b/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"); diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 07ae2b38609..c7257d9be16 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -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); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 370bf0a7ae8..cfcd3d0a570 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -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); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 03eb399c458..4d3b03239d4 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -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; diff --git a/gcc/opts.c b/gcc/opts.c index d9287845c96..0ddb1a0e582 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -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 diff --git a/gcc/profile.c b/gcc/profile.c index f8debfc38d4..3d0689afac3 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -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; - - 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; + unsigned t = COUNTER_FOR_HIST_TYPE (hist->type); - 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. */ diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 3131525fb8b..78b4d94573d 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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 (); diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index ba6c6ed4cf7..41879530303 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -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 (); diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 29c3e92b289..b75c36f87f7 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -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 - 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 + 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 - inliner). + the 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. + 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. - 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. */ + Value profiling internals + ========================== + + 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 -- 2.30.2