Speed-up indirect-call instrumentation
authorMartin Liska <mliska@suse.cz>
Fri, 9 Jun 2017 12:54:53 +0000 (14:54 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Fri, 9 Jun 2017 12:54:53 +0000 (12:54 +0000)
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

gcc/ChangeLog
gcc/tree-profile.c
libgcc/ChangeLog
libgcc/libgcov-profiler.c

index b5b16918642cda4170fb8280e0f9849fae08d4bc..b9612cf0ba883b5b50e8c4093e0ef344457d2471 100644 (file)
@@ -1,3 +1,11 @@
+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  Jan Hubicka  <hubicka@ucw.cz>
 
        * profile.c (edge_gcov_counts): Turn to pointer.
index a49ec37f8bbc7d3608f21e0108ded34d747501fc..f5c066844022c4050f7cd61e430c5c6bbbdc7be0 100644 (file)
@@ -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;
index 5d531d9cea63d4a0a9a6276291d16d7902f44697..9a97dba918fdea82b39de5a4ed21c3e6beb2c4db 100644 (file)
@@ -1,3 +1,8 @@
+2017-06-09  Martin Liska  <mliska@suse.cz>
+
+       * libgcov-profiler.c (__gcov_indirect_call_profiler_v2):
+       Reset __gcov_indirect_call_callee to NULL.
+
 2017-06-08  Olivier Hainque  <hainque@adacore.com>
 
        * config/t-vxworks (LIBGCC2_INCLUDES): Add path to wrn/coreip to
index 067d762c2af5c9ba6eec468fd9e493c8cd25f957..e4570a01318b47fa7a038f8a08e4226812abd2ad 100644 (file)
@@ -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