]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[libatomic] Add nvptx support
authorTom de Vries <tdevries@suse.de>
Mon, 7 Sep 2020 08:47:25 +0000 (10:47 +0200)
committerTom de Vries <tdevries@suse.de>
Fri, 11 Sep 2020 10:06:15 +0000 (12:06 +0200)
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.

gcc/ChangeLog:

PR target/96964
* config/nvptx/nvptx.md (define_expand "atomic_test_and_set"): New
expansion.

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
libatomic/config/nvptx/host-config.h [new file with mode: 0644]
libatomic/config/nvptx/lock.c [new file with mode: 0644]
libatomic/configure.tgt
libatomic/libatomic_i.h

index 4168190fa42d208f9930e1f3632e4f967c4d81d7..6178e6a0f777c663aa7ed80f99f95805da532576 100644 (file)
   "%.\\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/libatomic/config/nvptx/host-config.h b/libatomic/config/nvptx/host-config.h
new file mode 100644 (file)
index 0000000..eb9de81
--- /dev/null
@@ -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 (file)
index 0000000..dea85a3
--- /dev/null
@@ -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);
+}
index efb3b1efb6898c23318a7082544d72ac0279d18c..7834e0a6528360e73a7b866b4aacd15d112ec9b5 100644 (file)
@@ -174,6 +174,9 @@ case "${target}" in
        UNSUPPORTED=1
        ;;
 
+  nvptx*-*-*)
+       ;;
+
   *)
        # Who are you?
        UNSUPPORTED=1
index 081b154e9d7778a1185d80474e985772b6a06a78..37de992102430f41ee380a83db6cd539fe21d914 100644 (file)
@@ -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