[Mlir-commits] [mlir] [MLIR][XeGPU] Return element count from uarch for scatter ops (PR #206704)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Jun 30 03:42:01 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-gpu

Author: Artem Kroviakov (akroviakov)

<details>
<summary>Changes</summary>

This PR fixes uArch to return element count for scatter ops, rather than the byte count, to better comply with the use case.

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


2 Files Affected:

- (modified) mlir/include/mlir/Dialect/XeGPU/uArch/uArchBase.h (+7-3) 
- (modified) mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp (+17-11) 


``````````diff
diff --git a/mlir/include/mlir/Dialect/XeGPU/uArch/uArchBase.h b/mlir/include/mlir/Dialect/XeGPU/uArch/uArchBase.h
index e1879bb3ffe1c..00637526b1fbe 100644
--- a/mlir/include/mlir/Dialect/XeGPU/uArch/uArchBase.h
+++ b/mlir/include/mlir/Dialect/XeGPU/uArch/uArchBase.h
@@ -208,17 +208,21 @@ struct ScatterIoInstructionInterface : public Instruction {
     return B->getInstructionKind() == Kind;
   }
 
-  virtual int32_t getMaxLaneAccessSizeBytes() const = 0;
+  virtual int32_t getMaxLaneAccessSizeElements(int32_t elemBitwidth) const = 0;
   virtual ~ScatterIoInstructionInterface() = default;
 };
 struct LoadGatherInstruction
     : public ScatterIoInstructionInterface<InstructionKind::LoadGather> {
-  int32_t getMaxLaneAccessSizeBytes() const override { return 16; }
+  int32_t getMaxLaneAccessSizeElements(int32_t elemBitwidth) const override {
+    return 16 / (elemBitwidth / 8);
+  }
 };
 
 struct StoreScatterInstruction
     : public ScatterIoInstructionInterface<InstructionKind::StoreScatter> {
-  int32_t getMaxLaneAccessSizeBytes() const override { return 16; }
+  int32_t getMaxLaneAccessSizeElements(int32_t elemBitwidth) const override {
+    return 16 / (elemBitwidth / 8);
+  }
 };
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
index 61cd253508357..2a219fdf6348a 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
@@ -1713,8 +1713,9 @@ xegpu::DistributeLayoutAttr xegpu::setupLoadGatherAnchorLayout(
 
   const auto *uArchInstruction = dyn_cast<xegpu::uArch::LoadGatherInstruction>(
       uArch->getInstruction(xegpu::uArch::InstructionKind::LoadGather));
-  int maxChunkSize =
-      std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
+  int maxChunkSize = std::min(uArchInstruction->getMaxLaneAccessSizeElements(
+                                  resVecTy.getElementTypeBitWidth()),
+                              contigChunkSize);
 
   return setupGenericLoadAnchorLayout(layoutKind, context, consumerLayout,
                                       maxChunkSize, resShape, subgroupSize);
@@ -1734,8 +1735,9 @@ xegpu::setupLoadMatrixAnchorLayout(xegpu::LayoutKind layoutKind,
 
   const auto *uArchInstruction = dyn_cast<xegpu::uArch::LoadGatherInstruction>(
       uArch->getInstruction(xegpu::uArch::InstructionKind::LoadGather));
-  int maxChunkSize =
-      std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
+  int maxChunkSize = std::min(uArchInstruction->getMaxLaneAccessSizeElements(
+                                  resVecTy.getElementTypeBitWidth()),
+                              contigChunkSize);
   return setupGenericLoadAnchorLayout(layoutKind, context, consumerLayout,
                                       maxChunkSize, resShape, subgroupSize);
 }
@@ -1786,8 +1788,9 @@ xegpu::setupStoreScatterAnchorLayout(xegpu::LayoutKind layoutKind,
   const auto *uArchInstruction =
       dyn_cast<xegpu::uArch::StoreScatterInstruction>(
           uArch->getInstruction(xegpu::uArch::InstructionKind::StoreScatter));
-  int maxChunkSize =
-      std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
+  int maxChunkSize = std::min(uArchInstruction->getMaxLaneAccessSizeElements(
+                                  srcVecTy.getElementTypeBitWidth()),
+                              contigChunkSize);
   return setupGenericStoreAnchorLayout(layoutKind, context, maxChunkSize,
                                        srcShape, subgroupSize);
 }
@@ -1805,8 +1808,9 @@ xegpu::setupStoreMatrixAnchorLayout(xegpu::LayoutKind layoutKind,
   const auto *uArchInstruction =
       dyn_cast<xegpu::uArch::StoreScatterInstruction>(
           uArch->getInstruction(xegpu::uArch::InstructionKind::StoreScatter));
-  int maxChunkSize =
-      std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
+  int maxChunkSize = std::min(uArchInstruction->getMaxLaneAccessSizeElements(
+                                  srcVecTy.getElementTypeBitWidth()),
+                              contigChunkSize);
 
   return setupGenericStoreAnchorLayout(layoutKind, context, maxChunkSize,
                                        srcShape, subgroupSize);
@@ -1825,7 +1829,7 @@ xegpu::setupStoreMatrixAnchorLayout(xegpu::LayoutKind layoutKind,
 ///   - Otherwise a standard scatter-style factorization is computed via
 ///     `computeScatterIOLaneLayoutAndData`, bounded by `maxChunkSize` — the
 ///     per-lane load width reported by the uArch's LoadGather instruction
-///     (`getMaxLaneAccessSizeBytes`).
+///     (`getMaxLaneAccessSizeElements`).
 ///
 std::optional<xegpu::DistributeLayoutAttr>
 xegpu::completeScatterLoadLaneLayoutFromInstData(
@@ -1845,7 +1849,8 @@ xegpu::completeScatterLoadLaneLayoutFromInstData(
 
   // Reuse the load-side setup with inst_data as the destination shape.
   auto *context = specifiedLayout.getContext();
-  int maxChunkSize = uArchInstruction->getMaxLaneAccessSizeBytes();
+  int maxChunkSize = uArchInstruction->getMaxLaneAccessSizeElements(
+      getElementTypeOrSelf(elemTy).getIntOrFloatBitWidth());
   if (consumerLayout) {
     auto consumerLaneLayout = consumerLayout.getEffectiveLaneLayoutAsInt();
     auto consumerLaneData = consumerLayout.getEffectiveLaneDataAsInt();
@@ -1883,7 +1888,8 @@ xegpu::completeScatterStoreLaneLayoutFromInstData(
 
   // Reuse the store-side setup with inst_data as the source shape.
   auto *context = specifiedLayout.getContext();
-  int maxChunkSize = uArchInstruction->getMaxLaneAccessSizeBytes();
+  int maxChunkSize = uArchInstruction->getMaxLaneAccessSizeElements(
+      getElementTypeOrSelf(elemTy).getIntOrFloatBitWidth());
   auto [defLaneLayout, defLaneData] = computeScatterIOLaneLayoutAndData(
       specifiedInstData, subgroupSize, maxChunkSize);
   if (!isValidLaneLayout(specifiedInstData, defLaneLayout, defLaneData))

``````````

</details>


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


More information about the Mlir-commits mailing list