[Mlir-commits] [mlir] [MLIR][XeGPU] Unroll Dpasmx Op (PR #195179)

Charitha Saumya llvmlistbot at llvm.org
Fri May 1 11:03:35 PDT 2026


================
@@ -175,16 +177,105 @@ XeGPUBlockingPass::getTileShape(Operation *op) const {
     if ((*aTile)[1] != (*bTile)[0])
       return std::nullopt;
 
+    return std::make_pair(*aTile, *bTile);
+  };
+
+  // Helper lambda to validate C tile
+  auto validateCTile = [&](Operation *op, unsigned cOperandIdx,
+                           const SmallVector<int64_t> &aTile,
+                           const SmallVector<int64_t> &bTile) -> bool {
+    if (op->getNumOperands() <= cOperandIdx)
+      return true;
+
+    std::optional<SmallVector<int64_t>> cTile =
+        getTileShape(op->getOpOperand(cOperandIdx));
+    int64_t expectedCTile[2] = {aTile[0], bTile[1]};
+    if (!cTile || !llvm::equal(*cTile, expectedCTile))
+      return false;
+    return true;
+  };
+
+  // Helper lambda to validate scale A/B tiles for DpasMxOp
+  auto validateABScaleTiles =
+      [&](Operation *op, unsigned scaleAOperandIdx, unsigned scaleBOperandIdx,
+          const SmallVector<int64_t> &aTile,
+          const SmallVector<int64_t> &bTile) -> std::optional<int64_t> {
+    std::optional<SmallVector<int64_t>> aScaleTile =
+        getTileShape(op->getOpOperand(scaleAOperandIdx));
+    std::optional<SmallVector<int64_t>> bScaleTile =
+        getTileShape(op->getOpOperand(scaleBOperandIdx));
+
+    if (!aScaleTile || aScaleTile->size() != 2 || !bScaleTile ||
+        bScaleTile->size() != 2)
+      return std::nullopt;
+
+    // Validate scale tile dimensions
+    assert((*aScaleTile)[0] == aTile[0] && "aScaleTile[0] must equal aTile[0]");
+    assert((*bScaleTile)[1] == bTile[1] && "bScaleTile[1] must equal bTile[1]");
+
+    if ((*aScaleTile)[1] != (*bScaleTile)[0])
+      return std::nullopt;
+
+    // Return the K scale factor
+    return (*aScaleTile)[1];
+  };
+
+  if (isa<xegpu::DpasOp>(op)) {
+    auto abTiles = validateABTiles(op);
+    if (!abTiles)
+      return std::nullopt;
+
+    auto [aTile, bTile] = *abTiles;
+
     // semantic check for C
-    if (op->getNumOperands() == 3) {
-      std::optional<SmallVector<int64_t>> cTile =
-          getTileShape(op->getOpOperand(2));
-      int64_t expectedCTile[2] = {(*aTile)[0], (*bTile)[1]};
-      if (!cTile || !llvm::equal(*cTile, expectedCTile))
+    if (!validateCTile(op, 2, aTile, bTile))
+      return std::nullopt;
+
+    return SmallVector<int64_t>({aTile[0], aTile[1], bTile[1]});
+  }
+
+  if (auto dpasMxOp = dyn_cast<xegpu::DpasMxOp>(op)) {
+    auto abTiles = validateABTiles(op);
+    if (!abTiles)
+      return std::nullopt;
+
+    auto [aTile, bTile] = *abTiles;
+
+    // Get operand indices using AttrSizedOperandSegments
+    auto segmentSizesAttr = dpasMxOp->getAttrOfType<DenseI32ArrayAttr>(
+        dpasMxOp.getOperandSegmentSizesAttrName());
+    if (!segmentSizesAttr)
+      return std::nullopt;
+
+    auto segmentSizes = segmentSizesAttr.asArrayRef();
+    unsigned aSize = segmentSizes[0];
+    unsigned bSize = segmentSizes[1];
+    unsigned accSize = segmentSizes[2];
+    unsigned scaleASize = segmentSizes[3];
+    unsigned scaleBSize = segmentSizes[4];
----------------
charithaintc wrote:

I would encourage using the op specifc methods for these by casting the op to `DpasMxOp`. In the future if you make any change to operands these segmentSizesAttr based access will fail, but tablegen accessors always work. 

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


More information about the Mlir-commits mailing list