[Mlir-commits] [mlir] [mlir][SPIR-V] Verify NonPrivatePointer requirement for MakePointer{Available, Visible} (PR #213621)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Aug 3 01:49:43 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-spirv

Author: Arseniy Obolenskiy (aobolensk)

<details>
<summary>Changes</summary>

close #<!-- -->145485

---
Full diff: https://github.com/llvm/llvm-project/pull/213621.diff


2 Files Affected:

- (modified) mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp (+46-8) 
- (modified) mlir/test/Dialect/SPIRV/IR/memory-ops.mlir (+82) 


``````````diff
diff --git a/mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp b/mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp
index f9c03bf3b88c0..df97fec31bd03 100644
--- a/mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp
@@ -197,6 +197,35 @@ static LogicalResult verifyMemoryAccessAttribute(MemoryOpTy memoryOp) {
            << memAccessAttr;
   }
 
+  // MakePointerAvailable applies to writes through the pointer, so it is
+  // invalid for Load (which only reads through it).
+  if (isa<LoadOp>(op) &&
+      spirv::bitEnumContainsAll(memAccess.getValue(),
+                                spirv::MemoryAccess::MakePointerAvailable)) {
+    return memoryOp.emitOpError(
+        "not compatible with memory operand 'MakePointerAvailable'");
+  }
+
+  // MakePointerVisible applies to reads through the pointer, so it is invalid
+  // for Store and for the Target operand of CopyMemory, both of which only
+  // write through it.
+  if (isa<StoreOp, CopyMemoryOp>(op) &&
+      spirv::bitEnumContainsAll(memAccess.getValue(),
+                                spirv::MemoryAccess::MakePointerVisible)) {
+    return memoryOp.emitOpError(
+        "not compatible with memory operand 'MakePointerVisible'");
+  }
+
+  if (spirv::bitEnumContainsAny(memAccess.getValue(),
+                                spirv::MemoryAccess::MakePointerAvailable |
+                                    spirv::MemoryAccess::MakePointerVisible) &&
+      !spirv::bitEnumContainsAll(memAccess.getValue(),
+                                 spirv::MemoryAccess::NonPrivatePointer)) {
+    return memoryOp.emitOpError(
+        "memory operand 'MakePointerAvailable' or 'MakePointerVisible' "
+        "requires 'NonPrivatePointer' to also be specified");
+  }
+
   if (spirv::bitEnumContainsAll(memAccess.getValue(),
                                 spirv::MemoryAccess::Aligned)) {
     if (!op->getAttr(memoryOp.getAlignmentAttrName())) {
@@ -241,6 +270,23 @@ static LogicalResult verifySourceMemoryAccessAttribute(MemoryOpTy memoryOp) {
            << memAccess;
   }
 
+  // The source mask applies to the read through the source pointer, so it
+  // cannot include MakePointerAvailable, which applies to writes.
+  if (spirv::bitEnumContainsAll(memAccess.getValue(),
+                                spirv::MemoryAccess::MakePointerAvailable)) {
+    return memoryOp.emitOpError(
+        "not compatible with memory operand 'MakePointerAvailable'");
+  }
+
+  if (spirv::bitEnumContainsAll(memAccess.getValue(),
+                                spirv::MemoryAccess::MakePointerVisible) &&
+      !spirv::bitEnumContainsAll(memAccess.getValue(),
+                                 spirv::MemoryAccess::NonPrivatePointer)) {
+    return memoryOp.emitOpError(
+        "memory operand 'MakePointerAvailable' or 'MakePointerVisible' "
+        "requires 'NonPrivatePointer' to also be specified");
+  }
+
   if (spirv::bitEnumContainsAll(memAccess.getValue(),
                                 spirv::MemoryAccess::Aligned)) {
     if (!op->getAttr(memoryOp.getSourceAlignmentAttrName())) {
@@ -532,14 +578,6 @@ LogicalResult CopyMemoryOp::verify() {
   if (failed(verifyMemoryAccessAttribute(*this)))
     return failure();
 
-  // TODO - According to the spec:
-  //
-  // If two masks are present, the first applies to Target and cannot include
-  // MakePointerVisible, and the second applies to Source and cannot include
-  // MakePointerAvailable.
-  //
-  // Add such verification here.
-
   return verifySourceMemoryAccessAttribute(*this);
 }
 
diff --git a/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir b/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
index a3b96c698a344..370bcb03d2526 100644
--- a/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
@@ -191,6 +191,32 @@ func.func @volatile_aligned_load() -> () {
   return
 }
 
+// CHECK-LABEL: @make_pointer_visible_load
+func.func @make_pointer_visible_load() -> () {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  // CHECK: spirv.Load "Function" %{{.*}} ["MakePointerVisible|NonPrivatePointer"] : f32
+  %1 = spirv.Load "Function" %0 ["MakePointerVisible|NonPrivatePointer"] : f32
+  return
+}
+
+// -----
+
+func.func @load_bad_operand() -> () {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  // expected-error @+1 {{op not compatible with memory operand 'MakePointerAvailable'}}
+  %1 = spirv.Load "Function" %0 ["MakePointerAvailable|NonPrivatePointer"] : f32
+  return
+}
+
+// -----
+
+func.func @load_make_pointer_visible_missing_non_private() -> () {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  // expected-error @+1 {{op memory operand 'MakePointerAvailable' or 'MakePointerVisible' requires 'NonPrivatePointer' to also be specified}}
+  %1 = spirv.Load "Function" %0 ["MakePointerVisible"] : f32
+  return
+}
+
 // -----
 
 // CHECK-LABEL: load_none_access
@@ -393,6 +419,32 @@ func.func @aligned_store(%arg0 : f32) -> () {
   return
 }
 
+// CHECK-LABEL: @make_pointer_available_store
+func.func @make_pointer_available_store(%arg0 : f32) -> () {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  // CHECK: spirv.Store  "Function" %0, %arg0 ["MakePointerAvailable|NonPrivatePointer"] : f32
+  spirv.Store  "Function" %0, %arg0 ["MakePointerAvailable|NonPrivatePointer"] : f32
+  return
+}
+
+// -----
+
+func.func @store_bad_operand(%arg0 : f32) -> () {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  // expected-error @+1 {{op not compatible with memory operand 'MakePointerVisible'}}
+  spirv.Store  "Function" %0, %arg0 ["MakePointerVisible|NonPrivatePointer"] : f32
+  return
+}
+
+// -----
+
+func.func @store_make_pointer_available_missing_non_private(%arg0 : f32) -> () {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  // expected-error @+1 {{op memory operand 'MakePointerAvailable' or 'MakePointerVisible' requires 'NonPrivatePointer' to also be specified}}
+  spirv.Store  "Function" %0, %arg0 ["MakePointerAvailable"] : f32
+  return
+}
+
 // -----
 
 func.func @simple_store_missing_ptr_type(%arg0 : f32) -> () {
@@ -679,6 +731,36 @@ func.func @copy_memory_invalid_source_maa2() {
 
 // -----
 
+func.func @copy_memory_target_bad_operand() {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  %1 = spirv.Variable : !spirv.ptr<f32, Function>
+  // expected-error @+1 {{op not compatible with memory operand 'MakePointerVisible'}}
+  "spirv.CopyMemory"(%0, %1) {memory_access=#spirv.memory_access<MakePointerVisible|NonPrivatePointer>} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> ()
+  spirv.Return
+}
+
+// -----
+
+func.func @copy_memory_source_bad_operand() {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  %1 = spirv.Variable : !spirv.ptr<f32, Function>
+  // expected-error @+1 {{op not compatible with memory operand 'MakePointerAvailable'}}
+  "spirv.CopyMemory"(%0, %1) {source_memory_access=#spirv.memory_access<MakePointerAvailable|NonPrivatePointer>, memory_access=#spirv.memory_access<None>} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> ()
+  spirv.Return
+}
+
+// -----
+
+func.func @copy_memory_source_make_pointer_visible_missing_non_private() {
+  %0 = spirv.Variable : !spirv.ptr<f32, Function>
+  %1 = spirv.Variable : !spirv.ptr<f32, Function>
+  // expected-error @+1 {{op memory operand 'MakePointerAvailable' or 'MakePointerVisible' requires 'NonPrivatePointer' to also be specified}}
+  "spirv.CopyMemory"(%0, %1) {source_memory_access=#spirv.memory_access<MakePointerVisible>, memory_access=#spirv.memory_access<None>} : (!spirv.ptr<f32, Function>, !spirv.ptr<f32, Function>) -> ()
+  spirv.Return
+}
+
+// -----
+
 func.func @copy_memory_print_maa() {
   %0 = spirv.Variable : !spirv.ptr<f32, Function>
   %1 = spirv.Variable : !spirv.ptr<f32, Function>

``````````

</details>


https://github.com/llvm/llvm-project/pull/213621


More information about the Mlir-commits mailing list