diff mbox

Speed-up indirect-call instrumentation

Message ID fc4af520-5e2d-734c-1493-bf05777b1d62@suse.cz
State New
Headers show

Commit Message

Martin Liška June 9, 2017, 12:17 p.m. UTC
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, &current_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?
Martin

Comments

Jan Hubicka June 9, 2017, 12:21 p.m. UTC | #1
> 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, &current_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 <mliska@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  <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.
> 
> libgcc/ChangeLog:
> 
> 2017-06-09  Martin Liska  <mliska@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,
> -					     &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;
> 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
>
Markus Trippelsdorf June 9, 2017, 4:56 p.m. UTC | #2
On 2017.06.09 at 14:17 +0200, Martin Liška wrote:
> 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, &current_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.

But it crashes on gcc.dg/pr78582.c with -O0.
diff mbox

Patch

From 178b505b99499bb620492507684f85dd604172c9 Mon Sep 17 00:00:00 2001
From: marxin <mliska@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  <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.

libgcc/ChangeLog:

2017-06-09  Martin Liska  <mliska@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,
-					     &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;
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