[Mlir-commits] [mlir] [mlir][linalg] Improve inner tile size mismatch diagnostics in pack/unpack verifier (PR #188525)

Mehdi Amini llvmlistbot at llvm.org
Wed Mar 25 10:45:59 PDT 2026


https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/188525

>From 6ff8c79e78e3af7ce1452459780c26dd8815960e Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Wed, 25 Mar 2026 09:04:52 -0700
Subject: [PATCH 1/2] [mlir][linalg] Improve inner tile size mismatch
 diagnostics in pack/unpack verifier

Refactor the tile-size consistency check in `commonVerifierPackAndUnPackOp`
from a bulk `all_of` into an indexed loop so that error messages include
the offending dimension index and the conflicting values, making failures
easier to diagnose.

Before:
  error: mismatch in inner tile sizes specified and shaped of tiled
         dimension in the packed type

After (static/static mismatch):
  error: mismatch in inner tile sizes specified and shaped of tiled
         dimension in the packed type at index 1: got 8 \!= 4

After (dynamic tile, static packed dim):
  error: mismatch in inner tile sizes specified at index 1: got static
         shape 8 but dynamic tile size

Update the six affected expected-error lines in invalid.mlir accordingly.

Assisted-by: Claude Code
---
 mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | 32 +++++++++++++-----------
 mlir/test/Dialect/Linalg/invalid.mlir    | 12 ++++-----
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
index 8d511aeec5424..e79b3a7f20fe1 100644
--- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
+++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
@@ -5197,21 +5197,23 @@ static LogicalResult commonVerifierPackAndUnPackOp(OpTy packOrUnPack) {
   SmallVector<int64_t> expectedPackedShape = PackOp::inferPackedShape(
       unpackedType.getShape(), packOrUnPack.getStaticTiles(),
       packOrUnPack.getInnerDimsPos(), packOrUnPack.getOuterDimsPerm());
-  if (!llvm::all_of(
-          llvm::zip(packedType.getShape().take_back(mixedTiles.size()),
-                    mixedTiles),
-          [](std::tuple<int64_t, OpFoldResult> it) {
-            int64_t shape = std::get<0>(it);
-            if (Attribute attr =
-                    llvm::dyn_cast_if_present<Attribute>(std::get<1>(it))) {
-              IntegerAttr intAttr = dyn_cast_or_null<IntegerAttr>(attr);
-              int64_t staticTileSize = intAttr.getValue().getSExtValue();
-              return shape == staticTileSize;
-            }
-            return ShapedType::isDynamic(shape);
-          })) {
-    return op->emitError("mismatch in inner tile sizes specified and shaped of "
-                         "tiled dimension in the packed type");
+  for (auto it : llvm::enumerate(llvm::zip(
+           packedType.getShape().take_back(mixedTiles.size()), mixedTiles))) {
+    int64_t shape = std::get<0>(it.value());
+    if (Attribute attr =
+            llvm::dyn_cast_if_present<Attribute>(std::get<1>(it.value()))) {
+      IntegerAttr intAttr = dyn_cast_or_null<IntegerAttr>(attr);
+      int64_t staticTileSize = intAttr.getValue().getSExtValue();
+      if (shape != staticTileSize)
+        return op->emitError(
+                   "mismatch in inner tile sizes specified and shaped of "
+                   "tiled dimension in the packed type at index ")
+               << it.index() << ": got " << shape << " != " << staticTileSize;
+    } else if (!ShapedType::isDynamic(shape)) {
+      return op->emitError("mismatch in inner tile sizes specified at index ")
+             << it.index() << ": got static shape " << shape
+             << " but dynamic tile size";
+    }
   }
   if (failed(
           verifyCompatibleShape(expectedPackedShape, packedType.getShape()))) {
diff --git a/mlir/test/Dialect/Linalg/invalid.mlir b/mlir/test/Dialect/Linalg/invalid.mlir
index d2c0934e27fe7..d9192cbda14e7 100644
--- a/mlir/test/Dialect/Linalg/invalid.mlir
+++ b/mlir/test/Dialect/Linalg/invalid.mlir
@@ -1877,7 +1877,7 @@ func.func @pack_invalid(%input: tensor<256x128xf32>, %output: tensor<8x8x32x16xf
 
 func.func @pack_mismatch_inner_tile_size_and_output_shape(
   %input : tensor<?x?xf32>, %output : tensor<?x?x8x8xf32>) -> tensor<?x?x8x8xf32> {
-  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type}}
+  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type at index 1: got 8 != 4}}
   %0 = linalg.pack %input inner_dims_pos = [0, 1] inner_tiles = [8, 4] into %output : tensor<?x?xf32> -> tensor<?x?x8x8xf32>
   return %0 : tensor<?x?x8x8xf32>
 }
@@ -1887,7 +1887,7 @@ func.func @pack_mismatch_inner_tile_size_and_output_shape(
 func.func @pack_dynamic_inner_tile_size_and_static_output_shape(
   %input : tensor<?x?xf32>, %output : tensor<?x?x8x8xf32>) -> tensor<?x?x8x8xf32> {
   %c8 = arith.constant 8 : index
-  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type}}
+  // expected-error at +1 {{mismatch in inner tile sizes specified at index 1: got static shape 8 but dynamic tile size}}
   %0 = linalg.pack %input inner_dims_pos = [0, 1] inner_tiles = [8, %c8] into %output : tensor<?x?xf32> -> tensor<?x?x8x8xf32>
   return %0 : tensor<?x?x8x8xf32>
 }
@@ -1896,7 +1896,7 @@ func.func @pack_dynamic_inner_tile_size_and_static_output_shape(
 
 func.func @pack_static_inner_tile_size_and_dynamic_output_shape(
   %input : tensor<?x?xf32>, %output : tensor<?x?x8x?xf32>) -> tensor<?x?x8x?xf32> {
-  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type}}
+  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type at index 1: got}}
   %0 = linalg.pack %input inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %output : tensor<?x?xf32> -> tensor<?x?x8x?xf32>
   return %0 : tensor<?x?x8x?xf32>
 }
@@ -1987,7 +1987,7 @@ func.func @unpack_invalid_source_shape(%output: tensor<256x128xf32>, %input: ten
 
 func.func @unpack_mismatch_inner_tile_size_and_output_shape(
   %input : tensor<?x?x8x8xf32>, %output : tensor<?x?xf32>) -> tensor<?x?xf32> {
-  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type}}
+  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type at index 1: got 8 != 4}}
   %0 = linalg.unpack %input inner_dims_pos = [0, 1] inner_tiles = [8, 4] into %output : tensor<?x?x8x8xf32> -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
 }
@@ -1997,7 +1997,7 @@ func.func @unpack_mismatch_inner_tile_size_and_output_shape(
 func.func @unpack_dynamic_inner_tile_size_and_static_output_shape(
   %input : tensor<?x?x8x4xf32>, %output : tensor<?x?xf32>) -> tensor<?x?xf32> {
   %c8 = arith.constant 8 : index
-  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type}}
+  // expected-error at +1 {{mismatch in inner tile sizes specified at index 0: got static shape 8 but dynamic tile size}}
   %0 = linalg.unpack %input inner_dims_pos = [0, 1] inner_tiles = [%c8, 4] into %output : tensor<?x?x8x4xf32> -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
 }
@@ -2006,7 +2006,7 @@ func.func @unpack_dynamic_inner_tile_size_and_static_output_shape(
 
 func.func @unpack_static_inner_tile_size_and_dynamic_output_shape(
   %input : tensor<?x?x?x4xf32>, %output : tensor<?x?xf32>) -> tensor<?x?xf32> {
-  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type}}
+  // expected-error at +1 {{mismatch in inner tile sizes specified and shaped of tiled dimension in the packed type at index 0: got}}
   %0 = linalg.unpack %input inner_dims_pos = [0, 1] inner_tiles = [8, 4] into %output : tensor<?x?x?x4xf32> -> tensor<?x?xf32>
   return %0 : tensor<?x?xf32>
 }

>From 8f1d9fe3a06297a747a0e24d0275191696de7f74 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Wed, 25 Mar 2026 18:45:50 +0100
Subject: [PATCH 2/2] Update mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Andrzej WarzyƄski <andrzej.warzynski at gmail.com>
---
 mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
index e79b3a7f20fe1..6d4db414ea971 100644
--- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
+++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp
@@ -5199,7 +5199,7 @@ static LogicalResult commonVerifierPackAndUnPackOp(OpTy packOrUnPack) {
       packOrUnPack.getInnerDimsPos(), packOrUnPack.getOuterDimsPerm());
   for (auto it : llvm::enumerate(llvm::zip(
            packedType.getShape().take_back(mixedTiles.size()), mixedTiles))) {
-    int64_t shape = std::get<0>(it.value());
+    int64_t dimSize = std::get<0>(it.value());
     if (Attribute attr =
             llvm::dyn_cast_if_present<Attribute>(std::get<1>(it.value()))) {
       IntegerAttr intAttr = dyn_cast_or_null<IntegerAttr>(attr);



More information about the Mlir-commits mailing list