[Mlir-commits] [mlir] [mlir][tensor] Add runtime verification for expand_shape/concat/reshape (PR #236783)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Nov 2 03:10:47 PST 2026
https://github.com/Wijkqwe updated https://github.com/llvm/llvm-project/pull/236783
>From fbe0f739265063a3ad7287c0ed69ce6392f35b86 Mon Sep 17 00:00:00 2001
From: wzy <WZYqwe2004 at outlook.com>
Date: Thu, 29 Oct 2026 21:42:44 +0800
Subject: [PATCH 1/3] it just works
---
mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp | 5 +-
.../Transforms/RuntimeOpVerification.cpp | 227 ++++++++++++++++++
.../Dialect/Tensor/runtime-verification.mlir | 88 +++++++
.../Tensor/concat-runtime-verification.mlir | 66 +++++
.../expand-shape-runtime-verification.mlir | 45 ++++
.../Tensor/reshape-runtime-verification.mlir | 68 ++++++
6 files changed, 497 insertions(+), 2 deletions(-)
create mode 100644 mlir/test/Dialect/Tensor/runtime-verification.mlir
create mode 100644 mlir/test/Integration/Dialect/Tensor/concat-runtime-verification.mlir
create mode 100644 mlir/test/Integration/Dialect/Tensor/expand-shape-runtime-verification.mlir
create mode 100644 mlir/test/Integration/Dialect/Tensor/reshape-runtime-verification.mlir
diff --git a/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp b/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp
index 2c9cd87f14af25..d2a3c7c4277c88 100644
--- a/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp
+++ b/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp
@@ -58,8 +58,9 @@ void TensorDialect::initialize() {
InsertSliceOp, ReshapeOp>();
declarePromisedInterfaces<ReifyRankedShapedTypeOpInterface, ExpandShapeOp,
CollapseShapeOp, PadOp>();
- declarePromisedInterfaces<RuntimeVerifiableOpInterface, CastOp, DimOp,
- ExtractOp, InsertOp, ExtractSliceOp>();
+ declarePromisedInterfaces<RuntimeVerifiableOpInterface, CastOp, ConcatOp,
+ DimOp, ExpandShapeOp, ExtractOp, InsertOp,
+ ExtractSliceOp, ReshapeOp>();
declarePromisedInterfaces<SubsetOpInterface, ExtractSliceOp, InsertSliceOp,
ParallelInsertSliceOp>();
declarePromisedInterfaces<SubsetInsertionOpInterface, InsertSliceOp,
diff --git a/mlir/lib/Dialect/Tensor/Transforms/RuntimeOpVerification.cpp b/mlir/lib/Dialect/Tensor/Transforms/RuntimeOpVerification.cpp
index d35f458cbdb363..3a0fb352513a8f 100644
--- a/mlir/lib/Dialect/Tensor/Transforms/RuntimeOpVerification.cpp
+++ b/mlir/lib/Dialect/Tensor/Transforms/RuntimeOpVerification.cpp
@@ -237,6 +237,230 @@ struct ExtractSliceOpInterface
}
}
};
+
+struct ExpandShapeOpInterface
+ : public RuntimeVerifiableOpInterface::ExternalModel<ExpandShapeOpInterface,
+ ExpandShapeOp> {
+ void
+ generateRuntimeVerification(Operation *op, OpBuilder &builder, Location loc,
+ function_ref<std::string(Operation *, StringRef)>
+ generateErrorMessage) const {
+ auto expandShapeOp = cast<ExpandShapeOp>(op);
+
+ SmallVector<OpFoldResult> outputShape = expandShapeOp.getMixedOutputShape();
+
+ // Verify that the product of output dim sizes in each reassociation group
+ // equals the corresponding input dim size.
+ for (const auto &it :
+ llvm::enumerate(expandShapeOp.getReassociationIndices())) {
+ Value srcDimSz =
+ DimOp::create(builder, loc, expandShapeOp.getSrc(), it.index());
+ Value groupProduct = getValueOrCreateConstantIndexOp(
+ builder, loc, outputShape[it.value().front()]);
+ for (int64_t resultDim : llvm::drop_begin(it.value())) {
+ Value dimSz = getValueOrCreateConstantIndexOp(builder, loc,
+ outputShape[resultDim]);
+ groupProduct = arith::MulIOp::create(builder, loc, groupProduct, dimSz);
+ }
+ Value isEqual = arith::CmpIOp::create(
+ builder, loc, arith::CmpIPredicate::eq, groupProduct, srcDimSz);
+ cf::AssertOp::create(
+ builder, loc, isEqual,
+ generateErrorMessage(op, "product of output dims in reassoc group "
+ "does not equal input dim"));
+ }
+ }
+};
+
+struct ConcatOpInterface
+ : public RuntimeVerifiableOpInterface::ExternalModel<ConcatOpInterface,
+ ConcatOp> {
+ void
+ generateRuntimeVerification(Operation *op, OpBuilder &builder, Location loc,
+ function_ref<std::string(Operation *, StringRef)>
+ generateErrorMessage) const {
+ auto concatOp = cast<ConcatOp>(op);
+ ValueRange inputs = concatOp.getInputs();
+ int64_t concatDim = concatOp.getDim();
+ int64_t rank = concatOp.getRank();
+ RankedTensorType resultType = concatOp.getResultType();
+
+ // Materialize the size of `tensor` along dimension `i`. Static sizes are
+ // materialized as constants.
+ auto getDimSize = [&](Value tensor, int64_t i) -> Value {
+ auto tensorType = cast<RankedTensorType>(tensor.getType());
+ if (!tensorType.isDynamicDim(i))
+ return arith::ConstantIndexOp::create(builder, loc,
+ tensorType.getDimSize(i));
+ return DimOp::create(builder, loc, tensor, i);
+ };
+
+ // Check that all inputs have the same size along every non-concatenated
+ // dimension, and that this size matches the static result size (if any).
+ // Dynamic result dims are defined by the op itself and cannot be checked
+ // here (the result is not yet defined at the insertion point).
+ for (int64_t i : llvm::seq<int64_t>(0, rank)) {
+ if (i == concatDim)
+ continue;
+
+ bool hasDynamicInput = llvm::any_of(inputs, [&](Value input) {
+ return cast<RankedTensorType>(input.getType()).isDynamicDim(i);
+ });
+ if (!hasDynamicInput)
+ continue;
+
+ Value expectedSize = getDimSize(inputs.front(), i);
+ bool frontIsDynamic =
+ cast<RankedTensorType>(inputs.front().getType()).isDynamicDim(i);
+ for (Value input : llvm::drop_begin(inputs)) {
+ // Pairs of static sizes are verified statically.
+ if (!frontIsDynamic &&
+ !cast<RankedTensorType>(input.getType()).isDynamicDim(i))
+ continue;
+ Value size = getDimSize(input, i);
+ Value isSameSize = arith::CmpIOp::create(
+ builder, loc, arith::CmpIPredicate::eq, size, expectedSize);
+ cf::AssertOp::create(
+ builder, loc, isSameSize,
+ generateErrorMessage(op, "input size mismatch along "
+ "non-concatenated dimension " +
+ std::to_string(i)));
+ }
+
+ if (!resultType.isDynamicDim(i)) {
+ Value resultSize = arith::ConstantIndexOp::create(
+ builder, loc, resultType.getDimSize(i));
+ Value isSameSize = arith::CmpIOp::create(
+ builder, loc, arith::CmpIPredicate::eq, expectedSize, resultSize);
+ cf::AssertOp::create(
+ builder, loc, isSameSize,
+ generateErrorMessage(op, "input size does not match result size "
+ "along non-concatenated dimension " +
+ std::to_string(i)));
+ }
+ }
+
+ // Check that the sum of the input sizes along the concatenation dimension
+ // equals the static result size. Dynamic result sizes are reified as the
+ // sum of the input sizes (ConcatOp::reifyResultShapes), so they cannot
+ // mismatch after lowering.
+ if (resultType.isDynamicDim(concatDim))
+ return;
+
+ bool hasDynamicInput = llvm::any_of(inputs, [&](Value input) {
+ return cast<RankedTensorType>(input.getType()).isDynamicDim(concatDim);
+ });
+ if (!hasDynamicInput)
+ return;
+
+ Value sum = getDimSize(inputs.front(), concatDim);
+ for (Value input : llvm::drop_begin(inputs))
+ sum = arith::AddIOp::create(builder, loc, sum,
+ getDimSize(input, concatDim));
+ Value resultSize = arith::ConstantIndexOp::create(
+ builder, loc, resultType.getDimSize(concatDim));
+ Value isEqual = arith::CmpIOp::create(builder, loc,
+ arith::CmpIPredicate::eq, sum,
+ resultSize);
+ cf::AssertOp::create(
+ builder, loc, isEqual,
+ generateErrorMessage(op, "sum of input sizes along concatenated "
+ "dimension does not match result size"));
+ }
+};
+
+struct ReshapeOpInterface
+ : public RuntimeVerifiableOpInterface::ExternalModel<ReshapeOpInterface,
+ ReshapeOp> {
+ void
+ generateRuntimeVerification(Operation *op, OpBuilder &builder, Location loc,
+ function_ref<std::string(Operation *, StringRef)>
+ generateErrorMessage) const {
+ auto reshapeOp = cast<ReshapeOp>(op);
+ auto shapeType = cast<RankedTensorType>(reshapeOp.getShape().getType());
+ int64_t shapeSize = shapeType.getDimSize(0);
+
+ // A dynamic shape-operand length is only valid with an unranked result
+ // (verified statically); there is then nothing to check here.
+ if (ShapedType::isDynamic(shapeSize))
+ return;
+
+ // Extract the shape operand values and normalize them to index.
+ Type indexType = builder.getIndexType();
+ SmallVector<Value> shapeValues;
+ shapeValues.reserve(shapeSize);
+ for (int64_t i : llvm::seq<int64_t>(0, shapeSize)) {
+ Value idx = arith::ConstantIndexOp::create(builder, loc, i);
+ Value shapeValue =
+ ExtractOp::create(builder, loc, reshapeOp.getShape(), idx);
+ if (shapeValue.getType() != indexType)
+ shapeValue = arith::IndexCastOp::create(builder, loc, indexType,
+ shapeValue);
+ shapeValues.push_back(shapeValue);
+ }
+
+ // Check that the shape operand values agree with the static result sizes.
+ // The lowering of memref.reshape trusts the static result dimensions over
+ // the shape operand values, so a mismatch yields an inconsistent memref
+ // descriptor and out-of-bounds accesses.
+ if (auto resultType =
+ dyn_cast<RankedTensorType>(reshapeOp.getResult().getType())) {
+ for (int64_t i : llvm::seq<int64_t>(0, resultType.getRank())) {
+ if (resultType.isDynamicDim(i))
+ continue;
+ Value expectedSize = arith::ConstantIndexOp::create(
+ builder, loc, resultType.getDimSize(i));
+ Value isEqual = arith::CmpIOp::create(
+ builder, loc, arith::CmpIPredicate::eq, shapeValues[i],
+ expectedSize);
+ cf::AssertOp::create(
+ builder, loc, isEqual,
+ generateErrorMessage(op, "shape operand value does not match "
+ "static result size along dimension " +
+ std::to_string(i)));
+ }
+ }
+
+ // Check that the product of the shape operand values equals the number of
+ // elements in the source. This requires a ranked source.
+ auto sourceType =
+ dyn_cast<RankedTensorType>(reshapeOp.getSource().getType());
+ if (!sourceType)
+ return;
+
+ Value sourceNumElements;
+ if (sourceType.hasStaticShape()) {
+ sourceNumElements = arith::ConstantIndexOp::create(
+ builder, loc, sourceType.getNumElements());
+ } else {
+ sourceNumElements = DimOp::create(builder, loc, reshapeOp.getSource(), 0);
+ for (int64_t i : llvm::seq<int64_t>(1, sourceType.getRank())) {
+ Value dimSize = DimOp::create(builder, loc, reshapeOp.getSource(), i);
+ sourceNumElements =
+ arith::MulIOp::create(builder, loc, sourceNumElements, dimSize);
+ }
+ }
+
+ std::optional<Value> shapeProduct;
+ for (Value shapeValue : shapeValues) {
+ shapeProduct =
+ shapeProduct ? arith::MulIOp::create(builder, loc, *shapeProduct,
+ shapeValue)
+ : shapeValue;
+ }
+ if (!shapeProduct)
+ shapeProduct = arith::ConstantIndexOp::create(builder, loc, 1);
+
+ Value isEqual = arith::CmpIOp::create(
+ builder, loc, arith::CmpIPredicate::eq, *shapeProduct,
+ sourceNumElements);
+ cf::AssertOp::create(
+ builder, loc, isEqual,
+ generateErrorMessage(op, "product of shape operand values does not "
+ "equal number of elements in source"));
+ }
+};
+
} // namespace
} // namespace tensor
} // namespace mlir
@@ -245,10 +469,13 @@ void mlir::tensor::registerRuntimeVerifiableOpInterfaceExternalModels(
DialectRegistry ®istry) {
registry.addExtension(+[](MLIRContext *ctx, tensor::TensorDialect *dialect) {
CastOp::attachInterface<CastOpInterface>(*ctx);
+ ConcatOp::attachInterface<ConcatOpInterface>(*ctx);
DimOp::attachInterface<DimOpInterface>(*ctx);
+ ExpandShapeOp::attachInterface<ExpandShapeOpInterface>(*ctx);
ExtractOp::attachInterface<ExtractInsertOpInterface<ExtractOp>>(*ctx);
ExtractSliceOp::attachInterface<ExtractSliceOpInterface>(*ctx);
InsertOp::attachInterface<ExtractInsertOpInterface<InsertOp>>(*ctx);
+ ReshapeOp::attachInterface<ReshapeOpInterface>(*ctx);
// Load additional dialects of which ops may get created.
ctx->loadDialect<arith::ArithDialect, cf::ControlFlowDialect>();
diff --git a/mlir/test/Dialect/Tensor/runtime-verification.mlir b/mlir/test/Dialect/Tensor/runtime-verification.mlir
new file mode 100644
index 00000000000000..952d10e7dc8303
--- /dev/null
+++ b/mlir/test/Dialect/Tensor/runtime-verification.mlir
@@ -0,0 +1,88 @@
+// RUN: mlir-opt %s -generate-runtime-verification -cse -split-input-file | FileCheck %s
+
+// CHECK-LABEL: func @expand_shape(
+// CHECK-SAME: %[[m:.*]]: tensor<?xf32>
+// CHECK-SAME: %[[sz0:.*]]: index
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[dim:.*]] = tensor.dim %[[m]], %[[c0]]
+// CHECK: %[[c2:.*]] = arith.constant 2 : index
+// CHECK: %[[prod:.*]] = arith.muli %[[sz0]], %[[c2]]
+// CHECK: %[[cmpi:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
+// CHECK: cf.assert %[[cmpi]], "ERROR: Runtime op verification failed
+func.func @expand_shape(%m: tensor<?xf32>, %sz0: index) -> tensor<?x2xf32> {
+ %0 = tensor.expand_shape %m [[0, 1]] output_shape [%sz0, 2] : tensor<?xf32> into tensor<?x2xf32>
+ return %0 : tensor<?x2xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @concat(
+// CHECK-SAME: %[[a:.*]]: tensor<?x?xf32>,
+// CHECK-SAME: %[[b:.*]]: tensor<?x?xf32>
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[da:.*]] = tensor.dim %[[a]], %[[c0]]
+// CHECK: %[[db:.*]] = tensor.dim %[[b]], %[[c0]]
+// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[db]], %[[da]]
+// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
+func.func @concat(%a: tensor<?x?xf32>, %b: tensor<?x?xf32>) -> tensor<?x?xf32> {
+ %0 = tensor.concat dim(1) %a, %b : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+ return %0 : tensor<?x?xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @concat_sum(
+// CHECK-SAME: %[[a:.*]]: tensor<?x3xf32>,
+// CHECK-SAME: %[[b:.*]]: tensor<?x3xf32>
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[da:.*]] = tensor.dim %[[a]], %[[c0]]
+// CHECK: %[[db:.*]] = tensor.dim %[[b]], %[[c0]]
+// CHECK: %[[sum:.*]] = arith.addi %[[da]], %[[db]]
+// CHECK: %[[c5:.*]] = arith.constant 5 : index
+// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[sum]], %[[c5]]
+// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
+func.func @concat_sum(%a: tensor<?x3xf32>, %b: tensor<?x3xf32>) -> tensor<5x3xf32> {
+ %0 = tensor.concat dim(0) %a, %b : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+ return %0 : tensor<5x3xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @reshape(
+// CHECK-SAME: %[[x:.*]]: tensor<?xf32>
+// CHECK-SAME: %[[shape:.*]]: tensor<2xindex>
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[e0:.*]] = tensor.extract %[[shape]][%[[c0]]]
+// CHECK: %[[c1:.*]] = arith.constant 1 : index
+// CHECK: %[[e1:.*]] = tensor.extract %[[shape]][%[[c1]]]
+// CHECK: %[[dim:.*]] = tensor.dim %[[x]], %[[c0]]
+// CHECK: %[[prod:.*]] = arith.muli %[[e0]], %[[e1]]
+// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
+// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
+func.func @reshape(%x: tensor<?xf32>, %shape: tensor<2xindex>) -> tensor<?x?xf32> {
+ %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
+ return %0 : tensor<?x?xf32>
+}
+
+// -----
+
+// Check that shape operand values are compared against static result sizes.
+
+// CHECK-LABEL: func @reshape_static_result(
+// CHECK-SAME: %[[x:.*]]: tensor<?xf32>
+// CHECK-SAME: %[[shape:.*]]: tensor<2xindex>
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[e0:.*]] = tensor.extract %[[shape]][%[[c0]]]
+// CHECK: %[[c1:.*]] = arith.constant 1 : index
+// CHECK: %[[e1:.*]] = tensor.extract %[[shape]][%[[c1]]]
+// CHECK: %[[c6:.*]] = arith.constant 6 : index
+// CHECK: %[[cmp0:.*]] = arith.cmpi eq, %[[e0]], %[[c6]]
+// CHECK: cf.assert %[[cmp0]], "ERROR: Runtime op verification failed
+// CHECK: %[[dim:.*]] = tensor.dim %[[x]], %[[c0]]
+// CHECK: %[[prod:.*]] = arith.muli %[[e0]], %[[e1]]
+// CHECK: %[[cmp1:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
+// CHECK: cf.assert %[[cmp1]], "ERROR: Runtime op verification failed
+func.func @reshape_static_result(%x: tensor<?xf32>, %shape: tensor<2xindex>) -> tensor<6x?xf32> {
+ %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
+ return %0 : tensor<6x?xf32>
+}
\ No newline at end of file
diff --git a/mlir/test/Integration/Dialect/Tensor/concat-runtime-verification.mlir b/mlir/test/Integration/Dialect/Tensor/concat-runtime-verification.mlir
new file mode 100644
index 00000000000000..7221e8e07e2d72
--- /dev/null
+++ b/mlir/test/Integration/Dialect/Tensor/concat-runtime-verification.mlir
@@ -0,0 +1,66 @@
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -convert-to-llvm | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+func.func private @concat(%a: tensor<?x?xf32>, %b: tensor<?x?xf32>) -> tensor<?x?xf32> {
+ %c = tensor.concat dim(1) %a, %b : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+ return %c : tensor<?x?xf32>
+}
+
+func.func private @concat_sum(%a: tensor<?x3xf32>, %b: tensor<?x3xf32>) -> tensor<5x3xf32> {
+ %c = tensor.concat dim(0) %a, %b : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+ return %c : tensor<5x3xf32>
+}
+
+func.func @main() {
+ %x = tensor.empty() : tensor<2x3xf32>
+ %y = tensor.empty() : tensor<4x3xf32>
+ %z = tensor.empty() : tensor<3x3xf32>
+ %a = tensor.cast %x : tensor<2x3xf32> to tensor<?x?xf32>
+ %b = tensor.cast %y : tensor<4x3xf32> to tensor<?x?xf32>
+ %c = tensor.cast %z : tensor<3x3xf32> to tensor<?x?xf32>
+ %a3 = tensor.cast %x : tensor<2x3xf32> to tensor<?x3xf32>
+ %b3 = tensor.cast %z : tensor<3x3xf32> to tensor<?x3xf32>
+ %y3 = tensor.cast %y : tensor<4x3xf32> to tensor<?x3xf32>
+
+ // Non-concatenated dimension 0 mismatch: 2 vs 4.
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.concat dim(1) %{{.*}}, %{{.*}} : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+ // CHECK-NEXT: ^ input size mismatch along non-concatenated dimension 0
+ // CHECK-NEXT: Location: loc({{.*}})
+ %r1 = func.call @concat(%a, %b) : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+
+ // Sum 2+4=6 does not equal static result size 5.
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.concat dim(0) %{{.*}}, %{{.*}} : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+ // CHECK-NEXT: ^ sum of input sizes along concatenated dimension does not match result size
+ // CHECK-NEXT: Location: loc({{.*}})
+ %r2 = func.call @concat_sum(%a3, %y3) : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+
+ // Matching inputs. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %r3 = func.call @concat(%a, %c) : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+
+ // Sum 2+3=5 equals static result size 5. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %r4 = func.call @concat_sum(%a3, %b3) : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+
+ return
+}
\ No newline at end of file
diff --git a/mlir/test/Integration/Dialect/Tensor/expand-shape-runtime-verification.mlir b/mlir/test/Integration/Dialect/Tensor/expand-shape-runtime-verification.mlir
new file mode 100644
index 00000000000000..8adc4695d15b8a
--- /dev/null
+++ b/mlir/test/Integration/Dialect/Tensor/expand-shape-runtime-verification.mlir
@@ -0,0 +1,45 @@
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -convert-to-llvm | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+func.func private @expand(%a: tensor<?xf32>, %n: index) -> tensor<?x2xf32> {
+ %e = tensor.expand_shape %a [[0, 1]] output_shape [%n, 2] : tensor<?xf32> into tensor<?x2xf32>
+ return %e : tensor<?x2xf32>
+}
+
+func.func @main() {
+ %a = tensor.empty() : tensor<6xf32>
+ %a_dyn = tensor.cast %a : tensor<6xf32> to tensor<?xf32>
+
+ // Product 5*2=10 does not equal input dim 6.
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.expand_shape %{{.*}} {{\[}}[0, 1]{{\]}} output_shape [%{{.*}}, 2] : tensor<?xf32> into tensor<?x2xf32>
+ // CHECK-NEXT: ^ product of output dims in reassoc group does not equal input dim
+ // CHECK-NEXT: Location: loc({{.*}})
+ %n5 = arith.constant 5 : index
+ %r1 = func.call @expand(%a_dyn, %n5) : (tensor<?xf32>, index) -> tensor<?x2xf32>
+
+ // Product 3*2=6 equals input dim 6. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %n3 = arith.constant 3 : index
+ %r2 = func.call @expand(%a_dyn, %n3) : (tensor<?xf32>, index) -> tensor<?x2xf32>
+
+ return
+}
\ No newline at end of file
diff --git a/mlir/test/Integration/Dialect/Tensor/reshape-runtime-verification.mlir b/mlir/test/Integration/Dialect/Tensor/reshape-runtime-verification.mlir
new file mode 100644
index 00000000000000..d936150850a9ad
--- /dev/null
+++ b/mlir/test/Integration/Dialect/Tensor/reshape-runtime-verification.mlir
@@ -0,0 +1,68 @@
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -convert-to-llvm | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+func.func private @reshape(%x: tensor<?xf32>, %n: index, %m: index) -> tensor<?x?xf32> {
+ %shape = tensor.from_elements %n, %m : tensor<2xindex>
+ %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
+ return %0 : tensor<?x?xf32>
+}
+
+func.func private @reshape_static_result(%x: tensor<?xf32>, %n: index, %m: index) -> tensor<6x?xf32> {
+ %shape = tensor.from_elements %n, %m : tensor<2xindex>
+ %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
+ return %0 : tensor<6x?xf32>
+}
+
+func.func @main() {
+ %x = tensor.empty() : tensor<6xf32>
+ %x_dyn = tensor.cast %x : tensor<6xf32> to tensor<?xf32>
+
+ // Product 4*4=16 does not equal source size 6.
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.reshape %{{.*}}(%{{.*}}) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
+ // CHECK-NEXT: ^ product of shape operand values does not equal number of elements in source
+ // CHECK-NEXT: Location: loc({{.*}})
+ %c4 = arith.constant 4 : index
+ %r1 = func.call @reshape(%x_dyn, %c4, %c4) : (tensor<?xf32>, index, index) -> tensor<?x?xf32>
+
+ // Shape value 3 does not match static result size 6 (product 3*2=6 still
+ // matches the source, so only the static-size assert fires).
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.reshape %{{.*}}(%{{.*}}) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
+ // CHECK-NEXT: ^ shape operand value does not match static result size along dimension 0
+ // CHECK-NEXT: Location: loc({{.*}})
+ %c3 = arith.constant 3 : index
+ %c2 = arith.constant 2 : index
+ %r2 = func.call @reshape_static_result(%x_dyn, %c3, %c2) : (tensor<?xf32>, index, index) -> tensor<6x?xf32>
+
+ // Product 3*2=6 equals source size 6. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %r3 = func.call @reshape(%x_dyn, %c3, %c2) : (tensor<?xf32>, index, index) -> tensor<?x?xf32>
+
+ // Product 6*1=6 equals source size 6, and shape value 6 matches the static
+ // result size along dimension 0. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %c6 = arith.constant 6 : index
+ %c1 = arith.constant 1 : index
+ %r4 = func.call @reshape_static_result(%x_dyn, %c6, %c1) : (tensor<?xf32>, index, index) -> tensor<6x?xf32>
+
+ return
+}
>From 404c42cad18ef9a2885cb14cf94f4e4703e7e9d5 Mon Sep 17 00:00:00 2001
From: wzy <WZYqwe2004 at outlook.com>
Date: Fri, 30 Oct 2026 08:31:40 +0800
Subject: [PATCH 2/3] format
---
.../Transforms/RuntimeOpVerification.cpp | 28 +++++++++----------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/mlir/lib/Dialect/Tensor/Transforms/RuntimeOpVerification.cpp b/mlir/lib/Dialect/Tensor/Transforms/RuntimeOpVerification.cpp
index 3a0fb352513a8f..da5833657baa94 100644
--- a/mlir/lib/Dialect/Tensor/Transforms/RuntimeOpVerification.cpp
+++ b/mlir/lib/Dialect/Tensor/Transforms/RuntimeOpVerification.cpp
@@ -359,9 +359,8 @@ struct ConcatOpInterface
getDimSize(input, concatDim));
Value resultSize = arith::ConstantIndexOp::create(
builder, loc, resultType.getDimSize(concatDim));
- Value isEqual = arith::CmpIOp::create(builder, loc,
- arith::CmpIPredicate::eq, sum,
- resultSize);
+ Value isEqual = arith::CmpIOp::create(
+ builder, loc, arith::CmpIPredicate::eq, sum, resultSize);
cf::AssertOp::create(
builder, loc, isEqual,
generateErrorMessage(op, "sum of input sizes along concatenated "
@@ -394,8 +393,8 @@ struct ReshapeOpInterface
Value shapeValue =
ExtractOp::create(builder, loc, reshapeOp.getShape(), idx);
if (shapeValue.getType() != indexType)
- shapeValue = arith::IndexCastOp::create(builder, loc, indexType,
- shapeValue);
+ shapeValue =
+ arith::IndexCastOp::create(builder, loc, indexType, shapeValue);
shapeValues.push_back(shapeValue);
}
@@ -410,9 +409,9 @@ struct ReshapeOpInterface
continue;
Value expectedSize = arith::ConstantIndexOp::create(
builder, loc, resultType.getDimSize(i));
- Value isEqual = arith::CmpIOp::create(
- builder, loc, arith::CmpIPredicate::eq, shapeValues[i],
- expectedSize);
+ Value isEqual =
+ arith::CmpIOp::create(builder, loc, arith::CmpIPredicate::eq,
+ shapeValues[i], expectedSize);
cf::AssertOp::create(
builder, loc, isEqual,
generateErrorMessage(op, "shape operand value does not match "
@@ -444,23 +443,22 @@ struct ReshapeOpInterface
std::optional<Value> shapeProduct;
for (Value shapeValue : shapeValues) {
shapeProduct =
- shapeProduct ? arith::MulIOp::create(builder, loc, *shapeProduct,
- shapeValue)
- : shapeValue;
+ shapeProduct
+ ? arith::MulIOp::create(builder, loc, *shapeProduct, shapeValue)
+ : shapeValue;
}
if (!shapeProduct)
shapeProduct = arith::ConstantIndexOp::create(builder, loc, 1);
- Value isEqual = arith::CmpIOp::create(
- builder, loc, arith::CmpIPredicate::eq, *shapeProduct,
- sourceNumElements);
+ Value isEqual =
+ arith::CmpIOp::create(builder, loc, arith::CmpIPredicate::eq,
+ *shapeProduct, sourceNumElements);
cf::AssertOp::create(
builder, loc, isEqual,
generateErrorMessage(op, "product of shape operand values does not "
"equal number of elements in source"));
}
};
-
} // namespace
} // namespace tensor
} // namespace mlir
>From 46f025ca28b573df8031bf0e8a645c0b0297f82c Mon Sep 17 00:00:00 2001
From: wzy <WZYqwe2004 at outlook.com>
Date: Mon, 2 Nov 2026 19:10:20 +0800
Subject: [PATCH 3/3] fixed tests
---
.../Dialect/Tensor/runtime-verification.mlir | 174 +++++++++---------
.../Tensor/concat-runtime-verification.mlir | 138 +++++++-------
.../expand-shape-runtime-verification.mlir | 95 +++++-----
.../Tensor/reshape-runtime-verification.mlir | 143 +++++++-------
4 files changed, 286 insertions(+), 264 deletions(-)
diff --git a/mlir/test/Dialect/Tensor/runtime-verification.mlir b/mlir/test/Dialect/Tensor/runtime-verification.mlir
index 952d10e7dc8303..2e0de760ab573c 100644
--- a/mlir/test/Dialect/Tensor/runtime-verification.mlir
+++ b/mlir/test/Dialect/Tensor/runtime-verification.mlir
@@ -1,88 +1,88 @@
-// RUN: mlir-opt %s -generate-runtime-verification -cse -split-input-file | FileCheck %s
-
-// CHECK-LABEL: func @expand_shape(
-// CHECK-SAME: %[[m:.*]]: tensor<?xf32>
-// CHECK-SAME: %[[sz0:.*]]: index
-// CHECK: %[[c0:.*]] = arith.constant 0 : index
-// CHECK: %[[dim:.*]] = tensor.dim %[[m]], %[[c0]]
-// CHECK: %[[c2:.*]] = arith.constant 2 : index
-// CHECK: %[[prod:.*]] = arith.muli %[[sz0]], %[[c2]]
-// CHECK: %[[cmpi:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
-// CHECK: cf.assert %[[cmpi]], "ERROR: Runtime op verification failed
-func.func @expand_shape(%m: tensor<?xf32>, %sz0: index) -> tensor<?x2xf32> {
- %0 = tensor.expand_shape %m [[0, 1]] output_shape [%sz0, 2] : tensor<?xf32> into tensor<?x2xf32>
- return %0 : tensor<?x2xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @concat(
-// CHECK-SAME: %[[a:.*]]: tensor<?x?xf32>,
-// CHECK-SAME: %[[b:.*]]: tensor<?x?xf32>
-// CHECK: %[[c0:.*]] = arith.constant 0 : index
-// CHECK: %[[da:.*]] = tensor.dim %[[a]], %[[c0]]
-// CHECK: %[[db:.*]] = tensor.dim %[[b]], %[[c0]]
-// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[db]], %[[da]]
-// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
-func.func @concat(%a: tensor<?x?xf32>, %b: tensor<?x?xf32>) -> tensor<?x?xf32> {
- %0 = tensor.concat dim(1) %a, %b : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
- return %0 : tensor<?x?xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @concat_sum(
-// CHECK-SAME: %[[a:.*]]: tensor<?x3xf32>,
-// CHECK-SAME: %[[b:.*]]: tensor<?x3xf32>
-// CHECK: %[[c0:.*]] = arith.constant 0 : index
-// CHECK: %[[da:.*]] = tensor.dim %[[a]], %[[c0]]
-// CHECK: %[[db:.*]] = tensor.dim %[[b]], %[[c0]]
-// CHECK: %[[sum:.*]] = arith.addi %[[da]], %[[db]]
-// CHECK: %[[c5:.*]] = arith.constant 5 : index
-// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[sum]], %[[c5]]
-// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
-func.func @concat_sum(%a: tensor<?x3xf32>, %b: tensor<?x3xf32>) -> tensor<5x3xf32> {
- %0 = tensor.concat dim(0) %a, %b : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
- return %0 : tensor<5x3xf32>
-}
-
-// -----
-
-// CHECK-LABEL: func @reshape(
-// CHECK-SAME: %[[x:.*]]: tensor<?xf32>
-// CHECK-SAME: %[[shape:.*]]: tensor<2xindex>
-// CHECK: %[[c0:.*]] = arith.constant 0 : index
-// CHECK: %[[e0:.*]] = tensor.extract %[[shape]][%[[c0]]]
-// CHECK: %[[c1:.*]] = arith.constant 1 : index
-// CHECK: %[[e1:.*]] = tensor.extract %[[shape]][%[[c1]]]
-// CHECK: %[[dim:.*]] = tensor.dim %[[x]], %[[c0]]
-// CHECK: %[[prod:.*]] = arith.muli %[[e0]], %[[e1]]
-// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
-// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
-func.func @reshape(%x: tensor<?xf32>, %shape: tensor<2xindex>) -> tensor<?x?xf32> {
- %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
- return %0 : tensor<?x?xf32>
-}
-
-// -----
-
-// Check that shape operand values are compared against static result sizes.
-
-// CHECK-LABEL: func @reshape_static_result(
-// CHECK-SAME: %[[x:.*]]: tensor<?xf32>
-// CHECK-SAME: %[[shape:.*]]: tensor<2xindex>
-// CHECK: %[[c0:.*]] = arith.constant 0 : index
-// CHECK: %[[e0:.*]] = tensor.extract %[[shape]][%[[c0]]]
-// CHECK: %[[c1:.*]] = arith.constant 1 : index
-// CHECK: %[[e1:.*]] = tensor.extract %[[shape]][%[[c1]]]
-// CHECK: %[[c6:.*]] = arith.constant 6 : index
-// CHECK: %[[cmp0:.*]] = arith.cmpi eq, %[[e0]], %[[c6]]
-// CHECK: cf.assert %[[cmp0]], "ERROR: Runtime op verification failed
-// CHECK: %[[dim:.*]] = tensor.dim %[[x]], %[[c0]]
-// CHECK: %[[prod:.*]] = arith.muli %[[e0]], %[[e1]]
-// CHECK: %[[cmp1:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
-// CHECK: cf.assert %[[cmp1]], "ERROR: Runtime op verification failed
-func.func @reshape_static_result(%x: tensor<?xf32>, %shape: tensor<2xindex>) -> tensor<6x?xf32> {
- %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
- return %0 : tensor<6x?xf32>
+// RUN: mlir-opt %s -generate-runtime-verification -cse -split-input-file | FileCheck %s
+
+// CHECK-LABEL: func @expand_shape(
+// CHECK-SAME: %[[m:.*]]: tensor<?xf32>
+// CHECK-SAME: %[[sz0:.*]]: index
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[dim:.*]] = tensor.dim %[[m]], %[[c0]]
+// CHECK: %[[c2:.*]] = arith.constant 2 : index
+// CHECK: %[[prod:.*]] = arith.muli %[[sz0]], %[[c2]]
+// CHECK: %[[cmpi:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
+// CHECK: cf.assert %[[cmpi]], "ERROR: Runtime op verification failed
+func.func @expand_shape(%m: tensor<?xf32>, %sz0: index) -> tensor<?x2xf32> {
+ %0 = tensor.expand_shape %m [[0, 1]] output_shape [%sz0, 2] : tensor<?xf32> into tensor<?x2xf32>
+ return %0 : tensor<?x2xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @concat(
+// CHECK-SAME: %[[a:.*]]: tensor<?x?xf32>,
+// CHECK-SAME: %[[b:.*]]: tensor<?x?xf32>
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[da:.*]] = tensor.dim %[[a]], %[[c0]]
+// CHECK: %[[db:.*]] = tensor.dim %[[b]], %[[c0]]
+// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[db]], %[[da]]
+// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
+func.func @concat(%a: tensor<?x?xf32>, %b: tensor<?x?xf32>) -> tensor<?x?xf32> {
+ %0 = tensor.concat dim(1) %a, %b : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+ return %0 : tensor<?x?xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @concat_sum(
+// CHECK-SAME: %[[a:.*]]: tensor<?x3xf32>,
+// CHECK-SAME: %[[b:.*]]: tensor<?x3xf32>
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[da:.*]] = tensor.dim %[[a]], %[[c0]]
+// CHECK: %[[db:.*]] = tensor.dim %[[b]], %[[c0]]
+// CHECK: %[[sum:.*]] = arith.addi %[[da]], %[[db]]
+// CHECK: %[[c5:.*]] = arith.constant 5 : index
+// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[sum]], %[[c5]]
+// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
+func.func @concat_sum(%a: tensor<?x3xf32>, %b: tensor<?x3xf32>) -> tensor<5x3xf32> {
+ %0 = tensor.concat dim(0) %a, %b : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+ return %0 : tensor<5x3xf32>
+}
+
+// -----
+
+// CHECK-LABEL: func @reshape(
+// CHECK-SAME: %[[x:.*]]: tensor<?xf32>
+// CHECK-SAME: %[[shape:.*]]: tensor<2xindex>
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[e0:.*]] = tensor.extract %[[shape]][%[[c0]]]
+// CHECK: %[[c1:.*]] = arith.constant 1 : index
+// CHECK: %[[e1:.*]] = tensor.extract %[[shape]][%[[c1]]]
+// CHECK: %[[dim:.*]] = tensor.dim %[[x]], %[[c0]]
+// CHECK: %[[prod:.*]] = arith.muli %[[e0]], %[[e1]]
+// CHECK: %[[cmp:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
+// CHECK: cf.assert %[[cmp]], "ERROR: Runtime op verification failed
+func.func @reshape(%x: tensor<?xf32>, %shape: tensor<2xindex>) -> tensor<?x?xf32> {
+ %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
+ return %0 : tensor<?x?xf32>
+}
+
+// -----
+
+// Check that shape operand values are compared against static result sizes.
+
+// CHECK-LABEL: func @reshape_static_result(
+// CHECK-SAME: %[[x:.*]]: tensor<?xf32>
+// CHECK-SAME: %[[shape:.*]]: tensor<2xindex>
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+// CHECK: %[[e0:.*]] = tensor.extract %[[shape]][%[[c0]]]
+// CHECK: %[[c1:.*]] = arith.constant 1 : index
+// CHECK: %[[e1:.*]] = tensor.extract %[[shape]][%[[c1]]]
+// CHECK: %[[c6:.*]] = arith.constant 6 : index
+// CHECK: %[[cmp0:.*]] = arith.cmpi eq, %[[e0]], %[[c6]]
+// CHECK: cf.assert %[[cmp0]], "ERROR: Runtime op verification failed
+// CHECK: %[[dim:.*]] = tensor.dim %[[x]], %[[c0]]
+// CHECK: %[[prod:.*]] = arith.muli %[[e0]], %[[e1]]
+// CHECK: %[[cmp1:.*]] = arith.cmpi eq, %[[prod]], %[[dim]]
+// CHECK: cf.assert %[[cmp1]], "ERROR: Runtime op verification failed
+func.func @reshape_static_result(%x: tensor<?xf32>, %shape: tensor<2xindex>) -> tensor<6x?xf32> {
+ %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
+ return %0 : tensor<6x?xf32>
}
\ No newline at end of file
diff --git a/mlir/test/Integration/Dialect/Tensor/concat-runtime-verification.mlir b/mlir/test/Integration/Dialect/Tensor/concat-runtime-verification.mlir
index 7221e8e07e2d72..5728ab83499d23 100644
--- a/mlir/test/Integration/Dialect/Tensor/concat-runtime-verification.mlir
+++ b/mlir/test/Integration/Dialect/Tensor/concat-runtime-verification.mlir
@@ -1,66 +1,74 @@
-// RUN: mlir-opt %s -generate-runtime-verification \
-// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
-// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
-// RUN: -test-cf-assert \
-// RUN: -convert-scf-to-cf \
-// RUN: -convert-to-llvm | \
-// RUN: mlir-runner -e main -entry-point-result=void \
-// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
-// RUN: FileCheck %s
-
-// RUN: mlir-opt %s -generate-runtime-verification \
-// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
-// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
-// RUN: -test-cf-assert \
-// RUN: -convert-scf-to-cf \
-// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
-// RUN: -reconcile-unrealized-casts | \
-// RUN: mlir-runner -e main -entry-point-result=void \
-// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
-// RUN: FileCheck %s
-
-func.func private @concat(%a: tensor<?x?xf32>, %b: tensor<?x?xf32>) -> tensor<?x?xf32> {
- %c = tensor.concat dim(1) %a, %b : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
- return %c : tensor<?x?xf32>
-}
-
-func.func private @concat_sum(%a: tensor<?x3xf32>, %b: tensor<?x3xf32>) -> tensor<5x3xf32> {
- %c = tensor.concat dim(0) %a, %b : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
- return %c : tensor<5x3xf32>
-}
-
-func.func @main() {
- %x = tensor.empty() : tensor<2x3xf32>
- %y = tensor.empty() : tensor<4x3xf32>
- %z = tensor.empty() : tensor<3x3xf32>
- %a = tensor.cast %x : tensor<2x3xf32> to tensor<?x?xf32>
- %b = tensor.cast %y : tensor<4x3xf32> to tensor<?x?xf32>
- %c = tensor.cast %z : tensor<3x3xf32> to tensor<?x?xf32>
- %a3 = tensor.cast %x : tensor<2x3xf32> to tensor<?x3xf32>
- %b3 = tensor.cast %z : tensor<3x3xf32> to tensor<?x3xf32>
- %y3 = tensor.cast %y : tensor<4x3xf32> to tensor<?x3xf32>
-
- // Non-concatenated dimension 0 mismatch: 2 vs 4.
- // CHECK: ERROR: Runtime op verification failed
- // CHECK-NEXT: tensor.concat dim(1) %{{.*}}, %{{.*}} : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
- // CHECK-NEXT: ^ input size mismatch along non-concatenated dimension 0
- // CHECK-NEXT: Location: loc({{.*}})
- %r1 = func.call @concat(%a, %b) : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
-
- // Sum 2+4=6 does not equal static result size 5.
- // CHECK: ERROR: Runtime op verification failed
- // CHECK-NEXT: tensor.concat dim(0) %{{.*}}, %{{.*}} : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
- // CHECK-NEXT: ^ sum of input sizes along concatenated dimension does not match result size
- // CHECK-NEXT: Location: loc({{.*}})
- %r2 = func.call @concat_sum(%a3, %y3) : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
-
- // Matching inputs. No error.
- // CHECK-NOT: ERROR: Runtime op verification failed
- %r3 = func.call @concat(%a, %c) : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
-
- // Sum 2+3=5 equals static result size 5. No error.
- // CHECK-NOT: ERROR: Runtime op verification failed
- %r4 = func.call @concat_sum(%a3, %b3) : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
-
- return
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -expand-strided-metadata \
+// RUN: -lower-affine \
+// RUN: -convert-to-llvm \
+// RUN: -finalize-memref-to-llvm \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -expand-strided-metadata \
+// RUN: -lower-affine \
+// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
+// RUN: -finalize-memref-to-llvm \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+func.func private @concat(%a: tensor<?x?xf32>, %b: tensor<?x?xf32>) -> tensor<?x?xf32> {
+ %c = tensor.concat dim(1) %a, %b : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+ return %c : tensor<?x?xf32>
+}
+
+func.func private @concat_sum(%a: tensor<?x3xf32>, %b: tensor<?x3xf32>) -> tensor<5x3xf32> {
+ %c = tensor.concat dim(0) %a, %b : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+ return %c : tensor<5x3xf32>
+}
+
+func.func @main() {
+ %x = tensor.empty() : tensor<2x3xf32>
+ %y = tensor.empty() : tensor<4x3xf32>
+ %z = tensor.empty() : tensor<3x3xf32>
+ %w = tensor.empty() : tensor<2x3xf32>
+ %a = tensor.cast %x : tensor<2x3xf32> to tensor<?x?xf32>
+ %b = tensor.cast %y : tensor<4x3xf32> to tensor<?x?xf32>
+ %d = tensor.cast %w : tensor<2x3xf32> to tensor<?x?xf32>
+ %a3 = tensor.cast %x : tensor<2x3xf32> to tensor<?x3xf32>
+ %b3 = tensor.cast %z : tensor<3x3xf32> to tensor<?x3xf32>
+ %x3 = tensor.cast %x : tensor<2x3xf32> to tensor<?x3xf32>
+
+ // Non-concatenated dimension 0 mismatch: 2 vs 4.
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.concat dim(1) %{{.*}}, %{{.*}} : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+ // CHECK-NEXT: ^ input size mismatch along non-concatenated dimension 0
+ // CHECK-NEXT: Location: loc({{.*}})
+ %r1 = func.call @concat(%b, %a) : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+
+ // Sum 2+2=4 does not equal static result size 5.
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.concat dim(0) %{{.*}}, %{{.*}} : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+ // CHECK-NEXT: ^ sum of input sizes along concatenated dimension does not match result size
+ // CHECK-NEXT: Location: loc({{.*}})
+ %r2 = func.call @concat_sum(%a3, %x3) : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+
+ // Matching inputs (2x3 and 2x3, dim 0 agrees). No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %r3 = func.call @concat(%a, %d) : (tensor<?x?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
+
+ // Sum 2+3=5 equals static result size 5. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %r4 = func.call @concat_sum(%a3, %b3) : (tensor<?x3xf32>, tensor<?x3xf32>) -> tensor<5x3xf32>
+
+ return
}
\ No newline at end of file
diff --git a/mlir/test/Integration/Dialect/Tensor/expand-shape-runtime-verification.mlir b/mlir/test/Integration/Dialect/Tensor/expand-shape-runtime-verification.mlir
index 8adc4695d15b8a..39f0431c786bfd 100644
--- a/mlir/test/Integration/Dialect/Tensor/expand-shape-runtime-verification.mlir
+++ b/mlir/test/Integration/Dialect/Tensor/expand-shape-runtime-verification.mlir
@@ -1,45 +1,52 @@
-// RUN: mlir-opt %s -generate-runtime-verification \
-// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
-// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
-// RUN: -test-cf-assert \
-// RUN: -convert-scf-to-cf \
-// RUN: -convert-to-llvm | \
-// RUN: mlir-runner -e main -entry-point-result=void \
-// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
-// RUN: FileCheck %s
-
-// RUN: mlir-opt %s -generate-runtime-verification \
-// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
-// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
-// RUN: -test-cf-assert \
-// RUN: -convert-scf-to-cf \
-// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
-// RUN: -reconcile-unrealized-casts | \
-// RUN: mlir-runner -e main -entry-point-result=void \
-// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
-// RUN: FileCheck %s
-
-func.func private @expand(%a: tensor<?xf32>, %n: index) -> tensor<?x2xf32> {
- %e = tensor.expand_shape %a [[0, 1]] output_shape [%n, 2] : tensor<?xf32> into tensor<?x2xf32>
- return %e : tensor<?x2xf32>
-}
-
-func.func @main() {
- %a = tensor.empty() : tensor<6xf32>
- %a_dyn = tensor.cast %a : tensor<6xf32> to tensor<?xf32>
-
- // Product 5*2=10 does not equal input dim 6.
- // CHECK: ERROR: Runtime op verification failed
- // CHECK-NEXT: tensor.expand_shape %{{.*}} {{\[}}[0, 1]{{\]}} output_shape [%{{.*}}, 2] : tensor<?xf32> into tensor<?x2xf32>
- // CHECK-NEXT: ^ product of output dims in reassoc group does not equal input dim
- // CHECK-NEXT: Location: loc({{.*}})
- %n5 = arith.constant 5 : index
- %r1 = func.call @expand(%a_dyn, %n5) : (tensor<?xf32>, index) -> tensor<?x2xf32>
-
- // Product 3*2=6 equals input dim 6. No error.
- // CHECK-NOT: ERROR: Runtime op verification failed
- %n3 = arith.constant 3 : index
- %r2 = func.call @expand(%a_dyn, %n3) : (tensor<?xf32>, index) -> tensor<?x2xf32>
-
- return
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -expand-strided-metadata \
+// RUN: -lower-affine \
+// RUN: -convert-to-llvm \
+// RUN: -finalize-memref-to-llvm \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -expand-strided-metadata \
+// RUN: -lower-affine \
+// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
+// RUN: -finalize-memref-to-llvm \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+func.func private @expand(%a: tensor<?xf32>, %n: index) -> tensor<?x2xf32> {
+ %e = tensor.expand_shape %a [[0, 1]] output_shape [%n, 2] : tensor<?xf32> into tensor<?x2xf32>
+ return %e : tensor<?x2xf32>
+}
+
+func.func @main() {
+ %a = tensor.empty() : tensor<6xf32>
+ %a_dyn = tensor.cast %a : tensor<6xf32> to tensor<?xf32>
+
+ // Product 5*2=10 does not equal input dim 6.
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.expand_shape %{{.*}} {{\[}}[0, 1]{{\]}} output_shape [%{{.*}}, 2] : tensor<?xf32> into tensor<?x2xf32>
+ // CHECK-NEXT: ^ product of output dims in reassoc group does not equal input dim
+ // CHECK-NEXT: Location: loc({{.*}})
+ %n5 = arith.constant 5 : index
+ %r1 = func.call @expand(%a_dyn, %n5) : (tensor<?xf32>, index) -> tensor<?x2xf32>
+
+ // Product 3*2=6 equals input dim 6. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %n3 = arith.constant 3 : index
+ %r2 = func.call @expand(%a_dyn, %n3) : (tensor<?xf32>, index) -> tensor<?x2xf32>
+
+ return
}
\ No newline at end of file
diff --git a/mlir/test/Integration/Dialect/Tensor/reshape-runtime-verification.mlir b/mlir/test/Integration/Dialect/Tensor/reshape-runtime-verification.mlir
index d936150850a9ad..37d980df2d3ef3 100644
--- a/mlir/test/Integration/Dialect/Tensor/reshape-runtime-verification.mlir
+++ b/mlir/test/Integration/Dialect/Tensor/reshape-runtime-verification.mlir
@@ -1,68 +1,75 @@
-// RUN: mlir-opt %s -generate-runtime-verification \
-// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
-// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
-// RUN: -test-cf-assert \
-// RUN: -convert-scf-to-cf \
-// RUN: -convert-to-llvm | \
-// RUN: mlir-runner -e main -entry-point-result=void \
-// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
-// RUN: FileCheck %s
-
-// RUN: mlir-opt %s -generate-runtime-verification \
-// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
-// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
-// RUN: -test-cf-assert \
-// RUN: -convert-scf-to-cf \
-// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
-// RUN: -reconcile-unrealized-casts | \
-// RUN: mlir-runner -e main -entry-point-result=void \
-// RUN: -shared-libs=%mlir_runner_utils 2>&1 | \
-// RUN: FileCheck %s
-
-func.func private @reshape(%x: tensor<?xf32>, %n: index, %m: index) -> tensor<?x?xf32> {
- %shape = tensor.from_elements %n, %m : tensor<2xindex>
- %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
- return %0 : tensor<?x?xf32>
-}
-
-func.func private @reshape_static_result(%x: tensor<?xf32>, %n: index, %m: index) -> tensor<6x?xf32> {
- %shape = tensor.from_elements %n, %m : tensor<2xindex>
- %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
- return %0 : tensor<6x?xf32>
-}
-
-func.func @main() {
- %x = tensor.empty() : tensor<6xf32>
- %x_dyn = tensor.cast %x : tensor<6xf32> to tensor<?xf32>
-
- // Product 4*4=16 does not equal source size 6.
- // CHECK: ERROR: Runtime op verification failed
- // CHECK-NEXT: tensor.reshape %{{.*}}(%{{.*}}) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
- // CHECK-NEXT: ^ product of shape operand values does not equal number of elements in source
- // CHECK-NEXT: Location: loc({{.*}})
- %c4 = arith.constant 4 : index
- %r1 = func.call @reshape(%x_dyn, %c4, %c4) : (tensor<?xf32>, index, index) -> tensor<?x?xf32>
-
- // Shape value 3 does not match static result size 6 (product 3*2=6 still
- // matches the source, so only the static-size assert fires).
- // CHECK: ERROR: Runtime op verification failed
- // CHECK-NEXT: tensor.reshape %{{.*}}(%{{.*}}) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
- // CHECK-NEXT: ^ shape operand value does not match static result size along dimension 0
- // CHECK-NEXT: Location: loc({{.*}})
- %c3 = arith.constant 3 : index
- %c2 = arith.constant 2 : index
- %r2 = func.call @reshape_static_result(%x_dyn, %c3, %c2) : (tensor<?xf32>, index, index) -> tensor<6x?xf32>
-
- // Product 3*2=6 equals source size 6. No error.
- // CHECK-NOT: ERROR: Runtime op verification failed
- %r3 = func.call @reshape(%x_dyn, %c3, %c2) : (tensor<?xf32>, index, index) -> tensor<?x?xf32>
-
- // Product 6*1=6 equals source size 6, and shape value 6 matches the static
- // result size along dimension 0. No error.
- // CHECK-NOT: ERROR: Runtime op verification failed
- %c6 = arith.constant 6 : index
- %c1 = arith.constant 1 : index
- %r4 = func.call @reshape_static_result(%x_dyn, %c6, %c1) : (tensor<?xf32>, index, index) -> tensor<6x?xf32>
-
- return
-}
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -expand-strided-metadata \
+// RUN: -lower-affine \
+// RUN: -convert-to-llvm \
+// RUN: -finalize-memref-to-llvm \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+// RUN: mlir-opt %s -generate-runtime-verification \
+// RUN: -one-shot-bufferize="bufferize-function-boundaries" \
+// RUN: -buffer-deallocation-pipeline=private-function-dynamic-ownership \
+// RUN: -test-cf-assert \
+// RUN: -convert-scf-to-cf \
+// RUN: -expand-strided-metadata \
+// RUN: -lower-affine \
+// RUN: -convert-to-llvm="allow-pattern-rollback=0" \
+// RUN: -finalize-memref-to-llvm \
+// RUN: -reconcile-unrealized-casts | \
+// RUN: mlir-runner -e main -entry-point-result=void \
+// RUN: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils 2>&1 | \
+// RUN: FileCheck %s
+
+func.func private @reshape(%x: tensor<?xf32>, %n: index, %m: index) -> tensor<?x?xf32> {
+ %shape = tensor.from_elements %n, %m : tensor<2xindex>
+ %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
+ return %0 : tensor<?x?xf32>
+}
+
+func.func private @reshape_static_result(%x: tensor<?xf32>, %n: index, %m: index) -> tensor<6x?xf32> {
+ %shape = tensor.from_elements %n, %m : tensor<2xindex>
+ %0 = tensor.reshape %x(%shape) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
+ return %0 : tensor<6x?xf32>
+}
+
+func.func @main() {
+ %x = tensor.empty() : tensor<6xf32>
+ %x_dyn = tensor.cast %x : tensor<6xf32> to tensor<?xf32>
+
+ // Product 4*4=16 does not equal source size 6.
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.reshape %{{.*}}(%{{.*}}) : (tensor<?xf32>, tensor<2xindex>) -> tensor<?x?xf32>
+ // CHECK-NEXT: ^ product of shape operand values does not equal number of elements in source
+ // CHECK-NEXT: Location: loc({{.*}})
+ %c4 = arith.constant 4 : index
+ %r1 = func.call @reshape(%x_dyn, %c4, %c4) : (tensor<?xf32>, index, index) -> tensor<?x?xf32>
+
+ // Shape value 3 does not match static result size 6 (product 3*2=6 still
+ // matches the source, so only the static-size assert fires).
+ // CHECK: ERROR: Runtime op verification failed
+ // CHECK-NEXT: tensor.reshape %{{.*}}(%{{.*}}) : (tensor<?xf32>, tensor<2xindex>) -> tensor<6x?xf32>
+ // CHECK-NEXT: ^ shape operand value does not match static result size along dimension 0
+ // CHECK-NEXT: Location: loc({{.*}})
+ %c3 = arith.constant 3 : index
+ %c2 = arith.constant 2 : index
+ %r2 = func.call @reshape_static_result(%x_dyn, %c3, %c2) : (tensor<?xf32>, index, index) -> tensor<6x?xf32>
+
+ // Product 3*2=6 equals source size 6. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %r3 = func.call @reshape(%x_dyn, %c3, %c2) : (tensor<?xf32>, index, index) -> tensor<?x?xf32>
+
+ // Product 6*1=6 equals source size 6, and shape value 6 matches the static
+ // result size along dimension 0. No error.
+ // CHECK-NOT: ERROR: Runtime op verification failed
+ %c6 = arith.constant 6 : index
+ %c1 = arith.constant 1 : index
+ %r4 = func.call @reshape_static_result(%x_dyn, %c6, %c1) : (tensor<?xf32>, index, index) -> tensor<6x?xf32>
+
+ return
+}
More information about the Mlir-commits
mailing list