Commit 7d29f8e3 by Martin Liska Committed by Martin Liska

Make direct emission of time profiler counter

	* libgcov-profiler.c (__gcov_time_profiler): Remove.
	(__gcov_time_profiler_atomic): Likewise.
	* profile.c (instrument_values): Fix coding style.
	(branch_prob): Use renamed function.
	* tree-profile.c (init_ic_make_global_vars): Likewise.
	(gimple_init_edge_profiler): Rename to
	gimple_init_gcov_profiler.
	tree_time_profiler_counter variable declaration.
	(gimple_gen_time_profiler): Rewrite to do a direct gimple code
	emission.
	* value-prof.h: Remove an argument.
	* gcc.dg/no_profile_instrument_function-attr-1.c: Update scanned
	output.
	* gcc.dg/tree-prof/time-profiler-3.c: New test.

From-SVN: r241821
parent 5de3e2d8
2016-11-03 Martin Liska <mliska@suse.cz>
* profile.c (instrument_values): Fix coding style.
(branch_prob): Use renamed function.
* tree-profile.c (init_ic_make_global_vars): Likewise.
(gimple_init_edge_profiler): Rename to
gimple_init_gcov_profiler.
tree_time_profiler_counter variable declaration.
(gimple_gen_time_profiler): Rewrite to do a direct gimple code
emission.
* value-prof.h: Remove an argument.
2016-11-03 Richard Biener <rguenther@suse.de> 2016-11-03 Richard Biener <rguenther@suse.de>
* config/rs6000/rs6000.c (rs6000_xcoff_declare_object_name): Use * config/rs6000/rs6000.c (rs6000_xcoff_declare_object_name): Use
...@@ -193,14 +193,8 @@ instrument_values (histogram_values values) ...@@ -193,14 +193,8 @@ instrument_values (histogram_values values)
break; break;
case HIST_TYPE_TIME_PROFILE: case HIST_TYPE_TIME_PROFILE:
{ gimple_gen_time_profiler (t, 0);
basic_block bb =
split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
gimple_stmt_iterator gsi = gsi_start_bb (bb);
gimple_gen_time_profiler (t, 0, gsi);
break; break;
}
default: default:
gcc_unreachable (); gcc_unreachable ();
...@@ -1305,7 +1299,7 @@ branch_prob (void) ...@@ -1305,7 +1299,7 @@ branch_prob (void)
{ {
unsigned n_instrumented; unsigned n_instrumented;
gimple_init_edge_profiler (); gimple_init_gcov_profiler ();
n_instrumented = instrument_edges (el); n_instrumented = instrument_edges (el);
......
2016-11-03 Martin Liska <mliska@suse.cz>
* gcc.dg/no_profile_instrument_function-attr-1.c: Update scanned
output.
* gcc.dg/tree-prof/time-profiler-3.c: New test.
2016-11-03 Bernd Edlinger <bernd.edlinger@hotmail.de> 2016-11-03 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR libgcc/78067 PR libgcc/78067
......
...@@ -19,5 +19,5 @@ int main () ...@@ -19,5 +19,5 @@ int main ()
/* { dg-final { scan-tree-dump-times "__gcov0\\.main.* = PROF_edge_counter" 1 "optimized"} } */ /* { dg-final { scan-tree-dump-times "__gcov0\\.main.* = PROF_edge_counter" 1 "optimized"} } */
/* { dg-final { scan-tree-dump-times "__gcov_indirect_call_profiler_v2" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "__gcov_indirect_call_profiler_v2" 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "__gcov_time_profiler" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "__gcov_time_profiler_counter = " 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "__gcov_init" 1 "optimized" } } */ /* { dg-final { scan-tree-dump-times "__gcov_init" 1 "optimized" } } */
/* { dg-options "-O2 -fdump-ipa-profile -fprofile-update=atomic" } */
/* { dg-require-effective-target profile_update_atomic } */
__attribute__ ((noinline))
int foo()
{
return 0;
}
__attribute__ ((noinline))
int bar()
{
return 1;
}
int main ()
{
return foo ();
}
/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Read tp_first_run: 0" 1 "profile"} } */
/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Read tp_first_run: 1" 1 "profile"} } */
/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Read tp_first_run: 2" 1 "profile"} } */
...@@ -56,9 +56,9 @@ static GTY(()) tree tree_interval_profiler_fn; ...@@ -56,9 +56,9 @@ static GTY(()) tree tree_interval_profiler_fn;
static GTY(()) tree tree_pow2_profiler_fn; static GTY(()) tree tree_pow2_profiler_fn;
static GTY(()) tree tree_one_value_profiler_fn; static GTY(()) tree tree_one_value_profiler_fn;
static GTY(()) tree tree_indirect_call_profiler_fn; static GTY(()) tree tree_indirect_call_profiler_fn;
static GTY(()) tree tree_time_profiler_fn;
static GTY(()) tree tree_average_profiler_fn; static GTY(()) tree tree_average_profiler_fn;
static GTY(()) tree tree_ior_profiler_fn; 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_void_ptr_var;
...@@ -119,7 +119,7 @@ init_ic_make_global_vars (void) ...@@ -119,7 +119,7 @@ init_ic_make_global_vars (void)
/* Create the type and function decls for the interface with gcov. */ /* Create the type and function decls for the interface with gcov. */
void void
gimple_init_edge_profiler (void) gimple_init_gcov_profiler (void)
{ {
tree interval_profiler_fn_type; tree interval_profiler_fn_type;
tree pow2_profiler_fn_type; tree pow2_profiler_fn_type;
...@@ -127,7 +127,6 @@ gimple_init_edge_profiler (void) ...@@ -127,7 +127,6 @@ gimple_init_edge_profiler (void)
tree gcov_type_ptr; tree gcov_type_ptr;
tree ic_profiler_fn_type; tree ic_profiler_fn_type;
tree average_profiler_fn_type; tree average_profiler_fn_type;
tree time_profiler_fn_type;
const char *profiler_fn_name; const char *profiler_fn_name;
const char *fn_name; const char *fn_name;
...@@ -201,17 +200,17 @@ gimple_init_edge_profiler (void) ...@@ -201,17 +200,17 @@ gimple_init_edge_profiler (void)
= tree_cons (get_identifier ("leaf"), NULL, = tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
/* void (*) (gcov_type *, gcov_type, void *) */ tree_time_profiler_counter
time_profiler_fn_type = build_decl (UNKNOWN_LOCATION, VAR_DECL,
= build_function_type_list (void_type_node, get_identifier ("__gcov_time_profiler_counter"),
gcov_type_ptr, NULL_TREE); get_gcov_type ());
fn_name = concat ("__gcov_time_profiler", fn_suffix, NULL); TREE_PUBLIC (tree_time_profiler_counter) = 1;
tree_time_profiler_fn = build_fn_decl (fn_name, time_profiler_fn_type); DECL_EXTERNAL (tree_time_profiler_counter) = 1;
free (CONST_CAST (char *, fn_name)); TREE_STATIC (tree_time_profiler_counter) = 1;
TREE_NOTHROW (tree_time_profiler_fn) = 1; DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
DECL_ATTRIBUTES (tree_time_profiler_fn) DECL_INITIAL (tree_time_profiler_counter) = NULL;
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_time_profiler_fn)); varpool_node::finalize_decl (tree_time_profiler_counter);
/* void (*) (gcov_type *, gcov_type) */ /* void (*) (gcov_type *, gcov_type) */
average_profiler_fn_type average_profiler_fn_type
...@@ -239,7 +238,6 @@ gimple_init_edge_profiler (void) ...@@ -239,7 +238,6 @@ gimple_init_edge_profiler (void)
DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn); DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn); DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
DECL_ASSEMBLER_NAME (tree_time_profiler_fn);
DECL_ASSEMBLER_NAME (tree_average_profiler_fn); DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
DECL_ASSEMBLER_NAME (tree_ior_profiler_fn); DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
} }
...@@ -426,7 +424,7 @@ gimple_gen_ic_func_profiler (void) ...@@ -426,7 +424,7 @@ gimple_gen_ic_func_profiler (void)
if (c_node->only_called_directly_p ()) if (c_node->only_called_directly_p ())
return; return;
gimple_init_edge_profiler (); gimple_init_gcov_profiler ();
/* Insert code: /* Insert code:
...@@ -460,16 +458,74 @@ gimple_gen_ic_func_profiler (void) ...@@ -460,16 +458,74 @@ gimple_gen_ic_func_profiler (void)
counter position and GSI is the iterator we place the counter. */ counter position and GSI is the iterator we place the counter. */
void void
gimple_gen_time_profiler (unsigned tag, unsigned base, gimple_gen_time_profiler (unsigned tag, unsigned base)
gimple_stmt_iterator &gsi)
{ {
tree ref_ptr = tree_coverage_counter_addr (tag, base); tree type = get_gcov_type ();
gcall *call; basic_block cond_bb
= split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
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;
true_edge->probability = PROB_VERY_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;
gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
tree original_ref = tree_coverage_counter_ref (tag, base);
tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
true, GSI_SAME_STMT);
tree one = build_int_cst (type, 1);
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr, /* Emit: if (counters[0] != 0). */
true, NULL_TREE, true, GSI_SAME_STMT); gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr); NULL, NULL);
gsi_insert_before (&gsi, call, GSI_NEW_STMT); gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
gsi = gsi_start_bb (update_bb);
/* Emit: counters[0] = ++__gcov_time_profiler_counter. */
if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
{
tree ptr = make_temp_ssa_name (type, NULL, "time_profiler_counter_ptr");
tree addr = build1 (ADDR_EXPR, build_pointer_type (type),
tree_time_profiler_counter);
gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
? BUILT_IN_ATOMIC_ADD_FETCH_8:
BUILT_IN_ATOMIC_ADD_FETCH_4);
gcall *stmt = gimple_build_call (f, 3, ptr, one,
build_int_cst (integer_type_node,
MEMMODEL_RELAXED));
tree result_type = TREE_TYPE (TREE_TYPE (f));
tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
gimple_set_lhs (stmt, tmp);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
tmp = make_temp_ssa_name (type, NULL, "time_profile");
assign = gimple_build_assign (tmp, NOP_EXPR,
gimple_call_lhs (stmt));
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
assign = gimple_build_assign (original_ref, tmp);
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
}
else
{
tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
tmp = make_temp_ssa_name (type, NULL, "time_profile");
assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
one);
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
assign = gimple_build_assign (original_ref, tmp);
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
assign = gimple_build_assign (tree_time_profiler_counter, tmp);
gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
}
} }
/* Output instructions as GIMPLE trees to increment the average histogram /* Output instructions as GIMPLE trees to increment the average histogram
......
...@@ -96,15 +96,14 @@ bool check_ic_target (gcall *, struct cgraph_node *); ...@@ -96,15 +96,14 @@ bool check_ic_target (gcall *, struct cgraph_node *);
/* In tree-profile.c. */ /* In tree-profile.c. */
extern void gimple_init_edge_profiler (void); extern void gimple_init_gcov_profiler (void);
extern void gimple_gen_edge_profiler (int, edge); extern void gimple_gen_edge_profiler (int, edge);
extern void gimple_gen_interval_profiler (histogram_value, unsigned, unsigned); extern void gimple_gen_interval_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_pow2_profiler (histogram_value, unsigned, unsigned); extern void gimple_gen_pow2_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_one_value_profiler (histogram_value, unsigned, unsigned); extern void gimple_gen_one_value_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ic_profiler (histogram_value, unsigned, unsigned); extern void gimple_gen_ic_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ic_func_profiler (void); extern void gimple_gen_ic_func_profiler (void);
extern void gimple_gen_time_profiler (unsigned, unsigned, extern void gimple_gen_time_profiler (unsigned, unsigned);
gimple_stmt_iterator &);
extern void gimple_gen_average_profiler (histogram_value, unsigned, unsigned); extern void gimple_gen_average_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ior_profiler (histogram_value, unsigned, unsigned); extern void gimple_gen_ior_profiler (histogram_value, unsigned, unsigned);
extern void stream_out_histogram_value (struct output_block *, histogram_value); extern void stream_out_histogram_value (struct output_block *, histogram_value);
......
2016-11-03 Martin Liska <mliska@suse.cz>
* libgcov-profiler.c (__gcov_time_profiler): Remove.
(__gcov_time_profiler_atomic): Likewise.
2016-11-03 Bernd Edlinger <bernd.edlinger@hotmail.de> 2016-11-03 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR libgcc/78067 PR libgcc/78067
......
...@@ -342,30 +342,9 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func) ...@@ -342,30 +342,9 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func)
#ifdef L_gcov_time_profiler #ifdef L_gcov_time_profiler
/* Counter for first visit of each function. */ /* Counter for first visit of each function. */
static gcov_type function_counter; gcov_type __gcov_time_profiler_counter ATTRIBUTE_HIDDEN;
/* Sets corresponding COUNTERS if there is no value. */
void
__gcov_time_profiler (gcov_type* counters)
{
if (!counters[0])
counters[0] = ++function_counter;
}
#if GCOV_SUPPORTS_ATOMIC
/* Sets corresponding COUNTERS if there is no value.
Function is thread-safe. */
void
__gcov_time_profiler_atomic (gcov_type* counters)
{
if (!counters[0])
counters[0] = __atomic_add_fetch (&function_counter, 1, __ATOMIC_RELAXED);
}
#endif #endif
#endif
#ifdef L_gcov_average_profiler #ifdef L_gcov_average_profiler
/* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment