On 9/8/20 8:51 AM, Tom de Vries wrote:
> Hi,
> 
> Add nvptx support to libatomic.
> 
> Given that atomic_test_and_set is not implemented for nvptx (PR96964), the
> compiler translates __atomic_test_and_set falling back onto the "Failing all
> else, assume a single threaded environment and simply perform the operation"
> case in expand_atomic_test_and_set, so it doesn't map onto an actual atomic
> operation.
> 
> Still, that counts as supported for the configure test of libatomic, so we
> end up with HAVE_ATOMIC_TAS_1/2/4/8/16 == 1, and the corresponding
> __atomic_test_and_set_1/2/4/8/16 in libatomic all using that non-atomic
> implementation.
> 
> Fix this by adding an atomic_test_and_set expansion for nvptx, that uses
> libatomics __atomic_test_and_set_1.
> 
> This again makes the configure tests for HAVE_ATOMIC_TAS_1/2/4/8/16 fail, so
> instead we use this case in tas_n.c:
> ...
> /* If this type is smaller than word-sized, fall back to a word-sized
>    compare-and-swap loop.  */
> bool
> SIZE(libat_test_and_set) (UTYPE *mptr, int smodel)
> ...
> which for __atomic_test_and_set_8 uses INVERT_MASK_8.
> 
> Add INVERT_MASK_8 in libatomic_i.h, as well as MASK_8.
> 
> Tested libatomic testsuite on nvptx.
> 
> Non-target bits (sync-builtins.def, libatomic_i.h) OK for trunk?
> 
> Any other comments?
> 
> Thanks,
> - Tom
> 
> [libatomic] Add nvptx support
> 
> gcc/ChangeLog:
> 
>       PR target/96964
>       * config/nvptx/nvptx.md (define_expand "atomic_test_and_set"): New
>       expansion.
>       * sync-builtins.def (BUILT_IN_ATOMIC_TEST_AND_SET_1): New builtin.
> 

I realized after reading the header comment of write_fn_proto_from_insn
in nvptx.c that I could drop the sync-builtins.def bit.  So, committed
without the sync-builtins.def change.

Thanks,
- Tom

> libatomic/ChangeLog:
> 
>       PR target/96898
>       * configure.tgt: Add nvptx.
>       * libatomic_i.h (MASK_8, INVERT_MASK_8): New macro definition.
>       * config/nvptx/host-config.h: New file.
>       * config/nvptx/lock.c: New file.
> 
> ---
>  gcc/config/nvptx/nvptx.md            | 16 +++++++++++
>  gcc/sync-builtins.def                |  2 ++
>  libatomic/config/nvptx/host-config.h | 56 
> ++++++++++++++++++++++++++++++++++++
>  libatomic/config/nvptx/lock.c        | 56 
> ++++++++++++++++++++++++++++++++++++
>  libatomic/configure.tgt              |  3 ++
>  libatomic/libatomic_i.h              |  2 ++
>  6 files changed, 135 insertions(+)
> 
> diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md
> index 4168190fa42..6178e6a0f77 100644
> --- a/gcc/config/nvptx/nvptx.md
> +++ b/gcc/config/nvptx/nvptx.md
> @@ -1667,6 +1667,22 @@
>    "%.\\tatom%A1.b%T0.<logic>\\t%0, %1, %2;"
>    [(set_attr "atomic" "true")])
>  
> +(define_expand "atomic_test_and_set"
> +  [(match_operand:SI 0 "nvptx_register_operand")     ;; bool success output
> +   (match_operand:QI 1 "memory_operand")             ;; memory
> +   (match_operand:SI 2 "const_int_operand")]         ;; model
> +  ""
> +{
> +  rtx libfunc;
> +  rtx addr;
> +  libfunc = init_one_libfunc ("__atomic_test_and_set_1");
> +  addr = convert_memory_address (ptr_mode, XEXP (operands[1], 0));
> +  emit_library_call_value (libfunc, operands[0], LCT_NORMAL, SImode,
> +                       addr, ptr_mode,
> +                       operands[2], SImode);
> +  DONE;
> +})
> +
>  (define_insn "nvptx_barsync"
>    [(unspec_volatile [(match_operand:SI 0 "nvptx_nonmemory_operand" "Ri")
>                    (match_operand:SI 1 "const_int_operand")]
> diff --git a/gcc/sync-builtins.def b/gcc/sync-builtins.def
> index 156a13ce0f8..b802257bd1a 100644
> --- a/gcc/sync-builtins.def
> +++ b/gcc/sync-builtins.def
> @@ -261,6 +261,8 @@ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SYNCHRONIZE, 
> "__sync_synchronize",
>  
>  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET, "__atomic_test_and_set",
>                 BT_FN_BOOL_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
> +DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET_1, "__atomic_test_and_set_1",
> +               BT_FN_BOOL_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
>  
>  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", 
> BT_FN_VOID_VPTR_INT,
>                 ATTR_NOTHROWCALL_LEAF_LIST)
> diff --git a/libatomic/config/nvptx/host-config.h 
> b/libatomic/config/nvptx/host-config.h
> new file mode 100644
> index 00000000000..eb9de81f388
> --- /dev/null
> +++ b/libatomic/config/nvptx/host-config.h
> @@ -0,0 +1,56 @@
> +/* Copyright (C) 2020 Free Software Foundation, Inc.
> +
> +   This file is part of the GNU Atomic Library (libatomic).
> +
> +   Libatomic is free software; you can redistribute it and/or modify it
> +   under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   Libatomic is distributed in the hope that it will be useful, but WITHOUT 
> ANY
> +   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
> +   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> +   more details.
> +
> +   Under Section 7 of GPL version 3, you are granted additional
> +   permissions described in the GCC Runtime Library Exception, version
> +   3.1, as published by the Free Software Foundation.
> +
> +   You should have received a copy of the GNU General Public License and
> +   a copy of the GCC Runtime Library Exception along with this program;
> +   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* Copied from libatomic/config/posix/host-config.h.  */
> +
> +/* Included after all more target-specific host-config.h.  */
> +
> +
> +#ifndef protect_start_end
> +# ifdef HAVE_ATTRIBUTE_VISIBILITY
> +#  pragma GCC visibility push(hidden)
> +# endif
> +
> +void libat_lock_1 (void *ptr);
> +void libat_unlock_1 (void *ptr);
> +
> +static inline UWORD
> +protect_start (void *ptr)
> +{
> +  libat_lock_1 (ptr);
> +  return 0;
> +}
> +
> +static inline void
> +protect_end (void *ptr, UWORD dummy UNUSED)
> +{
> +  libat_unlock_1 (ptr);
> +}
> +
> +# define protect_start_end 1
> +# ifdef HAVE_ATTRIBUTE_VISIBILITY
> +#  pragma GCC visibility pop
> +# endif
> +#endif /* protect_start_end */
> +
> +#include_next <host-config.h>
> diff --git a/libatomic/config/nvptx/lock.c b/libatomic/config/nvptx/lock.c
> new file mode 100644
> index 00000000000..dea85a3e5bd
> --- /dev/null
> +++ b/libatomic/config/nvptx/lock.c
> @@ -0,0 +1,56 @@
> +/* Copyright (C) 2020 Free Software Foundation, Inc.
> +
> +   This file is part of the GNU Atomic Library (libatomic).
> +
> +   Libatomic is free software; you can redistribute it and/or modify it
> +   under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   Libatomic is distributed in the hope that it will be useful, but WITHOUT 
> ANY
> +   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
> +   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> +   more details.
> +
> +   Under Section 7 of GPL version 3, you are granted additional
> +   permissions described in the GCC Runtime Library Exception, version
> +   3.1, as published by the Free Software Foundation.
> +
> +   You should have received a copy of the GNU General Public License and
> +   a copy of the GCC Runtime Library Exception along with this program;
> +   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +/* Functions libat_lock_n/libat_unlock_n based on GOMP_atomic_start/end in
> +   libgomp/atomic.c.  */
> +
> +#include "libatomic_i.h"
> +
> +static int atomic_lock;
> +
> +void
> +libat_lock_n (void *ptr __attribute__((unused)),
> +           size_t n __attribute__((unused)))
> +{
> +  while (__sync_lock_test_and_set (&atomic_lock, 1))
> +    ;  /* Spin.  */
> +}
> +
> +void
> +libat_unlock_n (void *ptr __attribute__((unused)),
> +             size_t n __attribute__((unused)))
> +{
> +  __sync_lock_release (&atomic_lock);
> +}
> +
> +void
> +libat_lock_1 (void *ptr)
> +{
> +  libat_lock_n (ptr, 1);
> +}
> +
> +void
> +libat_unlock_1 (void *ptr)
> +{
> +  libat_unlock_n (ptr, 1);
> +}
> diff --git a/libatomic/configure.tgt b/libatomic/configure.tgt
> index efb3b1efb68..7834e0a6528 100644
> --- a/libatomic/configure.tgt
> +++ b/libatomic/configure.tgt
> @@ -174,6 +174,9 @@ case "${target}" in
>       UNSUPPORTED=1
>       ;;
>  
> +  nvptx*-*-*)
> +     ;;
> +
>    *)
>       # Who are you?
>       UNSUPPORTED=1
> diff --git a/libatomic/libatomic_i.h b/libatomic/libatomic_i.h
> index 081b154e9d7..37de9921024 100644
> --- a/libatomic/libatomic_i.h
> +++ b/libatomic/libatomic_i.h
> @@ -109,9 +109,11 @@ typedef unsigned UWORD __attribute__((mode(word)));
>  #define MASK_1               ((UWORD)0xff)
>  #define MASK_2               ((UWORD)0xffff)
>  #define MASK_4               ((UWORD)0xffffffff)
> +#define MASK_8               ((UWORD)0xffffffffffffffff)
>  #define INVERT_MASK_1        ((UWORD)WORDS_BIGENDIAN << ((WORDSIZE - 1) * 
> CHAR_BIT))
>  #define INVERT_MASK_2        ((UWORD)WORDS_BIGENDIAN << ((WORDSIZE - 2) * 
> CHAR_BIT))
>  #define INVERT_MASK_4        ((UWORD)WORDS_BIGENDIAN << ((WORDSIZE - 4) * 
> CHAR_BIT))
> +#define INVERT_MASK_8        ((UWORD)WORDS_BIGENDIAN << ((WORDSIZE - 8) * 
> CHAR_BIT))
>  
>  /* Most of the files in this library are compiled multiple times with
>     N defined to be a power of 2 between 1 and 16.  The SIZE macro is
> 

Reply via email to