Skip to content

Conversation

mshahneo
Copy link
Contributor

@mshahneo mshahneo commented Sep 11, 2025

Use upstream patterns to create a vectorlinearize pass needed for lowering to XeVM.
Linearizes n-D vectors to 1-D vectors.

This is needed because, vector-to-llvm does not linearize all the vectors.

@llvmbot
Copy link
Member

llvmbot commented Sep 11, 2025

@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-gpu

Author: Md Abdullah Shahneous Bari (mshahneo)

Changes

Use upstream patterns to create a vectorlinearize pass needed for lowering to XeVM.
Linearizes n-D vectors to 1-D vectors.


Full diff: https://github.com/llvm/llvm-project/pull/158084.diff

3 Files Affected:

  • (modified) mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td (+9)
  • (modified) mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt (+1)
  • (added) mlir/lib/Dialect/XeGPU/Transforms/XeGPUVectorLinearize.cpp (+111)
diff --git a/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td b/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td
index ddf6b4ac85a90..2db28a20935b1 100644
--- a/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/XeGPU/Transforms/Passes.td
@@ -71,4 +71,13 @@ def XeGPUBlocking: Pass<"xegpu-blocking"> {
       "index::IndexDialect"];
 }
 
+def XeGPUVectorLinearize : Pass<"xegpu-vector-linearize"> {
+  let summary = "Linearize n-D vectors to 1-D vectors";
+  let description = [{
+    This pass linearizes n-D vectors to 1-D vectors for lowering to XeVM.
+  }];
+  let dependentDialects = ["arith::ArithDialect", "memref::MemRefDialect",
+                           "scf::SCFDialect", "vector::VectorDialect"];
+}
+
 #endif // MLIR_DIALECT_XEGPU_TRANSFORMS_PASSES_TD
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt b/mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt
index 9c178d1d85642..e6f76067094ce 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/XeGPU/Transforms/CMakeLists.txt
@@ -5,6 +5,7 @@ add_mlir_dialect_library(MLIRXeGPUTransforms
   XeGPUUnroll.cpp
   XeGPUWgToSgDistribute.cpp
   XeGPUPropagateLayout.cpp
+  XeGPUVectorLinearize.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/XeGPU
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUVectorLinearize.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUVectorLinearize.cpp
new file mode 100644
index 0000000000000..a6a68716547c9
--- /dev/null
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUVectorLinearize.cpp
@@ -0,0 +1,111 @@
+//===- XeGPUVectorLinearize.cpp - Linearizes n-D vectors to 1-D vectors
+//-------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/SCF/IR/SCF.h"
+#include "mlir/Dialect/SCF/Transforms/Patterns.h"
+#include "mlir/Dialect/Vector/IR/VectorOps.h"
+#include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h"
+#include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h"
+#include "mlir/Dialect/XeGPU/IR/XeGPU.h"
+#include "mlir/Dialect/XeGPU/Transforms/Passes.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+
+#include <optional>
+
+namespace mlir {
+namespace xegpu {
+#define GEN_PASS_DEF_XEGPUVECTORLINEARIZE
+#include "mlir/Dialect/XeGPU/Transforms/Passes.h.inc"
+} // namespace xegpu
+} // namespace mlir
+
+#define DEBUG_TYPE "xegpu-vector-linearize"
+
+using namespace mlir;
+
+namespace {
+struct XeGPUVectorLinearizePass final
+    : public xegpu::impl::XeGPUVectorLinearizeBase<XeGPUVectorLinearizePass> {
+  void runOnOperation() override {
+    auto *context = &getContext();
+
+    // vector.broadcast and vector.gather requires progressive lowering
+    {
+      mlir::RewritePatternSet patterns(&getContext());
+      mlir::vector::populateVectorBroadcastLoweringPatterns(patterns);
+      mlir::vector::populateVectorGatherLoweringPatterns(patterns);
+      mlir::vector::populateVectorGatherToConditionalLoadPatterns(patterns);
+      // vector.transpose lowering
+      // Shuffle16x16 will fallback to Shuffle1D for non 16x16 sizes.
+      mlir::vector::populateVectorTransposeLoweringPatterns(
+          patterns, mlir::vector::VectorTransposeLowering::Shuffle16x16);
+      (void)mlir::applyPatternsGreedily(getOperation(), std::move(patterns));
+    }
+
+    // Unroll load store from <<MxN> to M <1xN> load/stores and then linearize
+    {
+      mlir::RewritePatternSet patterns(&getContext());
+      mlir::vector::UnrollVectorOptions vectorOptions;
+      vectorOptions.setNativeShapeFn(
+          [](mlir::Operation *op) -> std::optional<mlir::SmallVector<int64_t>> {
+            // Only unroll for vector::LoadOp and vector::StoreOp
+            if (mlir::isa<mlir::vector::LoadOp>(op)) {
+              if (auto vecType = mlir::dyn_cast<mlir::VectorType>(
+                      op->getResult(0).getType())) {
+                auto shape = vecType.getShape();
+                if (shape.size() == 2)
+                  return mlir::SmallVector<int64_t>{1, shape[1]};
+              }
+            }
+            if (mlir::isa<mlir::vector::StoreOp>(op)) {
+              if (auto vecType = mlir::dyn_cast<mlir::VectorType>(
+                      op->getOperand(0).getType())) {
+                auto shape = vecType.getShape();
+                if (shape.size() == 2)
+                  return mlir::SmallVector<int64_t>{1, shape[1]};
+              }
+            }
+            return std::nullopt;
+          });
+      mlir::vector::populateVectorUnrollPatterns(patterns, vectorOptions);
+      (void)mlir::applyPatternsGreedily(getOperation(), std::move(patterns));
+    }
+
+    // Use upstream linearization patterns
+    {
+      mlir::MLIRContext &context = getContext();
+      mlir::TypeConverter converter;
+      mlir::RewritePatternSet patterns(&context);
+      mlir::ConversionTarget target(context);
+      mlir::vector::populateForVectorLinearize(converter, target);
+      mlir::vector::populateVectorLinearizeBasePatterns(converter, target,
+                                                        patterns);
+      mlir::vector::populateVectorLinearizeShuffleLikeOpsPatterns(
+          converter, target, patterns);
+      mlir::scf::populateSCFStructuralTypeConversionsAndLegality(
+          converter, patterns, target);
+      if (failed(applyPartialConversion(getOperation(), target,
+                                        std::move(patterns))))
+        return signalPassFailure();
+    }
+
+    mlir::TypeConverter typeConverter;
+    mlir::RewritePatternSet patterns(context);
+    mlir::ConversionTarget target(*context);
+    typeConverter.addConversion([](mlir::Type type) { return type; });
+
+    target.addIllegalOp<mlir::vector::TransposeOp>();
+    target.addLegalOp<mlir::vector::ShapeCastOp>();
+    target.addLegalOp<mlir::vector::ExtractOp>();
+    target.addLegalDialect<mlir::xegpu::XeGPUDialect>();
+  }
+};
+} // namespace

@mshahneo mshahneo changed the title [XeGPU][Transform] Add vectorlinearize transform pass. [mlir][XeGPU][Transform] Add vectorlinearize transform pass. Sep 11, 2025
@Garra1980
Copy link

cc @nbpatel @silee2

@charithaintc
Copy link
Contributor

Can you update the desc with why vector-to-llvm is not enough to handle it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to check if this is needed. We won't have 16x16 sizes at SIMT level now.

Copy link
Contributor

@nbpatel nbpatel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a couple of tests in xegpu/transform?

@mshahneo
Copy link
Contributor Author

can you add a couple of tests in xegpu/transform?

Added :).

@charithaintc charithaintc self-requested a review September 15, 2025 22:15
Copy link
Contributor

@charithaintc charithaintc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM % comments

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: best to fit this in one line :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, fixed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, vector/arith linearize tests are already there. I think we only need XeGPU-specific tests here. I suggest removing duplicated tests.

Maybe we could have a few e2e lowering test for xegpu code samples like a simple GEMM with extracts/transpose etc that require the application of linearize pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestions. Fixed now, removed duplication and added some new ones.

Copy link
Contributor

@adam-smnk adam-smnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for the pass to enable e2e lowering

I still miss relevant tests (or the current ones could use documentation) that would justify its existence and really ensure no regressions.

@mshahneo
Copy link
Contributor Author

Thanks a lot, @adam-smnk , @charithaintc , @nbpatel .
Updated the PR based on your suggestion.
Please take a look whenever you have the time.

Copy link
Contributor

@adam-smnk adam-smnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 👍
I'm sure it'll evolve further once we start running more e2e examples.

Use upstream patterns to create a vectorlinearize pass needed
for lowering to xevm.
Linearizes n-D vectors to 1-D vectors.
Update the test case to remove duplication with vector-linearize.
Add new test cases for XeGPU, vector.broadcast, vector.gather.
Add vector unroll support for n-D laod/store.
@mshahneo mshahneo force-pushed the xegpu-vector-linearize branch from c177c25 to 6b22d6d Compare September 18, 2025 22:06
@mshahneo
Copy link
Contributor Author

Looks good 👍 I'm sure it'll evolve further once we start running more e2e examples.

Absolutely, not just e2e, with the proposed changes in vector dialect, this would definitely evolve :)

@mshahneo mshahneo merged commit 04c4e9d into llvm:main Sep 18, 2025
9 checks passed
mshahneo added a commit that referenced this pull request Sep 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants