[Mlir-commits] [mlir] [MLIR][XeGPU] Make shape cast respect full replication layout semantics (PR #229395)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Oct 6 05:23:52 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-gpu
@llvm/pr-subscribers-mlir
Author: Artem Kroviakov (akroviakov)
<details>
<summary>Changes</summary>
A non-distributed dimension is also the one that does full replication across lanes, not only `layout[d] == 1`.
Lanes on the replicated dimension share the same offset in tiling.
---
Full diff: https://github.com/llvm/llvm-project/pull/229395.diff
2 Files Affected:
- (modified) mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp (+18-2)
- (modified) mlir/test/Dialect/XeGPU/propagate-layout-inst-data.mlir (+15)
``````````diff
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
index 031d971cebe6c..2ea24aac2c375 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
@@ -2851,11 +2851,21 @@ xegpu::setupShapeCastResultLayout(xegpu::LayoutKind layoutKind,
consumerLayout.getEffectiveLaneLayoutAsInt();
SmallVector<int64_t> instData = consumerLayout.getEffectiveInstDataAsInt();
+ // A dim is not distributed when its lanes cover a single coordinate.
+ // TODO: partially replicated dims (1 < shape_dim / lane_data < lane_layout)
+ // are still treated as fully distributed.
+ auto isUndistributed = [&](int64_t dim, ArrayRef<int64_t> lanes,
+ ArrayRef<int64_t> data) {
+ return lanes[dim] == 1 || resShape[dim] / data[dim] <= 1;
+ };
+
xegpu::DistributeLayoutAttr resLayout = [&]() -> DistributeLayoutAttr {
+ SmallVector<int64_t> laneData = consumerLayout.getEffectiveLaneDataAsInt();
DistributeLayoutAttr layout = consumerLayout;
for (const SmallVector<int64_t> &dimGroup : splitDimGroups) {
size_t i = 0;
- while (i < dimGroup.size() && laneLayout[dimGroup[i]] == 1)
+ while (i < dimGroup.size() &&
+ isUndistributed(dimGroup[i], laneLayout, laneData))
++i;
for (++i; i < dimGroup.size(); ++i) {
@@ -2876,6 +2886,12 @@ xegpu::setupShapeCastResultLayout(xegpu::LayoutKind layoutKind,
SmallVector<int64_t> resInstData = resLayout.getEffectiveInstDataAsInt();
SmallVector<int64_t> resLaneLayout = resLayout.getEffectiveLaneLayoutAsInt();
SmallVector<int64_t> resLaneData = resLayout.getEffectiveLaneDataAsInt();
+ // `isContiguousTiling` assumes lanes have unique positions.
+ // Treat replicated dims the same way as single-lane dims.
+ SmallVector<int64_t> resSteppingLanes(resLaneLayout);
+ for (int64_t dim = 0, rank = resSteppingLanes.size(); dim < rank; ++dim)
+ if (isUndistributed(dim, resLaneLayout, resLaneData))
+ resSteppingLanes[dim] = 1;
for (const SmallVector<int64_t> &dimGroup : splitDimGroups) {
// One lane's elements must be a single contiguous run of the collapsed dim.
@@ -2887,7 +2903,7 @@ xegpu::setupShapeCastResultLayout(xegpu::LayoutKind layoutKind,
int64_t collapsedLaneData = 1;
for (int64_t dim : dimGroup)
collapsedLaneData *= resLaneData[dim];
- if (!isContiguousTiling(dimGroup, resShape, resLaneLayout, resLaneData,
+ if (!isContiguousTiling(dimGroup, resShape, resSteppingLanes, resLaneData,
/*expectedStride=*/collapsedLaneData))
return nullptr;
diff --git a/mlir/test/Dialect/XeGPU/propagate-layout-inst-data.mlir b/mlir/test/Dialect/XeGPU/propagate-layout-inst-data.mlir
index 30e02cc42095c..a0b261f12402d 100644
--- a/mlir/test/Dialect/XeGPU/propagate-layout-inst-data.mlir
+++ b/mlir/test/Dialect/XeGPU/propagate-layout-inst-data.mlir
@@ -772,3 +772,18 @@ func.func @shape_cast_split_fills_strided_inner_dim(%arg0: memref<16x1024xbf16>)
return
}
}
+
+// -----
+gpu.module @test {
+// CHECK-LABEL: func.func @shape_cast_insert_unit_dim_replicated_lanes(
+// CHECK: %[[CST:.*]] = arith.constant {layout_result_0 = #xegpu.slice<#xegpu.layout<inst_data = [1, 1, 4], lane_layout = [1, 4, 4], lane_data = [1, 1, 1]>, dims = [1]>} dense<0.000000e+00> : vector<8x32xf16>
+// CHECK: %[[CAST:.*]] = vector.shape_cast %[[CST]] {layout_result_0 = #xegpu.layout<inst_data = [1, 1, 4], lane_layout = [1, 4, 4], lane_data = [1, 1, 1]>} : vector<8x32xf16> to vector<8x1x32xf16>
+func.func @shape_cast_insert_unit_dim_replicated_lanes() {
+ %cst = arith.constant dense<0.000000e+00> : vector<8x32xf16>
+ %0 = vector.shape_cast %cst : vector<8x32xf16> to vector<8x1x32xf16>
+ %1 = xegpu.convert_layout %0
+ <{target_layout = #xegpu.layout<inst_data = [1, 1, 4], lane_layout = [1, 4, 4], lane_data = [1, 1, 1]>}>
+ : vector<8x1x32xf16>
+ return
+}
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/229395
More information about the Mlir-commits
mailing list