From patchwork Thu Nov 3 14:52:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 80676 Delivered-To: patch@linaro.org Received: by 10.140.97.247 with SMTP id m110csp674870qge; Thu, 3 Nov 2016 07:53:01 -0700 (PDT) X-Received: by 10.98.33.77 with SMTP id h74mr17564190pfh.104.1478184781247; Thu, 03 Nov 2016 07:53:01 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id 133si10004047pgh.245.2016.11.03.07.53.00 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 03 Nov 2016 07:53:01 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-440348-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-440348-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-440348-patch=linaro.org@gcc.gnu.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; q=dns; s=default; b=JOE53hDT50YavN+gpRbBDj+qDKclsDz+QirlI+XDAVlfpi8cBt BUCwZYbiwYHrQMLNsvpG5QoI9bBPlchFBMeYDHh5n8vldIr3oCc3rba/YLMDH0BX BT4y0XyHRBnnj+/H/1SH8UPAeLv94RmtCrHn4VBHAD4D7ZLqZzyOa9M6A= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:cc:message-id:date:mime-version:content-type; s= default; bh=9Pqs44UFSMFSOEhVlBTVBZOtLjc=; b=A5k1svipXRd/WrA/i/ug QMybyUdoUOZg6JYTAZ+1pJsMW/NkSmE00HXzzBBAIS9hkJKu3eNXwu1Nv/1crlbC Y4pRatpwquSDxEF7hv6n+HZHEoHCNqhBXGV1C5Oo6YkaCrb6TkSdyI01wN6coIpv rNHVtNrQG31sgRGt7n7fTWo= Received: (qmail 82000 invoked by alias); 3 Nov 2016 14:52:44 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 81379 invoked by uid 89); 3 Nov 2016 14:52:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.1 required=5.0 tests=BAYES_00, SPF_PASS, UNSUBSCRIBE_BODY autolearn=no version=3.3.2 spammy=9614, 4267, 3429, concat X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 03 Nov 2016 14:52:33 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 0526AAAC7; Thu, 3 Nov 2016 14:52:30 +0000 (UTC) From: =?UTF-8?Q?Martin_Li=c5=a1ka?= Subject: [PATCH] Make direct emission of time profiler counter To: GCC Patches Cc: Jan Hubicka Message-ID: Date: Thu, 3 Nov 2016 15:52:30 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 X-IsSubscribed: yes Hello. As Honza noticed we spent quite some time in __gcov_time_profiler: perf report for Postgres make check command: 4.10% postgres postgres[.]__gcov_time_profiler Thus I rewrote the profiling code directly to GIMPLE statements: _4 = __gcov7.main[0]; if (_4 == 0) goto ; else goto ; : time_profile_5 = __gcov_time_profiler_counter; time_profile_6 = time_profile_5 + 1; __gcov7.main[0] = time_profile_6; __gcov_time_profiler_counter = time_profile_6; thread-safe variant of the patch: _3 = __gcov7.foo[0]; if (_3 == 0) goto ; else goto ; : time_profiler_counter_ptr_4 = (long int) &__gcov_time_profiler_counter; time_profile_5 = __atomic_add_fetch_8 (time_profiler_counter_ptr_4, 1, 0); time_profile_6 = (long int) time_profile_5; __gcov7.foo[0] = time_profile_6; Patch can bootstrap on ppc64le-redhat-linux and survives regression tests. Ready to be installed? Martin >From 1a277ec6ef25cddbf0518b679fa8f1928cd3d891 Mon Sep 17 00:00:00 2001 From: marxin Date: Thu, 27 Oct 2016 09:37:34 +0200 Subject: [PATCH] Make direct emission of time profiler counter libgcc/ChangeLog: 2016-10-31 Martin Liska * libgcov-profiler.c (__gcov_time_profiler): Remove. (__gcov_time_profiler_atomic): Likewise. gcc/ChangeLog: 2016-10-31 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. gcc/testsuite/ChangeLog: 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. --- gcc/profile.c | 14 +-- .../gcc.dg/no_profile_instrument_function-attr-1.c | 2 +- gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c | 22 +++++ gcc/tree-profile.c | 106 ++++++++++++++++----- gcc/value-prof.h | 5 +- libgcc/libgcov-profiler.c | 23 +---- 6 files changed, 111 insertions(+), 61 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c diff --git a/gcc/profile.c b/gcc/profile.c index 2564f07..ef38f98 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/gcc.dg/no_profile_instrument_function-attr-1.c b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c index c93d171..e0c2600 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 0000000..69ce026 --- /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 abeee92..09a702f 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 07e2b3b..02220ac 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/libgcov-profiler.c b/libgcc/libgcov-profiler.c index 38ed5f1..4f0a406 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.10.1