[Mlir-commits] [mlir] 21f2cf9 - Reland "[mlir][SPIR-V] Verify NonPrivatePointer requirement for MakePointer{Available, Visible}" (#213621) (#225499)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed Sep 23 02:17:00 PDT 2026
Author: Arseniy Obolenskiy
Date: 2026-09-23T11:16:53+02:00
New Revision: 21f2cf952ccc3de5c0bb6a950cf1037122c13ce6
URL: https://github.com/llvm/llvm-project/commit/21f2cf952ccc3de5c0bb6a950cf1037122c13ce6
DIFF: https://github.com/llvm/llvm-project/commit/21f2cf952ccc3de5c0bb6a950cf1037122c13ce6.diff
LOG: Reland "[mlir][SPIR-V] Verify NonPrivatePointer requirement for MakePointer{Available,Visible}" (#213621) (#225499)
Added:
Modified:
mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp
mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp b/mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp
index 08d8b3beb8275..0b98825774c80 100644
--- a/mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/MemoryOps.cpp
@@ -196,6 +196,38 @@ 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 constexpr (std::is_same_v<MemoryOpTy, LoadOp>) {
+ if (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 constexpr (std::is_same_v<MemoryOpTy, StoreOp> ||
+ std::is_same_v<MemoryOpTy, CopyMemoryOp>) {
+ if (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 (!memoryOp.getAlignmentAttr()) {
@@ -239,6 +271,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 (!memoryOp.getSourceAlignmentAttr()) {
@@ -542,14 +591,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 c58f22cea5a4b..78dabf67ece35 100644
--- a/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/memory-ops.mlir
@@ -202,6 +202,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
@@ -404,6 +430,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) -> () {
@@ -690,6 +742,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>
More information about the Mlir-commits
mailing list