> Hello. > > I discussed with Honza possibility to speed-up instrumentation that we do for > indirect call target tracking. By direct emission of: > > if (__gcov_indirect_call_callee != NULL) > __gcov_indirect_call_profiler_v2 (profile_id, ¤t_function_decl); > > we can save reduce # of execution of __gcov_indirect_call_profiler_v2 > function. > I measured that tramp3d (-O2 -fprofile-generate) goes from 7.1s to 6.3s. > > Apart from that I slightly change probability for direct instrumentation of > time profiler. > > Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. > > Ready to be installed?
OK, Thanks! Honza > Martin > >From 178b505b99499bb620492507684f85dd604172c9 Mon Sep 17 00:00:00 2001 > From: marxin <mli...@suse.cz> > Date: Fri, 9 Jun 2017 11:18:44 +0200 > Subject: [PATCH] Speed-up indirect-call instrumentation > > gcc/ChangeLog: > > 2017-06-09 Martin Liska <mli...@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. > > libgcc/ChangeLog: > > 2017-06-09 Martin Liska <mli...@suse.cz> > > * libgcov-profiler.c (__gcov_indirect_call_profiler_v2): > Reset __gcov_indirect_call_callee to NULL. > --- > gcc/tree-profile.c | 59 > ++++++++++++++++++++++++++++++++++------------- > libgcc/libgcov-profiler.c | 2 ++ > 2 files changed, 45 insertions(+), 16 deletions(-) > > diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c > index a49ec37f8bb..f5c06684402 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; > diff --git a/libgcc/libgcov-profiler.c b/libgcc/libgcov-profiler.c > index 067d762c2af..e4570a01318 100644 > --- a/libgcc/libgcov-profiler.c > +++ b/libgcc/libgcov-profiler.c > @@ -336,6 +336,8 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* > cur_func) > || (__LIBGCC_VTABLE_USES_DESCRIPTORS__ && __gcov_indirect_call_callee > && *(void **) cur_func == *(void **) __gcov_indirect_call_callee)) > __gcov_one_value_profiler_body (__gcov_indirect_call_counters, value, 0); > + > + __gcov_indirect_call_callee = NULL; > } > #endif > > -- > 2.13.0 >