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.