From 7d29f8e3dc105bcc948377a3c68250f555119d8c Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 3 Nov 2016 16:24:22 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 12 ++ gcc/profile.c | 14 +-- gcc/testsuite/ChangeLog | 6 + .../no_profile_instrument_function-attr-1.c | 2 +- .../gcc.dg/tree-prof/time-profiler-3.c | 22 ++++ gcc/tree-profile.c | 106 +++++++++++++----- gcc/value-prof.h | 5 +- libgcc/ChangeLog | 5 + libgcc/libgcov-profiler.c | 23 +--- 9 files changed, 134 insertions(+), 61 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab31eee859e..3a632556680 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2016-11-03 Martin Liska + + * 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 * config/rs6000/rs6000.c (rs6000_xcoff_declare_object_name): Use diff --git a/gcc/profile.c b/gcc/profile.c index 2564f07abf7..ef38f988a34 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -192,15 +192,9 @@ instrument_values (histogram_values values) gimple_gen_ior_profiler (hist, t, 0); break; - case HIST_TYPE_TIME_PROFILE: - { - 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; - } + case HIST_TYPE_TIME_PROFILE: + gimple_gen_time_profiler (t, 0); + break; default: gcc_unreachable (); @@ -1305,7 +1299,7 @@ branch_prob (void) { unsigned n_instrumented; - gimple_init_edge_profiler (); + gimple_init_gcov_profiler (); n_instrumented = instrument_edges (el); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5f59bd83962..5a0467fadaa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-11-03 Martin Liska + + * 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 PR libgcc/78067 diff --git a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c index c93d1718b64..e0c2600b400 100644 --- a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c +++ b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c @@ -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 "__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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c new file mode 100644 index 00000000000..69ce0260828 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c @@ -0,0 +1,22 @@ +/* { 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"} } */ diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index abeee92204e..09a702f8bb0 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -56,9 +56,9 @@ static GTY(()) tree tree_interval_profiler_fn; static GTY(()) tree tree_pow2_profiler_fn; static GTY(()) tree tree_one_value_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_ior_profiler_fn; +static GTY(()) tree tree_time_profiler_counter; static GTY(()) tree ic_void_ptr_var; @@ -75,7 +75,7 @@ static GTY(()) tree ptr_void; static void init_ic_make_global_vars (void) { - tree gcov_type_ptr; + tree gcov_type_ptr; ptr_void = build_pointer_type (void_type_node); @@ -119,7 +119,7 @@ init_ic_make_global_vars (void) /* Create the type and function decls for the interface with gcov. */ void -gimple_init_edge_profiler (void) +gimple_init_gcov_profiler (void) { tree interval_profiler_fn_type; tree pow2_profiler_fn_type; @@ -127,7 +127,6 @@ gimple_init_edge_profiler (void) tree gcov_type_ptr; tree ic_profiler_fn_type; tree average_profiler_fn_type; - tree time_profiler_fn_type; const char *profiler_fn_name; const char *fn_name; @@ -201,17 +200,17 @@ gimple_init_edge_profiler (void) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (tree_indirect_call_profiler_fn)); - /* void (*) (gcov_type *, gcov_type, void *) */ - time_profiler_fn_type - = build_function_type_list (void_type_node, - gcov_type_ptr, NULL_TREE); - fn_name = concat ("__gcov_time_profiler", fn_suffix, NULL); - tree_time_profiler_fn = build_fn_decl (fn_name, time_profiler_fn_type); - free (CONST_CAST (char *, fn_name)); - TREE_NOTHROW (tree_time_profiler_fn) = 1; - DECL_ATTRIBUTES (tree_time_profiler_fn) - = tree_cons (get_identifier ("leaf"), NULL, - DECL_ATTRIBUTES (tree_time_profiler_fn)); + tree_time_profiler_counter + = build_decl (UNKNOWN_LOCATION, VAR_DECL, + get_identifier ("__gcov_time_profiler_counter"), + get_gcov_type ()); + TREE_PUBLIC (tree_time_profiler_counter) = 1; + DECL_EXTERNAL (tree_time_profiler_counter) = 1; + TREE_STATIC (tree_time_profiler_counter) = 1; + DECL_ARTIFICIAL (tree_time_profiler_counter) = 1; + DECL_INITIAL (tree_time_profiler_counter) = NULL; + + varpool_node::finalize_decl (tree_time_profiler_counter); /* void (*) (gcov_type *, gcov_type) */ average_profiler_fn_type @@ -239,7 +238,6 @@ gimple_init_edge_profiler (void) DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn); DECL_ASSEMBLER_NAME (tree_one_value_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_ior_profiler_fn); } @@ -426,7 +424,7 @@ gimple_gen_ic_func_profiler (void) if (c_node->only_called_directly_p ()) return; - gimple_init_edge_profiler (); + gimple_init_gcov_profiler (); /* Insert code: @@ -460,16 +458,74 @@ gimple_gen_ic_func_profiler (void) counter position and GSI is the iterator we place the counter. */ void -gimple_gen_time_profiler (unsigned tag, unsigned base, - gimple_stmt_iterator &gsi) +gimple_gen_time_profiler (unsigned tag, unsigned base) { - tree ref_ptr = tree_coverage_counter_addr (tag, base); - gcall *call; + tree type = get_gcov_type (); + 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, - true, NULL_TREE, true, GSI_SAME_STMT); - call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr); - gsi_insert_before (&gsi, call, GSI_NEW_STMT); + /* Emit: if (counters[0] != 0). */ + gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0), + NULL, NULL); + 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 diff --git a/gcc/value-prof.h b/gcc/value-prof.h index 07e2b3b5840..02220acb206 100644 --- a/gcc/value-prof.h +++ b/gcc/value-prof.h @@ -96,15 +96,14 @@ bool check_ic_target (gcall *, struct cgraph_node *); /* 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_interval_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_ic_profiler (histogram_value, unsigned, unsigned); extern void gimple_gen_ic_func_profiler (void); -extern void gimple_gen_time_profiler (unsigned, unsigned, - gimple_stmt_iterator &); +extern void gimple_gen_time_profiler (unsigned, unsigned); extern void gimple_gen_average_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); diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index e81444c841c..e3a81f6b026 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2016-11-03 Martin Liska + + * libgcov-profiler.c (__gcov_time_profiler): Remove. + (__gcov_time_profiler_atomic): Likewise. + 2016-11-03 Bernd Edlinger PR libgcc/78067 diff --git a/libgcc/libgcov-profiler.c b/libgcc/libgcov-profiler.c index 38ed5f113e7..4f0a40675a2 100644 --- a/libgcc/libgcov-profiler.c +++ b/libgcc/libgcov-profiler.c @@ -342,30 +342,9 @@ __gcov_indirect_call_profiler_v2 (gcov_type value, void* cur_func) #ifdef L_gcov_time_profiler /* 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 - #ifdef L_gcov_average_profiler /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want -- 2.30.2