[Mlir-commits] [mlir] e289b2e - [mlir][Utils] Add VerificationUtils (NFC) (#174336)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Jan 12 08:52:48 PST 2026
Author: Nick Kreeger
Date: 2026-01-12T16:52:44Z
New Revision: e289b2e765ed279e57e4643a4f602d2328ac4af4
URL: https://github.com/llvm/llvm-project/commit/e289b2e765ed279e57e4643a4f602d2328ac4af4
DIFF: https://github.com/llvm/llvm-project/commit/e289b2e765ed279e57e4643a4f602d2328ac4af4.diff
LOG: [mlir][Utils] Add VerificationUtils (NFC) (#174336)
Introduces `VerificationUtils` to consolidate common operation
verification patterns in MLIR. This initial implementation provides
`verifyDynamicDimensionCount()` to reduce code duplication across
dialect verifiers.
This is an NFC (No Functional Change) refactoring that improves code
maintainability by extracting reusable verification logic into a shared
utility.
Added:
mlir/include/mlir/Dialect/Utils/VerificationUtils.h
mlir/lib/Dialect/Utils/VerificationUtils.cpp
Modified:
mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
mlir/lib/Dialect/Utils/CMakeLists.txt
mlir/test/Dialect/Bufferization/invalid.mlir
mlir/test/Dialect/GPU/invalid.mlir
mlir/test/Dialect/MemRef/invalid.mlir
mlir/test/Dialect/Tensor/invalid.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/Utils/VerificationUtils.h b/mlir/include/mlir/Dialect/Utils/VerificationUtils.h
new file mode 100644
index 0000000000000..c1c3cc6231eb6
--- /dev/null
+++ b/mlir/include/mlir/Dialect/Utils/VerificationUtils.h
@@ -0,0 +1,32 @@
+//===- VerificationUtils.h - Common verification utilities ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file defines common verification utilities that can be shared
+// across multiple MLIR dialects. These utilities help reduce code duplication
+// for common verification patterns.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_UTILS_VERIFICATIONUTILS_H
+#define MLIR_DIALECT_UTILS_VERIFICATIONUTILS_H
+
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/Support/LLVM.h"
+
+namespace mlir {
+
+/// Verify that the number of dynamic size operands matches the number of
+/// dynamic dimensions in the shaped type. Returns failure and emits an error
+/// if the counts don't match.
+LogicalResult verifyDynamicDimensionCount(Operation *op, ShapedType type,
+ ValueRange dynamicSizes);
+
+} // namespace mlir
+
+#endif // MLIR_DIALECT_UTILS_VERIFICATIONUTILS_H
diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
index 56ff2121e4620..eda6bf276be06 100644
--- a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
+++ b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
@@ -12,6 +12,7 @@
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
+#include "mlir/Dialect/Utils/VerificationUtils.h"
#include "mlir/IR/Matchers.h"
#include <optional>
@@ -251,9 +252,9 @@ AllocTensorOp::getBufferType(Value value, const BufferizationOptions &options,
LogicalResult AllocTensorOp::verify() {
if (getCopy() && !getDynamicSizes().empty())
return emitError("dynamic sizes not needed when copying a tensor");
- if (!getCopy() && getType().getNumDynamicDims() != getDynamicSizes().size())
- return emitError("expected ")
- << getType().getNumDynamicDims() << " dynamic sizes";
+ if (!getCopy() && failed(verifyDynamicDimensionCount(
+ getOperation(), getType(), getDynamicSizes())))
+ return failure();
if (getCopy() && getCopy().getType() != getType())
return emitError("expected that `copy` and return type match");
return success();
diff --git a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
index 552485e748123..ff2d792f9cebd 100644
--- a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
+++ b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp
@@ -16,6 +16,7 @@
#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h"
#include "mlir/Dialect/Math/IR/Math.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/Dialect/Utils/VerificationUtils.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
@@ -2171,9 +2172,9 @@ void WaitOp::getCanonicalizationPatterns(RewritePatternSet &results,
LogicalResult AllocOp::verify() {
auto memRefType = llvm::cast<MemRefType>(getMemref().getType());
- if (getDynamicSizes().size() != memRefType.getNumDynamicDims())
- return emitOpError("dimension operand count does not equal memref "
- "dynamic dimension count");
+ if (failed(verifyDynamicDimensionCount(getOperation(), memRefType,
+ getDynamicSizes())))
+ return failure();
unsigned numSymbols = 0;
if (!memRefType.getLayout().isIdentity())
diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
index fe93b3e296400..a612475edf3b9 100644
--- a/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
+++ b/mlir/lib/Dialect/MemRef/IR/MemRefOps.cpp
@@ -10,6 +10,7 @@
#include "mlir/Dialect/Arith/Utils/Utils.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
+#include "mlir/Dialect/Utils/VerificationUtils.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinTypes.h"
@@ -192,9 +193,8 @@ static LogicalResult verifyAllocLikeOp(AllocLikeOp op) {
if (!memRefType)
return op.emitOpError("result must be a memref");
- if (op.getDynamicSizes().size() != memRefType.getNumDynamicDims())
- return op.emitOpError("dimension operand count does not equal memref "
- "dynamic dimension count");
+ if (failed(verifyDynamicDimensionCount(op, memRefType, op.getDynamicSizes())))
+ return failure();
unsigned numSymbols = 0;
if (!memRefType.getLayout().isIdentity())
@@ -3735,9 +3735,8 @@ LogicalResult ViewOp::verify() {
<< baseType << " and view memref type " << viewType;
// Verify that we have the correct number of sizes for the result type.
- unsigned numDynamicDims = viewType.getNumDynamicDims();
- if (getSizes().size() != numDynamicDims)
- return emitError("incorrect number of size operands for type ") << viewType;
+ if (failed(verifyDynamicDimensionCount(getOperation(), viewType, getSizes())))
+ return failure();
return success();
}
diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
index a0c7e40c20a46..11824a0ac6f05 100644
--- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
+++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp
@@ -15,6 +15,7 @@
#include "mlir/Dialect/Utils/IndexingUtils.h"
#include "mlir/Dialect/Utils/ReshapeOpsUtils.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
+#include "mlir/Dialect/Utils/VerificationUtils.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributeInterfaces.h"
#include "mlir/IR/BuiltinTypeInterfaces.h"
@@ -1075,11 +1076,8 @@ void EmptyOp::build(OpBuilder &builder, OperationState &result,
}
LogicalResult EmptyOp::verify() {
- if (getType().getNumDynamicDims() != getDynamicSizes().size())
- return emitOpError("incorrect number of dynamic sizes, has ")
- << getDynamicSizes().size() << ", expected "
- << getType().getNumDynamicDims();
- return success();
+ return verifyDynamicDimensionCount(getOperation(), getType(),
+ getDynamicSizes());
}
LogicalResult
@@ -1666,9 +1664,9 @@ LogicalResult GenerateOp::verify() {
// Ensure that the tensor type has as many dynamic dimensions as are
// specified by the operands.
RankedTensorType resultType = llvm::cast<RankedTensorType>(getType());
- if (getNumOperands() != resultType.getNumDynamicDims())
- return emitError("must have as many index operands as dynamic extents "
- "in the result type");
+ if (failed(verifyDynamicDimensionCount(getOperation(), resultType,
+ getOperands())))
+ return failure();
return success();
}
@@ -4039,11 +4037,8 @@ void SplatOp::getAsmResultNames(
}
LogicalResult SplatOp::verify() {
- if (getType().getNumDynamicDims() != getDynamicSizes().size())
- return emitOpError("incorrect number of dynamic sizes, has ")
- << getDynamicSizes().size() << ", expected "
- << getType().getNumDynamicDims();
- return success();
+ return verifyDynamicDimensionCount(getOperation(), getType(),
+ getDynamicSizes());
}
LogicalResult
diff --git a/mlir/lib/Dialect/Utils/CMakeLists.txt b/mlir/lib/Dialect/Utils/CMakeLists.txt
index f5bb687ae071a..7673da5932304 100644
--- a/mlir/lib/Dialect/Utils/CMakeLists.txt
+++ b/mlir/lib/Dialect/Utils/CMakeLists.txt
@@ -3,6 +3,7 @@ add_mlir_library(MLIRDialectUtils
ReshapeOpsUtils.cpp
StructuredOpsUtils.cpp
StaticValueUtils.cpp
+ VerificationUtils.cpp
DEPENDS
MLIRDialectUtilsIncGen
diff --git a/mlir/lib/Dialect/Utils/VerificationUtils.cpp b/mlir/lib/Dialect/Utils/VerificationUtils.cpp
new file mode 100644
index 0000000000000..22b224713a6a3
--- /dev/null
+++ b/mlir/lib/Dialect/Utils/VerificationUtils.cpp
@@ -0,0 +1,22 @@
+//===- VerificationUtils.cpp - Common verification utilities --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/Utils/VerificationUtils.h"
+
+using namespace mlir;
+
+LogicalResult mlir::verifyDynamicDimensionCount(Operation *op, ShapedType type,
+ ValueRange dynamicSizes) {
+ int64_t expectedCount = type.getNumDynamicDims();
+ int64_t actualCount = dynamicSizes.size();
+ if (expectedCount != actualCount) {
+ return op->emitOpError("incorrect number of dynamic sizes, has ")
+ << actualCount << ", expected " << expectedCount;
+ }
+ return success();
+}
diff --git a/mlir/test/Dialect/Bufferization/invalid.mlir b/mlir/test/Dialect/Bufferization/invalid.mlir
index 9884b040119d0..76aba14bc50f2 100644
--- a/mlir/test/Dialect/Bufferization/invalid.mlir
+++ b/mlir/test/Dialect/Bufferization/invalid.mlir
@@ -2,7 +2,7 @@
func.func @alloc_tensor_missing_dims(%arg0: index)
{
- // expected-error @+1 {{expected 2 dynamic sizes}}
+ // expected-error @+1 {{incorrect number of dynamic sizes, has 1, expected 2}}
%0 = bufferization.alloc_tensor(%arg0) : tensor<4x?x?x5xf32>
return
}
diff --git a/mlir/test/Dialect/GPU/invalid.mlir b/mlir/test/Dialect/GPU/invalid.mlir
index 26bcf948bc85d..5e9c25c36aa79 100644
--- a/mlir/test/Dialect/GPU/invalid.mlir
+++ b/mlir/test/Dialect/GPU/invalid.mlir
@@ -777,7 +777,7 @@ func.func @alloc() {
// Number of dynamic dimension operand count greater than memref dynamic dimension count.
func.func @alloc() {
%0 = arith.constant 7 : index
- // expected-error at +1 {{dimension operand count does not equal memref dynamic dimension count}}
+ // expected-error at +1 {{incorrect number of dynamic sizes, has 2, expected 1}}
%1 = gpu.alloc(%0, %0) : memref<2x?xf32, 1>
return
}
@@ -787,7 +787,7 @@ func.func @alloc() {
// Number of dynamic dimension operand count less than memref dynamic dimension count.
func.func @alloc() {
%0 = arith.constant 7 : index
- // expected-error at +1 {{dimension operand count does not equal memref dynamic dimension count}}
+ // expected-error at +1 {{incorrect number of dynamic sizes, has 1, expected 2}}
%1 = gpu.alloc(%0) : memref<2x?x?xf32, 1>
return
}
diff --git a/mlir/test/Dialect/MemRef/invalid.mlir b/mlir/test/Dialect/MemRef/invalid.mlir
index d10651f363711..2dfe733c13768 100644
--- a/mlir/test/Dialect/MemRef/invalid.mlir
+++ b/mlir/test/Dialect/MemRef/invalid.mlir
@@ -624,7 +624,7 @@ func.func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
func.func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) {
%0 = memref.alloc() : memref<2048xi8>
- // expected-error at +1 {{incorrect number of size operands for type}}
+ // expected-error at +1 {{incorrect number of dynamic sizes, has 1, expected 2}}
%1 = memref.view %0[%arg2][%arg0]
: memref<2048xi8> to memref<?x?xf32>
return
@@ -927,7 +927,7 @@ func.func @bad_alloc_wrong_dynamic_dim_count() {
^bb0:
%0 = arith.constant 7 : index
// Test alloc with wrong number of dynamic dimensions.
- // expected-error at +1 {{dimension operand count does not equal memref dynamic dimension count}}
+ // expected-error at +1 {{incorrect number of dynamic sizes, has 1, expected 0}}
%1 = memref.alloc(%0)[%0] : memref<2x4xf32, affine_map<(d0, d1)[s0] -> ((d0 + s0), d1)>, 1>
return
}
diff --git a/mlir/test/Dialect/Tensor/invalid.mlir b/mlir/test/Dialect/Tensor/invalid.mlir
index f36678c3d7589..63be5493e8935 100644
--- a/mlir/test/Dialect/Tensor/invalid.mlir
+++ b/mlir/test/Dialect/Tensor/invalid.mlir
@@ -100,7 +100,7 @@ func.func @tensor.from_elements_wrong_elements_count() {
func.func @tensor.generate(%m : index)
-> tensor<?x3x?xf32> {
- // expected-error @+1 {{must have as many index operands as dynamic extents in the result type}}
+ // expected-error @+1 {{incorrect number of dynamic sizes, has 1, expected 2}}
%tnsr = tensor.generate %m {
^bb0(%i : index, %j : index, %k : index):
%elem = arith.constant 8.0 : f32
More information about the Mlir-commits
mailing list