diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-01-19 18:34:02 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-01-19 18:34:02 +0000 |
commit | 167b550bfc882bd2fd23b33ca65ad2a6be197771 (patch) | |
tree | 41def031b05732ddcfbc26eac41ed55f2a54dc07 /gcc/tree-profile.c | |
parent | c1b4ac849bf1cc1fce4ed4820d6b2707f122cc36 (diff) | |
download | gcc-167b550bfc882bd2fd23b33ca65ad2a6be197771.tar.gz |
Patch by Tomas Bily <tbily@suse.cz>
* cgraphunit.c (cgraph_finalize_function): Updating of pid
* tree-profile.c:
(tree_init_ic_make_global_vars): New function
(tree_init_edge_profiler): call of tree_init_ic_make_global_vars
(tree_gen_ic_profiler): New function
(tree_gen_ic_func_profiler): New function
(tree_profiling): Added calling of tree_gen_ic_func_profiler
(tree_profile_hooks): Added hook for indirec/virtual calls
* value-prof.c (tree_find_values_to_profile): New case for
indirect calls
(tree_values_to_profile): Call for determining indirect/virtual
counters
(tree_indirect_call_to_profile): New function
(tree_ic_transform): New function
(tree_ic): New function
(find_func_by_pid): New function
(init_pid_map): New function
(tree_value_profile_transformations): Added check for
indirect/virtual call transformation
* value-prof.h (enum hist_type): New counter type for
indirect/virtual calls
(profile_hooks): Added new hook for profiling indirect/virtual
calls
* profile.c (instrument_values): New case for indirect/virtual
call added
* gcov-io.h (GCOV_LAST_VALUE_COUNTER): Changed to 6
(GCOV_COUNTER_V_INDIR): New counter type
(GCOV_COUNTER_NAMES): New name of counter "indirect" added
(GCOV_MERGE_FUNCTIONS): New merge function for indirect/virtual
call added
* cgraph.c: Definition of cgraph_max_pid
(cgraph_create_node): Default init of pid attribute
* cgraph.h: Declaration of cgraph_max_pid
(struct cgraph_node): Added pid attribute
* libgcov.c (__gcov_indirect_call_profiler): New function
(__gcov_one_value_profiler_body): New function
(__gcov_one_value_profiler): Body was moved to
__gcov_one_value_profiler_body and calls it
gcc.dg/tree-prof/indir-call-prof.c: New.
g++.dg/dg.exp: Add tree-prof subdirectory.
g++.dg/tree-prof/indir-call-prof.C: New.
g++.dg/tree-prof/tree-prof.exp: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120975 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-profile.c')
-rw-r--r-- | gcc/tree-profile.c | 144 |
1 files changed, 143 insertions, 1 deletions
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index 3ff39f34aec..2a4ec2ae9eb 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -45,15 +45,54 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "timevar.h" #include "value-prof.h" #include "ggc.h" +#include "cgraph.h" static GTY(()) tree gcov_type_node; static GTY(()) tree tree_interval_profiler_fn; static GTY(()) tree tree_pow2_profiler_fn; static GTY(()) tree tree_one_value_profiler_fn; +static GTY(()) tree tree_indirect_call_profiler_fn; +static GTY(()) tree ic_void_ptr_var; +static GTY(()) tree ic_gcov_type_ptr_var; +static GTY(()) tree ptr_void; + /* Do initialization work for the edge profiler. */ +/* Add code: + static gcov* __gcov_indirect_call_counters; // pointer to actual counter + static void* __gcov_indirect_call_callee; // actual callie addres +*/ +static void +tree_init_ic_make_global_vars (void) +{ + tree gcov_type_ptr; + + ptr_void = build_pointer_type (void_type_node); + + ic_void_ptr_var + = build_decl (VAR_DECL, + get_identifier ("__gcov_indirect_call_callee"), + ptr_void); + TREE_STATIC (ic_void_ptr_var) = 1; + TREE_PUBLIC (ic_void_ptr_var) = 0; + DECL_ARTIFICIAL (ic_void_ptr_var) = 1; + DECL_INITIAL (ic_void_ptr_var) = NULL; + assemble_variable (ic_void_ptr_var, 0, 0, 0); + + gcov_type_ptr = build_pointer_type (get_gcov_type ()); + ic_gcov_type_ptr_var + = build_decl (VAR_DECL, + get_identifier ("__gcov_indirect_call_counters"), + gcov_type_ptr); + TREE_STATIC (ic_gcov_type_ptr_var) = 1; + TREE_PUBLIC (ic_gcov_type_ptr_var) = 0; + DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1; + DECL_INITIAL (ic_gcov_type_ptr_var) = NULL; + assemble_variable (ic_gcov_type_ptr_var, 0, 0, 0); +} + static void tree_init_edge_profiler (void) { @@ -61,6 +100,7 @@ tree_init_edge_profiler (void) tree pow2_profiler_fn_type; tree one_value_profiler_fn_type; tree gcov_type_ptr; + tree ic_profiler_fn_type; if (!gcov_type_node) { @@ -93,6 +133,18 @@ tree_init_edge_profiler (void) tree_one_value_profiler_fn = build_fn_decl ("__gcov_one_value_profiler", one_value_profiler_fn_type); + + tree_init_ic_make_global_vars (); + + /* void (*) (gcov_type *, gcov_type, void *, void *) */ + ic_profiler_fn_type + = build_function_type_list (void_type_node, + gcov_type_ptr, gcov_type_node, + ptr_void, + ptr_void, NULL_TREE); + tree_indirect_call_profiler_fn + = build_fn_decl ("__gcov_indirect_call_profiler", + ic_profiler_fn_type); } } @@ -201,6 +253,90 @@ tree_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base) bsi_insert_before (&bsi, call, BSI_SAME_STMT); } + +/* Output instructions as GIMPLE trees for code to find the most + common called function in indirect call. + VALUE is the call expression whose indirect callie is profiled. + TAG is the tag of the section for counters, BASE is offset of the + counter position. */ + +static void +tree_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) +{ + tree tmp1, stmt1, stmt2, stmt3; + tree stmt = value->hvalue.stmt; + block_stmt_iterator bsi = bsi_for_stmt (stmt); + tree ref = tree_coverage_counter_ref (tag, base), ref_ptr; + + ref_ptr = force_gimple_operand_bsi (&bsi, + build_addr (ref, current_function_decl), + true, NULL_TREE); + + /* Insert code: + + __gcov_indirect_call_counters = get_relevant_counter_ptr (); + __gcov_indirect_call_callee = (void *) indirect call argument; + */ + + tmp1 = create_tmp_var (ptr_void, "PROF"); + stmt1 = build2 (GIMPLE_MODIFY_STMT, + build_pointer_type (get_gcov_type ()), + ic_gcov_type_ptr_var, ref_ptr); + stmt2 = build2 (GIMPLE_MODIFY_STMT, ptr_void, tmp1, + unshare_expr (value->hvalue.value)); + stmt3 = build2 (GIMPLE_MODIFY_STMT, ptr_void, + ic_void_ptr_var, tmp1); + + bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT); + bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT); + bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT); +} + + +/* Output instructions as GIMPLE trees for code to find the most + common called function in indirect call. Insert instructions at the + begining of every possible called function. + */ + +static void +tree_gen_ic_func_profiler (void) +{ + struct cgraph_node * c_node = cgraph_node (current_function_decl); + block_stmt_iterator bsi; + edge e; + basic_block bb; + edge_iterator ei; + tree stmt1; + tree args, tree_uid, cur_func; + + if (flag_unit_at_a_time) + { + if (!c_node->needed) + return; + } + + tree_init_edge_profiler (); + + FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) + { + bb = split_edge (e); + bsi = bsi_start (bb); + cur_func = force_gimple_operand_bsi (&bsi, + build_addr (current_function_decl, + current_function_decl), + true, NULL_TREE); + tree_uid = build_int_cst (gcov_type_node, c_node->pid); + args = tree_cons (NULL_TREE, ic_gcov_type_ptr_var, + tree_cons (NULL_TREE, tree_uid, + tree_cons (NULL_TREE, cur_func, + tree_cons (NULL_TREE, + ic_void_ptr_var, + NULL_TREE)))); + stmt1 = build_function_call_expr (tree_indirect_call_profiler_fn, args); + bsi_insert_after (&bsi, stmt1, BSI_SAME_STMT); + } +} + /* Output instructions as GIMPLE trees for code to find the most common value of a difference between two evaluations of an expression. VALUE is the expression whose value is profiled. TAG is the tag of the @@ -242,6 +378,11 @@ tree_profiling (void) if (cgraph_state == CGRAPH_STATE_FINISHED) return 0; branch_prob (); + + if (! flag_branch_probabilities + && flag_profile_values) + tree_gen_ic_func_profiler (); + if (flag_branch_probabilities && flag_profile_values && flag_value_profile_transformations) @@ -278,7 +419,8 @@ struct profile_hooks tree_profile_hooks = tree_gen_interval_profiler, /* gen_interval_profiler */ tree_gen_pow2_profiler, /* gen_pow2_profiler */ tree_gen_one_value_profiler, /* gen_one_value_profiler */ - tree_gen_const_delta_profiler /* gen_const_delta_profiler */ + tree_gen_const_delta_profiler,/* gen_const_delta_profiler */ + tree_gen_ic_profiler, /* gen_ic_profiler */ }; #include "gt-tree-profile.h" |