diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVBarrierOps.td @@ -77,7 +77,7 @@ let results = (outs); - let verifier = [{ return verifyMemorySemantics(*this); }]; + let verifier = [{ return verifyMemorySemantics(getOperation(), memory_semantics()); }]; let autogenSerialization = 0; @@ -131,7 +131,7 @@ let results = (outs); - let verifier = [{ return verifyMemorySemantics(*this); }]; + let verifier = [{ return verifyMemorySemantics(getOperation(), memory_semantics()); }]; let autogenSerialization = 0; diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp @@ -497,15 +497,14 @@ return success(); } -template -static LogicalResult verifyMemorySemantics(BarrierOp op) { +static LogicalResult +verifyMemorySemantics(Operation *op, spirv::MemorySemantics memorySemantics) { // According to the SPIR-V specification: // "Despite being a mask and allowing multiple bits to be combined, it is // invalid for more than one of these four bits to be set: Acquire, Release, // AcquireRelease, or SequentiallyConsistent. Requesting both Acquire and // Release semantics is done by setting the AcquireRelease bit, not by setting // two bits." - auto memorySemantics = op.memory_semantics(); auto atMostOneInSet = spirv::MemorySemantics::Acquire | spirv::MemorySemantics::Release | spirv::MemorySemantics::AcquireRelease | @@ -514,9 +513,10 @@ auto bitCount = llvm::countPopulation( static_cast(memorySemantics & atMostOneInSet)); if (bitCount > 1) { - return op.emitError("expected at most one of these four memory constraints " - "to be set: `Acquire`, `Release`," - "`AcquireRelease` or `SequentiallyConsistent`"); + return op->emitError( + "expected at most one of these four memory constraints " + "to be set: `Acquire`, `Release`," + "`AcquireRelease` or `SequentiallyConsistent`"); } return success(); } @@ -772,6 +772,11 @@ "pointer operand's pointee type ") << elementType << ", but found " << valueType; } + auto memorySemantics = static_cast( + op->getAttrOfType(kSemanticsAttrName).getInt()); + if (failed(verifyMemorySemantics(op, memorySemantics))) { + return failure(); + } return success(); } diff --git a/mlir/test/Dialect/SPIRV/IR/atomic-ops.mlir b/mlir/test/Dialect/SPIRV/IR/atomic-ops.mlir --- a/mlir/test/Dialect/SPIRV/IR/atomic-ops.mlir +++ b/mlir/test/Dialect/SPIRV/IR/atomic-ops.mlir @@ -29,6 +29,14 @@ // ----- +func @atomic_and(%ptr : !spv.ptr, %value : i32) -> i32 { + // expected-error @+1 {{expected at most one of these four memory constraints to be set: `Acquire`, `Release`,`AcquireRelease` or `SequentiallyConsistent`}} + %0 = spv.AtomicAnd "Device" "Acquire|Release" %ptr, %value : !spv.ptr + return %0 : i32 +} + +// ----- + //===----------------------------------------------------------------------===// // spv.AtomicCompareExchangeWeak //===----------------------------------------------------------------------===// diff --git a/mlir/utils/spirv/report_coverage.sh b/mlir/utils/spirv/report_coverage.sh --- a/mlir/utils/spirv/report_coverage.sh +++ b/mlir/utils/spirv/report_coverage.sh @@ -16,5 +16,5 @@ current_dir="$(dirname "$current_file")" python3 ${current_dir}/gen_spirv_dialect.py \ - --base-td-path ${current_dir}/../../include/mlir/Dialect/SPIRV/SPIRVBase.td \ + --base-td-path ${current_dir}/../../include/mlir/Dialect/SPIRV/IR/SPIRVBase.td \ --gen-inst-coverage