[Mlir-commits] [mlir] [mlir][SPIR-V] Combine storage class bit with atomic memory semantics (PR #195049)
Arseniy Obolenskiy
llvmlistbot at llvm.org
Thu Apr 30 03:09:19 PDT 2026
https://github.com/aobolensk created https://github.com/llvm/llvm-project/pull/195049
Per SPIR-V spec section 3.32 (Memory Semantics), atomic operations must combine the ordering bits (Acquire/Release/AcquireRelease/SequentiallyConsistent) with the relevant storage class bit (UniformMemory, WorkgroupMemory, CrossWorkgroupMemory, ...)
Equivalent to LLVM backend PR #193696
>From 8cee0e5fe27ab6da5140d078d3a3250c2c9e4c10 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Thu, 30 Apr 2026 12:04:06 +0200
Subject: [PATCH] [mlir][SPIR-V] Combine storage class bit with atomic memory
semantics
Per SPIR-V spec section 3.32 (Memory Semantics), atomic operations must combine the ordering bits (Acquire/Release/AcquireRelease/SequentiallyConsistent) with the relevant storage class bit (UniformMemory, WorkgroupMemory, CrossWorkgroupMemory, ...)
Equivalent to LLVM backend PR #193696
---
.../MemRefToSPIRV/MemRefToSPIRV.cpp | 56 ++++++++++++++-----
mlir/test/Conversion/MemRefToSPIRV/alloc.mlir | 4 +-
.../test/Conversion/MemRefToSPIRV/atomic.mlir | 18 +++---
.../MemRefToSPIRV/bitwidth-emulation.mlir | 28 +++++-----
4 files changed, 67 insertions(+), 39 deletions(-)
diff --git a/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp b/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp
index 3b2aab6c9a824..fe9f9c59e6ede 100644
--- a/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp
+++ b/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp
@@ -163,6 +163,36 @@ static std::optional<spirv::Scope> getAtomicOpScope(MemRefType type) {
return {};
}
+/// Returns the MemorySemantics storage-class bit corresponding to `sc`.
+/// Per SPIR-V spec section 3.32 (Memory Semantics) this bit must be OR'd
+/// with the ordering bits (Acquire/Release/...) on atomic operations.
+static spirv::MemorySemantics
+getMemorySemanticsForStorageClass(spirv::StorageClass sc) {
+ switch (sc) {
+ case spirv::StorageClass::StorageBuffer:
+ case spirv::StorageClass::Uniform:
+ return spirv::MemorySemantics::UniformMemory;
+ case spirv::StorageClass::Workgroup:
+ return spirv::MemorySemantics::WorkgroupMemory;
+ case spirv::StorageClass::CrossWorkgroup:
+ return spirv::MemorySemantics::CrossWorkgroupMemory;
+ case spirv::StorageClass::AtomicCounter:
+ return spirv::MemorySemantics::AtomicCounterMemory;
+ case spirv::StorageClass::Image:
+ return spirv::MemorySemantics::ImageMemory;
+ default:
+ return spirv::MemorySemantics::None;
+ }
+}
+
+/// Returns the AcquireRelease memory semantics OR'd with the storage-class
+/// bit derived from the memory space of `type`.
+static spirv::MemorySemantics getAtomicAcqRelMemorySemantics(MemRefType type) {
+ auto sc = cast<spirv::StorageClassAttr>(type.getMemorySpace()).getValue();
+ return spirv::MemorySemantics::AcquireRelease |
+ getMemorySemanticsForStorageClass(sc);
+}
+
/// Extracts the element type from a SPIR-V pointer type pointing to storage.
///
/// For Kernel capability, the pointer points directly to the element type
@@ -467,14 +497,15 @@ AtomicRMWOpPattern::matchAndRewrite(memref::AtomicRMWOp atomicOp,
int dstBits = static_cast<int>(dstType.getWidth());
assert(dstBits % srcBits == 0);
+ spirv::MemorySemantics memSem = getAtomicAcqRelMemorySemantics(memrefType);
+
// When the source and destination bitwidths match, emit the atomic operation
// directly.
if (srcBits == dstBits) {
#define ATOMIC_CASE(kind, spirvOp) \
case arith::AtomicRMWKind::kind: \
rewriter.replaceOpWithNewOp<spirv::spirvOp>( \
- atomicOp, resultType, ptr, *scope, \
- spirv::MemorySemantics::AcquireRelease, adaptor.getValue()); \
+ atomicOp, resultType, ptr, *scope, memSem, adaptor.getValue()); \
break
switch (atomicOp.getKind()) {
@@ -535,9 +566,8 @@ AtomicRMWOpPattern::matchAndRewrite(memref::AtomicRMWOp atomicOp,
loc, dstType, rewriter.getIntegerAttr(dstType, (1uLL << srcBits) - 1));
Value storeVal =
shiftValue(loc, adaptor.getValue(), offset, elemMask, rewriter);
- result = spirv::AtomicOrOp::create(
- rewriter, loc, dstType, adjustedPtr, *scope,
- spirv::MemorySemantics::AcquireRelease, storeVal);
+ result = spirv::AtomicOrOp::create(rewriter, loc, dstType, adjustedPtr,
+ *scope, memSem, storeVal);
break;
}
case arith::AtomicRMWKind::andi: {
@@ -554,9 +584,8 @@ AtomicRMWOpPattern::matchAndRewrite(memref::AtomicRMWOp atomicOp,
rewriter.createOrFold<spirv::NotOp>(loc, dstType, shiftedElemMask);
Value mask = rewriter.createOrFold<spirv::BitwiseOrOp>(loc, storeVal,
invertedElemMask);
- result = spirv::AtomicAndOp::create(
- rewriter, loc, dstType, adjustedPtr, *scope,
- spirv::MemorySemantics::AcquireRelease, mask);
+ result = spirv::AtomicAndOp::create(rewriter, loc, dstType, adjustedPtr,
+ *scope, memSem, mask);
break;
}
default:
@@ -1029,12 +1058,11 @@ IntStoreOpPattern::matchAndRewrite(memref::StoreOp storeOp, OpAdaptor adaptor,
if (!scope)
return rewriter.notifyMatchFailure(storeOp, "atomic scope not available");
- Value result = spirv::AtomicAndOp::create(
- rewriter, loc, dstType, adjustedPtr, *scope,
- spirv::MemorySemantics::AcquireRelease, clearBitsMask);
- result = spirv::AtomicOrOp::create(
- rewriter, loc, dstType, adjustedPtr, *scope,
- spirv::MemorySemantics::AcquireRelease, storeVal);
+ spirv::MemorySemantics memSem = getAtomicAcqRelMemorySemantics(memrefType);
+ Value result = spirv::AtomicAndOp::create(rewriter, loc, dstType, adjustedPtr,
+ *scope, memSem, clearBitsMask);
+ result = spirv::AtomicOrOp::create(rewriter, loc, dstType, adjustedPtr,
+ *scope, memSem, storeVal);
// The AtomicOrOp has no side effect. Since it is already inserted, we can
// just remove the original StoreOp. Note that rewriter.replaceOp()
diff --git a/mlir/test/Conversion/MemRefToSPIRV/alloc.mlir b/mlir/test/Conversion/MemRefToSPIRV/alloc.mlir
index bb71557faef41..1e7a45e5a8939 100644
--- a/mlir/test/Conversion/MemRefToSPIRV/alloc.mlir
+++ b/mlir/test/Conversion/MemRefToSPIRV/alloc.mlir
@@ -48,8 +48,8 @@ module attributes {
// CHECK: %{{.+}} = spirv.Load "Workgroup" %[[PTR]] : i32
// CHECK: %[[LOC:.+]] = spirv.SDiv
// CHECK: %[[PTR:.+]] = spirv.AccessChain %[[VAR]][%{{.+}}, %[[LOC]]]
-// CHECK: %{{.+}} = spirv.AtomicAnd <Workgroup> <AcquireRelease> %[[PTR]], %{{.+}} : !spirv.ptr<i32, Workgroup>
-// CHECK: %{{.+}} = spirv.AtomicOr <Workgroup> <AcquireRelease> %[[PTR]], %{{.+}} : !spirv.ptr<i32, Workgroup>
+// CHECK: %{{.+}} = spirv.AtomicAnd <Workgroup> <AcquireRelease|WorkgroupMemory> %[[PTR]], %{{.+}} : !spirv.ptr<i32, Workgroup>
+// CHECK: %{{.+}} = spirv.AtomicOr <Workgroup> <AcquireRelease|WorkgroupMemory> %[[PTR]], %{{.+}} : !spirv.ptr<i32, Workgroup>
// -----
diff --git a/mlir/test/Conversion/MemRefToSPIRV/atomic.mlir b/mlir/test/Conversion/MemRefToSPIRV/atomic.mlir
index 92f98637a1939..b5815a73ee8b2 100644
--- a/mlir/test/Conversion/MemRefToSPIRV/atomic.mlir
+++ b/mlir/test/Conversion/MemRefToSPIRV/atomic.mlir
@@ -6,7 +6,7 @@ module attributes {spirv.target_env = #spirv.target_env<#spirv.vce<v1.3, [Shader
// CHECK-SAME: (%[[VAL:.+]]: i32,
func.func @atomic_addi_storage_buffer(%value: i32, %memref: memref<2x3x4xi32, #spirv.storage_class<StorageBuffer>>, %i0: index, %i1: index, %i2: index) -> i32 {
// CHECK: %[[AC:.+]] = spirv.AccessChain
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicIAdd <Device> <AcquireRelease> %[[AC]], %[[VAL]] : !spirv.ptr<i32, StorageBuffer>
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicIAdd <Device> <AcquireRelease|UniformMemory> %[[AC]], %[[VAL]] : !spirv.ptr<i32, StorageBuffer>
// CHECK: return %[[ATOMIC]]
%0 = memref.atomic_rmw "addi" %value, %memref[%i0, %i1, %i2] : (i32, memref<2x3x4xi32, #spirv.storage_class<StorageBuffer>>) -> i32
return %0: i32
@@ -16,7 +16,7 @@ func.func @atomic_addi_storage_buffer(%value: i32, %memref: memref<2x3x4xi32, #s
// CHECK-SAME: (%[[VAL:.+]]: i32,
func.func @atomic_maxs_workgroup(%value: i32, %memref: memref<2x3x4xi32, #spirv.storage_class<Workgroup>>, %i0: index, %i1: index, %i2: index) -> i32 {
// CHECK: %[[AC:.+]] = spirv.AccessChain
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicSMax <Workgroup> <AcquireRelease> %[[AC]], %[[VAL]] : !spirv.ptr<i32, Workgroup>
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicSMax <Workgroup> <AcquireRelease|WorkgroupMemory> %[[AC]], %[[VAL]] : !spirv.ptr<i32, Workgroup>
// CHECK: return %[[ATOMIC]]
%0 = memref.atomic_rmw "maxs" %value, %memref[%i0, %i1, %i2] : (i32, memref<2x3x4xi32, #spirv.storage_class<Workgroup>>) -> i32
return %0: i32
@@ -26,7 +26,7 @@ func.func @atomic_maxs_workgroup(%value: i32, %memref: memref<2x3x4xi32, #spirv.
// CHECK-SAME: (%[[VAL:.+]]: i32,
func.func @atomic_maxu_storage_buffer(%value: i32, %memref: memref<2x3x4xi32, #spirv.storage_class<StorageBuffer>>, %i0: index, %i1: index, %i2: index) -> i32 {
// CHECK: %[[AC:.+]] = spirv.AccessChain
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicUMax <Device> <AcquireRelease> %[[AC]], %[[VAL]] : !spirv.ptr<i32, StorageBuffer>
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicUMax <Device> <AcquireRelease|UniformMemory> %[[AC]], %[[VAL]] : !spirv.ptr<i32, StorageBuffer>
// CHECK: return %[[ATOMIC]]
%0 = memref.atomic_rmw "maxu" %value, %memref[%i0, %i1, %i2] : (i32, memref<2x3x4xi32, #spirv.storage_class<StorageBuffer>>) -> i32
return %0: i32
@@ -36,7 +36,7 @@ func.func @atomic_maxu_storage_buffer(%value: i32, %memref: memref<2x3x4xi32, #s
// CHECK-SAME: (%[[VAL:.+]]: i32,
func.func @atomic_mins_workgroup(%value: i32, %memref: memref<2x3x4xi32, #spirv.storage_class<Workgroup>>, %i0: index, %i1: index, %i2: index) -> i32 {
// CHECK: %[[AC:.+]] = spirv.AccessChain
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicSMin <Workgroup> <AcquireRelease> %[[AC]], %[[VAL]] : !spirv.ptr<i32, Workgroup>
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicSMin <Workgroup> <AcquireRelease|WorkgroupMemory> %[[AC]], %[[VAL]] : !spirv.ptr<i32, Workgroup>
// CHECK: return %[[ATOMIC]]
%0 = memref.atomic_rmw "mins" %value, %memref[%i0, %i1, %i2] : (i32, memref<2x3x4xi32, #spirv.storage_class<Workgroup>>) -> i32
return %0: i32
@@ -46,7 +46,7 @@ func.func @atomic_mins_workgroup(%value: i32, %memref: memref<2x3x4xi32, #spirv.
// CHECK-SAME: (%[[VAL:.+]]: i32,
func.func @atomic_minu_storage_buffer(%value: i32, %memref: memref<2x3x4xi32, #spirv.storage_class<StorageBuffer>>, %i0: index, %i1: index, %i2: index) -> i32 {
// CHECK: %[[AC:.+]] = spirv.AccessChain
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicUMin <Device> <AcquireRelease> %[[AC]], %[[VAL]] : !spirv.ptr<i32, StorageBuffer>
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicUMin <Device> <AcquireRelease|UniformMemory> %[[AC]], %[[VAL]] : !spirv.ptr<i32, StorageBuffer>
// CHECK: return %[[ATOMIC]]
%0 = memref.atomic_rmw "minu" %value, %memref[%i0, %i1, %i2] : (i32, memref<2x3x4xi32, #spirv.storage_class<StorageBuffer>>) -> i32
return %0: i32
@@ -56,7 +56,7 @@ func.func @atomic_minu_storage_buffer(%value: i32, %memref: memref<2x3x4xi32, #s
// CHECK-SAME: (%[[VAL:.+]]: i32,
func.func @atomic_ori_workgroup(%value: i32, %memref: memref<2x3x4xi32, #spirv.storage_class<Workgroup>>, %i0: index, %i1: index, %i2: index) -> i32 {
// CHECK: %[[AC:.+]] = spirv.AccessChain
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicOr <Workgroup> <AcquireRelease> %[[AC]], %[[VAL]] : !spirv.ptr<i32, Workgroup>
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicOr <Workgroup> <AcquireRelease|WorkgroupMemory> %[[AC]], %[[VAL]] : !spirv.ptr<i32, Workgroup>
// CHECK: return %[[ATOMIC]]
%0 = memref.atomic_rmw "ori" %value, %memref[%i0, %i1, %i2] : (i32, memref<2x3x4xi32, #spirv.storage_class<Workgroup>>) -> i32
return %0: i32
@@ -66,7 +66,7 @@ func.func @atomic_ori_workgroup(%value: i32, %memref: memref<2x3x4xi32, #spirv.s
// CHECK-SAME: (%[[VAL:.+]]: i32,
func.func @atomic_andi_storage_buffer(%value: i32, %memref: memref<2x3x4xi32, #spirv.storage_class<StorageBuffer>>, %i0: index, %i1: index, %i2: index) -> i32 {
// CHECK: %[[AC:.+]] = spirv.AccessChain
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicAnd <Device> <AcquireRelease> %[[AC]], %[[VAL]] : !spirv.ptr<i32, StorageBuffer>
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[AC]], %[[VAL]] : !spirv.ptr<i32, StorageBuffer>
// CHECK: return %[[ATOMIC]]
%0 = memref.atomic_rmw "andi" %value, %memref[%i0, %i1, %i2] : (i32, memref<2x3x4xi32, #spirv.storage_class<StorageBuffer>>) -> i32
return %0: i32
@@ -100,7 +100,7 @@ func.func @atomic_ori_i8_storage_buffer(%value: i8, %memref: memref<16xi8, #spir
// CHECK: %[[MASKED:.+]] = spirv.BitwiseAnd %[[VAL]], %[[C255]]
// CHECK: %[[SHIFTED:.+]] = spirv.ShiftLeftLogical %[[MASKED]], %[[OFFSET]]
// Atomic OR
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicOr <Device> <AcquireRelease> %[[AC]], %[[SHIFTED]]
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicOr <Device> <AcquireRelease|UniformMemory> %[[AC]], %[[SHIFTED]]
// Extract old value from result
// CHECK: spirv.ShiftRightLogical %[[ATOMIC]], %[[OFFSET]]
// CHECK: spirv.BitwiseAnd
@@ -136,7 +136,7 @@ func.func @atomic_andi_i8_storage_buffer(%value: i8, %memref: memref<16xi8, #spi
// CHECK: %[[NOT_ELEM:.+]] = spirv.Not %[[ELEM_SHIFTED]]
// CHECK: %[[MASK:.+]] = spirv.BitwiseOr %[[SHIFTED]], %[[NOT_ELEM]]
// Atomic AND
- // CHECK: %[[ATOMIC:.+]] = spirv.AtomicAnd <Device> <AcquireRelease> %[[AC]], %[[MASK]]
+ // CHECK: %[[ATOMIC:.+]] = spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[AC]], %[[MASK]]
// Extract old value
// CHECK: spirv.ShiftRightLogical %[[ATOMIC]], %[[OFFSET]]
// CHECK: spirv.BitwiseAnd
diff --git a/mlir/test/Conversion/MemRefToSPIRV/bitwidth-emulation.mlir b/mlir/test/Conversion/MemRefToSPIRV/bitwidth-emulation.mlir
index bb003e11993f5..323b54e8d460d 100644
--- a/mlir/test/Conversion/MemRefToSPIRV/bitwidth-emulation.mlir
+++ b/mlir/test/Conversion/MemRefToSPIRV/bitwidth-emulation.mlir
@@ -93,8 +93,8 @@ func.func @store_i1(%arg0: memref<i1, #spirv.storage_class<StorageBuffer>>, %val
// CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32
// CHECK: %[[CASTED_ARG1:.+]] = spirv.Select %[[ARG1]], %[[ONE]], %[[ZERO]] : i1, i32
// CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]]
- // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK]]
- // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[CASTED_ARG1]]
+ // CHECK: spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[MASK]]
+ // CHECK: spirv.AtomicOr <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[CASTED_ARG1]]
memref.store %value, %arg0[] : memref<i1, #spirv.storage_class<StorageBuffer>>
return
}
@@ -111,8 +111,8 @@ func.func @store_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>, %val
// CHECK: %[[MASK2:.+]] = spirv.Constant -256 : i32
// CHECK: %[[CLAMPED_VAL:.+]] = spirv.BitwiseAnd %[[ARG1_CAST]], %[[MASK1]] : i32
// CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]]
- // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK2]]
- // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[CLAMPED_VAL]]
+ // CHECK: spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[MASK2]]
+ // CHECK: spirv.AtomicOr <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[CLAMPED_VAL]]
// INDEX64-DAG: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : i8 to i32
// INDEX64-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]]
@@ -121,8 +121,8 @@ func.func @store_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>, %val
// INDEX64: %[[MASK2:.+]] = spirv.Constant -256 : i32
// INDEX64: %[[CLAMPED_VAL:.+]] = spirv.BitwiseAnd %[[ARG1_CAST]], %[[MASK1]] : i32
// INDEX64: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]] : {{.+}}, i64, i64
- // INDEX64: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK2]]
- // INDEX64: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[CLAMPED_VAL]]
+ // INDEX64: spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[MASK2]]
+ // INDEX64: spirv.AtomicOr <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[CLAMPED_VAL]]
memref.store %value, %arg0[] : memref<i8, #spirv.storage_class<StorageBuffer>>
return
}
@@ -145,8 +145,8 @@ func.func @store_i16(%arg0: memref<10xi16, #spirv.storage_class<StorageBuffer>>,
// CHECK: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i32
// CHECK: %[[ACCESS_IDX:.+]] = spirv.SDiv %[[ARG1_CAST]], %[[TWO]] : i32
// CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]]
- // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK]]
- // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]]
+ // CHECK: spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[MASK]]
+ // CHECK: spirv.AtomicOr <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[STORE_VAL]]
memref.store %value, %arg0[%index] : memref<10xi16, #spirv.storage_class<StorageBuffer>>
return
}
@@ -210,8 +210,8 @@ func.func @store_i4(%arg0: memref<?xi4, #spirv.storage_class<StorageBuffer>>, %v
// CHECK: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[BITS]] : i32, i32
// CHECK: %[[ACCESS_INDEX:.+]] = spirv.SDiv %[[INDEX]], %[[EIGHT]] : i32
// CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[ACCESS_INDEX]]]
- // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK2]]
- // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]]
+ // CHECK: spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[MASK2]]
+ // CHECK: spirv.AtomicOr <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[STORE_VAL]]
memref.store %value, %arg0[%i] : memref<?xi4, #spirv.storage_class<StorageBuffer>>
return
}
@@ -265,16 +265,16 @@ func.func @store_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>, %val
// CHECK: %[[MASK1:.+]] = spirv.Constant -256 : i32
// CHECK: %[[ARG1_CAST:.+]] = spirv.UConvert %[[ARG1]] : i8 to i32
// CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]]
- // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK1]]
- // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[ARG1_CAST]]
+ // CHECK: spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[MASK1]]
+ // CHECK: spirv.AtomicOr <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[ARG1_CAST]]
// INDEX64-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]]
// INDEX64: %[[ZERO:.+]] = spirv.Constant 0 : i64
// INDEX64: %[[MASK1:.+]] = spirv.Constant -256 : i32
// INDEX64: %[[ARG1_CAST:.+]] = spirv.UConvert %[[ARG1]] : i8 to i32
// INDEX64: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]] : {{.+}}, i64, i64
- // INDEX64: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK1]]
- // INDEX64: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[ARG1_CAST]]
+ // INDEX64: spirv.AtomicAnd <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[MASK1]]
+ // INDEX64: spirv.AtomicOr <Device> <AcquireRelease|UniformMemory> %[[PTR]], %[[ARG1_CAST]]
memref.store %value, %arg0[] : memref<i8, #spirv.storage_class<StorageBuffer>>
return
}
More information about the Mlir-commits
mailing list