Workaround binutils PR14342
Workaround binutils PR14342 * tree-profile.c (init_ic_make_global_vars): Add LTO path. (gimple_init_edge_profiler): Likewise. (gimple_gen_ic_func_profiler): Likewise. * Makefile.in: Add _gcov_indirect_call_profiler_v2 symbol. * libgcov.c (L_gcov_indirect_call_profiler): Restore original API. (L_gcov_indirect_call_profiler_v2): New. From-SVN: r201648
This commit is contained in:
parent
5979aa5497
commit
748d71f394
5 changed files with 137 additions and 26 deletions
|
@ -1,3 +1,10 @@
|
|||
2013-08-10 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
Workaround binutils PR14342
|
||||
* tree-profile.c (init_ic_make_global_vars): Add LTO path.
|
||||
(gimple_init_edge_profiler): Likewise.
|
||||
(gimple_gen_ic_func_profiler): Likewise.
|
||||
|
||||
2013-08-09 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* cgraph.c (cgraph_create_edge_1): Clear speculative flag.
|
||||
|
|
|
@ -67,13 +67,28 @@ init_ic_make_global_vars (void)
|
|||
|
||||
ptr_void = build_pointer_type (void_type_node);
|
||||
|
||||
ic_void_ptr_var
|
||||
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
|
||||
get_identifier ("__gcov_indirect_call_callee"),
|
||||
ptr_void);
|
||||
/* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
|
||||
if (flag_lto)
|
||||
{
|
||||
ic_void_ptr_var
|
||||
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
|
||||
get_identifier ("__gcov_indirect_call_callee_ltopriv"),
|
||||
ptr_void);
|
||||
TREE_PUBLIC (ic_void_ptr_var) = 1;
|
||||
DECL_COMMON (ic_void_ptr_var) = 1;
|
||||
DECL_VISIBILITY (ic_void_ptr_var) = VISIBILITY_HIDDEN;
|
||||
DECL_VISIBILITY_SPECIFIED (ic_void_ptr_var) = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ic_void_ptr_var
|
||||
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
|
||||
get_identifier ("__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;
|
||||
TREE_PUBLIC (ic_void_ptr_var) = 1;
|
||||
DECL_EXTERNAL (ic_void_ptr_var) = 1;
|
||||
DECL_ARTIFICIAL (ic_void_ptr_var) = 1;
|
||||
DECL_INITIAL (ic_void_ptr_var) = NULL;
|
||||
if (targetm.have_tls)
|
||||
|
@ -83,13 +98,28 @@ init_ic_make_global_vars (void)
|
|||
varpool_finalize_decl (ic_void_ptr_var);
|
||||
|
||||
gcov_type_ptr = build_pointer_type (get_gcov_type ());
|
||||
ic_gcov_type_ptr_var
|
||||
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
|
||||
get_identifier ("__gcov_indirect_call_counters"),
|
||||
gcov_type_ptr);
|
||||
/* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
|
||||
if (flag_lto)
|
||||
{
|
||||
ic_gcov_type_ptr_var
|
||||
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
|
||||
get_identifier ("__gcov_indirect_call_counters_ltopriv"),
|
||||
gcov_type_ptr);
|
||||
TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
|
||||
DECL_COMMON (ic_gcov_type_ptr_var) = 1;
|
||||
DECL_VISIBILITY (ic_gcov_type_ptr_var) = VISIBILITY_HIDDEN;
|
||||
DECL_VISIBILITY_SPECIFIED (ic_gcov_type_ptr_var) = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ic_gcov_type_ptr_var
|
||||
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
|
||||
get_identifier ("__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;
|
||||
TREE_PUBLIC (ic_gcov_type_ptr_var) = 1;
|
||||
DECL_EXTERNAL (ic_gcov_type_ptr_var) = 1;
|
||||
DECL_ARTIFICIAL (ic_gcov_type_ptr_var) = 1;
|
||||
DECL_INITIAL (ic_gcov_type_ptr_var) = NULL;
|
||||
if (targetm.have_tls)
|
||||
|
@ -157,15 +187,31 @@ gimple_init_edge_profiler (void)
|
|||
|
||||
init_ic_make_global_vars ();
|
||||
|
||||
/* void (*) (gcov_type, void *) */
|
||||
ic_profiler_fn_type
|
||||
= build_function_type_list (void_type_node,
|
||||
gcov_type_node,
|
||||
ptr_void,
|
||||
NULL_TREE);
|
||||
tree_indirect_call_profiler_fn
|
||||
= build_fn_decl ("__gcov_indirect_call_profiler_v2",
|
||||
ic_profiler_fn_type);
|
||||
/* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
|
||||
if (flag_lto)
|
||||
{
|
||||
/* void (*) (gcov_type, void *) */
|
||||
ic_profiler_fn_type
|
||||
= build_function_type_list (void_type_node,
|
||||
gcov_type_ptr, gcov_type_node,
|
||||
ptr_void, ptr_void,
|
||||
NULL_TREE);
|
||||
tree_indirect_call_profiler_fn
|
||||
= build_fn_decl ("__gcov_indirect_call_profiler",
|
||||
ic_profiler_fn_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* void (*) (gcov_type, void *) */
|
||||
ic_profiler_fn_type
|
||||
= build_function_type_list (void_type_node,
|
||||
gcov_type_node,
|
||||
ptr_void,
|
||||
NULL_TREE);
|
||||
tree_indirect_call_profiler_fn
|
||||
= build_fn_decl ("__gcov_indirect_call_profiler_v2",
|
||||
ic_profiler_fn_type);
|
||||
}
|
||||
TREE_NOTHROW (tree_indirect_call_profiler_fn) = 1;
|
||||
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)
|
||||
= tree_cons (get_identifier ("leaf"), NULL,
|
||||
|
@ -375,8 +421,25 @@ gimple_gen_ic_func_profiler (void)
|
|||
true, GSI_SAME_STMT);
|
||||
tree_uid = build_int_cst
|
||||
(gcov_type_node, cgraph_get_node (current_function_decl)->profile_id);
|
||||
stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 2,
|
||||
tree_uid, cur_func);
|
||||
/* Workaround for binutils bug 14342. Once it is fixed, remove lto path. */
|
||||
if (flag_lto)
|
||||
{
|
||||
tree counter_ptr, ptr_var;
|
||||
counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var,
|
||||
true, NULL_TREE, true,
|
||||
GSI_SAME_STMT);
|
||||
ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var,
|
||||
true, NULL_TREE, true,
|
||||
GSI_SAME_STMT);
|
||||
|
||||
stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4,
|
||||
counter_ptr, tree_uid, cur_func, ptr_var);
|
||||
}
|
||||
else
|
||||
{
|
||||
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,
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2013-08-10 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
Work around binutils PR14342
|
||||
* Makefile.in: Add _gcov_indirect_call_profiler_v2 symbol.
|
||||
* libgcov.c (L_gcov_indirect_call_profiler): Restore original API.
|
||||
(L_gcov_indirect_call_profiler_v2): New.
|
||||
|
||||
2013-08-06 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* libgcov.c (__gcov_indirect_call_callee,
|
||||
|
|
|
@ -858,7 +858,7 @@ LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
|
|||
_gcov_execv _gcov_execvp _gcov_execve _gcov_reset _gcov_dump \
|
||||
_gcov_interval_profiler _gcov_pow2_profiler _gcov_one_value_profiler \
|
||||
_gcov_indirect_call_profiler _gcov_average_profiler _gcov_ior_profiler \
|
||||
_gcov_merge_ior
|
||||
_gcov_merge_ior _gcov_indirect_call_profiler_v2
|
||||
|
||||
libgcov-objects = $(patsubst %,%$(objext),$(LIBGCOV))
|
||||
|
||||
|
|
|
@ -1120,6 +1120,42 @@ __gcov_one_value_profiler (gcov_type *counters, gcov_type value)
|
|||
#endif
|
||||
|
||||
#ifdef L_gcov_indirect_call_profiler
|
||||
/* This function exist only for workaround of binutils bug 14342.
|
||||
Once this compatibility hack is obsolette, it can be removed. */
|
||||
|
||||
/* By default, the C++ compiler will use function addresses in the
|
||||
vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
|
||||
tells the compiler to use function descriptors instead. The value
|
||||
of this macro says how many words wide the descriptor is (normally 2),
|
||||
but it may be dependent on target flags. Since we do not have access
|
||||
to the target flags here we just check to see if it is set and use
|
||||
that to set VTABLE_USES_DESCRIPTORS to 0 or 1.
|
||||
|
||||
It is assumed that the address of a function descriptor may be treated
|
||||
as a pointer to a function. */
|
||||
|
||||
#ifdef TARGET_VTABLE_USES_DESCRIPTORS
|
||||
#define VTABLE_USES_DESCRIPTORS 1
|
||||
#else
|
||||
#define VTABLE_USES_DESCRIPTORS 0
|
||||
#endif
|
||||
|
||||
/* Tries to determine the most common value among its inputs. */
|
||||
void
|
||||
__gcov_indirect_call_profiler (gcov_type* counter, gcov_type value,
|
||||
void* cur_func, void* callee_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 == callee_func
|
||||
|| (VTABLE_USES_DESCRIPTORS && callee_func
|
||||
&& *(void **) cur_func == *(void **) callee_func))
|
||||
__gcov_one_value_profiler_body (counter, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef L_gcov_indirect_call_profiler_v2
|
||||
|
||||
/* These two variables are used to actually track caller and callee. Keep
|
||||
them in TLS memory so races are not common (they are written to often).
|
||||
|
@ -1135,7 +1171,6 @@ __thread
|
|||
#endif
|
||||
gcov_type * __gcov_indirect_call_counters;
|
||||
|
||||
|
||||
/* By default, the C++ compiler will use function addresses in the
|
||||
vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
|
||||
tells the compiler to use function descriptors instead. The value
|
||||
|
@ -1167,7 +1202,6 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func)
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef L_gcov_average_profiler
|
||||
/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
|
||||
to saturate up. */
|
||||
|
|
Loading…
Add table
Reference in a new issue