[Mlir-commits] [mlir] [[mlir][linalg] Infer reduction-neutral padding values in rewriteAsPaddedOp (PR #216517)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sat Aug 15 15:59:10 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
@llvm/pr-subscribers-mlir-linalg
Author: Jianhui Li (Jianhui-Li)
<details>
<summary>Changes</summary>
**Problem**:
with no explicit options.paddingValues, rewriteAsPaddedOp padded every operand with zero — silently corrupting reductions (a padded maximumf/mulf element gets combined).
**Change**:
Added a new public linalg::inferPaddingValues(builder, toPad) to pick a semantics-preserving value per operand:
- no reduction dim → zero;
- contraction → zero (0 annihilates through the multiply);
- other reductions → the combiner's neutral (-inf for maximumf, 1 for mulf, …), found via matchReduction so the real accumulator combiner is used.
rewriteAsPaddedOp calls it when options.paddingValues is empty. If no value can be inferred, it returns failure() with the error "could not infer a padding value"; the caller is then expected to determine the value and supply it explicitly through options.paddingValues.
assited-by-claude
---
Full diff: https://github.com/llvm/llvm-project/pull/216517.diff
4 Files Affected:
- (modified) mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h (+13)
- (modified) mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp (+6)
- (modified) mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp (+64-6)
- (added) mlir/test/Dialect/Linalg/transform-op-pad-tiling-interface-reduction.mlir (+296)
``````````diff
diff --git a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
index 130f7f6fd2792..6b31ee353f37d 100644
--- a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
+++ b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h
@@ -745,6 +745,19 @@ struct PadTilingInterfaceResult {
SmallVector<Value> replacements;
};
+/// Infers a semantics-preserving padding value for every operand of `toPad`
+/// (indexed by operand number). Operands that are reduced are padded with the
+/// neutral element of their reduction combiner (e.g. `-inf` for `maximumf`, `1`
+/// for `mulf`) because a plain zero would corrupt the reduction; every other
+/// operand is padded with the zero value of its element type.
+///
+/// Inference is conservative: it returns failure when a semantics-preserving
+/// value cannot be determined (a non-LinalgOp reduction, or a reduction whose
+/// neutral element is unknown), letting callers decide whether to set
+/// `options.paddingValues` explicitly.
+FailureOr<SmallVector<Attribute>> inferPaddingValues(OpBuilder &builder,
+ TilingInterface toPad);
+
/// Pad the iterator dimensions of `toPad`.
/// * "options.paddingSizes" indicates that each padding dimension should be
/// padded to the specified padding size.
diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
index 8c5bd50bd6f8b..bf63844a7f1a1 100644
--- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
+++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
@@ -2530,6 +2530,12 @@ transform::PadTilingInterfaceOp::apply(transform::TransformRewriter &rewriter,
if (failed(maybePadOps)) {
auto diag = emitSilenceableError() << "failed to pad op";
diag.attachNote(target->getLoc()) << "target op";
+ // With no explicit padding values the transform relies on inference,
+ // which fails when a semantics-preserving value cannot be determined
+ // (e.g. a reduction whose neutral element is unknown).
+ if (paddingValues.empty())
+ diag.attachNote(target->getLoc())
+ << "could not infer a padding value; specify `padding_values`";
return diag;
}
const auto &[paddedOperands, paddedOp, slicedResults] = maybePadOps.value();
diff --git a/mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp b/mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp
index ab2629b41a463..d1b517554b901 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/PadTilingInterface.cpp
@@ -8,8 +8,11 @@
#include "mlir/Dialect/Linalg/Transforms/Transforms.h"
+#include "mlir/Analysis/SliceAnalysis.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
+#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
+#include "mlir/Dialect/Linalg/IR/LinalgInterfaces.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/UB/IR/UBMatchers.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
@@ -263,6 +266,61 @@ static Value padOperand(OpBuilder &builder, TilingInterface opToPad,
paddingValue, /*nofold=*/false, dynDims);
}
+FailureOr<SmallVector<Attribute>>
+linalg::inferPaddingValues(OpBuilder &builder, TilingInterface toPad) {
+ Operation *op = toPad.getOperation();
+
+ // Padding acts on operands; default each to the zero of its element type.
+ SmallVector<Attribute> paddingValues;
+ for (Type t : op->getOperandTypes())
+ paddingValues.push_back(builder.getZeroAttr(getElementTypeOrSelf(t)));
+
+ // No reduction: padded elements are never combined, so zero is always safe.
+ SmallVector<utils::IteratorType> iterTypes = toPad.getLoopIteratorTypes();
+ if (!llvm::is_contained(iterTypes, utils::IteratorType::reduction))
+ return paddingValues;
+
+ // A reduction's neutral element requires inspecting the combiner, which is
+ // only possible for a LinalgOp; fail conservatively otherwise.
+ auto linalgOp = dyn_cast<linalg::LinalgOp>(op);
+ if (!linalgOp)
+ return failure();
+
+ // In a contraction, zero annihilates through the multiply (0 * x = 0), so the
+ // default zero is already correct for every operand.
+ if (isaContractionOpInterface(linalgOp))
+ return paddingValues;
+
+ // Only a single reduction has an unambiguous per-operand neutral.
+ if (linalgOp.getNumDpsInits() != 1)
+ return failure();
+ SmallVector<Operation *> combiners;
+ if (!matchReduction(linalgOp.getRegionOutputArgs(), 0, combiners))
+ return failure();
+ Operation *combiner = combiners.front();
+ std::optional<TypedAttr> neutral = arith::getNeutralElement(combiner);
+ if (!neutral)
+ return failure();
+
+ for (OpOperand *input : linalgOp.getDpsInputOperands()) {
+ // Only operands indexed along a reduction dim need a neutral.
+ AffineMap map = linalgOp.getMatchingIndexingMap(input);
+ bool reduced = llvm::any_of(llvm::enumerate(iterTypes), [&](auto it) {
+ return it.value() == utils::IteratorType::reduction &&
+ map.isFunctionOfDim(it.index());
+ });
+ if (!reduced)
+ continue;
+ // A reduced operand must feed the combiner directly to use its neutral; an
+ // indirect one (e.g. via a math.exp) has no valid pad value -> fail.
+ if (!llvm::is_contained(linalgOp.getMatchingBlockArgument(input).getUsers(),
+ combiner))
+ return failure();
+ paddingValues[input->getOperandNumber()] = *neutral;
+ }
+ return paddingValues;
+}
+
FailureOr<PadTilingInterfaceResult> linalg::rewriteAsPaddedOp(
OpBuilder &builder, TilingInterface toPad,
PadTilingInterfaceOptions options,
@@ -272,14 +330,14 @@ FailureOr<PadTilingInterfaceResult> linalg::rewriteAsPaddedOp(
Location loc = toPad.getLoc();
// Allow inference of pad values if they are not explicitly specified.
- // TODO: be mindful about the value depending on the actual operation.
if (options.paddingValues.empty()) {
- SmallVector<Type> types(toPad->getOperandTypes());
- llvm::append_range(types, toPad->getResultTypes());
- for (Type t : types) {
- options.paddingValues.push_back(
- builder.getZeroAttr(getElementTypeOrSelf(t)));
+ FailureOr<SmallVector<Attribute>> inferred =
+ inferPaddingValues(builder, toPad);
+ if (failed(inferred)) {
+ LLVM_DEBUG(DBGS() << "Could not infer pad values: FAIL\n");
+ return failure();
}
+ options.paddingValues = std::move(*inferred);
}
if (llvm::any_of(toPad->getOperands(),
diff --git a/mlir/test/Dialect/Linalg/transform-op-pad-tiling-interface-reduction.mlir b/mlir/test/Dialect/Linalg/transform-op-pad-tiling-interface-reduction.mlir
new file mode 100644
index 0000000000000..f3b0c52f40608
--- /dev/null
+++ b/mlir/test/Dialect/Linalg/transform-op-pad-tiling-interface-reduction.mlir
@@ -0,0 +1,296 @@
+// RUN: mlir-opt --transform-interpreter -canonicalize -split-input-file --verify-diagnostics %s | FileCheck %s
+
+// When padding values are not specified, `pad_tiling_interface` infers them.
+// For an operand that is reduced, a zero pad value would corrupt the result,
+// so the neutral element of the reduction combiner must be inferred instead.
+
+// CHECK-LABEL: @pad_reduce_maximumf
+func.func @pad_reduce_maximumf(%input: tensor<8x30xf32>, %init: tensor<8xf32>)
+ -> tensor<8xf32> {
+ // maximumf neutral element is -inf.
+ // CHECK-DAG: %[[NEUTRAL:.*]] = arith.constant 0xFF800000 : f32
+ // CHECK: %[[PAD:.*]] = tensor.pad %{{.*}} low[0, 0] high[0, 2]
+ // CHECK: tensor.yield %[[NEUTRAL]] : f32
+ // CHECK: } : tensor<8x30xf32> to tensor<8x32xf32>
+ // CHECK: linalg.reduce ins(%[[PAD]] : tensor<8x32xf32>)
+ %0 = linalg.reduce ins(%input : tensor<8x30xf32>) outs(%init : tensor<8xf32>)
+ dimensions = [1]
+ (%in: f32, %out: f32) {
+ %m = arith.maximumf %in, %out : f32
+ linalg.yield %m : f32
+ }
+ return %0 : tensor<8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %red = transform.structured.match ops{["linalg.reduce"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ // No padding_values: they are inferred.
+ %padded, %pad = transform.structured.pad_tiling_interface %red to padding_sizes [8, 32]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
+
+// -----
+
+// An operand reduced along several dimensions is padded with the neutral on all
+// of them (here d1 and d2); one neutral suffices since the combiner is the same.
+
+#in3 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
+#out3 = affine_map<(d0, d1, d2) -> (d0)>
+// CHECK-LABEL: @pad_reduce_two_reduction_dims
+func.func @pad_reduce_two_reduction_dims(%in: tensor<8x6x10xf32>, %init: tensor<8xf32>)
+ -> tensor<8xf32> {
+ // CHECK-DAG: %[[NINF:.*]] = arith.constant 0xFF800000 : f32
+ // CHECK: tensor.pad %{{.*}} low[0, 0, 0] high[0, 2, 6]
+ // CHECK: tensor.yield %[[NINF]] : f32
+ // CHECK: } : tensor<8x6x10xf32> to tensor<8x8x16xf32>
+ %0 = linalg.generic {indexing_maps = [#in3, #out3],
+ iterator_types = ["parallel", "reduction", "reduction"]}
+ ins(%in : tensor<8x6x10xf32>) outs(%init : tensor<8xf32>) {
+ ^bb0(%a: f32, %o: f32):
+ %m = arith.maximumf %a, %o : f32
+ linalg.yield %m : f32
+ } -> tensor<8xf32>
+ return %0 : tensor<8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %gen = transform.structured.match ops{["linalg.generic"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ %padded, %pad = transform.structured.pad_tiling_interface %gen to padding_sizes [8, 8, 16]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
+
+// -----
+
+// CHECK-LABEL: @pad_reduce_mulf
+func.func @pad_reduce_mulf(%input: tensor<8x30xf32>, %init: tensor<8xf32>)
+ -> tensor<8xf32> {
+ // mulf neutral element is 1.0 (a zero pad would zero out the product).
+ // CHECK-DAG: %[[NEUTRAL:.*]] = arith.constant 1.000000e+00 : f32
+ // CHECK: %[[PAD:.*]] = tensor.pad %{{.*}} low[0, 0] high[0, 2]
+ // CHECK: tensor.yield %[[NEUTRAL]] : f32
+ // CHECK: } : tensor<8x30xf32> to tensor<8x32xf32>
+ // CHECK: linalg.reduce ins(%[[PAD]] : tensor<8x32xf32>)
+ %0 = linalg.reduce ins(%input : tensor<8x30xf32>) outs(%init : tensor<8xf32>)
+ dimensions = [1]
+ (%in: f32, %out: f32) {
+ %m = arith.mulf %in, %out : f32
+ linalg.yield %m : f32
+ }
+ return %0 : tensor<8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %red = transform.structured.match ops{["linalg.reduce"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ %padded, %pad = transform.structured.pad_tiling_interface %red to padding_sizes [8, 32]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
+
+// -----
+
+// CHECK-LABEL: @pad_reduce_minimumf
+func.func @pad_reduce_minimumf(%input: tensor<8x30xf32>, %init: tensor<8xf32>)
+ -> tensor<8xf32> {
+ // minimumf neutral element is +inf.
+ // CHECK-DAG: %[[NEUTRAL:.*]] = arith.constant 0x7F800000 : f32
+ // CHECK: %[[PAD:.*]] = tensor.pad %{{.*}} low[0, 0] high[0, 2]
+ // CHECK: tensor.yield %[[NEUTRAL]] : f32
+ // CHECK: } : tensor<8x30xf32> to tensor<8x32xf32>
+ // CHECK: linalg.reduce ins(%[[PAD]] : tensor<8x32xf32>)
+ %0 = linalg.reduce ins(%input : tensor<8x30xf32>) outs(%init : tensor<8xf32>)
+ dimensions = [1]
+ (%in: f32, %out: f32) {
+ %m = arith.minimumf %in, %out : f32
+ linalg.yield %m : f32
+ }
+ return %0 : tensor<8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %red = transform.structured.match ops{["linalg.reduce"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ %padded, %pad = transform.structured.pad_tiling_interface %red to padding_sizes [8, 32]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
+
+// -----
+
+// maxnumf is the NaN-ignoring variant, so its neutral element is NaN. Padding
+// with NaN is correct here (maxnumf(NaN, x) = x), but note it would be unsound
+// under a `nnan` fast-math assumption.
+
+// CHECK-LABEL: @pad_reduce_maxnumf
+func.func @pad_reduce_maxnumf(%input: tensor<8x30xf32>, %init: tensor<8xf32>)
+ -> tensor<8xf32> {
+ // CHECK-DAG: %[[NAN:.*]] = arith.constant 0xFFC00000 : f32
+ // CHECK: tensor.pad %{{.*}} low[0, 0] high[0, 2]
+ // CHECK: tensor.yield %[[NAN]] : f32
+ // CHECK: } : tensor<8x30xf32> to tensor<8x32xf32>
+ %0 = linalg.reduce ins(%input : tensor<8x30xf32>) outs(%init : tensor<8xf32>) dimensions = [1]
+ (%in: f32, %out: f32) {
+ %m = arith.maxnumf %in, %out : f32
+ linalg.yield %m : f32
+ }
+ return %0 : tensor<8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %red = transform.structured.match ops{["linalg.reduce"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ %padded, %pad = transform.structured.pad_tiling_interface %red to padding_sizes [8, 32]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
+
+// -----
+
+// A contraction is padded with zero: its reduced operands feed the multiply and
+// zero annihilates it (0 * x = 0), so the add-reduction stays correct. The
+// combiner (arith.addf) must NOT be mistaken for the operands' direct combiner
+// (arith.mulf, whose neutral 1 would corrupt the result).
+
+// CHECK-LABEL: @pad_matmul_uses_zero
+func.func @pad_matmul_uses_zero(%A: tensor<8x10xf32>, %B: tensor<10x8xf32>,
+ %C: tensor<8x8xf32>) -> tensor<8x8xf32> {
+ // CHECK-DAG: %[[ZERO:.*]] = arith.constant 0.000000e+00 : f32
+ // CHECK: tensor.pad %{{.*}} low[0, 0] high[0, 6]
+ // CHECK: tensor.yield %[[ZERO]] : f32
+ // CHECK: } : tensor<8x10xf32> to tensor<8x16xf32>
+ // CHECK: tensor.pad %{{.*}} low[0, 0] high[6, 0]
+ // CHECK: tensor.yield %[[ZERO]] : f32
+ // CHECK: } : tensor<10x8xf32> to tensor<16x8xf32>
+ // CHECK-NOT: arith.constant 1.000000e+00
+ %0 = linalg.matmul ins(%A, %B : tensor<8x10xf32>, tensor<10x8xf32>)
+ outs(%C : tensor<8x8xf32>) -> tensor<8x8xf32>
+ return %0 : tensor<8x8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %mm = transform.structured.match ops{["linalg.matmul"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ %padded, %pad = transform.structured.pad_tiling_interface %mm to padding_sizes [8, 8, 16]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
+
+// -----
+
+// Only the reduced input takes the neutral (-inf); the non-reduced init operand
+// keeps zero. Both dims are padded so the init is padded along the parallel dim.
+
+// CHECK-LABEL: @pad_reduce_init_stays_zero
+func.func @pad_reduce_init_stays_zero(%in: tensor<8x30xf32>, %init: tensor<8xf32>)
+ -> tensor<8xf32> {
+ // CHECK-DAG: %[[ZERO:.*]] = arith.constant 0.000000e+00 : f32
+ // CHECK-DAG: %[[NINF:.*]] = arith.constant 0xFF800000 : f32
+ // Reduced input -> maximumf neutral (-inf).
+ // CHECK: tensor.pad %{{.*}}
+ // CHECK: tensor.yield %[[NINF]] : f32
+ // CHECK: } : tensor<8x30xf32> to tensor<16x32xf32>
+ // Init (non-reduced) operand -> plain zero.
+ // CHECK: tensor.pad %{{.*}}
+ // CHECK: tensor.yield %[[ZERO]] : f32
+ // CHECK: } : tensor<8xf32> to tensor<16xf32>
+ %0 = linalg.reduce ins(%in : tensor<8x30xf32>) outs(%init : tensor<8xf32>)
+ dimensions = [1]
+ (%a: f32, %o: f32) {
+ %m = arith.maximumf %a, %o : f32
+ linalg.yield %m : f32
+ }
+ return %0 : tensor<8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %red = transform.structured.match ops{["linalg.reduce"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ %padded, %pad = transform.structured.pad_tiling_interface %red to padding_sizes [16, 32]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
+
+// -----
+
+// Negative: the reduced operand is not consumed directly by a recognized
+// reduction combiner (it flows through math.exp first), so no safe neutral
+// element can be inferred and padding fails conservatively rather than
+// silently padding with a wrong value.
+
+func.func @pad_reduce_indirect_combiner_fails(
+ %input: tensor<8x30xf32>, %init: tensor<8xf32>) -> tensor<8xf32> {
+ // expected-note @below {{target op}}
+ // expected-note @below {{could not infer a padding value; specify `padding_values`}}
+ %0 = linalg.reduce ins(%input : tensor<8x30xf32>) outs(%init : tensor<8xf32>)
+ dimensions = [1]
+ (%in: f32, %out: f32) {
+ %e = math.exp %in : f32
+ %a = arith.addf %e, %out : f32
+ linalg.yield %a : f32
+ }
+ return %0 : tensor<8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %red = transform.structured.match ops{["linalg.reduce"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ // expected-error @below {{failed to pad op}}
+ %padded, %pad = transform.structured.pad_tiling_interface %red to padding_sizes [8, 32]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
+
+// -----
+
+// Negative: a fused op with two reductions (max and sum) over the same input
+// has no single correct neutral for that input (-inf breaks the sum, 0 breaks
+// the max), so inference fails instead of padding with a wrong value.
+
+#map = affine_map<(d0, d1) -> (d0, d1)>
+#mapr = affine_map<(d0, d1) -> (d0)>
+func.func @pad_multi_reduction_fails(%in: tensor<8x30xf32>, %m0: tensor<8xf32>,
+ %s0: tensor<8xf32>)
+ -> (tensor<8xf32>, tensor<8xf32>) {
+ // expected-note @below {{target op}}
+ // expected-note @below {{could not infer a padding value; specify `padding_values`}}
+ %r:2 = linalg.generic {indexing_maps = [#map, #mapr, #mapr],
+ iterator_types = ["parallel", "reduction"]}
+ ins(%in : tensor<8x30xf32>) outs(%m0, %s0 : tensor<8xf32>, tensor<8xf32>) {
+ ^bb0(%x: f32, %mo: f32, %so: f32):
+ %mx = arith.maximumf %x, %mo : f32
+ %sm = arith.addf %x, %so : f32
+ linalg.yield %mx, %sm : f32, f32
+ } -> (tensor<8xf32>, tensor<8xf32>)
+ return %r#0, %r#1 : tensor<8xf32>, tensor<8xf32>
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+ %gen = transform.structured.match ops{["linalg.generic"]} in %arg1
+ : (!transform.any_op) -> !transform.any_op
+ // expected-error @below {{failed to pad op}}
+ %padded, %pad = transform.structured.pad_tiling_interface %gen to padding_sizes [8, 32]
+ : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
+ transform.yield
+ }
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/216517
More information about the Mlir-commits
mailing list