aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-profile.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2017-06-09 14:54:53 +0200
committerMartin Liska <marxin@gcc.gnu.org>2017-06-09 12:54:53 +0000
commit4f751c5437988863e622fd8b3ff82ec65e281260 (patch)
treee9a69c8567c8e3789ca0f89d0560978b67d5d97b /gcc/tree-profile.c
parentf05d82a711d37d7958b6eda223f7afedb3eb5837 (diff)
downloadgcc-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.c59
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,
- &current_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, &current_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;