[Mlir-commits] [mlir] [MLIR][Linalg] Fix crash in packMatmulGreedily on non-matmul ops (PR #218947)
Chibuoyim Ogbonna
llvmlistbot at llvm.org
Wed Aug 26 08:00:01 PDT 2026
https://github.com/bruteforceboy created https://github.com/llvm/llvm-project/pull/218947
The following case currently causes a crash:
```
func.func @f(%a: tensor<1x1x1xf32>, %b: tensor<1x1x1xf32>, %c: tensor<1x1x1xf32>) -> tensor<1x1x1xf32> {
%0 = linalg.add ins(%a, %b : tensor<1x1x1xf32>, tensor<1x1x1xf32>) outs(%c : tensor<1x1x1xf32>) -> tensor<1x1x1xf32>
return %0 : tensor<1x1x1xf32>
}
module attributes {transform.with_named_sequence} {
transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
%0 = transform.structured.match interface{LinalgOp} in %arg0 : (!transform.any_op) -> !transform.any_op
transform.structured.pack_greedily %0
matmul_packed_sizes = [8, 8, 8] matmul_inner_dims_order = [0, 1, 2]
: (!transform.any_op) -> !transform.any_op
transform.yield
}
}
```
with `bin/mlir-opt repro.mlir --transform-interpreter`
`transform.structured.pack_greedily` crashes on any op with 2 inputs, 1 init and 3+ loops that is not actually matmul like. The `linalg.add` here is rank 3, so it has 3 loops, passes the `numLoops <= 2` check, and reaches the `m/n/k` usage. The crash happens at:
```
int64_t mPos = maybeDimensions->m.back(), nPos = maybeDimensions->n.back(),
kPos = maybeDimensions->k.back();
```
when trying to get the last element of an *empty* vector.
This patch checks that none of the inferred `m/n/k` vectors is empty, and if any of them is, the transformation will not pack this op.
>From 13f71d57ae1660a45207b0e3bc26adc98dc1489f Mon Sep 17 00:00:00 2001
From: bruteforceboy <chibuoyim.faith.ogbonna at huawei.com>
Date: Wed, 26 Aug 2026 14:24:07 +0100
Subject: [PATCH] [MLIR][Linalg] Fix crash in packMatmulGreedily on non-matmul
ops
---
.../Dialect/Linalg/Transforms/Transforms.cpp | 4 +-
.../Linalg/transform-pack-greedily.mlir | 86 +++++++++++++++++++
2 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp b/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp
index aa021cbad24a7..537b54d02fc4d 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Transforms.cpp
@@ -806,7 +806,9 @@ linalg::packMatmulGreedily(RewriterBase &rewriter, LinalgOp linalgOp,
// 1. Infer dims that are important for matmul.
FailureOr<ContractionDimensions> maybeDimensions =
inferContractionDims(linalgOp);
- if (failed(maybeDimensions)) {
+ // The inferred m/n/k may be empty when the op is not actually matmul-like.
+ if (failed(maybeDimensions) || maybeDimensions->m.empty() ||
+ maybeDimensions->n.empty() || maybeDimensions->k.empty()) {
LDBG() << "couldn't infer matmul iterators in: " << linalgOp;
return rewriter.notifyMatchFailure(linalgOp,
"couldn't infer matmul iterators");
diff --git a/mlir/test/Dialect/Linalg/transform-pack-greedily.mlir b/mlir/test/Dialect/Linalg/transform-pack-greedily.mlir
index 5812c4db88247..8f350744b62d7 100644
--- a/mlir/test/Dialect/Linalg/transform-pack-greedily.mlir
+++ b/mlir/test/Dialect/Linalg/transform-pack-greedily.mlir
@@ -369,6 +369,92 @@ module attributes {transform.with_named_sequence} {
// -----
+!A = tensor<1023x255x127xf32>
+
+// CHECK-LABEL: @elementwise_no_mnk(
+func.func @elementwise_no_mnk(%A : !A, %B : !A, %C : !A) -> !A {
+ // CHECK: linalg.add
+ %0 = linalg.add ins(%A, %B : !A, !A) outs(%C : !A) -> !A
+ return %0 : !A
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) {
+ %add = transform.structured.match ops{["linalg.add"]} in %module_op
+ : (!transform.any_op) -> !transform.op<"linalg.add">
+ transform.structured.pack_greedily %add
+ matmul_packed_sizes = [8, 16, 32] matmul_inner_dims_order = [1, 2, 0]
+ : (!transform.op<"linalg.add">) -> !transform.any_op
+ transform.yield
+ }
+}
+
+// -----
+
+!A = tensor<42x1023x255xf32>
+!X = tensor<42x255xf32>
+!Y = tensor<42x1023xf32>
+
+// CHECK-LABEL: @batch_matvec_no_n(
+func.func @batch_matvec_no_n(%A : !A, %x : !X, %y : !Y) -> !Y {
+ // CHECK: linalg.batch_matvec
+ %0 = linalg.batch_matvec ins(%A, %x : !A, !X) outs(%y : !Y) -> !Y
+ return %0 : !Y
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) {
+ %batch_matvec = transform.structured.match ops{["linalg.batch_matvec"]} in %module_op
+ : (!transform.any_op) -> !transform.op<"linalg.batch_matvec">
+ transform.structured.pack_greedily %batch_matvec
+ matmul_packed_sizes = [8, 16, 32] matmul_inner_dims_order = [1, 2, 0]
+ : (!transform.op<"linalg.batch_matvec">) -> !transform.any_op
+ transform.yield
+ }
+}
+
+// -----
+
+!A = tensor<1023x255xf32>
+!B = tensor<127xf32>
+!C = tensor<1023x127xf32>
+
+#mnr_accesses = [
+ affine_map<(m, n, r) -> (m, r)>,
+ affine_map<(m, n, r) -> (n)>,
+ affine_map<(m, n, r) -> (m, n)>
+]
+#mnr_trait = {
+ indexing_maps = #mnr_accesses,
+ iterator_types = ["parallel", "parallel", "reduction"]
+}
+
+// CHECK-LABEL: @lhs_only_reduction_no_k(
+func.func @lhs_only_reduction_no_k(%A : !A, %B : !B, %C : !C) -> !C {
+ // CHECK-NOT: linalg.pack
+ // CHECK: linalg.generic
+ %0 = linalg.generic #mnr_trait ins(%A, %B : !A, !B) outs(%C : !C) {
+ ^bb0(%a: f32, %b: f32, %c: f32):
+ %d = arith.mulf %a, %b : f32
+ %e = arith.addf %c, %d : f32
+ linalg.yield %e : f32
+ } -> !C
+ return %0 : !C
+}
+
+module attributes {transform.with_named_sequence} {
+ transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) {
+ %generic = transform.structured.match ops{["linalg.generic"]} in %module_op
+ : (!transform.any_op) -> !transform.op<"linalg.generic">
+ transform.structured.pack_greedily %generic
+ matmul_packed_sizes = [8, 16, 32] matmul_inner_dims_order = [1, 2, 0]
+ : (!transform.op<"linalg.generic">) -> !transform.any_op
+ transform.yield
+ }
+}
+
+// -----
+
func.func @no_padding_on_packs(%A: tensor<32x32xf32>, %B: tensor<32x32xf32>, %C: tensor<32x32xf32>)
-> tensor<32x32xf32> {
%0 = linalg.matmul ins(%A, %B: tensor<32x32xf32>, tensor<32x32xf32>)
More information about the Mlir-commits
mailing list