[Mlir-commits] [mlir] [MLIR][XeGPU] Relax LoadStoreMatrixToXeVMPattern to accept non-distributed load_matrix/store_matrix (PR #210595)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sun Jul 19 06:42:16 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-gpu

Author: Naaz30

<details>
<summary>Changes</summary>

`LoadStoreMatrixToXeVMPattern` currently rejects `xegpu.load_matrix` and `xegpu.store_matrix` operations in two situations that are not required for the plain (non-subgroup_block_io) lowering path:

1. **Vector shape restriction** : The pass asserts that the vector type has at most one non-unit dimension, assuming that xegpu-sg-to-lane-distribute has       already reduced the operation to a per-lane fragment. This causes the pass to fail (or behave incorrectly in NDEBUG builds) for valid multi-dimensional tiles such as vector<4x8xf32>.

2. **Chip-specific target check** : The pass requires the operation to reside inside a gpu.module with an xevm.target attribute identifying a supported architecture (PVC, BMG, or CRI) via xegpu::getChipStr(). However, this requirement is unnecessary for the plain lowering path, which only generates chip-independent LLVM::LoadOp and LLVM::StoreOp operations.

**Changes**
Remove the unnecessary vector shape restriction for the plain lowering path.
Remove the chip target requirement for the plain lowering path.

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


2 Files Affected:

- (modified) mlir/lib/Conversion/XeGPUToXeVM/XeGPUToXeVM.cpp (+7-7) 
- (modified) mlir/test/Conversion/XeGPUToXeVM/loadstore_matrix.mlir (+32-9) 


``````````diff
diff --git a/mlir/lib/Conversion/XeGPUToXeVM/XeGPUToXeVM.cpp b/mlir/lib/Conversion/XeGPUToXeVM/XeGPUToXeVM.cpp
index 6144d7c0c1a15..03808d2d0f8ff 100644
--- a/mlir/lib/Conversion/XeGPUToXeVM/XeGPUToXeVM.cpp
+++ b/mlir/lib/Conversion/XeGPUToXeVM/XeGPUToXeVM.cpp
@@ -719,9 +719,9 @@ class LoadStoreMatrixToXeVMPattern : public OpConversionPattern<OpType> {
       // Some transforms may leave unit dimension in the 2D vector, adaptors do
       // not catch it for results.
       if (auto vecType = dyn_cast<VectorType>(resType)) {
-        assert(llvm::count_if(vecType.getShape(),
-                              [](int64_t d) { return d != 1; }) <= 1 &&
-               "Expected either 1D vector or nD with unit dimensions");
+        // Flatten to 1D
+        // Accepts multi-dim tile as one flat, contiguous run. 
+        // This is only valid when the underlying mem_desc region is contiguous in memory
         resType = VectorType::get({vecType.getNumElements()},
                                   vecType.getElementType());
       }
@@ -787,9 +787,9 @@ class LoadStoreMatrixToXeVMPattern : public OpConversionPattern<OpType> {
 
     if (valOrResVecTy.getNumElements() >= 1) {
       auto chipOpt = xegpu::getChipStr(op);
-      if (!chipOpt ||
-          (*chipOpt != "pvc" && *chipOpt != "bmg" && *chipOpt != "cri")) {
-        // the lowering for chunk load only works for pvc, bmg or cri
+      // reject an explicitly unsupported chip
+      if (chipOpt && *chipOpt != "pvc" && *chipOpt != "bmg" &&
+          *chipOpt != "cri") {
         return rewriter.notifyMatchFailure(
             op, "The lowering is specific to pvc, bmg or cri.");
       }
@@ -1626,4 +1626,4 @@ void mlir::populateXeGPUToXeVMConversionPatterns(
   patterns.add<DpasMxToXeVMPattern>(typeConverter, patterns.getContext());
   patterns.add<ExtfToXeVMPattern, TruncfToXeVMPattern>(typeConverter,
                                                        patterns.getContext());
-}
+}
\ No newline at end of file
diff --git a/mlir/test/Conversion/XeGPUToXeVM/loadstore_matrix.mlir b/mlir/test/Conversion/XeGPUToXeVM/loadstore_matrix.mlir
index 07fb09fa2c24b..50f7263b65e05 100644
--- a/mlir/test/Conversion/XeGPUToXeVM/loadstore_matrix.mlir
+++ b/mlir/test/Conversion/XeGPUToXeVM/loadstore_matrix.mlir
@@ -1,10 +1,11 @@
 // RUN: mlir-opt  -split-input-file -convert-xegpu-to-xevm %s | FileCheck %s
 
-gpu.module @test_kernel [#xevm.target<chip = "pvc">] {
+gpu.module @test_kernel[#xevm.target<chip = "pvc">] {
 
   // e.g. for mem_desc<32x32xf16, @strides=[1, 16]>
-  // its memory layout tuple is (blocked shape = [1,1,32,32],strides=[1024,1024,32,1])
-  //CHECK-LABEL: load_store_matrix_plain
+  // its memory layout tuple is (blocked shape =
+  // [1,1,32,32],strides=[1024,1024,32,1])
+  // CHECK-LABEL: load_store_matrix_plain
   gpu.func @load_store_matrix_plain(%arg0: memref<4096xi8, 3>) -> f32 {
 
     //CHECK: %[[INTPTR:.*]] = memref.extract_aligned_pointer_as_index %arg0 : memref<4096xi8, 3> -> index
@@ -324,12 +325,34 @@ gpu.module @test_kernel [#xevm.target<chip = "pvc">] {
 
   //CHECK-LABEL: load_matrix_f8e8m0_vector
   gpu.func @load_matrix_f8e8m0_vector(%arg0: memref<1024xi8, 3>) -> vector<8xf8E8M0FNU> {
-    %c0 = arith.constant 0 : index
-    %0 = xegpu.create_mem_desc %arg0 : memref<1024xi8, 3> -> !xegpu.mem_desc<32x32xf8E8M0FNU>
-    //CHECK: %[[LOADEDV:.*]] = llvm.load %{{.*}} : !llvm.ptr<3> -> vector<8xi8>
-    //CHECK: vector.bitcast %[[LOADEDV]] : vector<8xi8> to vector<8xf8E8M0FNU>
-    %1 = xegpu.load_matrix %0[%c0, %c0]: !xegpu.mem_desc<32x32xf8E8M0FNU>, index, index -> vector<8xf8E8M0FNU>
-    gpu.return %1 : vector<8xf8E8M0FNU>
+    % c0 = arith.constant 0 : index % 0 =
+               xegpu.create_mem_desc %
+               arg0 : memref<1024xi8, 3>->!xegpu.mem_desc<32x32xf8E8M0FNU>
+               // CHECK: %[[LOADEDV:.*]] = llvm.load %{{.*}} : !llvm.ptr<3> ->
+               // vector<8xi8> CHECK: vector.bitcast %[[LOADEDV]] : vector<8xi8>
+               // to vector<8xf8E8M0FNU>
+               % 1 = xegpu.load_matrix % 0 [% c0, % c0]
+        : !xegpu.mem_desc<32x32xf8E8M0FNU>,
+      index, index->vector<8xf8E8M0FNU> gpu.return % 1 : vector<8xf8E8M0FNU>
   }
+}
 
+// -----
+
+// CHECK-LABEL: func.func @m(
+// CHECK: memref.extract_aligned_pointer_as_index
+// CHECK: llvm.inttoptr
+// CHECK: llvm.load
+// CHECK-SAME: vector<32xf32>
+
+module {
+  func.func @m(% arg0 : index) {
+    % alloca =
+        memref.alloca()
+        : memref<4x8xf32, 3> %
+        0 = xegpu.create_mem_desc %
+            alloca : memref<4x8xf32, 3>->!xegpu.mem_desc<4x8xf32> % 1 =
+                xegpu.load_matrix %
+                0 [0, 0] : !xegpu.mem_desc<4x8xf32>->vector<4x8xf32> return
+  }
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/210595


More information about the Mlir-commits mailing list