diff options
author | Martin Liska <mliska@suse.cz> | 2017-06-09 14:54:53 +0200 |
---|---|---|
committer | Martin Liska <marxin@gcc.gnu.org> | 2017-06-09 12:54:53 +0000 |
commit | 4f751c5437988863e622fd8b3ff82ec65e281260 (patch) | |
tree | e9a69c8567c8e3789ca0f89d0560978b67d5d97b /gcc/tree-profile.c | |
parent | f05d82a711d37d7958b6eda223f7afedb3eb5837 (diff) | |
download | gcc-4f751c5437988863e622fd8b3ff82ec65e281260.zip gcc-4f751c5437988863e622fd8b3ff82ec65e281260.tar.gz gcc-4f751c5437988863e622fd8b3ff82ec65e281260.tar.bz2 |
Speed-up indirect-call instrumentation
2017-06-09 Martin Liska <mliska@suse.cz>
* tree-profile.c (gimple_gen_ic_profiler): Update comment.
(gimple_gen_ic_func_profiler): Emit direct comparison
of __gcov_indirect_call_callee with NULL.
(gimple_gen_time_profiler): Change probability from
PROB_VERY_UNLIKELY to PROB_UNLIKELY.
2017-06-09 Martin Liska <mliska@suse.cz>
* libgcov-profiler.c (__gcov_indirect_call_profiler_v2):
Reset __gcov_indirect_call_callee to NULL.
From-SVN: r249058
Diffstat (limited to 'gcc/tree-profile.c')
-rw-r--r-- | gcc/tree-profile.c | 59 |
1 files changed, 43 insertions, 16 deletions
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index a49ec37..f5c0668 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -388,6 +388,13 @@ gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base) stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr (); stmt2: tmp1 = (void *) (indirect call argument value) stmt3: __gcov_indirect_call_callee = tmp1; + + Example: + f_1 = foo; + __gcov_indirect_call_counters = &__gcov4.main[0]; + PROF_9 = f_1; + __gcov_indirect_call_callee = PROF_9; + _4 = f_1 (); */ stmt1 = gimple_build_assign (ic_gcov_type_ptr_var, ref_ptr); @@ -410,9 +417,7 @@ void gimple_gen_ic_func_profiler (void) { struct cgraph_node * c_node = cgraph_node::get (current_function_decl); - gimple_stmt_iterator gsi; gcall *stmt1; - gassign *stmt2; tree tree_uid, cur_func, void0; if (c_node->only_called_directly_p ()) @@ -420,13 +425,43 @@ gimple_gen_ic_func_profiler (void) gimple_init_gcov_profiler (); + basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); + basic_block cond_bb = split_edge (single_succ_edge (entry)); + basic_block update_bb = split_edge (single_succ_edge (cond_bb)); + + edge true_edge = single_succ_edge (cond_bb); + true_edge->flags = EDGE_TRUE_VALUE; + + int probability; + if (DECL_VIRTUAL_P (current_function_decl)) + probability = PROB_VERY_LIKELY; + else + probability = PROB_UNLIKELY; + + true_edge->probability = probability; + edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest, + EDGE_FALSE_VALUE); + e->probability = REG_BR_PROB_BASE - true_edge->probability; + /* Insert code: - stmt1: __gcov_indirect_call_profiler_v2 (profile_id, - ¤t_function_decl) - */ - gsi = gsi_after_labels (split_edge (single_succ_edge - (ENTRY_BLOCK_PTR_FOR_FN (cfun)))); + if (__gcov_indirect_call_callee != NULL) + __gcov_indirect_call_profiler_v2 (profile_id, ¤t_function_decl); + + The function __gcov_indirect_call_profiler_v2 is responsible for + resetting __gcov_indirect_call_callee to NULL. */ + + gimple_stmt_iterator gsi = gsi_start_bb (cond_bb); + void0 = build_int_cst (build_pointer_type (void_type_node), 0); + + tree ref = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, true, NULL_TREE, + true, GSI_SAME_STMT); + + gcond *cond = gimple_build_cond (NE_EXPR, ref, + void0, NULL, NULL); + gsi_insert_before (&gsi, cond, GSI_NEW_STMT); + + gsi = gsi_after_labels (update_bb); cur_func = force_gimple_operand_gsi (&gsi, build_addr (current_function_decl), @@ -438,13 +473,6 @@ gimple_gen_ic_func_profiler (void) stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2, tree_uid, cur_func); gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT); - - /* Set __gcov_indirect_call_callee to 0, - so that calls from other modules won't get misattributed - to the last caller of the current callee. */ - void0 = build_int_cst (build_pointer_type (void_type_node), 0); - stmt2 = gimple_build_assign (ic_void_ptr_var, void0); - gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT); } /* Output instructions as GIMPLE tree at the beginning for each function. @@ -458,11 +486,10 @@ gimple_gen_time_profiler (unsigned tag, unsigned base) basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); basic_block cond_bb = split_edge (single_succ_edge (entry)); basic_block update_bb = split_edge (single_succ_edge (cond_bb)); - split_edge (single_succ_edge (update_bb)); edge true_edge = single_succ_edge (cond_bb); true_edge->flags = EDGE_TRUE_VALUE; - true_edge->probability = PROB_VERY_UNLIKELY; + true_edge->probability = PROB_UNLIKELY; edge e = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE); e->probability = REG_BR_PROB_BASE - true_edge->probability; |