https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96964

--- Comment #1 from Tom de Vries <vries at gcc dot gnu.org> ---
This is an attempt to implement it by using a fallback in libatomic (see also
PR96898):
...
diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md
index 4168190fa42..612240661f8 100644
--- a/gcc/config/nvptx/nvptx.md
+++ b/gcc/config/nvptx/nvptx.md
@@ -54,6 +54,7 @@
    UNSPECV_LOCK
    UNSPECV_CAS
    UNSPECV_XCHG
+   UNSPECV_TAS
    UNSPECV_BARSYNC
    UNSPECV_MEMBAR
    UNSPECV_MEMBAR_CTA
@@ -1667,6 +1668,35 @@
   "%.\\tatom%A1.b%T0.<logic>\\t%0, %1, %2;"
   [(set_attr "atomic" "true")])

+(define_insn "atomic_test_and_set"
+  [(set (match_operand:QI 0 "nvptx_register_operand" "=R")
+        (unspec_volatile:QI
+          [(match_operand:QI 1 "memory_operand" "+m")
+          (match_operand:SI 2 "const_int_operand")             ;; model
+         ]
+          UNSPECV_TAS))
+   (set (match_dup 1)
+        (unspec_volatile:QI [(match_dup 1)] UNSPECV_TAS))]
+  ""
+  { operands[1] = XEXP (operands[1], 0);
+    return
+      "// BEGIN GLOBAL FUNCTION DECL: __atomic_test_and_set_1\n"
+      ".extern .func (.param .u32 %%value_out)"
+      " __atomic_test_and_set_1 (.param .u64 %%in_ar0, .param .u32
%%in_ar1);\n"
+      "{\n"
+      " .param .u32 %%value_in;\n"
+      " .param .u64 %%out_arg1;\n"
+      " .reg.u64 %%ptr;\n"
+      " cvta.global.u64 %%ptr, %1;\n"
+      " st.param.u64 [%%out_arg1],%%ptr;\n"
+      " .param .u32 %%out_arg2;\n"
+      " st.param.u32 [%%out_arg2],%2;\n"
+      " call (%%value_in),__atomic_test_and_set_1,(%%out_arg1,%%out_arg2);\n"
+      " ld.param.u32 %0,[%%value_in];\n"
+      "}";
+  }
+[(set_attr "atomic" "true")])
+
 (define_insn "nvptx_barsync"
   [(unspec_volatile [(match_operand:SI 0 "nvptx_nonmemory_operand" "Ri")
                     (match_operand:SI 1 "const_int_operand")]
...

Funnily enough, doing this has the side-effect that the fallback
__atomic_test_and_set_1 in libatomic is fixed.

Reply via email to