llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-hlsl

Author: Joshua Batista (bob80905)

<details>
<summary>Changes</summary>

Compiling HLSL `InterlockedOr`/`InterlockedAdd`/`InterlockedXor` against
`groupshared` (or UAV) destinations through the clang HLSL→SPIR-V path
(`clang-dxc -spirv`) produced SPIR-V that `spirv-val` rejects for Vulkan.
The failure surfaced as a cascade of three independent, layered validation
errors, each masking the next. This patch fixes all three so a compute shader
using `groupshared` atomics validates cleanly against Vulkan 1.3.

The three bugs

1. Illegal OpCapability Linkage.
groupshared variables are emitted as `external hidden addrspace(3)`
(Workgroup) declarations. `getSpirvLinkageTypeFor` gave any non-interface
declaration `Import` linkage, which adds a `LinkageAttributes` decoration and
forces `OpCapability` Linkage, which is illegal in a Vulkan shader.
Fix: in a shader environment (no linker), Workgroup/Private declarations get
no linkage. Kernels (e.g. HIP dynamic LDS) still use `Import` as before.
2. Atomic memory scope `CrossDevice`.
`handleInterlockedOp` emitted `atomicrmw` with no syncscope, defaulting to
 System -&gt; CrossDevice, which Vulkan forbids (max is Device).
Fix: tag the atomic with a syncscope chosen by destination address space:
"workgroup" for groupshared , "device" otherwise. DXIL ignores the
syncscope, so its output is unchanged in behavior.
3. Storage-class semantics bit on a relaxed atomic.
`selectAtomicRMW` unconditionally OR'd the storage-class memory-semantics bit
(e.g. WorkgroupMemory ) onto the order bits. For a relaxed (monotonic) order
this yields a storage-class bit with no Acquire/Release, which Vulkan rejects
( VUID-StandaloneSpirv-MemorySemantics-10871 ).
Fix: in a shader environment, drop the storage-class bit when the order is
relaxed ( None ).

Fixes: https://github.com/llvm/offload-test-suite/issues/1404
Assisted by: Github Copilot

---

Patch is 48.03 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/212663.diff


16 Files Affected:

- (modified) clang/lib/CodeGen/CGHLSLBuiltins.cpp (+12-1) 
- (modified) clang/test/CodeGenHLSL/builtins/InterlockedAdd.hlsl (+12-12) 
- (modified) clang/test/CodeGenHLSL/builtins/InterlockedOr.hlsl (+12-12) 
- (modified) clang/test/CodeGenHLSL/builtins/InterlockedXor.hlsl (+13-13) 
- (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl (+6-6) 
- (modified) 
clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedAdd.hlsl (+8-8) 
- (modified) 
clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedOr.hlsl (+8-8) 
- (modified) 
clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedXor.hlsl (+8-8) 
- (modified) 
clang/test/CodeGenHLSL/builtins/RasterizerOrderedByteAddressBuffer-InterlockedAdd.hlsl
 (+4-4) 
- (modified) 
clang/test/CodeGenHLSL/builtins/RasterizerOrderedByteAddressBuffer-InterlockedOr.hlsl
 (+4-4) 
- (modified) 
clang/test/CodeGenHLSL/builtins/RasterizerOrderedByteAddressBuffer-InterlockedXor.hlsl
 (+4-4) 
- (modified) llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp (+3) 
- (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+13-1) 
- (modified) llvm/lib/Target/SPIRV/SPIRVUtils.cpp (+8-1) 
- (added) llvm/test/CodeGen/SPIRV/atomicrmw-vulkan-relaxed-workgroup.ll (+26) 
- (added) llvm/test/CodeGen/SPIRV/linkage/groupshared-no-import-linkage.ll 
(+31) 


``````````diff
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp 
b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 0796d121a9b43..9818f94fcdaca 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -310,6 +310,16 @@ static Value *handleElementwiseF32ToF16(CodeGenFunction 
&CGF,
   llvm_unreachable("Intrinsic F32ToF16 not supported by target architecture");
 }
 
+// Pick the atomic memory scope for an HLSL Interlocked* op by destination:
+// Workgroup for groupshared, Device otherwise (Vulkan forbids CrossDevice).
+static llvm::SyncScope::ID GetInterlockedScope(CodeGenFunction &CGF,
+                                               const LValue &DestLV) {
+  StringRef ScopeName = DestLV.getAddressSpace() == LangAS::hlsl_groupshared
+                            ? "workgroup"
+                            : "device";
+  return CGF.getLLVMContext().getOrInsertSyncScopeID(ScopeName);
+}
+
 static Value *handleInterlockedOp(CodeGenFunction &CGF, const CallExpr *E,
                                   llvm::AtomicRMWInst::BinOp Op) {
   // Emit `atomicrmw <op>` directly — no intermediate intrinsic needed on
@@ -321,7 +331,8 @@ static Value *handleInterlockedOp(CodeGenFunction &CGF, 
const CallExpr *E,
          "Intrinsic InterlockedOp value operand must be an integer");
 
   llvm::AtomicRMWInst *Call = CGF.Builder.CreateAtomicRMW(
-      Op, DestAddr, Val, llvm::AtomicOrdering::Monotonic);
+      Op, DestAddr, Val, llvm::AtomicOrdering::Monotonic,
+      GetInterlockedScope(CGF, DestLV));
 
   // The 3-arg overload writes the old value (the RMW's return value) into
   // the `original_value` reference parameter.
diff --git a/clang/test/CodeGenHLSL/builtins/InterlockedAdd.hlsl 
b/clang/test/CodeGenHLSL/builtins/InterlockedAdd.hlsl
index 6bb4fd25c4a0c..a878c372dcea6 100644
--- a/clang/test/CodeGenHLSL/builtins/InterlockedAdd.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/InterlockedAdd.hlsl
@@ -14,45 +14,45 @@ groupshared int64_t  gs_i64;
 groupshared uint64_t gs_u64;
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int_2arg
-// DXCHECK:  atomicrmw add ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw add ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw add ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw add ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_int_2arg(int v) {
   InterlockedAdd(gs_i32, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint_2arg
-// DXCHECK:  atomicrmw add ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw add ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw add ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw add ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_uint_2arg(uint v) {
   InterlockedAdd(gs_u32, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i32 %[[R]], ptr {{.*}}
 export void test_int_3arg(int v, out int orig) {
   InterlockedAdd(gs_i32, v, orig);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i32 %[[R]], ptr {{.*}}
 export void test_uint_3arg(uint v, out uint orig) {
   InterlockedAdd(gs_u32, v, orig);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int64_2arg
-// DXCHECK:  atomicrmw add ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw add ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw add ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw add ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_int64_2arg(int64_t v) {
   InterlockedAdd(gs_i64, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint64_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw add ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i64 %[[R]], ptr {{.*}}
 export void test_uint64_3arg(uint64_t v, out uint64_t orig) {
   InterlockedAdd(gs_u64, v, orig);
diff --git a/clang/test/CodeGenHLSL/builtins/InterlockedOr.hlsl 
b/clang/test/CodeGenHLSL/builtins/InterlockedOr.hlsl
index 9c23c5a055a03..c5def7368ecc6 100644
--- a/clang/test/CodeGenHLSL/builtins/InterlockedOr.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/InterlockedOr.hlsl
@@ -14,45 +14,45 @@ groupshared int64_t  gs_i64;
 groupshared uint64_t gs_u64;
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int_2arg
-// DXCHECK:  atomicrmw or ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw or ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw or ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw or ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_int_2arg(int v) {
   InterlockedOr(gs_i32, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint_2arg
-// DXCHECK:  atomicrmw or ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw or ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw or ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw or ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_uint_2arg(uint v) {
   InterlockedOr(gs_u32, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i32 %[[R]], ptr {{.*}}
 export void test_int_3arg(int v, out int orig) {
   InterlockedOr(gs_i32, v, orig);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i32 %[[R]], ptr {{.*}}
 export void test_uint_3arg(uint v, out uint orig) {
   InterlockedOr(gs_u32, v, orig);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int64_2arg
-// DXCHECK:  atomicrmw or ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw or ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw or ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw or ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_int64_2arg(int64_t v) {
   InterlockedOr(gs_i64, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint64_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw or ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i64 %[[R]], ptr {{.*}}
 export void test_uint64_3arg(uint64_t v, out uint64_t orig) {
   InterlockedOr(gs_u64, v, orig);
diff --git a/clang/test/CodeGenHLSL/builtins/InterlockedXor.hlsl 
b/clang/test/CodeGenHLSL/builtins/InterlockedXor.hlsl
index 8cd799c09eb01..e0a60736980ec 100644
--- a/clang/test/CodeGenHLSL/builtins/InterlockedXor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/InterlockedXor.hlsl
@@ -6,7 +6,7 @@
 // RUN:   spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | \
 // RUN:   FileCheck %s --check-prefixes=CHECK,SPVCHECK
 
-// Test basic lowering of HLSL InterlockedXor to `atomicrmw or monotonic`.
+// Test basic lowering of HLSL InterlockedXor to `atomicrmw xor monotonic`.
 
 groupshared int  gs_i32;
 groupshared uint gs_u32;
@@ -14,45 +14,45 @@ groupshared int64_t  gs_i64;
 groupshared uint64_t gs_u64;
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int_2arg
-// DXCHECK:  atomicrmw xor ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw xor ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw xor ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw xor ptr addrspace(3) {{.*}}@gs_i32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_int_2arg(int v) {
   InterlockedXor(gs_i32, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint_2arg
-// DXCHECK:  atomicrmw xor ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw xor ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw xor ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw xor ptr addrspace(3) {{.*}}@gs_u32{{.*}}, i32 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_uint_2arg(uint v) {
   InterlockedXor(gs_u32, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_i32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i32 %[[R]], ptr {{.*}}
 export void test_int_3arg(int v, out int orig) {
   InterlockedXor(gs_i32, v, orig);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_u32{{.*}}, 
i32 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i32 %[[R]], ptr {{.*}}
 export void test_uint_3arg(uint v, out uint orig) {
   InterlockedXor(gs_u32, v, orig);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_int64_2arg
-// DXCHECK:  atomicrmw xor ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
monotonic
-// SPVCHECK: atomicrmw xor ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
monotonic
+// DXCHECK:  atomicrmw xor ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
syncscope("workgroup") monotonic
+// SPVCHECK: atomicrmw xor ptr addrspace(3) {{.*}}@gs_i64{{.*}}, i64 %{{.*}} 
syncscope("workgroup") monotonic
 export void test_int64_2arg(int64_t v) {
   InterlockedXor(gs_i64, v);
 }
 
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_uint64_3arg
-// DXCHECK:  %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} monotonic
-// SPVCHECK: %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} syncscope("workgroup") monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw xor ptr addrspace(3) {{.*}}@gs_u64{{.*}}, 
i64 %{{.*}} syncscope("workgroup") monotonic
 // CHECK:    store i64 %[[R]], ptr {{.*}}
 export void test_uint64_3arg(uint64_t v, out uint64_t orig) {
   InterlockedXor(gs_u64, v, orig);
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl 
b/clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl
index 4d7050ba3a43c..0ef2b86bc45a5 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl
@@ -18,17 +18,17 @@ RWBuffer<int> Out : register(u0);
 
 // CHECK-LABEL: define void @main
 // DXCHECK:  %[[PTR1:.*]] = call {{.*}} 
@llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t.i32(target("dx.TypedBuffer",
 i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
-// DXCHECK:  atomicrmw add ptr %[[PTR1]], i32 1 monotonic
+// DXCHECK:  atomicrmw add ptr %[[PTR1]], i32 1 syncscope("device") monotonic
 // DXCHECK:  %[[PTR2:.*]] = call {{.*}} 
@llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t.i32(target("dx.TypedBuffer",
 i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
-// DXCHECK:  atomicrmw or ptr %[[PTR2]], i32 1 monotonic
+// DXCHECK:  atomicrmw or ptr %[[PTR2]], i32 1 syncscope("device") monotonic
 // DXCHECK:  %[[PTR3:.*]] = call {{.*}} 
@llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t.i32(target("dx.TypedBuffer",
 i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
-// DXCHECK:  atomicrmw xor ptr %[[PTR3]], i32 1 monotonic
+// DXCHECK:  atomicrmw xor ptr %[[PTR3]], i32 1 syncscope("device") monotonic
 // SPVCHECK: %[[PTR1:.*]] = call {{.*}} 
@llvm.spv.resource.getpointer.{{.*}}(target("spirv.{{Image|SignedImage}}", i32, 
{{.*}}) %{{.*}}, i32 %{{.*}})
-// SPVCHECK: atomicrmw add ptr addrspace(11) %[[PTR1]], i32 1 monotonic
+// SPVCHECK: atomicrmw add ptr addrspace(11) %[[PTR1]], i32 1 
syncscope("device") monotonic
 // SPVCHECK: %[[PTR2:.*]] = call {{.*}} 
@llvm.spv.resource.getpointer.{{.*}}(target("spirv.{{Image|SignedImage}}", i32, 
{{.*}}) %{{.*}}, i32 %{{.*}})
-// SPVCHECK: atomicrmw or ptr addrspace(11) %[[PTR2]], i32 1 monotonic
+// SPVCHECK: atomicrmw or ptr addrspace(11) %[[PTR2]], i32 1 
syncscope("device") monotonic
 // SPVCHECK: %[[PTR3:.*]] = call {{.*}} 
@llvm.spv.resource.getpointer.{{.*}}(target("spirv.{{Image|SignedImage}}", i32, 
{{.*}}) %{{.*}}, i32 %{{.*}})
-// SPVCHECK: atomicrmw xor ptr addrspace(11) %[[PTR3]], i32 1 monotonic
+// SPVCHECK: atomicrmw xor ptr addrspace(11) %[[PTR3]], i32 1 
syncscope("device") monotonic
 [shader("compute")]
 [numthreads(1,1,1)]
 void main(uint3 id : SV_DispatchThreadID) {
diff --git 
a/clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedAdd.hlsl 
b/clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedAdd.hlsl
index 576a1f0b70b95..5342c0a7c93f7 100644
--- a/clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedAdd.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedAdd.hlsl
@@ -16,10 +16,10 @@ RWByteAddressBuffer BAB : register(u0);
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_bab_int_2arg
 // DXCHECK:  %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr {{.*}}
 // DXCHECK:  %[[PTR:.*]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t.i32(target("dx.RawBuffer",
 i8, 1, 0) %[[HANDLE]], i32 %{{.*}})
-// DXCHECK:  atomicrmw add ptr %[[PTR]], i32 %{{.*}} monotonic
+// DXCHECK:  atomicrmw add ptr %[[PTR]], i32 %{{.*}} syncscope("device") 
monotonic
 // SPVCHECK: %[[HANDLE:.*]] = load target("spirv.VulkanBuffer", [0 x i8], 12, 
1), ptr {{.*}}
 // SPVCHECK: %[[PTR:.*]] = call ptr addrspace(11) 
@llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i8_12_1t.i32(target("spirv.VulkanBuffer",
 [0 x i8], 12, 1) %[[HANDLE]], i32 %{{.*}})
-// SPVCHECK: atomicrmw add ptr addrspace(11) %[[PTR]], i32 %{{.*}} monotonic
+// SPVCHECK: atomicrmw add ptr addrspace(11) %[[PTR]], i32 %{{.*}} 
syncscope("device") monotonic
 export void test_bab_int_2arg(uint off, int v) {
   BAB.InterlockedAdd(off, v);
 }
@@ -27,11 +27,11 @@ export void test_bab_int_2arg(uint off, int v) {
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_bab_uint_3arg
 // DXCHECK:  %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr {{.*}}
 // DXCHECK:  %[[PTR:.*]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t.i32(target("dx.RawBuffer",
 i8, 1, 0) %[[HANDLE]], i32 %{{.*}})
-// DXCHECK:  %[[R:.*]] = atomicrmw add ptr %[[PTR]], i32 %{{.*}} monotonic
+// DXCHECK:  %[[R:.*]] = atomicrmw add ptr %[[PTR]], i32 %{{.*}} 
syncscope("device") monotonic
 // DXCHECK:  store i32 %[[R]], ptr {{.*}}
 // SPVCHECK: %[[HANDLE:.*]] = load target("spirv.VulkanBuffer", [0 x i8], 12, 
1), ptr {{.*}}
 // SPVCHECK: %[[PTR:.*]] = call ptr addrspace(11) 
@llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i8_12_1t.i32(target("spirv.VulkanBuffer",
 [0 x i8], 12, 1) %[[HANDLE]], i32 %{{.*}})
-// SPVCHECK: %[[R:.*]] = atomicrmw add ptr addrspace(11) %[[PTR]], i32 %{{.*}} 
monotonic
+// SPVCHECK: %[[R:.*]] = atomicrmw add ptr addrspace(11) %[[PTR]], i32 %{{.*}} 
syncscope("device") monotonic
 // SPVCHECK: store i32 %[[R]], ptr {{.*}}
 export void test_bab_uint_3arg(uint off, uint v, out uint orig) {
   BAB.InterlockedAdd(off, v, orig);
@@ -40,10 +40,10 @@ export void test_bab_uint_3arg(uint off, uint v, out uint 
orig) {
 // CHECK-LABEL: define {{(dso_local |hidden |internal |protected |spir_func 
)*}}void @{{.*}}test_bab_int64_2arg
 // DXCHECK:  %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr {{.*}}
 // DXCHECK:  %[[PTR:.*]] = call ptr 
@llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t.i32(target("dx.RawBuffer",
 i8, 1, 0) %[[HANDLE]], i32 %{{.*}})
-// DXCHECK:  atomicrmw add ptr %[[PTR]], i64 %{{.*}} monotonic
+// DXCHECK:  atomicrmw add ptr %[[PTR]], i64 %{{.*}} syncscope("device") 
monotonic
 // SPVCHECK: %[[HANDLE:.*]] = load target("spirv.VulkanBuffer", [0 x i8], 12, 
1), ptr {{.*}}
 // SPVCHECK: %[[PTR:.*]] = call ptr addrspace(11) 
@llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i8_12_1t.i32(target("spirv.VulkanBuffer",
 [0 x i8], 12, 1) %[[HANDLE]], i32 %{{.*}})
-// SPVCHECK: atomicrmw add ptr addrspace(11) %[[PTR]], i64 %{...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/212663
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to