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:
Jan Hubicka 2013-08-10 22:52:06 +02:00 committed by Jan Hubicka
parent 5979aa5497
commit 748d71f394
5 changed files with 137 additions and 26 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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,

View File

@ -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))

View File

@ -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. */