Fix divergence in indirect profiling (PR gcov-profile/84107).
authorMartin Liska <mliska@suse.cz>
Thu, 4 Oct 2018 12:41:14 +0000 (14:41 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Thu, 4 Oct 2018 12:41:14 +0000 (12:41 +0000)
2018-10-04  Martin Liska  <mliska@suse.cz>

PR gcov-profile/84107
* tree-profile.c (init_ic_make_global_vars):
Remove ic_void_ptr_var and ic_gcov_type_ptr_var.
Come up with new ic_tuple* variables.  Emit
__gcov_indirect_call{,_topn} variables.
(gimple_gen_ic_profiler): Access the variable
and emit gimple.
(gimple_gen_ic_func_profiler): Access
__gcov_indirect_call.callee field.
(gimple_init_gcov_profiler): Use ptr_type_node.
* value-prof.c (gimple_ic): Use ptr_type_node.
2018-10-04  Martin Liska  <mliska@suse.cz>

PR gcov-profile/84107
* libgcov-profiler.c (__gcov_indirect_call):
Change type to indirect_call_tuple.
(struct indirect_call_tuple): New struct.
(__gcov_indirect_call_topn_profiler): Change type.
(__gcov_indirect_call_profiler_v2): Use the new
variables.
* libgcov.h (struct indirect_call_tuple): New struct
definition.

From-SVN: r264840

gcc/ChangeLog
gcc/tree-profile.c
gcc/value-prof.c
libgcc/ChangeLog
libgcc/libgcov-profiler.c
libgcc/libgcov.h

index 8022aabfc2166821655dfc9bcdb31c1920d1756c..fdae3d1909ae2c20345caef45913c4dd9516fad6 100644 (file)
@@ -1,3 +1,17 @@
+2018-10-04  Martin Liska  <mliska@suse.cz>
+
+       PR gcov-profile/84107
+       * tree-profile.c (init_ic_make_global_vars):
+       Remove ic_void_ptr_var and ic_gcov_type_ptr_var.
+       Come up with new ic_tuple* variables.  Emit
+       __gcov_indirect_call{,_topn} variables.
+       (gimple_gen_ic_profiler): Access the variable
+       and emit gimple.
+       (gimple_gen_ic_func_profiler): Access
+       __gcov_indirect_call.callee field.
+       (gimple_init_gcov_profiler): Use ptr_type_node.
+       * value-prof.c (gimple_ic): Use ptr_type_node.
+
 2018-10-04  Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>
 
        PR tree-optimization/85787
index f96bd4b97048718ad33fb9eab3d22277cea20b8c..d8f2a3b1ba40b83d949a02afe57d51ce6645a48e 100644 (file)
@@ -53,6 +53,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "tree-pretty-print.h"
+#include "langhooks.h"
+#include "stor-layout.h"
 
 static GTY(()) tree gcov_type_node;
 static GTY(()) tree tree_interval_profiler_fn;
@@ -64,9 +66,9 @@ static GTY(()) tree tree_ior_profiler_fn;
 static GTY(()) tree tree_time_profiler_counter;
 
 
-static GTY(()) tree ic_void_ptr_var;
-static GTY(()) tree ic_gcov_type_ptr_var;
-static GTY(()) tree ptr_void;
+static GTY(()) tree ic_tuple_var;
+static GTY(()) tree ic_tuple_counters_field;
+static GTY(()) tree ic_tuple_callee_field;
 
 /* Do initialization work for the edge profiler.  */
 
@@ -80,39 +82,35 @@ init_ic_make_global_vars (void)
 {
   tree gcov_type_ptr;
 
-  ptr_void = build_pointer_type (void_type_node);
+  gcov_type_ptr = build_pointer_type (get_gcov_type ());
 
-  ic_void_ptr_var
-    = build_decl (UNKNOWN_LOCATION, VAR_DECL,
-                 get_identifier (
-                         (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
-                          "__gcov_indirect_call_topn_callee" :
-                          "__gcov_indirect_call_callee")),
-                 ptr_void);
-  TREE_PUBLIC (ic_void_ptr_var) = 1;
-  DECL_EXTERNAL (ic_void_ptr_var) = 1;
-  TREE_STATIC (ic_void_ptr_var) = 1;
-  DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
-  DECL_INITIAL (ic_void_ptr_var) = NULL;
-  if (targetm.have_tls)
-    set_decl_tls_model (ic_void_ptr_var, decl_default_tls_model (ic_void_ptr_var));
+  tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE);
 
-  gcov_type_ptr = build_pointer_type (get_gcov_type ());
+  /* callee */
+  ic_tuple_callee_field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
+                                     ptr_type_node);
 
-  ic_gcov_type_ptr_var
+  /* counters */
+  ic_tuple_counters_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                       NULL_TREE, gcov_type_ptr);
+  DECL_CHAIN (ic_tuple_counters_field) = ic_tuple_callee_field;
+
+  finish_builtin_struct (tuple_type, "indirect_call_tuple",
+                        ic_tuple_counters_field, NULL_TREE);
+
+  ic_tuple_var
     = build_decl (UNKNOWN_LOCATION, VAR_DECL,
                  get_identifier (
                          (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
-                          "__gcov_indirect_call_topn_counters" :
-                          "__gcov_indirect_call_counters")),
-                 gcov_type_ptr);
-  TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
-  DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
-  TREE_STATIC (ic_gcov_type_ptr_var) = 1;
-  DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
-  DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
+                          "__gcov_indirect_call_topn" :
+                          "__gcov_indirect_call")),
+                 tuple_type);
+  TREE_PUBLIC (ic_tuple_var) = 1;
+  DECL_ARTIFICIAL (ic_tuple_var) = 1;
+  DECL_INITIAL (ic_tuple_var) = NULL;
+  DECL_EXTERNAL (ic_tuple_var) = 1;
   if (targetm.have_tls)
-    set_decl_tls_model (ic_gcov_type_ptr_var, decl_default_tls_model (ic_gcov_type_ptr_var));
+    set_decl_tls_model (ic_tuple_var, decl_default_tls_model (tuple_type));
 }
 
 /* Create the type and function decls for the interface with gcov.  */
@@ -185,7 +183,7 @@ gimple_init_gcov_profiler (void)
       ic_profiler_fn_type
               = build_function_type_list (void_type_node,
                                          gcov_type_node,
-                                         ptr_void,
+                                         ptr_type_node,
                                          NULL_TREE);
       profiler_fn_name = "__gcov_indirect_call_profiler_v2";
       if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
@@ -388,22 +386,29 @@ gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
 
   /* Insert code:
 
-    stmt1: __gcov_indirect_call_counters = get_relevant_counter_ptr ();
+    stmt1: __gcov_indirect_call.counters = get_relevant_counter_ptr ();
     stmt2: tmp1 = (void *) (indirect call argument value)
-    stmt3: __gcov_indirect_call_callee = tmp1;
+    stmt3: __gcov_indirect_call.callee = tmp1;
 
     Example:
       f_1 = foo;
-      __gcov_indirect_call_counters = &__gcov4.main[0];
+      __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);
-  tmp1 = make_temp_ssa_name (ptr_void, NULL, "PROF");
+  tree gcov_type_ptr = build_pointer_type (get_gcov_type ());
+
+  tree counter_ref = build3 (COMPONENT_REF, gcov_type_ptr,
+                            ic_tuple_var, ic_tuple_counters_field, NULL_TREE);
+
+  stmt1 = gimple_build_assign (counter_ref, ref_ptr);
+  tmp1 = make_temp_ssa_name (ptr_type_node, NULL, "PROF");
   stmt2 = gimple_build_assign (tmp1, unshare_expr (value->hvalue.value));
-  stmt3 = gimple_build_assign (ic_void_ptr_var, gimple_assign_lhs (stmt2));
+  tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
+                            ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
+  stmt3 = gimple_build_assign (callee_ref, tmp1);
 
   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
@@ -459,9 +464,12 @@ gimple_gen_ic_func_profiler (void)
      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);
+  void0 = build_int_cst (ptr_type_node, 0);
+
+  tree callee_ref = build3 (COMPONENT_REF, ptr_type_node,
+                           ic_tuple_var, ic_tuple_callee_field, NULL_TREE);
 
-  tree ref = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, true, NULL_TREE,
+  tree ref = force_gimple_operand_gsi (&gsi, callee_ref, true, NULL_TREE,
                                       true, GSI_SAME_STMT);
 
   gcond *cond = gimple_build_cond (NE_EXPR, ref,
index 29489e0f85f7ffd3f514a1d8e6d5c42c22286947..60b982793d10a83b21accaefcaa3da95ad457c0e 100644 (file)
@@ -1290,7 +1290,6 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
   gcond *cond_stmt;
   tree tmp0, tmp1, tmp;
   basic_block cond_bb, dcall_bb, icall_bb, join_bb = NULL;
-  tree optype = build_pointer_type (void_type_node);
   edge e_cd, e_ci, e_di, e_dj = NULL, e_ij;
   gimple_stmt_iterator gsi;
   int lp_nr, dflags;
@@ -1300,13 +1299,13 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node *direct_call,
   cond_bb = gimple_bb (icall_stmt);
   gsi = gsi_for_stmt (icall_stmt);
 
-  tmp0 = make_temp_ssa_name (optype, NULL, "PROF");
-  tmp1 = make_temp_ssa_name (optype, NULL, "PROF");
+  tmp0 = make_temp_ssa_name (ptr_type_node, NULL, "PROF");
+  tmp1 = make_temp_ssa_name (ptr_type_node, NULL, "PROF");
   tmp = unshare_expr (gimple_call_fn (icall_stmt));
   load_stmt = gimple_build_assign (tmp0, tmp);
   gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
 
-  tmp = fold_convert (optype, build_addr (direct_call->decl));
+  tmp = fold_convert (ptr_type_node, build_addr (direct_call->decl));
   load_stmt = gimple_build_assign (tmp1, tmp);
   gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
 
index d4abb3b11ca35ba02f58d6b5fc5be911005abd64..798712993b8d07248c25a0ed5389c1307f8e9b2d 100644 (file)
@@ -1,3 +1,15 @@
+2018-10-04  Martin Liska  <mliska@suse.cz>
+
+       PR gcov-profile/84107
+       * libgcov-profiler.c (__gcov_indirect_call):
+       Change type to indirect_call_tuple.
+       (struct indirect_call_tuple): New struct.
+       (__gcov_indirect_call_topn_profiler): Change type.
+       (__gcov_indirect_call_profiler_v2): Use the new
+       variables.
+       * libgcov.h (struct indirect_call_tuple): New struct
+       definition.
+
 2018-10-03  Uros Bizjak  <ubizjak@gmail.com>
 
        * libgcc2.c (isnan): Use __builtin_isnan.
index 7e208d75d86ba8c1a23b2fd38b7504bc81763ab3..7a5e50009ce15032c312cb7593bab052a5e2021d 100644 (file)
@@ -271,12 +271,7 @@ __gcov_topn_value_profiler_body (gcov_type *counters, gcov_type value)
 #if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
 __thread
 #endif
-gcov_type *__gcov_indirect_call_topn_counters ATTRIBUTE_HIDDEN;
-
-#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
-__thread
-#endif
-void *__gcov_indirect_call_topn_callee ATTRIBUTE_HIDDEN;
+struct indirect_call_tuple __gcov_indirect_call_topn;
 
 #ifdef TARGET_VTABLE_USES_DESCRIPTORS
 #define VTABLE_USES_DESCRIPTORS 1
@@ -290,14 +285,14 @@ void *__gcov_indirect_call_topn_callee ATTRIBUTE_HIDDEN;
 void
 __gcov_indirect_call_topn_profiler (gcov_type value, void* cur_func)
 {
-  void *callee_func = __gcov_indirect_call_topn_callee;
+  void *callee_func = __gcov_indirect_call_topn.callee;
   /* If the C++ virtual tables contain function descriptors then one
      function may have multiple descriptors and we need to dereference
      the descriptors to see if they point to the same function.  */
   if (cur_func == callee_func
       || (VTABLE_USES_DESCRIPTORS && callee_func
          && *(void **) cur_func == *(void **) callee_func))
-    __gcov_topn_value_profiler_body (__gcov_indirect_call_topn_counters, value);
+    __gcov_topn_value_profiler_body (__gcov_indirect_call_topn.counters, value);
 }
 #endif
 
@@ -311,11 +306,7 @@ __gcov_indirect_call_topn_profiler (gcov_type value, void* cur_func)
 #if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
 __thread
 #endif
-void * __gcov_indirect_call_callee;
-#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
-__thread
-#endif
-gcov_type * __gcov_indirect_call_counters;
+struct indirect_call_tuple __gcov_indirect_call;
 
 /* By default, the C++ compiler will use function addresses in the
    vtable entries.  Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
@@ -332,12 +323,12 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func)
   /* If the C++ virtual tables contain function descriptors then one
      function may have multiple descriptors and we need to dereference
      the descriptors to see if they point to the same function.  */
-  if (cur_func == __gcov_indirect_call_callee
+  if (cur_func == __gcov_indirect_call.callee
       || (__LIBGCC_VTABLE_USES_DESCRIPTORS__
-          && *(void **) cur_func == *(void **) __gcov_indirect_call_callee))
-    __gcov_one_value_profiler_body (__gcov_indirect_call_counters, value, 0);
+         && *(void **) cur_func == *(void **) __gcov_indirect_call.callee))
+    __gcov_one_value_profiler_body (__gcov_indirect_call.counters, value, 0);
 
-  __gcov_indirect_call_callee = NULL;
+  __gcov_indirect_call.callee = NULL;
 }
 #endif
 
index 21422873cf2260899d91a8bdb0c4a5ea9dc53ff9..ee05a68d2b2705d2d92524227bee2ced63cc81bb 100644 (file)
@@ -226,6 +226,15 @@ struct gcov_master
   gcov_unsigned_t version;
   struct gcov_root *root;
 };
+
+struct indirect_call_tuple
+{
+  /* Callee function.  */
+  void *callee;
+
+  /* Pointer to counters.  */
+  gcov_type *counters;
+};
   
 /* Exactly one of these will be active in the process.  */
 extern struct gcov_master __gcov_master;