[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