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.

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