[Mlir-commits] [mlir] [MLIR][XeGPU] Fix layout inference issues blocking MXFP_GEMM test (PR #196243)

Jianhui Li llvmlistbot at llvm.org
Wed May 6 22:44:16 PDT 2026


https://github.com/Jianhui-Li created https://github.com/llvm/llvm-project/pull/196243

  This branch fixes layout inference issues in XeGPU  passes that were blocking MXFP (microscaled floating point) GEMM workloads:
                                                        
  - Fix bitcast/interleave layout adjustment to use result shape instead of source shape. The setupBitCastResultLayout and  setupInterleaveResultLayout functions were incorrectly bounding the layout adjustment loop against the  source shape. 
  - Fix blocking pass to drop inst_data from anchor operations. Operations whose shape already matches inst_data don't get unrolled, so their layout  attributes retained stale inst_data that broke downstream passes. Now inst_data is unconditionally stripped from all op attributes after blocking.
  - Propagate layout to both results of vector.deinterleave. The layout recovery pass was only setting the layout on result 0, leaving result 1 without a layout.                                     
                  
  Test plan                                             
   
  - Added mlir/test/Integration/Dialect/XeGPU/WG/simple_ mxfp_gemm.mlir integration test exercising the full
  MXFP GEMM pipeline (bitcast, deinterleave, transpose, interleave, dpas_mx).
  
  Assisted by Claude

>From 1a47b8a276923764eac5f753377bf88f28f653a0 Mon Sep 17 00:00:00 2001
From: Jianhui Li <jian.hui.li at intel.com>
Date: Wed, 6 May 2026 22:14:13 +0000
Subject: [PATCH 1/5] [XeGPU] Fix blocking pass to drop inst_data from anchor
 operations

The blocking pass was only dropping inst_data from temporary layout
attributes on operation results, but not from intrinsic operation
attributes (e.g., layout, layout_a, layout_b, etc. on load/dpas_mx ops).

When an operation's inst_data already matched its vector shape, it
wouldn't be unrolled, and these layout attributes retained their
inst_data. This caused issues in downstream passes like propagate-layout
which would try to propagate inst_data to operations with incompatible
shapes.

This fix adds a call to dropInstDataOnAttrs() on all operation
attributes after unrolling to ensure anchor operations have no inst_data.

Co-Authored-By: Claude Sonnet 4.5 <noreply at anthropic.com>
---
 mlir/lib/Dialect/XeGPU/Transforms/XeGPUBlocking.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUBlocking.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUBlocking.cpp
index 7db887915b275..8804e5c9919f2 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUBlocking.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUBlocking.cpp
@@ -488,6 +488,13 @@ void XeGPUBlockingPass::runOnOperation() {
       }
     }
 
+    // Drop inst_data from operation attributes (e.g., layout, layout_a,
+    // layout_b, etc.) This is necessary for anchor operations that don't get
+    // unrolled because their inst_data already matches their shape.
+    SmallVector<NamedAttribute> newAttrs =
+        xegpu::dropInstDataOnAttrs(op->getAttrs());
+    op->setAttrs(newAttrs);
+
     // Resolve unrealized conversion cast ops emulating pack/unpack
     if (auto castOp = dyn_cast<UnrealizedConversionCastOp>(op))
       resolveUnrealizedConversionCastOp(castOp);

>From 4105027898183daa16eebb3b4bc916d11bbd2958 Mon Sep 17 00:00:00 2001
From: Jianhui Li <jian.hui.li at intel.com>
Date: Thu, 7 May 2026 00:32:35 +0000
Subject: [PATCH 2/5] [XeGPU] Fix MXFP layout inference and add debug
 instrumentation

This commit addresses several issues in layout propagation for MXFP operations:

1. Add inferExtractStridedSliceSourceLayout to properly scale inst_data and
   lane_data when extracting slices, accounting for distributed vs non-distributed
   dimensions.

2. Fix setupBitCastResultLayout and setupInterleaveResultLayout to validate
   against result shape instead of source shape, ensuring proper layout scaling.

3. Add layout propagation for the second result of vector::DeinterleaveOp.

4. Add extensive debug logging to track transpose validation and bitcast
   layout setup for easier debugging of layout-related issues.

Co-Authored-By: Claude Sonnet 4.5 <noreply at anthropic.com>
---
 .../XeGPU/Transforms/XeGPULayoutImpl.h        |   7 +
 mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp    |  77 ++++++++-
 .../XeGPU/Transforms/XeGPULayoutImpl.cpp      | 162 +++++++++++++++---
 .../XeGPU/Transforms/XeGPUPropagateLayout.cpp |   7 +
 .../Transforms/XeGPUWgToSgDistribute.cpp      |  24 ++-
 5 files changed, 247 insertions(+), 30 deletions(-)

diff --git a/mlir/include/mlir/Dialect/XeGPU/Transforms/XeGPULayoutImpl.h b/mlir/include/mlir/Dialect/XeGPU/Transforms/XeGPULayoutImpl.h
index 299f9f18e3be6..24e65f3a2e4fd 100644
--- a/mlir/include/mlir/Dialect/XeGPU/Transforms/XeGPULayoutImpl.h
+++ b/mlir/include/mlir/Dialect/XeGPU/Transforms/XeGPULayoutImpl.h
@@ -133,6 +133,13 @@ DistributeLayoutAttr inferExtractSourceLayout(DistributeLayoutAttr resLayout,
                                               ArrayRef<int64_t> resShape,
                                               ArrayRef<int64_t> srcShape);
 
+/// Infers the source layout attribute for an extract strided slice operation.
+/// Source and result have the same rank and same lane distribution. The innermost
+/// dimension of inst_data and lane_data are scaled by the ratio of source to result shapes.
+DistributeLayoutAttr inferExtractStridedSliceSourceLayout(DistributeLayoutAttr resLayout,
+                                                          ArrayRef<int64_t> resShape,
+                                                          ArrayRef<int64_t> srcShape);
+
 /// Infers the layout attribute for mask and offset operand for Chunked load
 /// and store, given the anchor layout attribute for the value being load/store.
 DistributeLayoutAttr
diff --git a/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp b/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp
index e92b109c2223e..f1b83d5e1474a 100644
--- a/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp
+++ b/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp
@@ -682,6 +682,17 @@ DistributeLayoutAttr LayoutAttr::transposeDims(ArrayRef<int64_t> permutation) {
 bool LayoutAttr::isTransposeOf(const xegpu::DistributeLayoutAttr &other,
                                ArrayRef<int64_t> perm,
                                const xegpu::LayoutKind kind) {
+  llvm::dbgs() << "[DEBUG isTransposeOf] ENTRY\n";
+  llvm::dbgs() << "[DEBUG isTransposeOf] this layout: " << *this << "\n";
+  llvm::dbgs() << "[DEBUG isTransposeOf] other layout: " << other << "\n";
+  llvm::dbgs() << "[DEBUG isTransposeOf] kind: " << static_cast<int>(kind) << " (0=Subgroup, 1=InstData, 2=Lane)\n";
+  llvm::dbgs() << "[DEBUG isTransposeOf] permutation: [";
+  for (size_t i = 0; i < perm.size(); ++i) {
+    if (i > 0) llvm::dbgs() << ", ";
+    llvm::dbgs() << perm[i];
+  }
+  llvm::dbgs() << "]\n";
+
   if (!other)
     return false;
   if (getRank() != other.getRank() ||
@@ -697,13 +708,65 @@ bool LayoutAttr::isTransposeOf(const xegpu::DistributeLayoutAttr &other,
     }
     return true;
   };
-  if (kind == xegpu::LayoutKind::Subgroup)
-    return checkTranspose(getEffectiveSgLayoutAsInt(),
-                          other.getEffectiveSgLayoutAsInt(), perm) &&
-           checkTranspose(getEffectiveSgDataAsInt(),
-                          other.getEffectiveSgDataAsInt(), perm) &&
-           checkTranspose(getEffectiveOrderAsInt(),
-                          other.getEffectiveOrderAsInt(), perm);
+  if (kind == xegpu::LayoutKind::Subgroup) {
+    auto thisSgLayout = getEffectiveSgLayoutAsInt();
+    auto otherSgLayout = other.getEffectiveSgLayoutAsInt();
+    auto thisSgData = getEffectiveSgDataAsInt();
+    auto otherSgData = other.getEffectiveSgDataAsInt();
+    auto thisOrder = getEffectiveOrderAsInt();
+    auto otherOrder = other.getEffectiveOrderAsInt();
+
+    llvm::dbgs() << "[DEBUG isTransposeOf] Checking Subgroup level:\n";
+    llvm::dbgs() << "[DEBUG isTransposeOf]   this.sgLayout: [";
+    for (size_t i = 0; i < thisSgLayout.size(); ++i) {
+      if (i > 0) llvm::dbgs() << ", ";
+      llvm::dbgs() << thisSgLayout[i];
+    }
+    llvm::dbgs() << "]\n";
+    llvm::dbgs() << "[DEBUG isTransposeOf]   other.sgLayout: [";
+    for (size_t i = 0; i < otherSgLayout.size(); ++i) {
+      if (i > 0) llvm::dbgs() << ", ";
+      llvm::dbgs() << otherSgLayout[i];
+    }
+    llvm::dbgs() << "]\n";
+
+    llvm::dbgs() << "[DEBUG isTransposeOf]   this.sgData: [";
+    for (size_t i = 0; i < thisSgData.size(); ++i) {
+      if (i > 0) llvm::dbgs() << ", ";
+      llvm::dbgs() << thisSgData[i];
+    }
+    llvm::dbgs() << "]\n";
+    llvm::dbgs() << "[DEBUG isTransposeOf]   other.sgData: [";
+    for (size_t i = 0; i < otherSgData.size(); ++i) {
+      if (i > 0) llvm::dbgs() << ", ";
+      llvm::dbgs() << otherSgData[i];
+    }
+    llvm::dbgs() << "]\n";
+
+    llvm::dbgs() << "[DEBUG isTransposeOf]   this.order: [";
+    for (size_t i = 0; i < thisOrder.size(); ++i) {
+      if (i > 0) llvm::dbgs() << ", ";
+      llvm::dbgs() << thisOrder[i];
+    }
+    llvm::dbgs() << "]\n";
+    llvm::dbgs() << "[DEBUG isTransposeOf]   other.order: [";
+    for (size_t i = 0; i < otherOrder.size(); ++i) {
+      if (i > 0) llvm::dbgs() << ", ";
+      llvm::dbgs() << otherOrder[i];
+    }
+    llvm::dbgs() << "]\n";
+
+    bool sgLayoutOk = checkTranspose(thisSgLayout, otherSgLayout, perm);
+    bool sgDataOk = checkTranspose(thisSgData, otherSgData, perm);
+    bool orderOk = checkTranspose(thisOrder, otherOrder, perm);
+
+    llvm::dbgs() << "[DEBUG isTransposeOf]   sgLayout check: " << sgLayoutOk << "\n";
+    llvm::dbgs() << "[DEBUG isTransposeOf]   sgData check: " << sgDataOk << "\n";
+    llvm::dbgs() << "[DEBUG isTransposeOf]   order check: " << orderOk << "\n";
+    llvm::dbgs() << "[DEBUG isTransposeOf]   RESULT: " << (sgLayoutOk && sgDataOk && orderOk) << "\n";
+
+    return sgLayoutOk && sgDataOk && orderOk;
+  }
   if (kind == xegpu::LayoutKind::InstData)
     return checkTranspose(getEffectiveInstDataAsInt(),
                           other.getEffectiveInstDataAsInt(), perm);
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
index 4cab1e24bf9e6..dd485993b9167 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
@@ -148,6 +148,9 @@ static void propagateResultsToRegularOperands(Operation *op) {
   if (isa<VectorType>(resultType) || isa<vector::MultiDimReductionOp>(op))
     xegpu::setTemporaryLayout(result, resLayout);
 
+  if (isa<vector::DeinterleaveOp>(op))
+    xegpu::setTemporaryLayout(op->getResult(1), resLayout);
+
   for (OpOperand &opr : op->getOpOperands()) {
     xegpu::DistributeLayoutAttr operandLayout =
         xegpu::inferSourceLayoutFromResult(opr, resLayout);
@@ -528,6 +531,67 @@ xegpu::inferDeinterleaveSourceLayout(xegpu::DistributeLayoutAttr resLayout) {
   return resLayout.setDimData(dim, sgDataValue, instDataValue, laneDataValue);
 }
 
+/// Infers the source layout attribute for an extract strided slice operation
+/// given the result layout attribute, result shape, and source shape. Since the
+/// source and result are from the same lane, sg_layout and lane_layout remain
+/// the same.
+/// For dimensions where extraction occurs (source shape > result shape):
+/// - If the dimension is distributed (lane_layout > 1), lane_data stays the
+/// same
+/// - If the dimension is not distributed (lane_layout == 1), scale
+///   lane_data by the ratio of source shape to result shape
+/// scale the inst_data and sg_data by the ratio of source shape to result shape
+xegpu::DistributeLayoutAttr xegpu::inferExtractStridedSliceSourceLayout(
+    xegpu::DistributeLayoutAttr resLayout, ArrayRef<int64_t> resShape,
+    ArrayRef<int64_t> srcShape) {
+
+  SmallVector<int64_t> sgData = resLayout.getEffectiveSgDataAsInt();
+  SmallVector<int64_t> instData = resLayout.getEffectiveInstDataAsInt();
+  SmallVector<int64_t> laneData = resLayout.getEffectiveLaneDataAsInt();
+  SmallVector<int64_t> laneLayout = resLayout.getEffectiveLaneLayoutAsInt();
+
+  // Verify shapes have the same rank
+  assert(resShape.size() == srcShape.size() &&
+         "source and result must have the same rank");
+
+  auto srcLayout = resLayout;
+
+  // Loop through all dimensions and scale inst_data and lane_data
+  // where extraction occurs (srcShape[i] > resShape[i])
+  for (size_t i = 0; i < srcShape.size(); ++i) {
+    assert(srcShape[i] >= resShape[i] &&
+           "source shape must be >= result shape for extraction");
+
+    if (srcShape[i] == resShape[i])
+      continue; // No extraction on this dimension
+
+    assert(srcShape[i] % resShape[i] == 0 &&
+           "source shape must be divisible by result shape");
+
+    int64_t ratio = srcShape[i] / resShape[i];
+
+    // Check if this dimension is distributed (lane_layout > 1)
+    bool isDistributed = (laneLayout[i] > 1);
+
+    int64_t sgDataValue = -1;
+    int64_t instDataValue = -1;
+    int64_t laneDataValue = -1;
+
+    if (sgData.size())
+      sgDataValue = sgData[i] * ratio;
+    if (instData.size())
+      instDataValue = instData[i] * ratio;
+
+    if (laneData.size())
+        laneDataValue = isDistributed ? laneData[i]: laneData[i] * ratio;
+
+    srcLayout =
+        srcLayout.setDimData(i, sgDataValue, instDataValue, laneDataValue);
+  }
+
+  return srcLayout;
+}
+
 /// Infers the source layout attribute for an insert strided slice operation
 /// given the result layout attribute, result shape, and source shape. Removes
 /// leading dimensions from the result layout to match the source shape size.
@@ -1003,44 +1067,95 @@ xegpu::DistributeLayoutAttr xegpu::setupBitCastResultLayout(
   int resElemTyBitWidth = resVecTy.getElementType().getIntOrFloatBitWidth();
 
   ArrayRef<int64_t> srcShape = srcVecTy.getShape();
+  ArrayRef<int64_t> resShape = resVecTy.getShape();
   SmallVector<int64_t> sgData = consumerLayout.getEffectiveSgDataAsInt();
   SmallVector<int64_t> instData = consumerLayout.getEffectiveInstDataAsInt();
   SmallVector<int64_t> laneData = consumerLayout.getEffectiveLaneDataAsInt();
   assert(consumerLayout.getRank() == static_cast<int64_t>(srcShape.size()) &&
          "laneData must be available for all dimensions");
-  size_t dim = srcShape.size() - 1;
+  size_t innerMostDim = srcShape.size() - 1;
   int64_t sgDataValue = -1;
   int64_t instDataValue = -1;
   int64_t laneDataValue = -1;
   const int subgroupSize = uArch->getSubgroupSize();
 
+  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] ENTRY\n";
+  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] srcVecTy = " << srcVecTy
+               << "\n";
+  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] resVecTy = " << resVecTy
+               << "\n";
+  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] consumerLayout = "
+               << consumerLayout << "\n";
+  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] srcElemTyBitWidth = "
+               << srcElemTyBitWidth << "\n";
+  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] resElemTyBitWidth = "
+               << resElemTyBitWidth << "\n";
+  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] srcShape = [";
+  for (size_t i = 0; i < srcShape.size(); ++i) {
+    if (i > 0)
+      llvm::dbgs() << ", ";
+    llvm::dbgs() << srcShape[i];
+  }
+  llvm::dbgs() << "]\n";
+  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] instData from consumer = [";
+  for (size_t i = 0; i < instData.size(); ++i) {
+    if (i > 0)
+      llvm::dbgs() << ", ";
+    llvm::dbgs() << instData[i];
+  }
+  llvm::dbgs() << "]\n";
+
   if (srcElemTyBitWidth > resElemTyBitWidth) {
     // When casting to a smaller bitwidth, multiply the result layout
     // accordingly to ensure it can be divided by the ratio back to the
     // source layout.
     int bitWidthRatio = srcElemTyBitWidth / resElemTyBitWidth;
+    llvm::dbgs() << "[DEBUG setupBitCastResultLayout] bitWidthRatio = "
+                 << bitWidthRatio << "\n";
     int innermostDimLaneLayout = subgroupSize;
     if (layoutKind == xegpu::LayoutKind::Subgroup) {
-      sgDataValue = sgData[dim];
+      sgDataValue = sgData[innerMostDim];
     } else if (layoutKind == xegpu::LayoutKind::InstData) {
-      instDataValue = instData[dim];
+      instDataValue = instData[innerMostDim];
+      llvm::dbgs()
+          << "[DEBUG setupBitCastResultLayout] Initial instDataValue = "
+          << instDataValue << "\n";
+      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] srcShape[dim="
+                   << innerMostDim << "] = " << srcShape[innerMostDim] << "\n";
+      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] Adjustment condition: "
+                      "(instDataValue <= srcShape[innerMostDim]) = "
+
+                   << (instDataValue <= srcShape[innerMostDim]) << "\n";
+      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] Adjustment condition: "
+                      "(instDataValue % "
+                   << (innermostDimLaneLayout * bitWidthRatio) << ") = "
+                   << (instDataValue % (innermostDimLaneLayout * bitWidthRatio))
+                   << "\n";
       // Adjust instDataValue so it still fits within an instruction after
       // dividing by bitWidthRatio
-      while ((instDataValue <= srcShape[dim]) &&
+      while ((instDataValue <= resShape[innerMostDim]) &&
              (instDataValue % (innermostDimLaneLayout * bitWidthRatio) != 0))
         instDataValue *= 2;
-      assert((srcShape[dim] % instDataValue) == 0 &&
-             "srcShape, instData, and lanelayout for innermost must be 2^n !");
+      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] After adjustment "
+                      "instDataValue = "
+                   << instDataValue << "\n";
+      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] Final check: "
+                      "resShape[innerMostDim] % instDataValue = "
+
+                   << resShape[innerMostDim] << " % " << instDataValue << " = "
+                   << (resShape[innerMostDim] % instDataValue) << "\n";
+      assert((resShape[innerMostDim] % instDataValue) == 0 &&
+             "resShape, instData, and lanelayout for innermost must be 2^n !");
     } else if (layoutKind == xegpu::LayoutKind::Lane) {
-      laneDataValue = laneData[dim];
-      while ((laneDataValue <= srcShape[dim]) &&
+      laneDataValue = laneData[innerMostDim];
+      while ((laneDataValue <= resShape[innerMostDim]) &&
              (laneDataValue % bitWidthRatio != 0))
         laneDataValue *= 2;
     }
     // Now set only instData and laneData, preserving sgData
     xegpu::DistributeLayoutAttr resLayout;
-    resLayout = consumerLayout.setDimData(dim, sgDataValue, instDataValue,
-                                          laneDataValue);
+    resLayout = consumerLayout.setDimData(innerMostDim, sgDataValue,
+                                          instDataValue, laneDataValue);
     return resLayout;
   }
   return consumerLayout;
@@ -1066,6 +1181,7 @@ xegpu::DistributeLayoutAttr xegpu::setupInterleaveResultLayout(
     DistributeLayoutAttr consumerLayout, const xegpu::uArch::uArch *uArch) {
 
   ArrayRef<int64_t> srcShape = srcVecTy.getShape();
+  ArrayRef<int64_t> resShape = resVecTy.getShape();
   SmallVector<int64_t> sgData = consumerLayout.getEffectiveSgDataAsInt();
   SmallVector<int64_t> instData = consumerLayout.getEffectiveInstDataAsInt();
   SmallVector<int64_t> laneData = consumerLayout.getEffectiveLaneDataAsInt();
@@ -1083,24 +1199,20 @@ xegpu::DistributeLayoutAttr xegpu::setupInterleaveResultLayout(
 
   if (layoutKind == xegpu::LayoutKind::Subgroup) {
     sgDataValue = sgData[innerMostDim];
-    // Ensure sgDataValue is divisible by ratio so source sgData can be inferred
-    while ((sgDataValue <= srcShape[innerMostDim]) &&
-           (sgDataValue % ratio != 0))
-      sgDataValue *= ratio;
   } else if (layoutKind == xegpu::LayoutKind::InstData) {
     instDataValue = instData[innerMostDim];
     // Adjust instDataValue so it can be divided by (innermostDimLaneLayout *
     // ratio) when inferring the source layout
-    while ((instDataValue <= srcShape[innerMostDim]) &&
+    while ((instDataValue <= resShape[innerMostDim]) &&
            (instDataValue % (innermostDimLaneLayout * ratio) != 0))
       instDataValue *= ratio;
-    assert((srcShape[innerMostDim] % instDataValue) == 0 &&
-           "srcShape, instData, and laneLayout for innermost must be 2^n!");
+    assert((resShape[innerMostDim] % instDataValue) == 0 &&
+           "resShape, instData, and laneLayout for innermost must be 2^n!");
   } else if (layoutKind == xegpu::LayoutKind::Lane) {
     laneDataValue = laneData[innerMostDim];
     // Ensure laneDataValue is at least 2 and divisible by ratio
     // so that source laneData = laneDataValue/2 is valid
-    while ((laneDataValue <= srcShape[innerMostDim]) &&
+    while ((laneDataValue <= resShape[innerMostDim]) &&
            (laneDataValue % ratio != 0))
       laneDataValue *= ratio;
   }
@@ -1884,9 +1996,17 @@ xegpu::inferSourceLayoutFromResult(OpOperand &operand,
     return xegpu::inferDeinterleaveSourceLayout(resLayout);
   }
 
-  // For vector::ExtractStridedSliceOp, simply return result layout
-  if (dyn_cast<vector::ExtractStridedSliceOp>(op))
-    return resLayout;
+  // For vector::ExtractStridedSliceOp, infer source layout from result layout
+  // using shapes
+  if (auto extractSlice = dyn_cast<vector::ExtractStridedSliceOp>(op)) {
+    VectorType srcVecTy = extractSlice.getSourceVectorType();
+    VectorType resVecTy =
+        dyn_cast<VectorType>(extractSlice.getResult().getType());
+    if (!srcVecTy || !resVecTy)
+      return nullptr;
+    return xegpu::inferExtractStridedSliceSourceLayout(
+        resLayout, resVecTy.getShape(), srcVecTy.getShape());
+  }
   // For elementwise operations, all operands must have the same layout as the
   // result.
   if (OpTrait::hasElementwiseMappableTraits(op) && op->getNumResults() == 1)
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
index 9c63beda281ad..7b9df03fad1a9 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
@@ -1101,11 +1101,18 @@ void LayoutInfoPropagation::visitVectorBitcastOp(
   auto srcVecType = bitcast.getSourceVectorType();
   auto resVecType = bitcast.getResultVectorType();
 
+  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] bitcast op: " << bitcast << "\n";
+  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] srcVecType: " << srcVecType << "\n";
+  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] resVecType: " << resVecType << "\n";
+
   auto consumerLayoutAttr =
       dyn_cast<xegpu::DistributeLayoutAttr>(resLayoutInfo.get());
+  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] consumerLayoutAttr: " << consumerLayoutAttr << "\n";
+
   const uArch *uArch = getUArch(xegpu::getChipStr(bitcast).value_or(""));
   if (!uArch)
     return;
+  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] About to call setupBitCastResultLayout...\n";
   auto requiredResLayoutAttr = setupBitCastResultLayout(
       layoutKind, srcVecType, resVecType, consumerLayoutAttr, uArch);
 
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp
index 119ec59daf765..7fae3c2bee879 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp
@@ -1337,19 +1337,36 @@ struct WgToSgVectorTransposeOp
   LogicalResult
   matchAndRewrite(vector::TransposeOp op, OneToNOpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] ENTRY for op: " << op << "\n";
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] adaptor.getVector().size() = " << adaptor.getVector().size() << "\n";
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] op.getVector() = " << op.getVector() << "\n";
     VectorType resultType = op.getResultVectorType();
 
     ArrayRef<int64_t> wgShape = resultType.getShape();
     xegpu::DistributeLayoutAttr layout =
         xegpu::getTemporaryLayout(dyn_cast<OpResult>(op.getResult()));
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] layout = " << layout << "\n";
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] layout.isForWorkgroup() = " << (layout ? layout.isForWorkgroup() : false) << "\n";
     if (!layout || !layout.isForWorkgroup())
       return failure();
     // TODO-LayoutRefactor: handle the case using getTemporaryLayout
     xegpu::DistributeLayoutAttr sourceLayout =
         xegpu::getDistributeLayoutAttr(op.getVector());
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] sourceLayout = " << sourceLayout << "\n";
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] sourceLayout.isForWorkgroup() = " << (sourceLayout ? sourceLayout.isForWorkgroup() : false) << "\n";
     if (!sourceLayout || !sourceLayout.isForWorkgroup())
       return failure();
 
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] transpose op: " << op << "\n";
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] sourceLayout: " << sourceLayout << "\n";
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] resultLayout: " << layout << "\n";
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] permutation: [";
+    for (size_t i = 0; i < op.getPermutation().size(); ++i) {
+      if (i > 0) llvm::dbgs() << ", ";
+      llvm::dbgs() << op.getPermutation()[i];
+    }
+    llvm::dbgs() << "]\n";
+
     SmallVector<int64_t> sourceSgLayout =
         sourceLayout.getEffectiveSgLayoutAsInt();
     SmallVector<int64_t> resultSgLayout = layout.getEffectiveSgLayoutAsInt();
@@ -1364,8 +1381,11 @@ struct WgToSgVectorTransposeOp
 
     // Check that sgLayout, sgData & order are properly transposed for source
     // and result
-    if (!layout.isTransposeOf(sourceLayout, permutation,
-                              xegpu::LayoutKind::Subgroup))
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] About to check isTransposeOf...\n";
+    bool isValidTranspose = layout.isTransposeOf(sourceLayout, permutation,
+                              xegpu::LayoutKind::Subgroup);
+    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] isTransposeOf result: " << isValidTranspose << "\n";
+    if (!isValidTranspose)
       return rewriter.notifyMatchFailure(
           op, "Result layout is not a valid transpose of source layout "
               "according to permutation");

>From 18d9732b005e2c20dc664d57964b4a6a04e6793c Mon Sep 17 00:00:00 2001
From: Jianhui Li <jian.hui.li at intel.com>
Date: Thu, 7 May 2026 05:16:36 +0000
Subject: [PATCH 3/5] [XeGPU] Remove debug print statements from layout passes

Remove all llvm::dbgs() debug instrumentation that was added during
development. The actual logic fixes are preserved.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply at anthropic.com>
---
 mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp    |  77 +----------
 .../XeGPU/Transforms/XeGPULayoutImpl.cpp      | 125 +-----------------
 .../XeGPU/Transforms/XeGPUPropagateLayout.cpp |   6 -
 .../Transforms/XeGPUWgToSgDistribute.cpp      |  24 +---
 4 files changed, 12 insertions(+), 220 deletions(-)

diff --git a/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp b/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp
index f1b83d5e1474a..e92b109c2223e 100644
--- a/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp
+++ b/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp
@@ -682,17 +682,6 @@ DistributeLayoutAttr LayoutAttr::transposeDims(ArrayRef<int64_t> permutation) {
 bool LayoutAttr::isTransposeOf(const xegpu::DistributeLayoutAttr &other,
                                ArrayRef<int64_t> perm,
                                const xegpu::LayoutKind kind) {
-  llvm::dbgs() << "[DEBUG isTransposeOf] ENTRY\n";
-  llvm::dbgs() << "[DEBUG isTransposeOf] this layout: " << *this << "\n";
-  llvm::dbgs() << "[DEBUG isTransposeOf] other layout: " << other << "\n";
-  llvm::dbgs() << "[DEBUG isTransposeOf] kind: " << static_cast<int>(kind) << " (0=Subgroup, 1=InstData, 2=Lane)\n";
-  llvm::dbgs() << "[DEBUG isTransposeOf] permutation: [";
-  for (size_t i = 0; i < perm.size(); ++i) {
-    if (i > 0) llvm::dbgs() << ", ";
-    llvm::dbgs() << perm[i];
-  }
-  llvm::dbgs() << "]\n";
-
   if (!other)
     return false;
   if (getRank() != other.getRank() ||
@@ -708,65 +697,13 @@ bool LayoutAttr::isTransposeOf(const xegpu::DistributeLayoutAttr &other,
     }
     return true;
   };
-  if (kind == xegpu::LayoutKind::Subgroup) {
-    auto thisSgLayout = getEffectiveSgLayoutAsInt();
-    auto otherSgLayout = other.getEffectiveSgLayoutAsInt();
-    auto thisSgData = getEffectiveSgDataAsInt();
-    auto otherSgData = other.getEffectiveSgDataAsInt();
-    auto thisOrder = getEffectiveOrderAsInt();
-    auto otherOrder = other.getEffectiveOrderAsInt();
-
-    llvm::dbgs() << "[DEBUG isTransposeOf] Checking Subgroup level:\n";
-    llvm::dbgs() << "[DEBUG isTransposeOf]   this.sgLayout: [";
-    for (size_t i = 0; i < thisSgLayout.size(); ++i) {
-      if (i > 0) llvm::dbgs() << ", ";
-      llvm::dbgs() << thisSgLayout[i];
-    }
-    llvm::dbgs() << "]\n";
-    llvm::dbgs() << "[DEBUG isTransposeOf]   other.sgLayout: [";
-    for (size_t i = 0; i < otherSgLayout.size(); ++i) {
-      if (i > 0) llvm::dbgs() << ", ";
-      llvm::dbgs() << otherSgLayout[i];
-    }
-    llvm::dbgs() << "]\n";
-
-    llvm::dbgs() << "[DEBUG isTransposeOf]   this.sgData: [";
-    for (size_t i = 0; i < thisSgData.size(); ++i) {
-      if (i > 0) llvm::dbgs() << ", ";
-      llvm::dbgs() << thisSgData[i];
-    }
-    llvm::dbgs() << "]\n";
-    llvm::dbgs() << "[DEBUG isTransposeOf]   other.sgData: [";
-    for (size_t i = 0; i < otherSgData.size(); ++i) {
-      if (i > 0) llvm::dbgs() << ", ";
-      llvm::dbgs() << otherSgData[i];
-    }
-    llvm::dbgs() << "]\n";
-
-    llvm::dbgs() << "[DEBUG isTransposeOf]   this.order: [";
-    for (size_t i = 0; i < thisOrder.size(); ++i) {
-      if (i > 0) llvm::dbgs() << ", ";
-      llvm::dbgs() << thisOrder[i];
-    }
-    llvm::dbgs() << "]\n";
-    llvm::dbgs() << "[DEBUG isTransposeOf]   other.order: [";
-    for (size_t i = 0; i < otherOrder.size(); ++i) {
-      if (i > 0) llvm::dbgs() << ", ";
-      llvm::dbgs() << otherOrder[i];
-    }
-    llvm::dbgs() << "]\n";
-
-    bool sgLayoutOk = checkTranspose(thisSgLayout, otherSgLayout, perm);
-    bool sgDataOk = checkTranspose(thisSgData, otherSgData, perm);
-    bool orderOk = checkTranspose(thisOrder, otherOrder, perm);
-
-    llvm::dbgs() << "[DEBUG isTransposeOf]   sgLayout check: " << sgLayoutOk << "\n";
-    llvm::dbgs() << "[DEBUG isTransposeOf]   sgData check: " << sgDataOk << "\n";
-    llvm::dbgs() << "[DEBUG isTransposeOf]   order check: " << orderOk << "\n";
-    llvm::dbgs() << "[DEBUG isTransposeOf]   RESULT: " << (sgLayoutOk && sgDataOk && orderOk) << "\n";
-
-    return sgLayoutOk && sgDataOk && orderOk;
-  }
+  if (kind == xegpu::LayoutKind::Subgroup)
+    return checkTranspose(getEffectiveSgLayoutAsInt(),
+                          other.getEffectiveSgLayoutAsInt(), perm) &&
+           checkTranspose(getEffectiveSgDataAsInt(),
+                          other.getEffectiveSgDataAsInt(), perm) &&
+           checkTranspose(getEffectiveOrderAsInt(),
+                          other.getEffectiveOrderAsInt(), perm);
   if (kind == xegpu::LayoutKind::InstData)
     return checkTranspose(getEffectiveInstDataAsInt(),
                           other.getEffectiveInstDataAsInt(), perm);
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
index dd485993b9167..cf898629f91ef 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
@@ -531,67 +531,6 @@ xegpu::inferDeinterleaveSourceLayout(xegpu::DistributeLayoutAttr resLayout) {
   return resLayout.setDimData(dim, sgDataValue, instDataValue, laneDataValue);
 }
 
-/// Infers the source layout attribute for an extract strided slice operation
-/// given the result layout attribute, result shape, and source shape. Since the
-/// source and result are from the same lane, sg_layout and lane_layout remain
-/// the same.
-/// For dimensions where extraction occurs (source shape > result shape):
-/// - If the dimension is distributed (lane_layout > 1), lane_data stays the
-/// same
-/// - If the dimension is not distributed (lane_layout == 1), scale
-///   lane_data by the ratio of source shape to result shape
-/// scale the inst_data and sg_data by the ratio of source shape to result shape
-xegpu::DistributeLayoutAttr xegpu::inferExtractStridedSliceSourceLayout(
-    xegpu::DistributeLayoutAttr resLayout, ArrayRef<int64_t> resShape,
-    ArrayRef<int64_t> srcShape) {
-
-  SmallVector<int64_t> sgData = resLayout.getEffectiveSgDataAsInt();
-  SmallVector<int64_t> instData = resLayout.getEffectiveInstDataAsInt();
-  SmallVector<int64_t> laneData = resLayout.getEffectiveLaneDataAsInt();
-  SmallVector<int64_t> laneLayout = resLayout.getEffectiveLaneLayoutAsInt();
-
-  // Verify shapes have the same rank
-  assert(resShape.size() == srcShape.size() &&
-         "source and result must have the same rank");
-
-  auto srcLayout = resLayout;
-
-  // Loop through all dimensions and scale inst_data and lane_data
-  // where extraction occurs (srcShape[i] > resShape[i])
-  for (size_t i = 0; i < srcShape.size(); ++i) {
-    assert(srcShape[i] >= resShape[i] &&
-           "source shape must be >= result shape for extraction");
-
-    if (srcShape[i] == resShape[i])
-      continue; // No extraction on this dimension
-
-    assert(srcShape[i] % resShape[i] == 0 &&
-           "source shape must be divisible by result shape");
-
-    int64_t ratio = srcShape[i] / resShape[i];
-
-    // Check if this dimension is distributed (lane_layout > 1)
-    bool isDistributed = (laneLayout[i] > 1);
-
-    int64_t sgDataValue = -1;
-    int64_t instDataValue = -1;
-    int64_t laneDataValue = -1;
-
-    if (sgData.size())
-      sgDataValue = sgData[i] * ratio;
-    if (instData.size())
-      instDataValue = instData[i] * ratio;
-
-    if (laneData.size())
-        laneDataValue = isDistributed ? laneData[i]: laneData[i] * ratio;
-
-    srcLayout =
-        srcLayout.setDimData(i, sgDataValue, instDataValue, laneDataValue);
-  }
-
-  return srcLayout;
-}
-
 /// Infers the source layout attribute for an insert strided slice operation
 /// given the result layout attribute, result shape, and source shape. Removes
 /// leading dimensions from the result layout to match the source shape size.
@@ -1079,71 +1018,21 @@ xegpu::DistributeLayoutAttr xegpu::setupBitCastResultLayout(
   int64_t laneDataValue = -1;
   const int subgroupSize = uArch->getSubgroupSize();
 
-  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] ENTRY\n";
-  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] srcVecTy = " << srcVecTy
-               << "\n";
-  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] resVecTy = " << resVecTy
-               << "\n";
-  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] consumerLayout = "
-               << consumerLayout << "\n";
-  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] srcElemTyBitWidth = "
-               << srcElemTyBitWidth << "\n";
-  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] resElemTyBitWidth = "
-               << resElemTyBitWidth << "\n";
-  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] srcShape = [";
-  for (size_t i = 0; i < srcShape.size(); ++i) {
-    if (i > 0)
-      llvm::dbgs() << ", ";
-    llvm::dbgs() << srcShape[i];
-  }
-  llvm::dbgs() << "]\n";
-  llvm::dbgs() << "[DEBUG setupBitCastResultLayout] instData from consumer = [";
-  for (size_t i = 0; i < instData.size(); ++i) {
-    if (i > 0)
-      llvm::dbgs() << ", ";
-    llvm::dbgs() << instData[i];
-  }
-  llvm::dbgs() << "]\n";
-
   if (srcElemTyBitWidth > resElemTyBitWidth) {
     // When casting to a smaller bitwidth, multiply the result layout
     // accordingly to ensure it can be divided by the ratio back to the
     // source layout.
     int bitWidthRatio = srcElemTyBitWidth / resElemTyBitWidth;
-    llvm::dbgs() << "[DEBUG setupBitCastResultLayout] bitWidthRatio = "
-                 << bitWidthRatio << "\n";
     int innermostDimLaneLayout = subgroupSize;
     if (layoutKind == xegpu::LayoutKind::Subgroup) {
       sgDataValue = sgData[innerMostDim];
     } else if (layoutKind == xegpu::LayoutKind::InstData) {
       instDataValue = instData[innerMostDim];
-      llvm::dbgs()
-          << "[DEBUG setupBitCastResultLayout] Initial instDataValue = "
-          << instDataValue << "\n";
-      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] srcShape[dim="
-                   << innerMostDim << "] = " << srcShape[innerMostDim] << "\n";
-      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] Adjustment condition: "
-                      "(instDataValue <= srcShape[innerMostDim]) = "
-
-                   << (instDataValue <= srcShape[innerMostDim]) << "\n";
-      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] Adjustment condition: "
-                      "(instDataValue % "
-                   << (innermostDimLaneLayout * bitWidthRatio) << ") = "
-                   << (instDataValue % (innermostDimLaneLayout * bitWidthRatio))
-                   << "\n";
       // Adjust instDataValue so it still fits within an instruction after
       // dividing by bitWidthRatio
       while ((instDataValue <= resShape[innerMostDim]) &&
              (instDataValue % (innermostDimLaneLayout * bitWidthRatio) != 0))
         instDataValue *= 2;
-      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] After adjustment "
-                      "instDataValue = "
-                   << instDataValue << "\n";
-      llvm::dbgs() << "[DEBUG setupBitCastResultLayout] Final check: "
-                      "resShape[innerMostDim] % instDataValue = "
-
-                   << resShape[innerMostDim] << " % " << instDataValue << " = "
-                   << (resShape[innerMostDim] % instDataValue) << "\n";
       assert((resShape[innerMostDim] % instDataValue) == 0 &&
              "resShape, instData, and lanelayout for innermost must be 2^n !");
     } else if (layoutKind == xegpu::LayoutKind::Lane) {
@@ -1996,17 +1885,9 @@ xegpu::inferSourceLayoutFromResult(OpOperand &operand,
     return xegpu::inferDeinterleaveSourceLayout(resLayout);
   }
 
-  // For vector::ExtractStridedSliceOp, infer source layout from result layout
-  // using shapes
-  if (auto extractSlice = dyn_cast<vector::ExtractStridedSliceOp>(op)) {
-    VectorType srcVecTy = extractSlice.getSourceVectorType();
-    VectorType resVecTy =
-        dyn_cast<VectorType>(extractSlice.getResult().getType());
-    if (!srcVecTy || !resVecTy)
-      return nullptr;
-    return xegpu::inferExtractStridedSliceSourceLayout(
-        resLayout, resVecTy.getShape(), srcVecTy.getShape());
-  }
+  // For vector::ExtractStridedSliceOp, simply return result layout
+  if (dyn_cast<vector::ExtractStridedSliceOp>(op))
+    return resLayout;
   // For elementwise operations, all operands must have the same layout as the
   // result.
   if (OpTrait::hasElementwiseMappableTraits(op) && op->getNumResults() == 1)
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
index 7b9df03fad1a9..b91a629a2fce0 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
@@ -1101,18 +1101,12 @@ void LayoutInfoPropagation::visitVectorBitcastOp(
   auto srcVecType = bitcast.getSourceVectorType();
   auto resVecType = bitcast.getResultVectorType();
 
-  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] bitcast op: " << bitcast << "\n";
-  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] srcVecType: " << srcVecType << "\n";
-  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] resVecType: " << resVecType << "\n";
-
   auto consumerLayoutAttr =
       dyn_cast<xegpu::DistributeLayoutAttr>(resLayoutInfo.get());
-  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] consumerLayoutAttr: " << consumerLayoutAttr << "\n";
 
   const uArch *uArch = getUArch(xegpu::getChipStr(bitcast).value_or(""));
   if (!uArch)
     return;
-  llvm::dbgs() << "[DEBUG visitVectorBitcastOp] About to call setupBitCastResultLayout...\n";
   auto requiredResLayoutAttr = setupBitCastResultLayout(
       layoutKind, srcVecType, resVecType, consumerLayoutAttr, uArch);
 
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp
index 7fae3c2bee879..119ec59daf765 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUWgToSgDistribute.cpp
@@ -1337,36 +1337,19 @@ struct WgToSgVectorTransposeOp
   LogicalResult
   matchAndRewrite(vector::TransposeOp op, OneToNOpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] ENTRY for op: " << op << "\n";
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] adaptor.getVector().size() = " << adaptor.getVector().size() << "\n";
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] op.getVector() = " << op.getVector() << "\n";
     VectorType resultType = op.getResultVectorType();
 
     ArrayRef<int64_t> wgShape = resultType.getShape();
     xegpu::DistributeLayoutAttr layout =
         xegpu::getTemporaryLayout(dyn_cast<OpResult>(op.getResult()));
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] layout = " << layout << "\n";
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] layout.isForWorkgroup() = " << (layout ? layout.isForWorkgroup() : false) << "\n";
     if (!layout || !layout.isForWorkgroup())
       return failure();
     // TODO-LayoutRefactor: handle the case using getTemporaryLayout
     xegpu::DistributeLayoutAttr sourceLayout =
         xegpu::getDistributeLayoutAttr(op.getVector());
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] sourceLayout = " << sourceLayout << "\n";
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] sourceLayout.isForWorkgroup() = " << (sourceLayout ? sourceLayout.isForWorkgroup() : false) << "\n";
     if (!sourceLayout || !sourceLayout.isForWorkgroup())
       return failure();
 
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] transpose op: " << op << "\n";
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] sourceLayout: " << sourceLayout << "\n";
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] resultLayout: " << layout << "\n";
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] permutation: [";
-    for (size_t i = 0; i < op.getPermutation().size(); ++i) {
-      if (i > 0) llvm::dbgs() << ", ";
-      llvm::dbgs() << op.getPermutation()[i];
-    }
-    llvm::dbgs() << "]\n";
-
     SmallVector<int64_t> sourceSgLayout =
         sourceLayout.getEffectiveSgLayoutAsInt();
     SmallVector<int64_t> resultSgLayout = layout.getEffectiveSgLayoutAsInt();
@@ -1381,11 +1364,8 @@ struct WgToSgVectorTransposeOp
 
     // Check that sgLayout, sgData & order are properly transposed for source
     // and result
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] About to check isTransposeOf...\n";
-    bool isValidTranspose = layout.isTransposeOf(sourceLayout, permutation,
-                              xegpu::LayoutKind::Subgroup);
-    llvm::dbgs() << "[DEBUG WgToSgVectorTransposeOp] isTransposeOf result: " << isValidTranspose << "\n";
-    if (!isValidTranspose)
+    if (!layout.isTransposeOf(sourceLayout, permutation,
+                              xegpu::LayoutKind::Subgroup))
       return rewriter.notifyMatchFailure(
           op, "Result layout is not a valid transpose of source layout "
               "according to permutation");

>From 68b52a0b1e0c84aeba4768596d9e9288b31fbbb5 Mon Sep 17 00:00:00 2001
From: Jianhui Li <jian.hui.li at intel.com>
Date: Thu, 7 May 2026 05:18:25 +0000
Subject: [PATCH 4/5] add tests

---
 .../XeGPU/Transforms/XeGPULayoutImpl.h        |  7 --
 .../Dialect/XeGPU/WG/simple_mxfp_gemm.mlir    | 73 +++++++++++++++++++
 2 files changed, 73 insertions(+), 7 deletions(-)
 create mode 100644 mlir/test/Integration/Dialect/XeGPU/WG/simple_mxfp_gemm.mlir

diff --git a/mlir/include/mlir/Dialect/XeGPU/Transforms/XeGPULayoutImpl.h b/mlir/include/mlir/Dialect/XeGPU/Transforms/XeGPULayoutImpl.h
index 24e65f3a2e4fd..299f9f18e3be6 100644
--- a/mlir/include/mlir/Dialect/XeGPU/Transforms/XeGPULayoutImpl.h
+++ b/mlir/include/mlir/Dialect/XeGPU/Transforms/XeGPULayoutImpl.h
@@ -133,13 +133,6 @@ DistributeLayoutAttr inferExtractSourceLayout(DistributeLayoutAttr resLayout,
                                               ArrayRef<int64_t> resShape,
                                               ArrayRef<int64_t> srcShape);
 
-/// Infers the source layout attribute for an extract strided slice operation.
-/// Source and result have the same rank and same lane distribution. The innermost
-/// dimension of inst_data and lane_data are scaled by the ratio of source to result shapes.
-DistributeLayoutAttr inferExtractStridedSliceSourceLayout(DistributeLayoutAttr resLayout,
-                                                          ArrayRef<int64_t> resShape,
-                                                          ArrayRef<int64_t> srcShape);
-
 /// Infers the layout attribute for mask and offset operand for Chunked load
 /// and store, given the anchor layout attribute for the value being load/store.
 DistributeLayoutAttr
diff --git a/mlir/test/Integration/Dialect/XeGPU/WG/simple_mxfp_gemm.mlir b/mlir/test/Integration/Dialect/XeGPU/WG/simple_mxfp_gemm.mlir
new file mode 100644
index 0000000000000..d4f9e08019ead
--- /dev/null
+++ b/mlir/test/Integration/Dialect/XeGPU/WG/simple_mxfp_gemm.mlir
@@ -0,0 +1,73 @@
+// RUN: mlir-opt %s --gpu-lower-to-xevm-pipeline="xegpu-op-level=lane zebin-chip=cri" \
+// RUN: | mlir-runner \
+// RUN:   --shared-libs=%mlir_levelzero_runtime \
+// RUN:   --shared-libs=%mlir_runner_utils \
+// RUN:   --shared-libs=%mlir_c_runner_utils \
+// RUN:   --entry-point-result=void \
+// RUN: | FileCheck %s
+
+// XFAIL: *
+#a = #xegpu.layout<sg_layout = [8, 8], sg_data = [16, 512], inst_data = [8, 64], lane_layout = [1, 16], lane_data = [1, 1]>
+#b_packed = #xegpu.layout<sg_layout = [8, 8], sg_data = [256, 16], inst_data = [32, 16], lane_layout = [1, 16], lane_data = [4, 1]>
+#b = #xegpu.layout<sg_layout = [8, 8], sg_data = [512, 16], inst_data = [64, 16], lane_layout = [1, 16], lane_data = [8, 1]>
+#c = #xegpu.layout<sg_layout = [8, 8], sg_data = [16, 16], inst_data = [8, 16], lane_layout = [1, 16], lane_data = [1, 1]>
+#a_scale = #xegpu.layout<sg_layout = [8, 8], sg_data = [16, 16], inst_data = [8, 2], lane_layout = [8, 1], lane_data = [1, 1]>
+#b_scale = #xegpu.layout<sg_layout = [8, 8], sg_data = [16, 16], inst_data = [2, 16], lane_layout = [1, 16], lane_data = [1, 1]>
+
+gpu.module @test {
+  gpu.func @gemm_mxfp(%arg0: memref<1024x4096xf4E2M1FN>, %arg1: memref<2048x1024xui8>, %arg2: memref<1024x128xf8E8M0FNU>, %arg3: memref<128x1024xf8E8M0FNU>, %arg4: memref<1024x1024xf32>) {
+    %c0 = arith.constant 0 : index
+    %c4 = arith.constant 4 : index
+    %c128 = arith.constant 128 : index
+    %c1024 = arith.constant 1024 : index
+    %block_id_x = gpu.block_id x
+    %block_id_y = gpu.block_id y
+    %0 = arith.muli %block_id_x, %c128 : index
+    %1 = arith.muli %block_id_y, %c128 : index
+
+    %a_tdesc = xegpu.create_nd_tdesc %arg0 : memref<1024x4096xf4E2M1FN> -> !xegpu.tensor_desc<128x512xf4E2M1FN>
+    %bp_tdesc = xegpu.create_nd_tdesc %arg1 : memref<2048x1024xui8> -> !xegpu.tensor_desc<256x128xui8>
+    // load_nd with offset
+    %a = xegpu.load_nd %a_tdesc[%0, %c0] {layout = #a}: !xegpu.tensor_desc<128x512xf4E2M1FN> -> vector<128x512xf4E2M1FN>
+    %bp = xegpu.load_nd %bp_tdesc[%c0, %1] {layout = #b_packed}: !xegpu.tensor_desc<256x128xui8> -> vector<256x128xui8>
+
+    // Bitcast to fp4: 256x128 uint8 -> 256x256 fp4 (each uint8 holds 2 fp4 values)
+    %b_bitcast = vector.bitcast %bp : vector<256x128xui8> to vector<256x256xf4E2M1FN>
+
+    // De-interleave: extract even and odd columns
+    // Even columns (indices 0, 2, 4, ..., 254) -> first half
+    // Odd columns (indices 1, 3, 5, ..., 255) -> second half
+    %b_even, %b_odd = vector.deinterleave %b_bitcast : vector<256x256xf4E2M1FN> -> vector<256x128xf4E2M1FN>
+
+    // Reconstruct 512x128 by interleaving even/odd rows:
+    // Transpose to move the row dim to trailing position, interleave, transpose back.
+    %b_even_t = vector.transpose %b_even, [1, 0] : vector<256x128xf4E2M1FN> to vector<128x256xf4E2M1FN>
+    %b_odd_t = vector.transpose %b_odd, [1, 0] : vector<256x128xf4E2M1FN> to vector<128x256xf4E2M1FN>
+    %b_interleaved = vector.interleave %b_even_t, %b_odd_t : vector<128x256xf4E2M1FN> -> vector<128x512xf4E2M1FN>
+    %b = vector.transpose %b_interleaved, [1, 0] : vector<128x512xf4E2M1FN> to vector<512x128xf4E2M1FN>
+
+    %cd_tdesc = xegpu.create_nd_tdesc %arg4 : memref<1024x1024xf32> -> !xegpu.tensor_desc<128x128xf32, #c>
+    %c = xegpu.load_nd %cd_tdesc[%0, %1] {layout = #c}: !xegpu.tensor_desc<128x128xf32, #c> -> vector<128x128xf32>
+
+    %a_scale_tdesc = xegpu.create_nd_tdesc %arg2 : memref<1024x128xf8E8M0FNU> -> !xegpu.tensor_desc<128x16xf8E8M0FNU>
+    %scale_a = xegpu.load_nd %a_scale_tdesc[%0, %c0] {layout = #a_scale}: !xegpu.tensor_desc<128x16xf8E8M0FNU> -> vector<128x16xf8E8M0FNU>
+
+    %b_scale_tdesc = xegpu.create_nd_tdesc %arg3 : memref<128x1024xf8E8M0FNU> -> !xegpu.tensor_desc<16x128xf8E8M0FNU>
+    %scale_b = xegpu.load_nd %b_scale_tdesc[%c0, %1] {layout = #b_scale}: !xegpu.tensor_desc<16x128xf8E8M0FNU> -> vector<16x128xf8E8M0FNU>
+
+    %d = xegpu.dpas_mx %a, %b, %c scale_a = %scale_a scale_b = %scale_b
+          {layout_a = #a,
+           layout_b = #b,
+           layout_cd = #c,
+           layout_a_scale = #a_scale,
+           layout_b_scale = #b_scale}
+        : vector<128x512xf4E2M1FN>, vector<512x128xf4E2M1FN>,
+          vector<128x128xf32>,
+          vector<128x16xf8E8M0FNU>, vector<16x128xf8E8M0FNU>
+        -> vector<128x128xf32>
+
+    // store_nd with offset
+    xegpu.store_nd %d, %cd_tdesc[%0, %1] {layout = #c} : vector<128x128xf32>, !xegpu.tensor_desc<128x128xf32, #c>
+    gpu.return
+  }
+}

>From 381bfba0ce1f03a8681f5d6bdee0324e8624ed98 Mon Sep 17 00:00:00 2001
From: Jianhui Li <jian.hui.li at intel.com>
Date: Thu, 7 May 2026 05:34:45 +0000
Subject: [PATCH 5/5] polish

---
 .../XeGPU/Transforms/XeGPULayoutImpl.cpp      | 23 +++++++++++--------
 .../XeGPU/Transforms/XeGPUPropagateLayout.cpp |  1 -
 2 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
index cf898629f91ef..156c10b4118a1 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPULayoutImpl.cpp
@@ -1012,12 +1012,11 @@ xegpu::DistributeLayoutAttr xegpu::setupBitCastResultLayout(
   SmallVector<int64_t> laneData = consumerLayout.getEffectiveLaneDataAsInt();
   assert(consumerLayout.getRank() == static_cast<int64_t>(srcShape.size()) &&
          "laneData must be available for all dimensions");
-  size_t innerMostDim = srcShape.size() - 1;
+  size_t dim = srcShape.size() - 1;
   int64_t sgDataValue = -1;
   int64_t instDataValue = -1;
   int64_t laneDataValue = -1;
   const int subgroupSize = uArch->getSubgroupSize();
-
   if (srcElemTyBitWidth > resElemTyBitWidth) {
     // When casting to a smaller bitwidth, multiply the result layout
     // accordingly to ensure it can be divided by the ratio back to the
@@ -1025,26 +1024,26 @@ xegpu::DistributeLayoutAttr xegpu::setupBitCastResultLayout(
     int bitWidthRatio = srcElemTyBitWidth / resElemTyBitWidth;
     int innermostDimLaneLayout = subgroupSize;
     if (layoutKind == xegpu::LayoutKind::Subgroup) {
-      sgDataValue = sgData[innerMostDim];
+      sgDataValue = sgData[dim];
     } else if (layoutKind == xegpu::LayoutKind::InstData) {
-      instDataValue = instData[innerMostDim];
+      instDataValue = instData[dim];
       // Adjust instDataValue so it still fits within an instruction after
       // dividing by bitWidthRatio
-      while ((instDataValue <= resShape[innerMostDim]) &&
+      while ((instDataValue <= resShape[dim]) &&
              (instDataValue % (innermostDimLaneLayout * bitWidthRatio) != 0))
         instDataValue *= 2;
-      assert((resShape[innerMostDim] % instDataValue) == 0 &&
+      assert((resShape[dim] % instDataValue) == 0 &&
              "resShape, instData, and lanelayout for innermost must be 2^n !");
     } else if (layoutKind == xegpu::LayoutKind::Lane) {
-      laneDataValue = laneData[innerMostDim];
-      while ((laneDataValue <= resShape[innerMostDim]) &&
+      laneDataValue = laneData[dim];
+      while ((laneDataValue <= resShape[dim]) &&
              (laneDataValue % bitWidthRatio != 0))
         laneDataValue *= 2;
     }
     // Now set only instData and laneData, preserving sgData
     xegpu::DistributeLayoutAttr resLayout;
-    resLayout = consumerLayout.setDimData(innerMostDim, sgDataValue,
-                                          instDataValue, laneDataValue);
+    resLayout = consumerLayout.setDimData(dim, sgDataValue, instDataValue,
+                                          laneDataValue);
     return resLayout;
   }
   return consumerLayout;
@@ -1088,6 +1087,10 @@ xegpu::DistributeLayoutAttr xegpu::setupInterleaveResultLayout(
 
   if (layoutKind == xegpu::LayoutKind::Subgroup) {
     sgDataValue = sgData[innerMostDim];
+    // Ensure sgDataValue is divisible by ratio so source sgData can be inferred
+    while ((sgDataValue <= resShape[innerMostDim]) &&
+           (sgDataValue % ratio != 0))
+      sgDataValue *= ratio;
   } else if (layoutKind == xegpu::LayoutKind::InstData) {
     instDataValue = instData[innerMostDim];
     // Adjust instDataValue so it can be divided by (innermostDimLaneLayout *
diff --git a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
index b91a629a2fce0..9c63beda281ad 100644
--- a/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
+++ b/mlir/lib/Dialect/XeGPU/Transforms/XeGPUPropagateLayout.cpp
@@ -1103,7 +1103,6 @@ void LayoutInfoPropagation::visitVectorBitcastOp(
 
   auto consumerLayoutAttr =
       dyn_cast<xegpu::DistributeLayoutAttr>(resLayoutInfo.get());
-
   const uArch *uArch = getUArch(xegpu::getChipStr(bitcast).value_or(""));
   if (!uArch)
     return;



More information about the Mlir-commits mailing list