[Mlir-commits] [llvm] [mlir] [Linalg] Fix crash in vectorizeScalableVectorPrecondition with undersized vector sizes (PR #205493)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Jun 24 02:40:54 PDT 2026


https://github.com/LouisLu060211 updated https://github.com/llvm/llvm-project/pull/205493

>From 41919e43354b33eb48c238bebba1bd492ca85a36 Mon Sep 17 00:00:00 2001
From: LouisLu0602 <yaolu0602 at gmail.com>
Date: Wed, 24 Jun 2026 15:09:36 +0800
Subject: [PATCH 1/8] Fix crash in vectorizeOpPrecondition when vector sizes
 array is too short

---
 .gitignore                                    |  1 +
 .../TransformOps/LinalgTransformOps.cpp       |  2 +-
 .../Linalg/Transforms/Vectorization.cpp       | 12 ++++++++++
 .../vectorize-dynamic-mixed-sizes.mlir        | 22 +++++++++++++++++++
 4 files changed, 36 insertions(+), 1 deletion(-)
 create mode 100644 mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir

diff --git a/.gitignore b/.gitignore
index a4382c9ea7390..30e994aefd8bd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,3 +90,4 @@ pythonenv*
 /clang/utils/analyzer/projects/*/RefScanBuildResults
 # automodapi puts generated documentation files here.
 /lldb/docs/python_api/
+mlir_venv/
diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
index f44693096b26b..602f9607ad618 100644
--- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
+++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
@@ -4171,7 +4171,7 @@ DiagnosedSilenceableFailure transform::VectorizeOp::apply(
   // TODO: Check that the correct number of vectorSizes was provided.
   for (Operation *target : targets) {
     if (!linalg::hasVectorizationImpl(target)) {
-      return mlir::emitSilenceableFailure(target->getLoc())
+      return mlir::emitSilenceableFailure(getLoc())
              << "Unsupported Op, cannot vectorize";
     }
     FailureOr<VectorizationResult> vectorResults =
diff --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
index b57e66a1c3580..07c5bef17c851 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
@@ -2381,6 +2381,18 @@ vectorizeScalableVectorPrecondition(Operation *op,
     return success(isa<linalg::UnPackOp>(op));
   }
 
+  // Ensure that the number of vector sizes and scalable flags provided by the
+  // user does not exceed the number of loops in the target Linalg op.
+  // Accessing iterator types with an out-of-bounds index would cause an
+  // assertion failure (SmallVector::operator[]). This check converts such a
+  // crash into a clean failure, allowing the transform interpreter to report
+  // an error gracefully.
+  // Regression test:
+  // mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir
+  if (inputScalableVecDims.size() > linalgOp.getNumLoops() ||
+      inputVectorSizes.size() > linalgOp.getNumLoops())
+    return failure();
+
   // Cond 2: There's been no need for more than 2 scalable dims so far
   if (numOfScalableDims > 2)
     return failure();
diff --git a/mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir b/mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir
new file mode 100644
index 0000000000000..2af5e26898fb9
--- /dev/null
+++ b/mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir
@@ -0,0 +1,22 @@
+// RUN: mlir-opt %s -transform-interpreter -verify-diagnostics
+
+// Regression test for bug #204100.
+// Assertion idx < size() in SmallVector.h used to happen here.
+
+// CHECK-LABEL: func @add_dynamic
+module {
+  func.func @add_dynamic(%arg0: memref<?x?xbf16>, %arg1: memref<?x?xbf16>, %arg2: memref<?x?xbf16>) {
+    linalg.add ins(%arg0, %arg1 : memref<?x?xbf16>, memref<?x?xbf16>) outs(%arg2 : memref<?x?xbf16>)
+    return
+  }
+
+  module attributes {transform.with_named_sequence} {
+    transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
+      %0 = transform.structured.match ops{["linalg.add"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+      // This combination was crashing (static/dynamic mismatch)
+      transform.structured.vectorize %0 vector_sizes [8, [16], 4] : !transform.any_op
+      // expected-error @above {{Attempted to vectorize, but failed}}
+      transform.yield
+    }
+  }
+}

>From f97bab1b088d8d2548b326f3e2540bc0c359cbd3 Mon Sep 17 00:00:00 2001
From: LouisLu0602 <yaolu0602 at gmail.com>
Date: Wed, 24 Jun 2026 16:08:30 +0800
Subject: [PATCH 2/8] [MLIR][Vector] Add regression test for bug #204100 (mixed
 static/dynamic vector sizes)

---
 .../Vector/transform-op-vector-to-llvm.mlir   | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlir b/mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlir
index 271cdf0e059f4..a74e52dfd4bdb 100644
--- a/mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlir
+++ b/mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlir
@@ -19,3 +19,29 @@ module attributes {transform.with_named_sequence} {
     transform.yield
   }
 }
+
+// -----
+
+// RUN: mlir-opt %s -transform-interpreter -verify-diagnostics
+// Regression test for bug #204100.
+// Assertion idx < size() in SmallVector.h used to happen here.
+// CHECK-LABEL: func @add_dynamic
+module {
+  func.func @add_dynamic(%arg0: memref<?x?xbf16>, %arg1: memref<?x?xbf16>, %arg2: memref<?x?xbf16>) {
+    linalg.add ins(%arg0, %arg1 : memref<?x?xbf16>, memref<?x?xbf16>) outs(%arg2 : memref<?x?xbf16>)
+    return
+  }
+  module attributes {transform.with_named_sequence} {
+    transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
+      %0 = transform.structured.match ops{["linalg.add"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+      // This combination was crashing (static/dynamic mismatch)
+      transform.structured.vectorize %0 vector_sizes [8, [16], 4] : !transform.any_op
+      // expected-error @above {{Attempted to vectorize, but failed}}
+      transform.yield
+    }
+  }
+}
+
+
+
+

>From 50ff1d24063e281fdfc247bef1d26ae97441b4f2 Mon Sep 17 00:00:00 2001
From: LouisLu0602 <yaolu0602 at gmail.com>
Date: Wed, 24 Jun 2026 16:25:55 +0800
Subject: [PATCH 3/8] Remove accidentally created file
 vectorize-dynamic-mixed-sizes.mlir

---
 .../vectorize-dynamic-mixed-sizes.mlir        | 22 -------------------
 1 file changed, 22 deletions(-)
 delete mode 100644 mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir

diff --git a/mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir b/mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir
deleted file mode 100644
index 2af5e26898fb9..0000000000000
--- a/mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: mlir-opt %s -transform-interpreter -verify-diagnostics
-
-// Regression test for bug #204100.
-// Assertion idx < size() in SmallVector.h used to happen here.
-
-// CHECK-LABEL: func @add_dynamic
-module {
-  func.func @add_dynamic(%arg0: memref<?x?xbf16>, %arg1: memref<?x?xbf16>, %arg2: memref<?x?xbf16>) {
-    linalg.add ins(%arg0, %arg1 : memref<?x?xbf16>, memref<?x?xbf16>) outs(%arg2 : memref<?x?xbf16>)
-    return
-  }
-
-  module attributes {transform.with_named_sequence} {
-    transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
-      %0 = transform.structured.match ops{["linalg.add"]} in %arg0 : (!transform.any_op) -> !transform.any_op
-      // This combination was crashing (static/dynamic mismatch)
-      transform.structured.vectorize %0 vector_sizes [8, [16], 4] : !transform.any_op
-      // expected-error @above {{Attempted to vectorize, but failed}}
-      transform.yield
-    }
-  }
-}

>From 60b8d4a3f5d2725b31d4856b6e89c256dc56eddf Mon Sep 17 00:00:00 2001
From: LouisLu0602 <yaolu0602 at gmail.com>
Date: Wed, 24 Jun 2026 16:29:05 +0800
Subject: [PATCH 4/8] Remove mlir_venv/ from .gitignore (directory already
 deleted)

---
 .gitignore | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 30e994aefd8bd..a4382c9ea7390 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,4 +90,3 @@ pythonenv*
 /clang/utils/analyzer/projects/*/RefScanBuildResults
 # automodapi puts generated documentation files here.
 /lldb/docs/python_api/
-mlir_venv/

>From 69939a8c3b1ad1c73e606e3e9d11363fd367c392 Mon Sep 17 00:00:00 2001
From: LouisLu060211 <38174270+LouisLu060211 at users.noreply.github.com>
Date: Wed, 24 Jun 2026 16:32:20 +0800
Subject: [PATCH 5/8] remove venv

---
 .gitignore | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 30e994aefd8bd..57caa8f8b94ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,4 +90,4 @@ pythonenv*
 /clang/utils/analyzer/projects/*/RefScanBuildResults
 # automodapi puts generated documentation files here.
 /lldb/docs/python_api/
-mlir_venv/
+

>From 9754ba69bff4c06d97163a288ce9eed0d6c4e825 Mon Sep 17 00:00:00 2001
From: LouisLu060211 <38174270+LouisLu060211 at users.noreply.github.com>
Date: Wed, 24 Jun 2026 16:32:52 +0800
Subject: [PATCH 6/8] Remove lldb/python_api from .gitignore

---
 .gitignore | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.gitignore b/.gitignore
index 57caa8f8b94ea..a4382c9ea7390 100644
--- a/.gitignore
+++ b/.gitignore
@@ -90,4 +90,3 @@ pythonenv*
 /clang/utils/analyzer/projects/*/RefScanBuildResults
 # automodapi puts generated documentation files here.
 /lldb/docs/python_api/
-

>From 911d64bd3fe207433af508fb3cb6443e0d53a162 Mon Sep 17 00:00:00 2001
From: LouisLu0602 <yaolu0602 at gmail.com>
Date: Wed, 24 Jun 2026 16:52:51 +0800
Subject: [PATCH 7/8] Fix comment about regression test location in
 Vectorization.cpp

Correct the path in the comment from .../Linalg/transform/... to .../Linalg/...
(the test actually lives directly under Linalg). Also update the
related vector-to-llvm test for consistency.
---
 mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
index 07c5bef17c851..95b05be723d7e 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp
@@ -2388,7 +2388,7 @@ vectorizeScalableVectorPrecondition(Operation *op,
   // crash into a clean failure, allowing the transform interpreter to report
   // an error gracefully.
   // Regression test:
-  // mlir/test/Dialect/Linalg/transform/vectorize-dynamic-mixed-sizes.mlir
+  // mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlir
   if (inputScalableVecDims.size() > linalgOp.getNumLoops() ||
       inputVectorSizes.size() > linalgOp.getNumLoops())
     return failure();

>From c5ed44c540426c06604880a6d84d1191b0bbe1ff Mon Sep 17 00:00:00 2001
From: LouisLu0602 <yaolu0602 at gmail.com>
Date: Wed, 24 Jun 2026 17:39:51 +0800
Subject: [PATCH 8/8] Fix emitSilenceableFailure to use target->getLoc()

---
 .gitignorees                                  | 92 +++++++++++++++++++
 a.mlir                                        | 13 +++
 .../TransformOps/LinalgTransformOps.cpp       |  3 +-
 .../Vector/transform-op-vector-to-llvm.mlires | 43 +++++++++
 4 files changed, 149 insertions(+), 2 deletions(-)
 create mode 100644 .gitignorees
 create mode 100644 a.mlir
 create mode 100644 mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlires

diff --git a/.gitignorees b/.gitignorees
new file mode 100644
index 0000000000000..a4382c9ea7390
--- /dev/null
+++ b/.gitignorees
@@ -0,0 +1,92 @@
+#==============================================================================#
+# This file specifies intentionally untracked files that git should ignore.
+# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html
+#
+# This file is intentionally different from the output of `git svn show-ignore`,
+# as most of those are useless.
+#==============================================================================#
+
+#==============================================================================#
+# File extensions to be ignored anywhere in the tree.
+#==============================================================================#
+# Temp files created by most text editors.
+*~
+# Emacs lock files
+.#*
+# Merge files created by git.
+*.orig
+# Reject files created by patch.
+*.rej
+# Byte compiled python modules.
+*.pyc
+# vim swap files
+.*.sw?
+.sw?
+#macOS specific
+.DS_Store
+
+# Ignore the user specified CMake presets in subproject directories.
+/*/CMakeUserPresets.json
+
+# Nested build directory
+/build*
+
+#==============================================================================#
+# Explicit files to ignore (only matches one).
+#==============================================================================#
+# Various tag programs
+/tags
+/TAGS
+/GPATH
+/GRTAGS
+/GSYMS
+/GTAGS
+/ID
+.gitusers
+autom4te.cache
+cscope.files
+cscope.out
+autoconf/aclocal.m4
+autoconf/autom4te.cache
+/compile_commands.json
+/tablegen_compile_commands.yml
+# Visual Studio built-in CMake configuration
+/CMakeSettings.json
+# CLion project configuration
+/.idea
+/cmake-build*
+# Coding assistants' stuff
+.agents/
+/CLAUDE.md
+/instructions.md
+.claude/
+/GEMINI.md
+.gemini/
+AGENTS.md
+.codex/
+# Cursor specific files
+.cursor
+.cursorignore
+.cursorindexingignore
+
+#==============================================================================#
+# Directories to ignore (do not add trailing '/'s, they skip symlinks).
+#==============================================================================#
+# VS2017 and VSCode config files.
+.vscode
+.vs
+#zed config files
+.zed
+# pythonenv for github Codespaces
+pythonenv*
+# clangd index. (".clangd" is a config file now, thus trailing slash)
+.clangd/
+.cache
+.clangd
+# static analyzer regression testing project files
+/clang/utils/analyzer/projects/*/CachedSource
+/clang/utils/analyzer/projects/*/PatchedSource
+/clang/utils/analyzer/projects/*/ScanBuildResults
+/clang/utils/analyzer/projects/*/RefScanBuildResults
+# automodapi puts generated documentation files here.
+/lldb/docs/python_api/
diff --git a/a.mlir b/a.mlir
new file mode 100644
index 0000000000000..17b8861438a17
--- /dev/null
+++ b/a.mlir
@@ -0,0 +1,13 @@
+module {
+  func.func @add_dynamic(%arg0: memref<?x?bf16>, %arg1: memref<?x?bf16>, %arg2: memref<?x?bf16>) {
+    linalg.add ins(%arg0, %arg1 : memref<?x?bf16>, memref<?x?bf16>) outs(%arg2 : memref<?x?bf16>)
+    return
+  }
+  module attributes {transform.with_named_sequence} {
+    transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
+      %0 = transform.structured.match ops{["linalg.add"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+      transform.structured.vectorize %0 vector_sizes [8, 16, 4] : !transform.any_op
+      transform.yield 
+    }
+  }
+}
diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
index 602f9607ad618..4f9eb70d661e2 100644
--- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
+++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
@@ -4171,10 +4171,9 @@ DiagnosedSilenceableFailure transform::VectorizeOp::apply(
   // TODO: Check that the correct number of vectorSizes was provided.
   for (Operation *target : targets) {
     if (!linalg::hasVectorizationImpl(target)) {
-      return mlir::emitSilenceableFailure(getLoc())
+      return mlir::emitSilenceableFailure(target->getLoc())
              << "Unsupported Op, cannot vectorize";
     }
-    FailureOr<VectorizationResult> vectorResults =
         linalg::vectorize(rewriter, target, vectorSizes, getScalableSizes(),
                           getVectorizeNdExtract().value_or(false),
                           /*flatten1DDepthwiseConv=*/false,
diff --git a/mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlires b/mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlires
new file mode 100644
index 0000000000000..0ef5c7efaeab9
--- /dev/null
+++ b/mlir/test/Dialect/Vector/transform-op-vector-to-llvm.mlires
@@ -0,0 +1,43 @@
+// RUN: mlir-opt %s -transform-interpreter -verify-diagnostics -allow-unregistered-dialect -split-input-file | FileCheck %s
+
+// CHECK-LABEL: func @lower_to_llvm
+//   CHECK-NOT:   vector.bitcast
+//       CHECK:   llvm.bitcast
+func.func @lower_to_llvm(%input: vector<f32>) -> vector<i32> {
+  %0 = vector.bitcast %input : vector<f32> to vector<i32>
+  return %0 : vector<i32>
+}
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+    %0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    transform.apply_conversion_patterns to %0 {
+      transform.apply_conversion_patterns.vector.vector_to_llvm
+    } with type_converter {
+      transform.apply_conversion_patterns.memref.memref_to_llvm_type_converter
+    } {legal_dialects = ["func", "llvm"]} : !transform.any_op
+    transform.yield
+  }
+}
+
+// RUN: mlir-opt %s -transform-interpreter -verify-diagnostics
+// Regression test for bug #204100.
+// Assertion idx < size() in SmallVector.h used to happen here.
+// CHECK-LABEL: func @add_dynamic
+module {
+  func.func @add_dynamic(%arg0: memref<?x?xbf16>, %arg1: memref<?x?xbf16>, %arg2: memref<?x?xbf16>) {
+    linalg.add ins(%arg0, %arg1 : memref<?x?xbf16>, memref<?x?xbf16>) outs(%arg2 : memref<?x?xbf16>)
+    return
+  }
+  module attributes {transform.with_named_sequence} {
+    transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
+      %0 = transform.structured.match ops{["linalg.add"]} in %arg0 : (!transform.any_op) -> !transform.any_op
+      // This combination was crashing (static/dynamic mismatch)
+      transform.structured.vectorize %0 vector_sizes [8, [16], 4] : !transform.any_op
+      // expected-error @above {{Attempted to vectorize, but failed}}
+      transform.yield
+    }
+  }
+}
+
+



More information about the Mlir-commits mailing list