From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17616 invoked by alias); 16 Aug 2016 12:56:10 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 17604 invoked by uid 89); 16 Aug 2016 12:56:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.5 required=5.0 tests=BAYES_05,SPF_PASS autolearn=ham version=3.3.2 spammy=Detect, 3x, Map, AFTER 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; Tue, 16 Aug 2016 12:55:58 +0000 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 99872AD54; Tue, 16 Aug 2016 12:55:56 +0000 (UTC) Subject: [PATCH] Detect whether target can use -fprofile-update=atomic To: Nathan Sidwell , gcc-patches@gcc.gnu.org References: <53c4f874443d63de99393a9816041ba75f1d605e.1470041316.git.mliska@suse.cz> <95628fa2-8719-bb82-d1ab-ca8d46355020@acm.org> <0ec1ad3f-0fc7-507e-878c-907adae1c011@suse.cz> <0e248978-3717-1d78-b3b1-9fc60ded5c8e@suse.cz> <882f0f98-9b33-a764-833b-ca61796f3143@acm.org> <87f2bc4f-c4df-eadd-aec6-a937ed0ccaba@acm.org> <1253ac69-3301-f185-e43a-a34cadf8f51e@suse.cz> <67fda6d2-9b3e-a0d1-effc-34e1115030b2@acm.org> <1ff3cc75-7cee-79f3-395b-ef7a4d286a3d@acm.org> <04a05835-4666-4d7d-c1a9-d4bcc4ea924a@suse.cz> Cc: jh@suse.cz, Andreas Schwab From: =?UTF-8?Q?Martin_Li=c5=a1ka?= Message-ID: <19c4a81d-6ecd-8c6e-b641-e257c1959baf@suse.cz> Date: Tue, 16 Aug 2016 12:56:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2 MIME-Version: 1.0 In-Reply-To: <04a05835-4666-4d7d-c1a9-d4bcc4ea924a@suse.cz> Content-Type: multipart/mixed; boundary="------------632E873B871D34E9EF3FDBDD" X-IsSubscribed: yes X-SW-Source: 2016-08/txt/msg01178.txt.bz2 This is a multi-part message in MIME format. --------------632E873B871D34E9EF3FDBDD Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Content-length: 904 Hello. As reported in [1], m68k has been broken since I installed the patch. Reason is that the target does not support atomic operations (add, or) for a mode of gcov_type. Because of that, we see an undefined symbols. Proper fix contains of 2 parts: a) compiler emission must verify that -fprofile-update=atomic is doable for a given target; it's done via a new function can_generate_atomic_builtin b) libgcc must detect whether __atomic_fetch_add_x can be expanded on the target; that requires configure support and if the target is not capable to expand these, we must conditionally remove all gcov_.*profiler_atomic functions from libgcov.a. Andreas reported that it fixes the test-case mentioned in the PR and I tested that on -march=i386. Apart from that I've been doing bootstrap on x86_64-linux-gnu. Ready after it finishes? Martin [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58306#c30 --------------632E873B871D34E9EF3FDBDD Content-Type: text/x-patch; name="0002-Detect-whether-target-can-use-fprofile-update-atomic.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0002-Detect-whether-target-can-use-fprofile-update-atomic.pa"; filename*1="tch" Content-length: 16467 >From a5c6dbdbabc36193f7becce78af58b276b0d3660 Mon Sep 17 00:00:00 2001 From: marxin Date: Tue, 16 Aug 2016 10:13:13 +0200 Subject: [PATCH 2/2] Detect whether target can use -fprofile-update=atomic gcc/ChangeLog: 2016-08-12 Martin Liska * optabs.c (can_generate_atomic_builtin): New function. * optabs.h (can_generate_atomic_builtin): Declare the function. * tree-profile.c (tree_profiling): Detect whether target can use -fprofile-update=atomic. gcc/testsuite/ChangeLog: 2016-08-12 Martin Liska * gcc.dg/profile-update-warning.c: New test. libgcc/ChangeLog: 2016-08-16 Martin Liska * acinclude.m4: New file. * config.in: New macro defines. * configure: Regenerated. * configure.ac: Detect atomic operations. * libgcov-profiler.c: Detect GCOV_SUPPORTS_ATOMIC and conditionaly enable/disable *_atomic functions. --- gcc/optabs.c | 13 ++ gcc/optabs.h | 5 + gcc/testsuite/gcc.dg/profile-update-warning.c | 7 + gcc/tree-profile.c | 18 +++ libgcc/acinclude.m4 | 22 ++++ libgcc/config.in | 15 ++- libgcc/configure | 179 +++++++++++++++++++++++++- libgcc/configure.ac | 8 ++ libgcc/libgcov-profiler.c | 24 +++- 9 files changed, 279 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/profile-update-warning.c create mode 100644 libgcc/acinclude.m4 diff --git a/gcc/optabs.c b/gcc/optabs.c index 87b4f97..3be0dfe 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6476,6 +6476,19 @@ get_atomic_op_for_code (struct atomic_op_functions *op, enum rtx_code code) } } +bool +can_generate_atomic_builtin (enum rtx_code code, machine_mode mode) +{ + struct atomic_op_functions optab; + get_atomic_op_for_code (&optab, code); + enum insn_code icode = direct_optab_handler (optab.mem_no_result, mode); + if (icode != CODE_FOR_nothing) + return true; + + return can_compare_and_swap_p (mode, false) + || can_compare_and_swap_p (mode, true); +} + /* See if there is a more optimal way to implement the operation "*MEM CODE VAL" using memory order MODEL. If AFTER is true the operation needs to return the value of *MEM after the operation, otherwise the previous value. diff --git a/gcc/optabs.h b/gcc/optabs.h index 03fd94d..769685a 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -348,4 +348,9 @@ extern void expand_jump_insn (enum insn_code icode, unsigned int nops, extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp); +/* Return true when a target is capable of expansion of an atomic builtin + with CODE of a specified machine MODE. */ + +extern bool can_generate_atomic_builtin (enum rtx_code code, machine_mode mode); + #endif /* GCC_OPTABS_H */ diff --git a/gcc/testsuite/gcc.dg/profile-update-warning.c b/gcc/testsuite/gcc.dg/profile-update-warning.c new file mode 100644 index 0000000..0614fad --- /dev/null +++ b/gcc/testsuite/gcc.dg/profile-update-warning.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fprofile-update=atomic -fprofile-generate -march=i386 -m32" } */ + +int main(int argc, char *argv[]) +{ + return 0; +} /* { dg-warning "target does not support atomic profile update, single mode is selected" } */ diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index 622869e..799de84 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -49,6 +49,8 @@ along with GCC; see the file COPYING3. If not see #include "profile.h" #include "tree-cfgcleanup.h" #include "params.h" +#include "rtl.h" +#include "optabs.h" static GTY(()) tree gcov_type_node; static GTY(()) tree tree_interval_profiler_fn; @@ -535,6 +537,22 @@ tree_profiling (void) { struct cgraph_node *node; + /* Verify whether we can utilize atomic update operations. */ + if (flag_profile_update == PROFILE_UPDATE_ATOMIC) + { + machine_mode mode = mode_for_size (LONG_LONG_TYPE_SIZE > 32 ? 64: 32, + MODE_INT, 1); + bool r = can_generate_atomic_builtin (PLUS, mode) + && can_generate_atomic_builtin (IOR, mode); + + if (!r) + { + warning (0, "target does not support atomic profile update, " + "single mode is selected"); + flag_profile_update = PROFILE_UPDATE_SINGLE; + } + } + /* This is a small-ipa pass that gets called only once, from cgraphunit.c:ipa_passes(). */ gcc_assert (symtab->state == IPA_SSA); diff --git a/libgcc/acinclude.m4 b/libgcc/acinclude.m4 new file mode 100644 index 0000000..87ac32b --- /dev/null +++ b/libgcc/acinclude.m4 @@ -0,0 +1,22 @@ +dnl Check whether the target supports __atomic_operations. +AC_DEFUN([LIBGCC_CHECK_ATOMIC_OPERATION], [ + AC_CACHE_CHECK([whether the target supports atomic operations for $1B], + libgcc_cv_have_atomic_operations_$1, [ + libgcc_cv_have_atomic_operations_$1=no + + AC_LANG_CONFTEST( + [AC_LANG_PROGRAM([[int foovar = 0;]], [[__atomic_fetch_add_$1 (&foovar, 1, 0); + __atomic_fetch_or_$1 (&foovar, 1, 0)]])]) + if AC_TRY_COMMAND(${CC-cc} -Werror -S -o conftest.s conftest.c 1>&AS_MESSAGE_LOG_FD); then + if grep __atomic_fetch_add_$1 conftest.s > /dev/null; then + : + else + libgcc_cv_have_atomic_operations_$1=yes + fi + fi + rm -f conftest.* + ]) + if test $libgcc_cv_have_atomic_operations_$1 = yes; then + AC_DEFINE(HAVE_ATOMIC_OPERATIONS_$1, 1, + [Define to 1 if the target supports atomic operations for $1B]) + fi]) diff --git a/libgcc/config.in b/libgcc/config.in index 4d33411..03e848c 100644 --- a/libgcc/config.in +++ b/libgcc/config.in @@ -1,5 +1,17 @@ /* config.in. Generated from configure.ac by autoheader. */ +/* Define to 1 if the target supports atomic operations for 16B */ +#undef HAVE_ATOMIC_OPERATIONS_16 + +/* Define to 1 if the target supports atomic operations for 32B */ +#undef HAVE_ATOMIC_OPERATIONS_32 + +/* Define to 1 if the target supports atomic operations for 4B */ +#undef HAVE_ATOMIC_OPERATIONS_4 + +/* Define to 1 if the target supports atomic operations for 8B */ +#undef HAVE_ATOMIC_OPERATIONS_8 + /* Define to 1 if the target assembler supports thread-local storage. */ #undef HAVE_CC_TLS @@ -21,9 +33,6 @@ /* Define if the system-provided CRTs are present on Solaris. */ #undef HAVE_SOLARIS_CRTS -/* Define if the system-provided CRTs are present on Solaris. */ -#undef HAVE_SOLARIS_CRTS - /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H diff --git a/libgcc/configure b/libgcc/configure index bf96aec..0058467 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -2321,10 +2321,6 @@ case "${host}" in ;; i[34567]86-*-mingw* | x86_64-*-mingw*) ;; - i[34567]86-*-interix[3-9]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; i[34567]86-*-nto-qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. @@ -5080,6 +5076,180 @@ esac +# Check out sync builtins support. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports atomic operations for 32B" >&5 +$as_echo_n "checking whether the target supports atomic operations for 32B... " >&6; } +if test "${libgcc_cv_have_atomic_operations_32+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + libgcc_cv_have_atomic_operations_32=no + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foovar = 0; +int +main () +{ +__atomic_fetch_add_32 (&foovar, 1, 0); + __atomic_fetch_or_32 (&foovar, 1, 0) + ; + return 0; +} +_ACEOF + if { ac_try='${CC-cc} -Werror -S -o conftest.s conftest.c 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if grep __atomic_fetch_add_32 conftest.s > /dev/null; then + : + else + libgcc_cv_have_atomic_operations_32=yes + fi + fi + rm -f conftest.* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_have_atomic_operations_32" >&5 +$as_echo "$libgcc_cv_have_atomic_operations_32" >&6; } + if test $libgcc_cv_have_atomic_operations_32 = yes; then + +$as_echo "#define HAVE_ATOMIC_OPERATIONS_32 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports atomic operations for 16B" >&5 +$as_echo_n "checking whether the target supports atomic operations for 16B... " >&6; } +if test "${libgcc_cv_have_atomic_operations_16+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + libgcc_cv_have_atomic_operations_16=no + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foovar = 0; +int +main () +{ +__atomic_fetch_add_16 (&foovar, 1, 0); + __atomic_fetch_or_16 (&foovar, 1, 0) + ; + return 0; +} +_ACEOF + if { ac_try='${CC-cc} -Werror -S -o conftest.s conftest.c 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if grep __atomic_fetch_add_16 conftest.s > /dev/null; then + : + else + libgcc_cv_have_atomic_operations_16=yes + fi + fi + rm -f conftest.* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_have_atomic_operations_16" >&5 +$as_echo "$libgcc_cv_have_atomic_operations_16" >&6; } + if test $libgcc_cv_have_atomic_operations_16 = yes; then + +$as_echo "#define HAVE_ATOMIC_OPERATIONS_16 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports atomic operations for 8B" >&5 +$as_echo_n "checking whether the target supports atomic operations for 8B... " >&6; } +if test "${libgcc_cv_have_atomic_operations_8+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + libgcc_cv_have_atomic_operations_8=no + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foovar = 0; +int +main () +{ +__atomic_fetch_add_8 (&foovar, 1, 0); + __atomic_fetch_or_8 (&foovar, 1, 0) + ; + return 0; +} +_ACEOF + if { ac_try='${CC-cc} -Werror -S -o conftest.s conftest.c 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if grep __atomic_fetch_add_8 conftest.s > /dev/null; then + : + else + libgcc_cv_have_atomic_operations_8=yes + fi + fi + rm -f conftest.* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_have_atomic_operations_8" >&5 +$as_echo "$libgcc_cv_have_atomic_operations_8" >&6; } + if test $libgcc_cv_have_atomic_operations_8 = yes; then + +$as_echo "#define HAVE_ATOMIC_OPERATIONS_8 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports atomic operations for 4B" >&5 +$as_echo_n "checking whether the target supports atomic operations for 4B... " >&6; } +if test "${libgcc_cv_have_atomic_operations_4+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + libgcc_cv_have_atomic_operations_4=no + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foovar = 0; +int +main () +{ +__atomic_fetch_add_4 (&foovar, 1, 0); + __atomic_fetch_or_4 (&foovar, 1, 0) + ; + return 0; +} +_ACEOF + if { ac_try='${CC-cc} -Werror -S -o conftest.s conftest.c 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + if grep __atomic_fetch_add_4 conftest.s > /dev/null; then + : + else + libgcc_cv_have_atomic_operations_4=yes + fi + fi + rm -f conftest.* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_have_atomic_operations_4" >&5 +$as_echo "$libgcc_cv_have_atomic_operations_4" >&6; } + if test $libgcc_cv_have_atomic_operations_4 = yes; then + +$as_echo "#define HAVE_ATOMIC_OPERATIONS_4 1" >>confdefs.h + + fi + # Substitute configuration variables @@ -5100,6 +5270,7 @@ ac_config_files="$ac_config_files Makefile" ac_config_commands="$ac_config_commands default" + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 269997f..f74be17 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -11,6 +11,7 @@ sinclude(../config/dfp.m4) sinclude(../config/unwind_ipinfo.m4) sinclude(../config/gthr.m4) sinclude(../config/sjlj.m4) +sinclude(acinclude.m4) AC_PREREQ(2.64) AC_INIT([GNU C Runtime Library], 1.0,,[libgcc]) @@ -544,6 +545,12 @@ AC_SUBST(tm_defines) # Map from thread model to thread header. GCC_AC_THREAD_HEADER([$target_thread_file]) +# Check out sync builtins support. +LIBGCC_CHECK_ATOMIC_OPERATION(32) +LIBGCC_CHECK_ATOMIC_OPERATION(16) +LIBGCC_CHECK_ATOMIC_OPERATION(8) +LIBGCC_CHECK_ATOMIC_OPERATION(4) + # Substitute configuration variables AC_SUBST(cpu_type) AC_SUBST(extra_parts) @@ -572,4 +579,5 @@ CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} libgcc_topdir=${libgcc_topdir} CC="${CC}" ]]) + AC_OUTPUT diff --git a/libgcc/libgcov-profiler.c b/libgcc/libgcov-profiler.c index 70a821d..d07f81a 100644 --- a/libgcc/libgcov-profiler.c +++ b/libgcc/libgcov-profiler.c @@ -24,8 +24,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include "libgcov.h" +#include "auto-target.h" #if !defined(inhibit_libc) +/* Detect whether target can support atomic update of profilers. */ +#if LONG_LONG_TYPE_SIZE <= 32 && HAVE_ATOMIC_OPERATIONS_4 +#define GCOV_SUPPORTS_ATOMIC 1 +#else +#if LONG_LONG_TYPE_SIZE > 32 && HAVE_ATOMIC_OPERATIONS_8 +#define GCOV_SUPPORTS_ATOMIC 1 +#else +#define GCOV_SUPPORTS_ATOMIC 0 +#endif +#endif + #ifdef L_gcov_interval_profiler /* If VALUE is in interval , then increases the corresponding counter in COUNTERS. If the VALUE is above or below @@ -46,7 +58,7 @@ __gcov_interval_profiler (gcov_type *counters, gcov_type value, } #endif -#ifdef L_gcov_interval_profiler_atomic +#if defined(L_gcov_interval_profiler_atomic) && GCOV_SUPPORTS_ATOMIC /* If VALUE is in interval , then increases the corresponding counter in COUNTERS. If the VALUE is above or below the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased @@ -80,7 +92,7 @@ __gcov_pow2_profiler (gcov_type *counters, gcov_type value) } #endif -#ifdef L_gcov_pow2_profiler_atomic +#if defined(L_gcov_pow2_profiler_atomic) && GCOV_SUPPORTS_ATOMIC /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise COUNTERS[0] is incremented. Function is thread-safe. */ @@ -134,7 +146,7 @@ __gcov_one_value_profiler (gcov_type *counters, gcov_type value) } #endif -#ifdef L_gcov_one_value_profiler_atomic +#if defined(L_gcov_one_value_profiler_atomic) && GCOV_SUPPORTS_ATOMIC /* Update one value profilers (COUNTERS) for a given VALUE. @@ -342,6 +354,7 @@ __gcov_time_profiler (gcov_type* counters) counters[0] = ++function_counter; } +#if GCOV_SUPPORTS_ATOMIC /* Sets corresponding COUNTERS if there is no value. Function is thread-safe. */ @@ -352,6 +365,7 @@ __gcov_time_profiler_atomic (gcov_type* counters) counters[0] = __atomic_add_fetch (&function_counter, 1, MEMMODEL_RELAXED); } #endif +#endif #ifdef L_gcov_average_profiler @@ -366,7 +380,7 @@ __gcov_average_profiler (gcov_type *counters, gcov_type value) } #endif -#ifdef L_gcov_average_profiler_atomic +#if defined(L_gcov_average_profiler_atomic) && GCOV_SUPPORTS_ATOMIC /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want to saturate up. Function is thread-safe. */ @@ -388,7 +402,7 @@ __gcov_ior_profiler (gcov_type *counters, gcov_type value) } #endif -#ifdef L_gcov_ior_profiler_atomic +#if defined(L_gcov_ior_profiler_atomic) && GCOV_SUPPORTS_ATOMIC /* Bitwise-OR VALUE into COUNTER. Function is thread-safe. */ void -- 2.9.2 --------------632E873B871D34E9EF3FDBDD--