[Mlir-commits] [mlir] [mlir][Vector] Guard scalable reduction dim in matmul lowering (PR #226024)
Cheng-Chieh Liu
llvmlistbot at llvm.org
Wed Sep 23 22:34:36 PDT 2026
https://github.com/jay87406 created https://github.com/llvm/llvm-project/pull/226024
`ContractionOpToMatmulOpLowering` previously rejected scalable `vector.contract` ops by checking only the result type. While this covers the M and N dimensions, it misses the K (reduction) dimension. For contractions with static M/N but a scalable K (e.g., `vector<2x[4]xf32>` times `vector<[4]x3xf32>`), the guard incorrectly passed. The pattern then attempted to build a flattened, non-scalable LHS/RHS type via `VectorType::get(lhsType.getNumElements(), ...)`, followed by a `vector.shape_cast`. This caused the `shape_cast` verifier to reject the conversion (source has a scalable dimension, result doesn't), crashing the pass instead of gracefully failing the match.
Also check the LHS/RHS operand types for a scalable dimension, and add a regression test.
>From 2ae840806d5cd7f004462478cbf239e83a62b380 Mon Sep 17 00:00:00 2001
From: Cheng-Chieh Liu <jay87406 at gmail.com>
Date: Wed, 23 Sep 2026 22:45:53 -0500
Subject: [PATCH] [mlir][Vector] Guard scalable reduction dim in matmul
lowering
ContractionOpToMatmulOpLowering rejects a scalable vector.contract by
checking only the result type, which reflects the M and N dims but
never the K (reduction) dim. For a contraction with a static M and N
but a scalable K, e.g. vector<2x[4]xf32> times vector<[4]x3xf32>, the
guard passes and the pattern proceeds to build a flattened, non-
scalable LHS/RHS type via VectorType::get(lhsType.getNumElements(),
...), then vector.shape_cast into it -- which the shape_cast verifier
rejects (source has a scalable dim, result doesn't), crashing the
pass instead of gracefully declining the match.
Also check the LHS/RHS operand types for a scalable dim, and add a
regression test.
---
.../Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp | 8 +++++---
...ector-contract-to-matrix-intrinsics-transforms.mlir | 10 ++++++++++
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
index dd62377c2f6d3..5065104c9ba7a 100644
--- a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
+++ b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
@@ -2094,10 +2094,12 @@ FailureOr<Value> ContractionOpToMatmulOpLowering::matchAndRewriteMaskableOp(
Type opResType = op.getType();
VectorType vecType = dyn_cast<VectorType>(opResType);
- if (vecType && vecType.isScalable()) {
- // Note - this is sufficient to reject all cases with scalable vectors.
+ if (vecType && vecType.isScalable())
+ return failure();
+ // The result type only reflects the M and N dims, so a scalable K
+ // (reduction) dim would slip through the check above.
+ if (op.getLhsType().isScalable() || op.getRhsType().isScalable())
return failure();
- }
Type elementType = op.getLhsType().getElementType();
if (!elementType.isIntOrFloat())
diff --git a/mlir/test/Dialect/Vector/vector-contract-to-matrix-intrinsics-transforms.mlir b/mlir/test/Dialect/Vector/vector-contract-to-matrix-intrinsics-transforms.mlir
index bf9b2ace35622..995f29b7f8eef 100644
--- a/mlir/test/Dialect/Vector/vector-contract-to-matrix-intrinsics-transforms.mlir
+++ b/mlir/test/Dialect/Vector/vector-contract-to-matrix-intrinsics-transforms.mlir
@@ -75,3 +75,13 @@ func.func @matmul_scalable(%arg0: vector<2x4xf32>,
: vector<2x4xf32>, vector<4x[3]xf32> into vector<2x[3]xf32>
return %0 : vector<2x[3]xf32>
}
+
+// CHECK-LABEL: func @matmul_scalable_reduction
+// CHECK-NOT: llvm.intr.matrix.multiply
+func.func @matmul_scalable_reduction(%arg0: vector<2x[4]xf32>,
+ %arg1: vector<[4]x3xf32>,
+ %arg2: vector<2x3xf32>) -> vector<2x3xf32> {
+ %0 = vector.contract #matmat_trait %arg0, %arg1, %arg2
+ : vector<2x[4]xf32>, vector<[4]x3xf32> into vector<2x3xf32>
+ return %0 : vector<2x3xf32>
+}
More information about the Mlir-commits
mailing list