[Mlir-commits] [mlir] [MLIR][vector] vector.deinterleave to vector.shuffle decomposition (PR #177897)

Noah Prisament llvmlistbot at llvm.org
Sun Jan 25 20:54:13 PST 2026


https://github.com/nprisament created https://github.com/llvm/llvm-project/pull/177897

This PR adds a rewrite pattern for vector.deinterleave ops that rewrites them using vector.shuffle ops. This is similar to the existing pattern for vector.interleave and allows for supporting these ops for lowering to targets without native deinterleave support. A transform dialect op is also added to apply this pattern.

>From b55f6d14395a665a9ae30dff5256d977ca3031fe Mon Sep 17 00:00:00 2001
From: Noah Prisament <nprisament at gmail.com>
Date: Sat, 24 Jan 2026 22:59:51 -0500
Subject: [PATCH] Adds a vector.deinterleave to vector.shuffle decomposition
 pattern and transform dialect op

---
 .../Vector/TransformOps/VectorTransformOps.td | 14 ++++++
 .../Vector/Transforms/LoweringPatterns.h      |  3 ++
 .../TransformOps/VectorTransformOps.cpp       |  5 ++
 .../Transforms/LowerVectorInterleave.cpp      | 48 +++++++++++++++++++
 .../vector-deinterleave-to-shuffle.mlir       | 21 ++++++++
 5 files changed, 91 insertions(+)
 create mode 100644 mlir/test/Dialect/Vector/vector-deinterleave-to-shuffle.mlir

diff --git a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td
index 03d25505dc65c..04e6e887a24e2 100644
--- a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td
+++ b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td
@@ -387,6 +387,20 @@ def ApplyInterleaveToShufflePatternsOp : Op<Transform_Dialect,
   let assemblyFormat = "attr-dict";
 }
 
+def ApplyDeinterleaveToShufflePatternsOp : Op<Transform_Dialect,
+    "apply_patterns.vector.deinterleave_to_shuffle",
+    [DeclareOpInterfaceMethods<PatternDescriptorOpInterface>]> {
+  let description = [{
+    Indicates that 1D vector deinterleave operations should be rewritten as
+    vector shuffle operations.
+
+    This is motivated by some current codegen backends not handling vector
+    deinterleave operations.
+  }];
+
+  let assemblyFormat = "attr-dict";
+}
+
 def ApplyRewriteNarrowTypePatternsOp : Op<Transform_Dialect,
     "apply_patterns.vector.rewrite_narrow_types",
     [DeclareOpInterfaceMethods<PatternDescriptorOpInterface>]> {
diff --git a/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h b/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h
index 7bd96c8a6d1a1..c0fa1afdee9b8 100644
--- a/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h
+++ b/mlir/include/mlir/Dialect/Vector/Transforms/LoweringPatterns.h
@@ -284,6 +284,9 @@ void populateVectorInterleaveLoweringPatterns(RewritePatternSet &patterns,
 void populateVectorInterleaveToShufflePatterns(RewritePatternSet &patterns,
                                                PatternBenefit benefit = 1);
 
+void populateVectorDeinterleaveToShufflePatterns(RewritePatternSet &patterns,
+                                                 PatternBenefit benefit = 1);
+
 /// Populates the pattern set with the following patterns:
 ///
 /// [UnrollBitCastOp]
diff --git a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp
index 7faa222a9e574..2bf8c3175a986 100644
--- a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp
+++ b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp
@@ -195,6 +195,11 @@ void transform::ApplyInterleaveToShufflePatternsOp::populatePatterns(
   vector::populateVectorInterleaveToShufflePatterns(patterns);
 }
 
+void transform::ApplyDeinterleaveToShufflePatternsOp::populatePatterns(
+    RewritePatternSet &patterns) {
+  vector::populateVectorDeinterleaveToShufflePatterns(patterns);
+}
+
 void transform::ApplyRewriteNarrowTypePatternsOp::populatePatterns(
     RewritePatternSet &patterns) {
   populateVectorNarrowTypeRewritePatterns(patterns);
diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp
index 479fc0c6a9d8c..c6324554168ec 100644
--- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorInterleave.cpp
@@ -16,6 +16,7 @@
 #include "mlir/Dialect/Vector/Utils/VectorUtils.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/PatternMatch.h"
+#include "llvm/ADT/STLExtras.h"
 
 #define DEBUG_TYPE "vector-interleave-lowering"
 
@@ -147,6 +148,7 @@ class UnrollDeinterleaveOp final
 private:
   int64_t targetRank = 1;
 };
+
 /// Rewrite vector.interleave op into an equivalent vector.shuffle op, when
 /// applicable: `sourceType` must be 1D and non-scalable.
 ///
@@ -180,6 +182,47 @@ struct InterleaveToShuffle final : OpRewritePattern<vector::InterleaveOp> {
   }
 };
 
+/// Rewrite vector.deinterleave op into two equivalent vector.shuffle ops, when
+/// applicable: `sourceType` must be 1D and non-scalable.
+///
+/// Example:
+///
+/// ```mlir
+/// %evens, %odds = vector.deinterleave %arg0 : vector<4xi32> -> vector<2xi32>
+/// ```
+///
+/// Is rewritten into:
+///
+/// ```mlir
+/// %evens = vector.shuffle %arg0, %arg0 [0, 2] : vector<4xi32>, vector<4xi32>
+/// %odds = vector.shuffle %arg0, %arg0 [1, 3] : vector<4xi32>, vector<4xi32>
+/// ```
+struct DeinterleaveToShuffle final : OpRewritePattern<vector::DeinterleaveOp> {
+  using Base::Base;
+
+  LogicalResult matchAndRewrite(vector::DeinterleaveOp op,
+                                PatternRewriter &rewriter) const override {
+    VectorType sourceType = op.getSourceVectorType();
+    if (sourceType.getRank() != 1 || sourceType.isScalable()) {
+      return failure();
+    }
+
+    auto seq = llvm::seq<int64_t>(sourceType.getNumElements() / 2);
+    auto evenZip =
+        llvm::to_vector(llvm::map_range(seq, [](int64_t i) { return i * 2; }));
+    auto oddZip = llvm::to_vector(
+        llvm::map_range(evenZip, [](int64_t i) { return i + 1; }));
+
+    Value evenResult = vector::ShuffleOp::create(
+        rewriter, op.getLoc(), op.getOperand(), op.getOperand(), evenZip);
+    Value oddResult = vector::ShuffleOp::create(
+        rewriter, op.getLoc(), op.getOperand(), op.getOperand(), oddZip);
+
+    rewriter.replaceOp(op, ValueRange{evenResult, oddResult});
+    return success();
+  }
+};
+
 } // namespace
 
 void mlir::vector::populateVectorInterleaveLoweringPatterns(
@@ -192,3 +235,8 @@ void mlir::vector::populateVectorInterleaveToShufflePatterns(
     RewritePatternSet &patterns, PatternBenefit benefit) {
   patterns.add<InterleaveToShuffle>(patterns.getContext(), benefit);
 }
+
+void mlir::vector::populateVectorDeinterleaveToShufflePatterns(
+    RewritePatternSet &patterns, PatternBenefit benefit) {
+  patterns.add<DeinterleaveToShuffle>(patterns.getContext(), benefit);
+}
diff --git a/mlir/test/Dialect/Vector/vector-deinterleave-to-shuffle.mlir b/mlir/test/Dialect/Vector/vector-deinterleave-to-shuffle.mlir
new file mode 100644
index 0000000000000..d238a8fe28ae4
--- /dev/null
+++ b/mlir/test/Dialect/Vector/vector-deinterleave-to-shuffle.mlir
@@ -0,0 +1,21 @@
+// RUN: mlir-opt %s --transform-interpreter | FileCheck %s
+
+// CHECK-LABEL: @vector_deinterleave_to_shuffle
+func.func @vector_deinterleave_to_shuffle(%arg0: vector<14xi16>) -> (vector<7xi16>, vector<7xi16>) {
+  %evens, %odds = vector.deinterleave %arg0 : vector<14xi16> -> vector<7xi16>
+  return %evens, %odds : vector<7xi16>, vector<7xi16>
+}
+// CHECK: vector.shuffle %arg0, %arg0 [0, 2, 4, 6, 8, 10, 12] : vector<14xi16>, vector<14xi16>
+// CHECK: vector.shuffle %arg0, %arg0 [1, 3, 5, 7, 9, 11, 13] : vector<14xi16>, vector<14xi16>
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) {
+    %f = transform.structured.match ops{["func.func"]} in %module_op
+      : (!transform.any_op) -> !transform.any_op
+
+    transform.apply_patterns to %f {
+      transform.apply_patterns.vector.deinterleave_to_shuffle
+    } : !transform.any_op
+    transform.yield
+  }
+}



More information about the Mlir-commits mailing list