[Mlir-commits] [mlir] [MLIR][Vector] Fix RewriteAlignedSubByteIntExt/Trunc producing invalid IR when source is already i8 (PR #188941)

Mehdi Amini llvmlistbot at llvm.org
Fri Mar 27 03:06:21 PDT 2026


https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/188941

When the conversion destination type is i8 (e.g., extsi i4->i8), RewriteAlignedSubByteIntExt was unconditionally creating a new ConversionOp with identical source and result types (vector<8xi8> -> vector<8xi8>), which is invalid IR. Similarly, RewriteAlignedSubByteIntTrunc was creating arith.trunci from vector<Nxi8> to vector<Nxi8> when the source was already i8.

Fix by:
- In RewriteAlignedSubByteIntExt: replace the op directly with subByteExt when it already has the destination type, instead of wrapping in a new conversion op.
- In RewriteAlignedSubByteIntTrunc: skip the intermediate truncation to i8 when the source is already i8, passing srcValue directly to the i8->i4 rewrite logic.

This matches the existing test expectations in
vector-rewrite-subbyte-ext-and-trunci.mlir.

Assisted-by: Claude Code
Fix a failure present with MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS=ON.

>From 500a38aa3472913a638ac6d56c397a5a6cda8cbb Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Thu, 26 Mar 2026 15:57:59 -0700
Subject: [PATCH] [MLIR][Vector] Fix RewriteAlignedSubByteIntExt/Trunc
 producing invalid IR when source is already i8

When the conversion destination type is i8 (e.g., extsi i4->i8),
RewriteAlignedSubByteIntExt was unconditionally creating a new
ConversionOp with identical source and result types (vector<8xi8> ->
vector<8xi8>), which is invalid IR. Similarly, RewriteAlignedSubByteIntTrunc
was creating arith.trunci from vector<Nxi8> to vector<Nxi8> when the
source was already i8.

Fix by:
- In RewriteAlignedSubByteIntExt: replace the op directly with subByteExt
  when it already has the destination type, instead of wrapping in a new
  conversion op.
- In RewriteAlignedSubByteIntTrunc: skip the intermediate truncation to i8
  when the source is already i8, passing srcValue directly to the i8->i4
  rewrite logic.

This matches the existing test expectations in
vector-rewrite-subbyte-ext-and-trunci.mlir.

Assisted-by: Claude Code
Fix a failure present with MLIR_ENABLE_EXPENSIVE_PATTERN_API_CHECKS=ON.
---
 .../Transforms/VectorEmulateNarrowType.cpp      | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp
index c53242b526cb6..583cda7ac2810 100644
--- a/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp
@@ -2163,9 +2163,14 @@ struct RewriteAlignedSubByteIntExt : OpRewritePattern<ConversionOpType> {
       return failure();
     }
 
-    // Finalize the rewrite.
-    rewriter.replaceOpWithNewOp<ConversionOpType>(
-        conversionOp, conversionOp.getType(), subByteExt);
+    // Finalize the rewrite. If subByteExt already has the destination type
+    // (e.g. extsi i4->i8 where the container is i8), replace directly without
+    // creating a new conversion op that would have identical src and dst types.
+    if (subByteExt.getType() == conversionOp.getType())
+      rewriter.replaceOp(conversionOp, subByteExt);
+    else
+      rewriter.replaceOpWithNewOp<ConversionOpType>(
+          conversionOp, conversionOp.getType(), subByteExt);
     return success();
   }
 };
@@ -2213,11 +2218,13 @@ struct RewriteAlignedSubByteIntTrunc : OpRewritePattern<arith::TruncIOp> {
             /*containerTy=*/rewriter.getI8Type(), truncOp)))
       return failure();
 
-    // Create a new iX -> i8 truncation op.
+    // Create a new iX -> i8 truncation op, unless the source is already i8.
     Location loc = truncOp.getLoc();
     auto i8VecType = srcVecType.cloneWith(std::nullopt, rewriter.getI8Type());
     Value i8TruncVal =
-        arith::TruncIOp::create(rewriter, loc, i8VecType, srcValue);
+        srcVecType == i8VecType
+            ? srcValue
+            : arith::TruncIOp::create(rewriter, loc, i8VecType, srcValue);
 
     // Rewrite the i8 -> i4 truncation part.
     Value subByteTrunc = rewriteI8ToI4Trunc(rewriter, loc, i8TruncVal);



More information about the Mlir-commits mailing list