30#include "llvm/ADT/PostOrderIterator.h"
31#include "llvm/Support/FormatVariadic.h"
40 out.reserve(attrs.size());
42 for (
auto attr : attrs) {
43 if (
auto dist = dyn_cast<xegpu::DistributeLayoutAttr>(attr.getValue())) {
44 auto newLayout = dist.dropSgLayoutAndData();
46 out.emplace_back(attr.getName(), newLayout);
58 out.reserve(attrs.size());
60 for (
auto attr : attrs) {
61 if (
auto dist = dyn_cast<xegpu::DistributeLayoutAttr>(attr.getValue())) {
62 auto newLayout = dist.dropInstData();
64 out.emplace_back(attr.getName(), newLayout);
76 auto tensorDescTy = dyn_cast<xegpu::TensorDescType>(val.
getType());
77 if (!tensorDescTy || tensorDescTy.getLayoutAttr())
79 auto typeWithLayout = xegpu::TensorDescType::get(
80 tensorDescTy.getContext(), tensorDescTy.getShape(),
81 tensorDescTy.getElementType(), tensorDescTy.getEncoding(), layout);
96 llvm::ReversePostOrderTraversal<Region *> rpot(®ion);
98 for (
Block *block : llvm::reverse(blocks)) {
100 for (
Operation &op : llvm::reverse(*block)) {
108 for (
Region &nested : op.getRegions())
117 xegpu::DistributeLayoutAttr layout =
nullptr;
152 if (op->
getNumResults() > 1 && !isa<vector::DeinterleaveOp>(op))
163 if (isa<xegpu::TensorDescType>(resultType))
168 if (isa<VectorType>(resultType) || isa<vector::MultiDimReductionOp>(op))
171 if (isa<vector::DeinterleaveOp>(op))
175 xegpu::DistributeLayoutAttr operandLayout =
177 if (isa<VectorType>(opr.get().getType()) && operandLayout)
189 mlir::RegionBranchTerminatorOpInterface yieldOp) {
190 auto regionBranchOp =
191 dyn_cast<RegionBranchOpInterface>(yieldOp->getParentOp());
197 yieldOp.getSuccessorRegions(operandAttrs, successors);
200 OperandRange succOps = yieldOp.getSuccessorOperands(successor);
204 ValueRange successorInputs = regionBranchOp.getSuccessorInputs(successor);
205 unsigned count = std::min<unsigned>(succOps.size(), successorInputs.size());
207 for (
unsigned i = 0; i < count; ++i) {
208 xegpu::DistributeLayoutAttr layout;
209 if (successor.isOperation()) {
212 auto regionResult = regionBranchOp->getResult(i);
217 if (isa<xegpu::TensorDescType>(regionResult.getType()))
228 auto operandType = succOps[i].
getType();
229 if (isa<VectorType>(operandType) ||
230 dyn_cast<xegpu::TensorDescType>(operandType))
251 mlir::RegionBranchTerminatorOpInterface terminator,
254 auto branchOp = dyn_cast<RegionBranchOpInterface>(terminator->getParentOp());
259 branchOp.getSuccessorOperandInputMapping(mapping,
261 for (
const auto &[successorOperand, successorInputs] : mapping) {
262 for (
Value successorInput : successorInputs) {
263 Type inputType = successorInput.getType();
265 if (!isa<VectorType>(inputType))
267 xegpu::DistributeLayoutAttr successorOperandLayout =
268 getLayoutOfValue(successorOperand->get());
271 if (!successorOperandLayout)
274 if (
auto result = dyn_cast<OpResult>(successorInput))
291 for (
Region ®ion : regionOp->getRegions()) {
296 ValueRange successorInputs = regionOp.getSuccessorInputs(regionSuccessor);
297 for (
auto [inputIdx, regionArg] : llvm::enumerate(successorInputs)) {
298 auto layout = getLayoutOfValue(regionArg);
303 if (isa<xegpu::TensorDescType>(regionArg.getType()))
309 regionOp.getPredecessorValues(regionSuccessor, inputIdx, predValues);
310 for (
Value predVal : predValues) {
312 for (
OpOperand &operand : regionOp->getOpOperands()) {
313 if (operand.get() == predVal)
352 auto processFunc = [&](
Region &body, StringRef funcName) {
354 if (
auto regionOp = dyn_cast<mlir::RegionBranchOpInterface>(op)) {
357 }
else if (
auto yieldOp =
358 dyn_cast<mlir::RegionBranchTerminatorOpInterface>(op)) {
360 }
else if (!dyn_cast<xegpu::AnchorLayoutInterface>(op)) {
366 rootOp->
walk([&](func::FuncOp
func) {
367 processFunc(
func.getBody(),
func.getSymName());
369 rootOp->
walk([&](gpu::GPUFuncOp
func) {
370 processFunc(
func.getBody(),
func.getName());
376template <
typename T,
typename>
378 Operation *owner = operandOrResult.getOwner();
396 for (
auto namedAttr : nestOp->
getAttrs()) {
397 if (isa<DistributeLayoutAttr>(namedAttr.getValue()))
398 attrsToRemove.push_back(namedAttr.getName());
400 for (
auto attrName : attrsToRemove)
409 if (isa<xegpu::DistributeLayoutAttr>(namedAttr.getValue()))
410 attrsToRemove.push_back(namedAttr.getName());
412 for (
auto attrName : attrsToRemove)
421 int numLeading =
static_cast<int>(
shape.size()) - numInnerDims;
424 return llvm::all_of(
shape.take_front(numLeading),
425 [](
int64_t dim) { return dim == 1; });
432 auto toI32Attr = [&](
auto range) {
436 return xegpu::LayoutAttr::get(context,
nullptr,
437 nullptr, toI32Attr(instData),
438 toI32Attr(laneLayout), toI32Attr(laneData),
445 return !llvm::any_of(llvm::seq<int>(0, dataShape.size()), [&](
int dim) {
446 return dataShape[dim] % (laneLayout[dim] * laneData[dim]) != 0;
450static xegpu::LayoutAttr
454 auto toI32Attr = [&](
auto range) {
458 return xegpu::LayoutAttr::get(context,
nullptr,
460 nullptr, toI32Attr(laneLayout),
461 toI32Attr(laneData), orderAttr);
464static xegpu::LayoutAttr
469 auto toI32Attr = [&](
auto range) {
473 return xegpu::LayoutAttr::get(
474 context, sgLayout.empty() ?
nullptr : toI32Attr(sgLayout),
475 sgData.empty() ?
nullptr : toI32Attr(sgData),
476 instData.empty() ?
nullptr : toI32Attr(instData),
477 laneLayout.empty() ?
nullptr : toI32Attr(laneLayout),
478 laneData.empty() ?
nullptr : toI32Attr(laneData), orderAttr);
487 for (
int dim = 0; dim < (int)sgLayout.size(); ++dim) {
489 sgData[dim] = wgTileShape[dim];
491 sgData[dim] = wgTileShape[dim] / sgLayout[dim];
500xegpu::DistributeLayoutAttr
506 size_t dimDiff = resShape.size() - srcShape.size();
507 auto bcastSourceLayout = resLayout;
510 for (
size_t i = dimDiff; i < resShape.size(); i++) {
511 if ((srcShape[i - dimDiff] == 1) && (resShape[i] != 1))
512 bcastDims.push_back(i);
517 if (!bcastDims.empty())
518 bcastSourceLayout = bcastSourceLayout.setUnitDimData(bcastDims);
523 bool isOuterDimDiffUnitDims = llvm::all_of(
524 resShape.take_front(dimDiff), [&](
int64_t dim) { return dim == 1; });
525 if (dimDiff && bcastDims.size() == dimDiff && isOuterDimDiffUnitDims) {
528 sliceDims.assign(bcastDims.begin(), bcastDims.end());
532 llvm::append_range(sliceDims, llvm::seq<int64_t>(0, dimDiff));
534 bcastSourceLayout = xegpu::SliceAttr::get(
535 resLayout.getContext(), bcastSourceLayout,
538 return bcastSourceLayout;
543xegpu::DistributeLayoutAttr
547 assert(isa<xegpu::SliceAttr>(resLayout) &&
548 "reduction result layout must be slice layout");
550 xegpu::SliceAttr sliceLayout = dyn_cast<xegpu::SliceAttr>(resLayout);
552 assert((reduceDims == sliceLayout.getDims().asArrayRef()) &&
553 "reduction dims must match with slice dims");
555 return sliceLayout.getParent();
558xegpu::DistributeLayoutAttr
569xegpu::DistributeLayoutAttr
580xegpu::DistributeLayoutAttr
582 int resElemTyBitWidth,
int srcElemTyBitWidth) {
587 size_t sgDataSize = sgData.size();
588 size_t instDataSize = instData.size();
589 size_t laneDataSize = laneData.size();
593 int64_t dim = resLayout.getRank() - 1;
595 if (srcElemTyBitWidth <= resElemTyBitWidth) {
596 int bitWidthRatio = resElemTyBitWidth / srcElemTyBitWidth;
598 sgDataValue = sgData.back() * bitWidthRatio;
600 instDataValue = instData.back() * bitWidthRatio;
602 laneDataValue = laneData.back() * bitWidthRatio;
604 int bitWidthRatio = srcElemTyBitWidth / resElemTyBitWidth;
606 assert((sgData.back() % bitWidthRatio) == 0 &&
607 "sgData not divisible by bitWidthRatio");
608 sgDataValue = sgData.back() / bitWidthRatio;
611 assert((instData.back() % bitWidthRatio) == 0 &&
612 "instData not divisible by bitWidthRatio");
613 instDataValue = instData.back() / bitWidthRatio;
616 assert((laneData.back() % bitWidthRatio) == 0 &&
617 "laneData not divisible by bitWidthRatio");
618 laneDataValue = laneData.back() / bitWidthRatio;
622 xegpu::DistributeLayoutAttr finalSrcLayout;
624 resLayout.setDimData(dim, sgDataValue, instDataValue, laneDataValue);
626 return finalSrcLayout;
633xegpu::DistributeLayoutAttr
639 size_t sgDataSize = sgData.size();
640 size_t instDataSize = instData.size();
641 size_t laneDataSize = laneData.size();
645 int64_t dim = resLayout.getRank() - 1;
649 constexpr int ratio = 2;
651 assert((sgData.back() % ratio) == 0 &&
652 "sgData not divisible by interleave ratio");
653 sgDataValue = sgData.back() / ratio;
656 assert((instData.back() % ratio) == 0 &&
657 "instData not divisible by interleave ratio");
658 instDataValue = instData.back() / ratio;
661 assert((laneData.back() % ratio) == 0 &&
662 "laneData not divisible by interleave ratio");
663 laneDataValue = laneData.back() / ratio;
666 return resLayout.setDimData(dim, sgDataValue, instDataValue, laneDataValue);
673xegpu::DistributeLayoutAttr
679 size_t sgDataSize = sgData.size();
680 size_t instDataSize = instData.size();
681 size_t laneDataSize = laneData.size();
685 int64_t dim = resLayout.getRank() - 1;
689 constexpr int ratio = 2;
691 sgDataValue = sgData.back() * ratio;
693 instDataValue = instData.back() * ratio;
695 laneDataValue = laneData.back() * ratio;
697 return resLayout.setDimData(dim, sgDataValue, instDataValue, laneDataValue);
707 int srcShapeSize = srcShape.size();
708 int resShapeSize = resShape.size();
709 int dimDiff = resShapeSize - srcShapeSize;
714 auto resSgLayout = resLayout.getEffectiveSgLayoutAsInt();
715 auto resLaneLayout = resLayout.getEffectiveLaneLayoutAsInt();
716 for (
int i = 0; i < dimDiff; i++) {
717 assert((resSgLayout.size() == 0 || resSgLayout[i] == 1) &&
718 (resLaneLayout.size() == 0 || resLaneLayout[i] == 1) &&
719 "Leading dimensions being sliced off must not be distributed");
721 return resLayout.dropDims(llvm::to_vector(llvm::seq<int64_t>(0, dimDiff)));
730xegpu::DistributeLayoutAttr
735 int srcShapeSize = srcShape.size();
736 int resShapeSize = resShape.size();
737 int dimDiff = resShapeSize - srcShapeSize;
742 auto resSgLayout = resLayout.getEffectiveSgLayoutAsInt();
743 auto resLaneLayout = resLayout.getEffectiveLaneLayoutAsInt();
744 for (
int i = 0; i < dimDiff; i++) {
745 assert((resSgLayout.size() == 0 || resSgLayout[i] == 1) &&
746 (resLaneLayout.size() == 0 || resLaneLayout[i] == 1) &&
747 "Leading dimensions being sliced off must not be distributed");
749 return resLayout.dropDims(llvm::to_vector(llvm::seq<int64_t>(0, dimDiff)));
759xegpu::DistributeLayoutAttr
764 int srcShapeSize = srcShape.size();
765 int resShapeSize = resShape.size();
766 int dimDiff = srcShapeSize - resShapeSize;
767 auto context = resLayout.getContext();
771 auto sgLayout = resLayout.getEffectiveSgLayoutAsInt();
772 auto sgData = resLayout.getEffectiveSgDataAsInt();
773 auto instData = resLayout.getEffectiveInstDataAsInt();
774 auto laneLayout = resLayout.getEffectiveLaneLayoutAsInt();
775 auto laneData = resLayout.getEffectiveLaneDataAsInt();
776 auto order = resLayout.getEffectiveOrderAsInt();
786 for (
auto &o : order)
792 for (
int i = 0; i < dimDiff; i++) {
793 if (!sgLayout.empty())
794 sgLayout.insert(sgLayout.begin(), 1);
796 sgData.insert(sgData.begin(), 1);
797 if (!instData.empty())
798 instData.insert(instData.begin(), 1);
799 if (!laneLayout.empty())
800 laneLayout.insert(laneLayout.begin(), 1);
801 if (!laneData.empty())
802 laneData.insert(laneData.begin(), 1);
803 order.push_back(dimDiff - 1 - i);
808 if (!resLayout.getOrder())
811 return buildLayout(context, sgLayout, sgData, instData, laneLayout,
812 laneData, orderAttr);
819xegpu::DistributeLayoutAttr
843 xegpu::SliceAttr::get(resLayout.getContext(), resLayout, sliceDimsAttr);
850 auto srcLayout = resLayout;
851 for (
const auto &dimGroup : splitDimGroups)
852 srcLayout = srcLayout.collapseDims(dimGroup);
861 auto srcLayout = resLayout;
862 for (
int64_t dstIdx =
static_cast<int64_t>(collapseDims.size()) - 1;
863 dstIdx >= 0; --dstIdx) {
865 if (srcDims.empty()) {
866 srcLayout = srcLayout.dropDims({dstIdx});
869 if (srcDims.size() == 1)
872 targetShape.reserve(srcDims.size());
874 targetShape.push_back(srcShape[d]);
875 srcLayout = srcLayout.expandDim(dstIdx, targetShape);
893xegpu::DistributeLayoutAttr
896 return srcLayout.transposeDims(permutation);
907xegpu::DistributeLayoutAttr
916 auto resLayout = srcLayout;
919 for (
int64_t srcIdx =
static_cast<int64_t>(splitDimGroups.size()) - 1;
920 srcIdx >= 0; --srcIdx) {
922 if (resDims.size() <= 1)
925 targetShape.reserve(resDims.size());
927 targetShape.push_back(resShape[d]);
928 resLayout = resLayout.expandDim(srcIdx, targetShape);
937 auto resLayout = srcLayout;
940 for (
int64_t dstIdx =
static_cast<int64_t>(collapseDims.size()) - 1;
941 dstIdx >= 0; --dstIdx) {
947 if (srcDims.size() == 1)
949 resLayout = resLayout.collapseDims(llvm::to_vector(srcDims));
966 if (
auto transpose = dyn_cast<vector::TransposeOp>(op)) {
967 if (!operandLayouts[0])
970 transpose.getPermutation());
974 if (
auto shapeCast = dyn_cast<vector::ShapeCastOp>(op)) {
975 if (!operandLayouts[0])
978 operandLayouts[0], shapeCast.getSourceVectorType().getShape(),
979 shapeCast.getResultVectorType().getShape());
985 for (xegpu::DistributeLayoutAttr layout : operandLayouts)
1008 xegpu::DistributeLayoutAttr payloadLayout,
int chunkSize) {
1009 auto rank = payloadLayout.getRank();
1011 return payloadLayout.dropDims(
1012 llvm::to_vector(llvm::seq<int64_t>(rank - 1, rank)));
1013 return payloadLayout;
1033 auto getDivisors = [](
int64_t n) {
1035 for (
int64_t i = 1; i * i <= n; ++i) {
1039 divs.push_back(n / i);
1048 if (dim == rank - 1) {
1049 current[dim] = remaining;
1053 for (
int64_t factor : getDivisors(remaining)) {
1054 current[dim] = factor;
1055 generate(dim + 1, remaining / factor);
1076 int64_t rank = wgShape.size();
1077 assert(rank > 0 &&
"wgShape must be non-empty");
1078 assert(
static_cast<int64_t>(instData.size()) == rank &&
1079 "instData rank must match wgShape rank");
1086 for (
const auto &sgLayout : allFactorizations) {
1088 for (
int64_t dim = 0; dim < rank; ++dim) {
1089 if (wgShape[dim] % sgLayout[dim] != 0) {
1093 int64_t sgData = wgShape[dim] / sgLayout[dim];
1094 if (sgData % instData[dim] != 0) {
1100 candidates.push_back(sgLayout);
1106 int64_t spreadLhs = *llvm::max_element(
lhs) - *llvm::min_element(
lhs);
1107 int64_t spreadRhs = *llvm::max_element(
rhs) - *llvm::min_element(
rhs);
1108 if (spreadLhs != spreadRhs)
1109 return spreadLhs < spreadRhs;
1120 bool transform =
false,
bool transpose =
false) {
1121 int rank = dataShape.size();
1125 return std::nullopt;
1126 auto [bWidths, bHeights, bCounts] = blockWHC.value();
1132 assert(rank >= 2 &&
"dataShape must be at least 2D for 2D-block IO");
1137 instData.back() = instWidth;
1138 instData[rank - 2] = instHeight;
1149 VectorType aTy, VectorType bTy, VectorType cdTy,
1153 const unsigned dataALen = aTy.getShape()[aTy.getRank() - 2];
1154 auto supportedALen = uArchInstruction->
getSupportedM(aTy.getElementType());
1159 const unsigned dataBLen = bTy.getShape().back();
1160 auto supportedBLen = uArchInstruction->
getSupportedN(bTy.getElementType());
1164 auto supportedCLen = uArchInstruction->
getSupportedN(cdTy.getElementType());
1167 if (maxALen == -1 || maxBLen == -1 || maxCLen == -1)
1168 return std::nullopt;
1170 auto supportedKLen = uArchInstruction->
getSupportedK(aTy.getElementType());
1171 if (supportedKLen.empty())
1172 return std::nullopt;
1173 auto kDimSize = supportedKLen[0];
1176 instDataA[aTy.getRank() - 2] = maxALen;
1177 instDataA[aTy.getRank() - 1] = kDimSize;
1179 instDataB[bTy.getRank() - 2] = kDimSize;
1180 instDataB[bTy.getRank() - 1] = maxBLen;
1182 instDataCD[cdTy.getRank() - 2] = maxALen;
1183 instDataCD[cdTy.getRank() - 1] = maxCLen;
1184 return std::make_tuple(instDataA, instDataB, instDataCD);
1197 int64_t rank = instShape.size();
1200 laneLayout[innermost] = std::min(subgroupSize, instShape[innermost]);
1201 laneData[innermost] =
1202 std::min(instShape[innermost] / laneLayout[innermost], maxChunkSize);
1203 return {laneLayout, laneData};
1213 int64_t rank = instShape.size();
1215 int kDim =
transform ? rank - 2 : rank - 1;
1216 unsigned vnniFactor = packingSize / bitwidth;
1217 laneData[kDim] = bitwidth < packingSize ? vnniFactor : 1;
1219 std::min(subgroupSize, instShape.back() / laneData.back());
1222 for (
int64_t i = 0; i < rank; ++i) {
1223 int64_t laneProduct = laneLayout[i] * laneData[i];
1224 assert(instShape[i] % laneProduct == 0 &&
1225 "lane_layout * lane_data must evenly divide the inst shape");
1228 return {laneLayout, laneData};
1247 int subgroupSize,
int64_t maxReduceVectorSize,
1248 bool verticalLaneLayout =
false) {
1249 int srcRank = srcShape.size();
1252 int innermost = srcRank - 1;
1253 int secondInnermost = srcRank - 2;
1255 if (verticalLaneLayout && secondInnermost >= 0) {
1256 std::swap(innermost, secondInnermost);
1258 int laneDim = innermost;
1259 int vectorDim = secondInnermost;
1261 laneLayout[laneDim] =
1262 std::min(
static_cast<int64_t>(subgroupSize), srcShape[laneDim]);
1264 laneData[vectorDim] = std::min(maxReduceVectorSize, srcShape[vectorDim]);
1266 return {laneLayout, laneData};
1332static std::optional<
1333 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
1334 xegpu::DistributeLayoutAttr>>
1337 xegpu::DistributeLayoutAttr consumerLayout,
int numSg,
1340 auto [instDataA, instDataB, instDataCD] = instDataVecs;
1342 std::optional<LayoutRepresentation> consumerSgLayout = std::nullopt;
1343 if (consumerLayout && consumerLayout.isForWorkgroup()) {
1344 consumerSgLayout = consumerLayout.getEffectiveSgLayoutAsInt();
1351 if (layoutsA.empty() || layoutsB.empty() || layoutsCD.empty())
1352 return std::nullopt;
1355 std::optional<LayoutRepresentation> bestPick;
1357 return aTy.getShape().back() / sgLayout[1] ==
1358 bTy.getShape().front() / sgLayout[0];
1360 for (
auto &sgLayout : layoutsB) {
1361 if (llvm::is_contained(layoutsA, sgLayout) &&
1362 llvm::is_contained(layoutsCD, sgLayout)) {
1363 if (!checkAlignedSgDataAB(sgLayout))
1366 if (consumerSgLayout.has_value() && sgLayout == *consumerSgLayout) {
1367 bestPick = sgLayout;
1375 bestPick = sgLayout;
1379 return std::nullopt;
1381 const auto &picked = *bestPick;
1383 auto dpasALayout =
buildSgLayout(context, aTy.getShape(), picked,
1385 auto dpasBLayout =
buildSgLayout(context, bTy.getShape(), picked,
1387 auto dpasCDLayout =
buildSgLayout(context, cdTy.getShape(), picked);
1388 return std::make_tuple(dpasALayout, dpasBLayout, dpasCDLayout);
1395 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
1396 xegpu::DistributeLayoutAttr>>
1398 VectorType bTy, VectorType cdTy,
1399 xegpu::DistributeLayoutAttr consumerLayout,
int numSg,
1401 auto context = aTy.getContext();
1402 const auto *uArchInstruction =
1403 dyn_cast<xegpu::uArch::SubgroupMatrixMultiplyAcc>(uArch->
getInstruction(
1405 if (!uArchInstruction)
1406 return std::nullopt;
1410 aTy.getShape(), subgroupSize,
1411 aTy.getElementType().getIntOrFloatBitWidth(),
1412 uArchInstruction->getPackedFormatBitSizeA());
1414 bTy.getShape(), subgroupSize,
1415 bTy.getElementType().getIntOrFloatBitWidth(),
1416 uArchInstruction->getPackedFormatBitSizeB(),
true);
1418 cdTy.getShape(), subgroupSize,
1419 cdTy.getElementType().getIntOrFloatBitWidth(),
1420 cdTy.getElementType().getIntOrFloatBitWidth());
1424 return std::nullopt;
1428 "Number of subgroups must be provided for sg layout creation.");
1430 numSg, *instDataVecs);
1432 auto [instDataA, instDataB, instDataCD] = *instDataVecs;
1433 return std::make_tuple(
1442 return std::make_tuple(aLayout, bLayout, cdLayout);
1444 return std::nullopt;
1451static xegpu::DistributeLayoutAttr
1453 VectorType scaleTy, xegpu::DistributeLayoutAttr matrixLayout,
1455 if (!scaleTy || !matrixLayout)
1463 if (scaleShape.empty())
1466 auto uArchInstruction =
1467 dyn_cast<xegpu::uArch::SubgroupScaledMatrixMultiplyAcc>(
1471 int64_t rank = matrixLayout.getRank();
1472 assert(rank >= 2 &&
"dpas layouts must be at least two dimensions");
1479 auto order = matrixLayout.getOrder();
1483 if (!sgLayout.empty() && !sgData.empty()) {
1484 scaleSgLayout.assign(sgLayout.begin(), sgLayout.end());
1485 scaleSgData.assign(sgData.begin(), sgData.end());
1486 scaleSgData[rank - 2] = std::max<int64_t>(
1487 scaleShape[rank - 2] / (matrixShape[rank - 2] / sgData[rank - 2]), 1);
1488 scaleSgData[rank - 1] = std::max<int64_t>(
1489 scaleShape[rank - 1] / (matrixShape[rank - 1] / sgData[rank - 1]), 1);
1496 if (!instData.empty()) {
1497 scaleInstData.assign(instData.begin(), instData.end());
1499 scaleInstData[rank - 2] = std::max<int64_t>(
1500 scaleShape[rank - 2] / (matrixShape[rank - 2] / instData[rank - 2]),
1503 scaleInstData[rank - 1] = std::max<int64_t>(
1504 scaleShape[rank - 1] / (matrixShape[rank - 1] / instData[rank - 1]),
1510 if (!laneLayout.empty() && !laneData.empty()) {
1511 scaleLaneLayout.assign(laneLayout.begin(), laneLayout.end());
1512 scaleLaneData.assign(laneData.size(), 1);
1514 bool isRowMajor = uArchInstruction->isLaneLayoutRowMajorOrder();
1515 if (isBScale ^ isRowMajor)
1516 std::swap(scaleLaneLayout[rank - 2], scaleLaneLayout[rank - 1]);
1521 auto layoutCap = scaleInstData.empty() ? scaleShape : scaleInstData;
1522 for (
int64_t d = rank - 2; d < rank; ++d)
1523 scaleLaneLayout[d] = std::min<int64_t>(layoutCap[d], scaleLaneLayout[d]);
1525 return buildLayout(context, scaleSgLayout, scaleSgData, scaleInstData,
1526 scaleLaneLayout, scaleLaneData, order);
1533 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
1534 xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
1535 xegpu::DistributeLayoutAttr>>
1537 VectorType bTy, VectorType cdTy, VectorType aScaleTy,
1538 VectorType bScaleTy,
1539 xegpu::DistributeLayoutAttr consumerLayout,
int numSg,
1541 auto context = aTy.getContext();
1542 const auto *uArchInstruction =
1543 dyn_cast<xegpu::uArch::SubgroupMatrixMultiplyAcc>(uArch->
getInstruction(
1545 if (!uArchInstruction)
1546 return std::nullopt;
1550 aTy.getShape(), subgroupSize,
1551 aTy.getElementType().getIntOrFloatBitWidth(),
1552 uArchInstruction->getPackedFormatBitSizeA());
1554 bTy.getShape(), subgroupSize,
1555 bTy.getElementType().getIntOrFloatBitWidth(),
1556 uArchInstruction->getPackedFormatBitSizeB(),
true);
1558 cdTy.getShape(), subgroupSize,
1559 cdTy.getElementType().getIntOrFloatBitWidth(),
1560 cdTy.getElementType().getIntOrFloatBitWidth());
1563 return std::nullopt;
1567 "Number of subgroups must be provided for sg layout creation.");
1569 context, aTy, bTy, cdTy, consumerLayout, numSg, *instDataVecs);
1571 return std::nullopt;
1573 auto [dpasALayout, dpasBLayout, dpasCDLayout] = *dpasLayouts;
1582 return std::make_tuple(dpasALayout, dpasBLayout, dpasCDLayout, aScaleLayout,
1586 auto [instDataA, instDataB, instDataCD] = *instDataVecs;
1593 laneLayoutCD, laneDataCD);
1600 return std::make_tuple(dpasALayout, dpasBLayout, dpasCDLayout, aScaleLayout,
1605 auto dpasCDLayout =
buildLaneLayout(context, laneLayoutCD, laneDataCD);
1612 return std::make_tuple(dpasALayout, dpasBLayout, dpasCDLayout, aScaleLayout,
1615 return std::nullopt;
1621xegpu::DistributeLayoutAttr
1623 VectorType srcVecTy,
int numSg,
1625 const auto *uArchInstruction =
1626 dyn_cast<xegpu::uArch::Subgroup2DBlockStoreInstruction>(
1627 uArch->getInstruction(
1629 if (!uArchInstruction)
1632 auto context = srcVecTy.getContext();
1633 Type elemTy = srcVecTy.getElementType();
1634 auto subgroupSize =
uArch->getSubgroupSize();
1635 auto dataShape = srcVecTy.getShape();
1636 [[maybe_unused]]
int rank = srcVecTy.getRank();
1637 assert(rank >= 2 &&
"Expected at least 2D shape for ND op");
1642 dataShape, subgroupSize, bitwidth,
1643 uArchInstruction->getPackedFormatBitSize());
1653 "Expected the store layout to satisfy uArch block constraints");
1660 "Number of subgroups must be provided for sg layout creation.");
1662 if (sgLayouts.empty())
1664 return buildSgLayout(context, dataShape, sgLayouts.front(), -1);
1673xegpu::DistributeLayoutAttr
1675 xegpu::TensorDescType tdescTy,
int numSg,
1678 const auto *uArchInstruction =
1679 dyn_cast<xegpu::uArch::Subgroup2DBlockPrefetchInstruction>(
1682 if (!uArchInstruction)
1685 auto context = tdescTy.getContext();
1686 Type elemTy = tdescTy.getElementType();
1688 auto dataShape = tdescTy.getShape();
1689 [[maybe_unused]]
int rank = tdescTy.getRank();
1690 assert(rank >= 2 &&
"Expected at least 2D shape for ND op");
1695 dataShape, subgroupSize, bitwidth,
1696 uArchInstruction->getPackedFormatBitSize());
1706 "Expected the prefetch layout to satisfy uArch block constraints");
1713 "Number of subgroups must be provided for sg layout creation.");
1715 if (sgLayouts.empty())
1717 return buildSgLayout(context, dataShape, sgLayouts.front(), -1);
1728xegpu::DistributeLayoutAttr
1730 VectorType resVecTy,
1731 xegpu::DistributeLayoutAttr consumerLayout,
1734 assert(consumerLayout &&
"Expected a valid consumer layout");
1736 assert(consumerLayout.isForWorkgroup() &&
1737 "Expected consumer layout to be a complete workgroup-level layout");
1738 return consumerLayout;
1741 auto context = resVecTy.getContext();
1742 Type elemTy = resVecTy.getElementType();
1744 auto dataShape = resVecTy.getShape();
1745 const auto *uArchInstruction =
1746 dyn_cast<xegpu::uArch::Subgroup2DBlockLoadInstruction>(
1749 if (!uArchInstruction)
1752 int rank = resVecTy.getRank();
1754 consumerLayout.getEffectiveInstDataAsInt();
1756 consumerLayout.getEffectiveLaneLayoutAsInt();
1758 consumerLayout.getEffectiveLaneDataAsInt();
1759 auto consumerOrderAttr = consumerLayout.getOrder();
1761 assert(!consumerLaneLayout.empty() && !consumerLaneData.empty() &&
1762 "Expected consumer layout to have lane_layout and lane_data");
1768 consumerLaneLayout[rank - 2] > 1 && consumerLaneLayout[rank - 1] == 1;
1769 bool hasTransform = !hasTranspose && consumerLaneData[rank - 2] > 1 &&
1770 consumerLaneData[rank - 1] == 1;
1771 assert((consumerLaneData[rank - 2] == 1 || consumerLaneData[rank - 1] == 1) &&
1772 "Expected consumer lane data to have at most one non-unit dim");
1775 auto blockWHC = uArchInstruction->getBlockWidthHeightCount(
1776 elemTy, hasTransform, hasTranspose,
1780 auto [bWidths, bHeights, bCounts] = blockWHC.value();
1786 for (
int i = 0; i < rank; i++) {
1787 if (consumerLaneLayout[i] > 1)
1788 laneLayout.push_back(std::max(
static_cast<int64_t>(subgroupSize),
1789 consumerLaneLayout[i]));
1791 laneLayout.push_back(1);
1795 int64_t height = consumerInstData[rank - 2];
1796 int64_t width = consumerInstData[rank - 1];
1797 auto maxBlockCount = *llvm::max_element(bCounts);
1798 auto maxWidth = *llvm::max_element(bWidths);
1799 if (llvm::is_contained(bWidths,
static_cast<int>(width)) ||
1800 (width % maxWidth == 0 && width / maxWidth < maxBlockCount)) {
1801 if (llvm::is_contained(bHeights,
static_cast<int>(height))) {
1803 laneLayout, consumerLaneData,
1811 dataShape, elemTy, uArchInstruction, hasTransform, hasTranspose);
1816 "Expected the load layout to satisfy uArch block constraints");
1818 consumerLaneData, consumerOrderAttr);
1822 "Expected the lane layout to satisfy uArch block constraints");
1823 return consumerLayout;
1843 xegpu::DistributeLayoutAttr consumerLayout,
int maxChunkSize,
1847 return consumerLayout;
1850 consumerLayout.getEffectiveInstDataAsInt();
1852 consumerLayout.getEffectiveLaneLayoutAsInt();
1854 consumerLayout.getEffectiveLaneDataAsInt();
1858 assert(!consumerLaneLayout.empty() && !consumerLaneData.empty() &&
1859 "Expected consumer layout to have lane_layout and lane_data");
1860 laneLayout.assign(consumerLaneLayout.begin(), consumerLaneLayout.end());
1861 laneData.assign(consumerLaneData.begin(), consumerLaneData.end());
1865 instData.resize(resShape.size());
1866 for (
size_t i = 0; i < resShape.size(); ++i)
1867 instData[i] = laneLayout[i] * laneData[i];
1878 xegpu::DistributeLayoutAttr consumerLayout,
const uArch::uArch *uArch) {
1880 const int subgroupSize = uArch->getSubgroupSize();
1882 auto context = resVecTy.getContext();
1884 const auto *uArchInstruction = dyn_cast<xegpu::uArch::LoadGatherInstruction>(
1887 std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
1890 maxChunkSize, resShape, subgroupSize);
1895xegpu::DistributeLayoutAttr
1897 VectorType resVecTy,
int contigChunkSize,
1898 xegpu::DistributeLayoutAttr consumerLayout,
1903 auto context = resVecTy.getContext();
1905 const auto *uArchInstruction = dyn_cast<xegpu::uArch::LoadGatherInstruction>(
1908 std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
1910 maxChunkSize, resShape, subgroupSize);
1916static xegpu::DistributeLayoutAttr
1920 if (candidates.empty())
1923 return buildSgLayout(context, wgShape, candidates.front(), -1);
1933 auto [laneLayout, laneData] =
1937 for (
size_t i = 0; i < srcShape.size(); ++i)
1938 instData[i] = laneLayout[i] * laneData[i];
1942 "Number of subgroups must be provided for sg layout creation.");
1955xegpu::DistributeLayoutAttr
1957 VectorType srcVecTy,
int contigChunkSize,
1960 const int subgroupSize =
uArch->getSubgroupSize();
1962 auto context = srcVecTy.getContext();
1964 const auto *uArchInstruction =
1965 dyn_cast<xegpu::uArch::StoreScatterInstruction>(
1968 std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
1970 srcShape, subgroupSize, numSg);
1978 const int subgroupSize =
uArch->getSubgroupSize();
1980 auto context = srcVecTy.getContext();
1982 const auto *uArchInstruction =
1983 dyn_cast<xegpu::uArch::StoreScatterInstruction>(
1986 std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
1989 srcShape, subgroupSize, numSg);
2007std::optional<xegpu::DistributeLayoutAttr>
2009 xegpu::DistributeLayoutAttr specifiedLayout,
2010 xegpu::DistributeLayoutAttr consumerLayout,
Type elemTy,
2012 const int subgroupSize) {
2013 if (!specifiedLayout)
2014 return specifiedLayout;
2016 specifiedLayout.getEffectiveInstDataAsInt();
2017 if (specifiedInstData.empty())
2018 return specifiedLayout;
2019 if (!specifiedLayout.getEffectiveLaneLayoutAsInt().empty() &&
2020 !specifiedLayout.getEffectiveLaneDataAsInt().empty())
2021 return specifiedLayout;
2024 auto *context = specifiedLayout.getContext();
2026 if (consumerLayout) {
2027 auto consumerLaneLayout = consumerLayout.getEffectiveLaneLayoutAsInt();
2028 auto consumerLaneData = consumerLayout.getEffectiveLaneDataAsInt();
2029 if (!consumerLaneLayout.empty() && !consumerLaneData.empty() &&
2033 consumerLaneLayout, consumerLaneData);
2036 specifiedInstData, subgroupSize, maxChunkSize);
2038 return std::nullopt;
2046std::optional<xegpu::DistributeLayoutAttr>
2048 xegpu::DistributeLayoutAttr specifiedLayout,
Type elemTy,
2050 const int subgroupSize) {
2051 if (!specifiedLayout)
2052 return specifiedLayout;
2054 specifiedLayout.getEffectiveInstDataAsInt();
2055 if (specifiedInstData.empty())
2056 return specifiedLayout;
2057 if (!specifiedLayout.getEffectiveLaneLayoutAsInt().empty() &&
2058 !specifiedLayout.getEffectiveLaneDataAsInt().empty())
2059 return specifiedLayout;
2062 auto *context = specifiedLayout.getContext();
2065 specifiedInstData, subgroupSize, maxChunkSize);
2067 return std::nullopt;
2076std::optional<xegpu::DistributeLayoutAttr>
2078 xegpu::DistributeLayoutAttr specifiedLayout,
Type elemTy,
2080 const int subgroupSize) {
2081 if (!specifiedLayout)
2082 return specifiedLayout;
2084 specifiedLayout.getEffectiveInstDataAsInt();
2085 if (specifiedInstData.empty())
2086 return specifiedLayout;
2087 if (!specifiedLayout.getEffectiveLaneLayoutAsInt().empty() &&
2088 !specifiedLayout.getEffectiveLaneDataAsInt().empty())
2089 return specifiedLayout;
2091 auto *context = specifiedLayout.getContext();
2096 return std::nullopt;
2105std::optional<xegpu::DistributeLayoutAttr>
2107 xegpu::DistributeLayoutAttr specifiedLayout,
2108 xegpu::DistributeLayoutAttr consumerLayout,
Type elemTy,
2110 const int subgroupSize) {
2111 if (!specifiedLayout)
2112 return specifiedLayout;
2114 specifiedLayout.getEffectiveInstDataAsInt();
2115 if (specifiedInstData.empty())
2116 return specifiedLayout;
2117 if (!specifiedLayout.getEffectiveLaneLayoutAsInt().empty() &&
2118 !specifiedLayout.getEffectiveLaneDataAsInt().empty())
2119 return specifiedLayout;
2120 if (!consumerLayout)
2121 return specifiedLayout;
2123 consumerLayout.getEffectiveLaneLayoutAsInt();
2125 consumerLayout.getEffectiveLaneDataAsInt();
2126 if (consumerLaneLayout.empty() || consumerLaneData.empty())
2127 return specifiedLayout;
2129 auto *context = specifiedLayout.getContext();
2130 int rank = specifiedInstData.size();
2135 for (
int i = 0; i < rank; i++) {
2136 if (consumerLaneLayout[i] > 1) {
2137 laneLayout.push_back(
2138 std::max(
static_cast<int64_t>(subgroupSize), consumerLaneLayout[i]));
2140 laneLayout.push_back(1);
2145 return std::nullopt;
2148 consumerLayout.getOrder());
2156 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
2157 xegpu::DistributeLayoutAttr>>
2159 xegpu::DistributeLayoutAttr bLayout,
2160 xegpu::DistributeLayoutAttr cdLayout,
2161 VectorType aTy, VectorType bTy,
2164 auto context = aTy.getContext();
2165 const auto *uArchInstruction =
2166 dyn_cast<xegpu::uArch::SubgroupMatrixMultiplyAcc>(uArch->
getInstruction(
2168 if (!uArchInstruction)
2169 return std::nullopt;
2172 laneLayoutCD, laneDataCD;
2177 if (isa<xegpu::uArch::Xe2, xegpu::uArch::Xe3>(uArch)) {
2179 aTy.getShape(), subgroupSize,
2180 aTy.getElementType().getIntOrFloatBitWidth(),
2181 uArchInstruction->getPackedFormatBitSizeA());
2183 bTy.getShape(), subgroupSize,
2184 bTy.getElementType().getIntOrFloatBitWidth(),
2185 uArchInstruction->getPackedFormatBitSizeB(),
true);
2187 cdTy.getShape(), subgroupSize,
2188 cdTy.getElementType().getIntOrFloatBitWidth(),
2189 cdTy.getElementType().getIntOrFloatBitWidth());
2191 assert(
false &&
"Unsupported uArch for DPAS lane layout completion");
2197 return std::nullopt;
2198 return std::make_tuple(
2200 aLayout.getOrder()),
2202 bLayout.getOrder()),
2204 cdLayout.getOrder()));
2211 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
2212 xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
2213 xegpu::DistributeLayoutAttr>>
2215 xegpu::DistributeLayoutAttr aLayout, xegpu::DistributeLayoutAttr bLayout,
2216 xegpu::DistributeLayoutAttr cdLayout, VectorType aTy, VectorType bTy,
2217 VectorType cdTy, VectorType aScaleTy, VectorType bScaleTy,
2220 aLayout, bLayout, cdLayout, aTy, bTy, cdTy, uArch);
2222 return std::nullopt;
2223 auto context = aTy.getContext();
2224 auto [completedA, completedB, completedCD] = *completed;
2231 return std::make_tuple(completedA, completedB, completedCD, aScaleLayout,
2363 auto srcShape = srcVecTy.getShape();
2364 int srcRank = srcShape.size();
2365 auto context = srcVecTy.getContext();
2367 const int subgroupSize =
uArch->getSubgroupSize();
2368 int64_t maxReduceVectorSize = 1;
2369 xegpu::DistributeLayoutAttr srcLayout;
2371 xegpu::SliceAttr consumerSliceLayout =
2372 dyn_cast_if_present<xegpu::SliceAttr>(consumerLayout);
2373 if (consumerSliceLayout &&
2374 consumerSliceLayout.getDims().asArrayRef().equals(reductionDims)) {
2375 srcLayout = consumerSliceLayout.getParent();
2377 srcLayout.getEffectiveSgLayoutAsInt();
2380 for (
int dim = 0; dim < srcRank; dim++) {
2381 if (llvm::is_contained(reductionDims, dim))
2383 srcLayout.setDimData(dim, srcSgData.value()[dim], -1, -1);
2387 consumerLayout ? consumerLayout.getEffectiveSgLayoutAsInt()
2390 consumerLayout ? consumerLayout.getEffectiveSgDataAsInt()
2393 consumerLayout ? consumerLayout.getEffectiveOrderAsInt()
2396 consumerLayout ? consumerLayout.getOrder() :
nullptr;
2398 int remainingSgCount =
2399 consumerLayout ? consumerLayout.getNumSubgroups() : numSg;
2400 int consumerIdx = 0;
2403 for (
int i = 0; i < srcRank; i++) {
2404 if (!llvm::is_contained(reductionDims, i) &&
2405 consumerIdx <
static_cast<int>(consumerSgLayout.size())) {
2406 sgLayout[i] = consumerSgLayout[consumerIdx];
2407 sgData[i] = consumerSgData[consumerIdx];
2408 remainingSgCount /= sgLayout[i];
2409 order[i] = consumerOrder[consumerIdx];
2416 int64_t remainOrder = consumerSgLayout.size();
2417 for (
int i = 0; i < srcRank; i++) {
2418 if (llvm::is_contained(reductionDims, i)) {
2420 std::min(srcShape[i],
static_cast<int64_t>(remainingSgCount));
2421 assert((srcShape[i] % sgLayout[i] == 0) &&
2422 "source shape not divisible by sg_layout");
2423 sgData[i] = srcShape[i] / sgLayout[i];
2424 remainingSgCount /= sgLayout[i];
2425 order[i] = remainOrder++;
2430 if (!orderAttr || orderAttr.empty())
2431 resOrderAttr =
nullptr;
2432 assert(remainingSgCount == 1 &&
"not all subgroups distributed");
2433 srcLayout =
buildLayout(context, sgLayout, sgData,
2438 xegpu::SliceAttr consumerSliceLayout =
2439 dyn_cast_if_present<xegpu::SliceAttr>(consumerLayout);
2440 auto consumerReductionDims =
2446 bool verticalLaneLayout = consumerReductionDims.empty() &&
2447 reductionDims.size() == 1 &&
2448 reductionDims[0] == (srcRank - 1);
2450 srcShape, reductionDims, subgroupSize, maxReduceVectorSize,
2451 verticalLaneLayout);
2455 for (
int i = 0; i < srcRank; i++)
2456 instData[i] = laneLayout[i] * laneData[i];
2463 "Lane reduction layout assumes all leading (non-innermost-two) "
2464 "dimensions are unit dimensions");
2465 xegpu::SliceAttr consumerSliceLayout =
2466 dyn_cast_if_present<xegpu::SliceAttr>(consumerLayout);
2467 auto consumerReductionDims =
2471 if (consumerSliceLayout &&
2472 consumerSliceLayout.getDims().asArrayRef().equals(reductionDims)) {
2476 srcLayout = consumerSliceLayout.getParent();
2478 bool verticalLaneLayout = consumerReductionDims.empty() &&
2479 reductionDims.size() == 1 &&
2480 reductionDims[0] == (srcRank - 1);
2482 srcShape, reductionDims, subgroupSize, maxReduceVectorSize,
2483 verticalLaneLayout);
2488 return xegpu::SliceAttr::get(context, srcLayout,
2496 VectorType srcVecTy,
2499 auto srcShape = srcVecTy.getShape();
2500 auto context = srcVecTy.getContext();
2501 auto subgroupSize =
uArch->getSubgroupSize();
2502 xegpu::LayoutAttr srcLayout;
2506 "subgroup layout assignment not supported for reduction (op "
2507 "is not expected at this level).");
2510 "instData layout assignment not supported for reduction (op "
2511 "is not expected at this level).");
2514 laneLayout[0] = std::min(
static_cast<int64_t>(subgroupSize), srcShape[0]);
2519 auto result = xegpu::SliceAttr::get(context, srcLayout,
2537static xegpu::DistributeLayoutAttr
2540 size_t innerMostDim,
int ratio,
int64_t bound,
2546 consumerLayout.getEffectiveLaneLayoutAsInt();
2553 sgDataValue = sgData[innerMostDim];
2554 while ((sgDataValue <= bound) && (sgDataValue % ratio) != 0)
2557 instDataValue = instData[innerMostDim];
2558 const int innermostDimLaneLayout = laneLayout.empty()
2560 : laneLayout[innerMostDim];
2561 while ((instDataValue <= bound) &&
2562 (instDataValue % (innermostDimLaneLayout * ratio) != 0))
2564 assert((bound % instDataValue) == 0 &&
2565 "bound, instData, and laneLayout for innermost must be 2^n!");
2567 laneDataValue = laneData[innerMostDim];
2568 while ((laneDataValue <= bound) && (laneDataValue % ratio) != 0)
2572 return consumerLayout.setDimData(innerMostDim, sgDataValue, instDataValue,
2602 int srcElemTyBitWidth = srcVecTy.getElementType().getIntOrFloatBitWidth();
2603 int resElemTyBitWidth = resVecTy.getElementType().getIntOrFloatBitWidth();
2608 assert(consumerLayout.getRank() ==
static_cast<int64_t>(srcShape.size()) &&
2609 "laneData must be available for all dimensions");
2613 if (srcElemTyBitWidth <= resElemTyBitWidth)
2614 return consumerLayout;
2619 size_t innerMostDim = srcShape.size() - 1;
2620 int bitWidthRatio = srcElemTyBitWidth / resElemTyBitWidth;
2622 innerMostDim, bitWidthRatio,
2623 resShape[innerMostDim],
uArch);
2646 assert(consumerLayout.getRank() ==
static_cast<int64_t>(resShape.size()) &&
2647 "consumer layout rank must match source shape rank");
2652 const size_t innerMostDim = resShape.size() - 1;
2653 constexpr int ratio = 2;
2655 innerMostDim, ratio,
2656 resShape[innerMostDim],
uArch);
2664 VectorType resVectorTy, xegpu::DistributeLayoutAttr consumerLayout,
2667 xegpu::DistributeLayoutAttr requiredResLayout;
2669 consumerLayout.getEffectiveInstDataAsInt();
2671 consumerLayout.getEffectiveLaneDataAsInt();
2673 consumerLayout.getEffectiveLaneLayoutAsInt();
2677 requiredResLayout = consumerLayout;
2678 int srcRank = srcShape.size();
2682 assert(
false &&
"subgroup/instData layout assignment not supported for "
2683 "insertStridedSlice.");
2685 for (
int dim = 0; dim < srcRank; dim++) {
2686 assert(srcShape[dim] % consumerLaneLayout[dim] == 0 &&
2687 "srcShape must be divisible by laneLayout for all dimensions");
2688 laneDataValue = std::min(srcShape[dim] / consumerLaneLayout[dim],
2689 consumerLaneData[dim]);
2691 requiredResLayout.setDimData(dim, -1, -1, laneDataValue);
2694 return requiredResLayout;
2704 OpOperand &operand, xegpu::DistributeLayoutAttr resLayout) {
2711 if (
auto broadcast = dyn_cast<vector::BroadcastOp>(op)) {
2712 auto srcTy = dyn_cast<VectorType>(
broadcast.getSourceType());
2716 resLayout,
broadcast.getResultVectorType().getShape(),
2723 if (
auto reduction = dyn_cast<vector::MultiDimReductionOp>(op)) {
2732 if (
auto reduction = dyn_cast<vector::ReductionOp>(op))
2737 if (
auto bitcast = dyn_cast<vector::BitCastOp>(op)) {
2738 int resElemBitWidth =
2739 bitcast.getResultVectorType().getElementType().getIntOrFloatBitWidth();
2740 int srcElemBitWidth =
2741 bitcast.getSourceVectorType().getElementType().getIntOrFloatBitWidth();
2748 if (
auto shapeCast = dyn_cast<vector::ShapeCastOp>(op)) {
2750 resLayout, shapeCast.getResultVectorType().getShape(),
2751 shapeCast.getSourceVectorType().getShape());
2756 if (
auto insertSlice = dyn_cast<vector::InsertStridedSliceOp>(op)) {
2759 resLayout, insertSlice.getDestVectorType().getShape(),
2760 insertSlice.getSourceVectorType().getShape());
2768 if (
auto insert = dyn_cast<vector::InsertOp>(op)) {
2769 VectorType resVecTy = dyn_cast<VectorType>(insert.getResult().getType());
2770 VectorType valueToStoreTy =
2771 dyn_cast<VectorType>(insert.getValueToStore().getType());
2773 if ((idx == 0) && valueToStoreTy) {
2775 valueToStoreTy.getShape());
2783 if (
auto extract = dyn_cast<vector::ExtractOp>(op)) {
2784 VectorType srcVecTy = dyn_cast<VectorType>(extract.getSource().getType());
2785 VectorType resVecTy = dyn_cast<VectorType>(extract.getResult().getType());
2786 if (!srcVecTy || !resVecTy)
2789 srcVecTy.getShape());
2794 if (
auto transpose = dyn_cast<vector::TransposeOp>(op)) {
2796 transpose.getPermutation());
2801 if (
auto bitcast = dyn_cast<vector::BitCastOp>(op)) {
2802 int resElemBitWidth =
2803 bitcast.getResultVectorType().getElementType().getIntOrFloatBitWidth();
2804 int srcElemBitWidth =
2805 bitcast.getSourceVectorType().getElementType().getIntOrFloatBitWidth();
2811 if (
auto interleave = dyn_cast<vector::InterleaveOp>(op)) {
2816 if (
auto deinterleave = dyn_cast<vector::DeinterleaveOp>(op)) {
2821 if (dyn_cast<vector::ExtractStridedSliceOp>(op))
2840 if (isa<xegpu::AnchorLayoutInterface>(op))
2844 xegpu::DistributeLayoutAttr resLayout;
2845 if (op->
getNumResults() == 1 || isa<vector::DeinterleaveOp>(op))
static void visit(Operation *op, DenseSet< Operation * > &visited)
Visits all the pdl.operand(s), pdl.result(s), and pdl.operation(s) connected to the given operation.
static Value broadcast(Location loc, Value toBroadcast, unsigned numElements, const TypeConverter &typeConverter, ConversionPatternRewriter &rewriter)
Broadcasts the value to vector with numElements number of elements.
static xegpu::LayoutAttr buildLayout(mlir::MLIRContext *context, ArrayRef< int64_t > sgLayout, ArrayRef< int64_t > sgData, ArrayRef< int64_t > instData, ArrayRef< int64_t > laneLayout, ArrayRef< int64_t > laneData, DenseI32ArrayAttr orderAttr=nullptr)
static xegpu::DistributeLayoutAttr getStoreSubgroupLayouts(mlir::MLIRContext *context, ArrayRef< int64_t > wgShape, ArrayRef< int64_t > instData, int numSg)
Picks the subgroup layout for a scatter-style store (store_scatter / store_matrix): the most balanced...
static xegpu::DistributeLayoutAttr createScaleLayout(mlir::MLIRContext *context, VectorType matrixTy, VectorType scaleTy, xegpu::DistributeLayoutAttr matrixLayout, bool isBScale, const xegpu::uArch::uArch *uArch)
Helper to create a scale layout derived from a matrix operand layout.
static bool leadingDimsAreUnit(ArrayRef< int64_t > shape, int numInnerDims)
Returns true if every dimension of shape except the innermost numInnerDims is a unit (size-1) dimensi...
static xegpu::DistributeLayoutAttr adjustInnermostDimForDivisibility(xegpu::DistributeLayoutAttr consumerLayout, xegpu::LayoutKind layoutKind, size_t innerMostDim, int ratio, int64_t bound, const xegpu::uArch::uArch *uArch)
Adjusts consumerLayout's innermost-dim data field selected by layoutKind so that the source layout ca...
static std::pair< SmallVector< int64_t >, SmallVector< int64_t > > compute2DBlockIOLaneLayoutAndData(ArrayRef< int64_t > instShape, int64_t subgroupSize, int64_t bitwidth, int64_t packingSize, bool transform=false)
static std::pair< SmallVector< int64_t >, SmallVector< int64_t > > computeScatterIOLaneLayoutAndData(ArrayRef< int64_t > instShape, int64_t subgroupSize, int64_t maxChunkSize)
Computes lane_layout and lane_data for scatter-style store anchor layouts (store scatter,...
static xegpu::LayoutAttr buildInstDataLayoutWithLane(mlir::MLIRContext *context, ArrayRef< int64_t > instData, ArrayRef< int64_t > laneLayout, ArrayRef< int64_t > laneData, DenseI32ArrayAttr orderAttr=nullptr)
static xegpu::LayoutAttr buildSgLayout(mlir::MLIRContext *context, ArrayRef< int64_t > wgTileShape, ArrayRef< int64_t > sgLayout, int dimK=-1, DenseI32ArrayAttr orderAttr=nullptr)
static std::pair< SmallVector< int64_t >, SmallVector< int64_t > > computeReductionLaneLayoutAndData(ArrayRef< int64_t > srcShape, ArrayRef< int64_t > reductionDims, int subgroupSize, int64_t maxReduceVectorSize, bool verticalLaneLayout=false)
Computes the (lane_layout, lane_data) for a multi-reduction's source layout.
static std::optional< SmallVector< int64_t > > get2DBlockIOInstDataLayout(ArrayRef< int64_t > dataShape, Type elemTy, const xegpu::uArch::BlockIOInstructionInterface *uArchInstruction, bool transform=false, bool transpose=false)
Helper function to compute inst_data vectors for DPAS operands A, B, and C/D.
static std::optional< std::tuple< xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr > > getDpasSubgroupLayouts(mlir::MLIRContext *context, VectorType aTy, VectorType bTy, VectorType cdTy, xegpu::DistributeLayoutAttr consumerLayout, int numSg, std::tuple< SmallVector< int64_t >, SmallVector< int64_t >, SmallVector< int64_t > > instDataVecs)
Helper function to set up subgroup layouts for DPAS operands A, B, and C/D.
static SmallVector< LayoutRepresentation > enumerateFactorizations(int64_t total, int64_t rank)
Enumerates all ways to split total into rank factors whose product equals total.
static xegpu::DistributeLayoutAttr setupGenericLoadAnchorLayout(xegpu::LayoutKind layoutKind, mlir::MLIRContext *context, xegpu::DistributeLayoutAttr consumerLayout, int maxChunkSize, ArrayRef< int64_t > resShape, int subgroupSize)
Sets up the anchor layout for load gather and load matrix operation.
SmallVector< int64_t > LayoutRepresentation
static xegpu::DistributeLayoutAttr getLayoutFromUsePoints(Value result)
static xegpu::DistributeLayoutAttr setupGenericStoreAnchorLayout(xegpu::LayoutKind layoutKind, mlir::MLIRContext *context, int maxChunkSize, ArrayRef< int64_t > srcShape, int subgroupSize, int numSg)
Sets up the anchor layout for store scatter and store matrix operation, which share the same logic.
static SmallVector< LayoutRepresentation > getSgLayoutCandidates(ArrayRef< int64_t > wgShape, ArrayRef< int64_t > instData, int64_t sgCount)
static void propagateResultsToRegularOperands(Operation *op)
static void propagateRegionResultsToYieldOperands(mlir::RegionBranchTerminatorOpInterface yieldOp)
static bool isValidLaneLayout(ArrayRef< int64_t > dataShape, ArrayRef< int64_t > laneLayout, ArrayRef< int64_t > laneData)
static void setTensorDescLayout(Value val, xegpu::DistributeLayoutAttr layout)
static void walkRegionBackward(Region ®ion, llvm::function_ref< void(Operation *)> visit)
static xegpu::LayoutAttr buildLaneLayout(mlir::MLIRContext *context, ArrayRef< int64_t > laneLayout, ArrayRef< int64_t > laneData, DenseI32ArrayAttr orderAttr=nullptr)
static std::optional< std::tuple< SmallVector< int64_t >, SmallVector< int64_t >, SmallVector< int64_t > > > getDpasInstDataLayouts(VectorType aTy, VectorType bTy, VectorType cdTy, const xegpu::uArch::MMAInstructionInterface *uArchInstruction)
Helper function to compute inst_data vectors for DPAS operands A, B, and C/D.
Block represents an ordered list of Operations.
MLIRContext is the top-level object for a collection of MLIR operations.
This class represents an operand of an operation.
unsigned getOperandNumber() const
Return which operand this is in the OpOperand list of the Operation.
This is a value defined by a result of an operation.
This class implements the operand iterators for the Operation class.
unsigned getBeginOperandIndex() const
Return the operand index of the first element of this range.
type_range getType() const
Operation is the basic unit of execution within MLIR.
bool hasAttrOfType(NameT &&name)
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
unsigned getNumRegions()
Returns the number of regions held by this operation.
MutableArrayRef< OpOperand > getOpOperands()
auto getDiscardableAttrs()
Return a range of all of discardable attributes on this operation.
Attribute removeDiscardableAttr(StringAttr name)
Remove the discardable attribute with the specified name if it exists.
operand_range getOperands()
Returns an iterator on the underlying Value's.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Attribute removeAttr(StringAttr name)
Remove the attribute with the specified name if it exists.
unsigned getNumResults()
Return the number of results held by this operation.
This class represents a point being branched from in the methods of the RegionBranchOpInterface.
This class represents a successor of a region.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
void setType(Type newType)
Mutate the type of this Value to be of the specified type.
Type getType() const
Return the type of this value.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Operation * getOwner() const
Return the owner of this operand.
bool hasElementwiseMappableTraits(Operation *op)
Together, Elementwise, Scalarizable, Vectorizable, and Tensorizable provide an easy way for scalar op...
@ Subgroup2DBlockPrefetch
@ SubgroupMatrixMultiplyAcc
@ SubgroupScaledMatrixMultiplyAcc
DistributeLayoutAttr inferShapeCastSourceLayout(DistributeLayoutAttr resLayout, ArrayRef< int64_t > resShape, ArrayRef< int64_t > srcShape)
Infers the source layout attribute for a shape cast operation given the result layout attribute,...
bool matchDimCollapse(ArrayRef< int64_t > src, ArrayRef< int64_t > dst, SmallVector< SmallVector< int64_t > > &collapseDims)
DistributeLayoutAttr setupLoadNdAnchorLayout(LayoutKind layoutKind, VectorType vectorTy, DistributeLayoutAttr consumerLayout, int numSg, const uArch::uArch *uArch)
Sets up the anchor layout for a load_nd operation.
DistributeLayoutAttr inferResultLayoutFromSourceForNonAnchorOp(Operation *op, ArrayRef< DistributeLayoutAttr > operandLayouts)
Infers the result layout attribute for a non-anchor operation from the layouts of its source operands...
DistributeLayoutAttr setupLoadMatrixAnchorLayout(LayoutKind layoutKind, VectorType vectorTy, int contigChunkSize, DistributeLayoutAttr consumerLayout, const uArch::uArch *uArch)
Sets up the anchor layout for load matrix operation.
DistributeLayoutAttr setupInterleaveResultLayout(LayoutKind layoutKind, VectorType srcVectorTy, VectorType resVectorTy, DistributeLayoutAttr consumerLayout, const uArch::uArch *uArch)
Sets up the result layout for an interleave operation to ensure the source layout can be safely deriv...
DistributeLayoutAttr inferTransposeSourceLayout(DistributeLayoutAttr resLayout, ArrayRef< int64_t > permutation)
Infers the source layout attribute for a transpose operation given the result layout attribute and pe...
DistributeLayoutAttr inferInsertSourceLayout(DistributeLayoutAttr resLayout, ArrayRef< int64_t > resShape, ArrayRef< int64_t > srcShape)
Infers the source layout attribute for an insert operation.
std::optional< std::tuple< DistributeLayoutAttr, DistributeLayoutAttr, DistributeLayoutAttr, DistributeLayoutAttr, DistributeLayoutAttr > > completeDpasMxLaneLayoutFromInstData(DistributeLayoutAttr aLayout, DistributeLayoutAttr bLayout, DistributeLayoutAttr cdLayout, VectorType aTy, VectorType bTy, VectorType cdTy, VectorType aScaleTy, VectorType bScaleTy, const uArch::uArch *uArch)
Like completeDpasLaneLayoutFromInstData, but for dpas_mx: additionally re-derives the A_scale / B_sca...
DistributeLayoutAttr inferInsertStridedSliceSourceLayout(DistributeLayoutAttr resLayout, ArrayRef< int64_t > resShape, ArrayRef< int64_t > srcShape)
Infers the source layout attribute for an insert strided slice operation given the result layout attr...
DistributeLayoutAttr setupStoreMatrixAnchorLayout(LayoutKind layoutKind, VectorType vectorTy, int contigChunkSize, int numSg, const uArch::uArch *uArch)
Sets up the anchor layout for a store matrix operation.
void removeTemporaryLayoutAttrs(Operation *op)
Removes the temporary layout attributes for each OpOperand and OpResult of the given operation.
std::optional< std::tuple< DistributeLayoutAttr, DistributeLayoutAttr, DistributeLayoutAttr > > completeDpasLaneLayoutFromInstData(DistributeLayoutAttr aLayout, DistributeLayoutAttr bLayout, DistributeLayoutAttr cdLayout, VectorType aTy, VectorType bTy, VectorType cdTy, const uArch::uArch *uArch)
Completes user-provided DPAS A/B/C-D anchors that carry only inst_data by filling in lane_layout / la...
void setTemporaryLayout(const T &operandOrResult, const DistributeLayoutAttr layout)
LayoutKind
Specifies the level of a layout hierarchy for comparison or propagation.
void setDistributeLayoutAttr(const OpResult &Result, const DistributeLayoutAttr layout)
[to-be-deprecated] Sets the DistributeLayoutAttr for a given OpResult user should use setAnchorLayout...
SmallVector< NamedAttribute > dropInstDataOnAttrs(ArrayRef< NamedAttribute > attrs)
Updates the NamedAttribute sequence by dropping inst-data information from any DistributeLayoutAttr f...
DistributeLayoutAttr inferSourceLayoutFromResultForNonAnchorOp(OpOperand &operand, DistributeLayoutAttr resLayout)
Infers the source layout attribute for an operand using result layout attribute.
DistributeLayoutAttr inferInterleaveSourceLayout(DistributeLayoutAttr resLayout)
Infers the source layout attribute for an interleave operation given the result layout attribute.
bool matchUnitDimExpansion(ArrayRef< int64_t > src, ArrayRef< int64_t > dst, SmallVector< int64_t > &expandedUnitDims)
int getLargestDivisor(T dim, ArrayRef< T > candidates, ArrayRef< T > candidateMultiples={})
Helper Function to find a proper instruction multiple for the user-supplied sg-level data shape (dive...
bool recoverTemporaryLayouts(Operation *rootOp)
Attach layout attributes to all vector-type operands of operations within the given operation's neste...
DistributeLayoutAttr inferBroadcastSourceLayout(DistributeLayoutAttr resLayout, ArrayRef< int64_t > resShape, ArrayRef< int64_t > srcShape)
Infers the source layout attribute for a broadcast operation given the result layout attribute,...
std::optional< std::tuple< DistributeLayoutAttr, DistributeLayoutAttr, DistributeLayoutAttr, DistributeLayoutAttr, DistributeLayoutAttr > > setupDpasMxLayout(LayoutKind layoutKind, VectorType aTy, VectorType bTy, VectorType cdTy, VectorType aScaleTy, VectorType bScaleTy, DistributeLayoutAttr consumerLayout, int numSg, const uArch::uArch *uArch)
Sets up the anchor layouts for dpas_mx operands (A, B, C/D, A_scale, and B_scale).
SliceAttr setupMultiReductionResultLayout(LayoutKind layoutKind, VectorType srcVectorTy, DistributeLayoutAttr consumerLayout, SmallVector< int64_t > reductionDims, int numSg, const uArch::uArch *uArch)
Note on the consumerLayout argument used by the consumer-driven setup* / complete* helpers below:
DistributeLayoutAttr setupLoadGatherAnchorLayout(LayoutKind layoutKind, VectorType vectorTy, int contigChunkSize, DistributeLayoutAttr consumerLayout, const uArch::uArch *uArch)
Sets up the anchor layout for a load gather operation.
llvm::function_ref< DistributeLayoutAttr(Value)> GetLayoutFnTy
Callable returning the propagated layout for a given Value, used by the layout-propagation helpers be...
std::optional< DistributeLayoutAttr > completeScatterLoadLaneLayoutFromInstData(DistributeLayoutAttr userSpecifiedLayout, DistributeLayoutAttr consumerLayout, Type elemTy, const xegpu::uArch::LoadGatherInstruction *uArchInstruction, const int subgroupSize)
If the consumer layout has only inst_data (no lane_layout/lane_data), completes it by running the cor...
bool matchSplitDimExpansion(ArrayRef< int64_t > src, ArrayRef< int64_t > dst, SmallVector< SmallVector< int64_t > > &splitDimGroups)
DistributeLayoutAttr setupStoreScatterAnchorLayout(LayoutKind layoutKind, VectorType vectorTy, int contigChunkSize, int numSg, const uArch::uArch *uArch)
Sets up the anchor layout for a store scatter operation.
DistributeLayoutAttr setupBitCastResultLayout(LayoutKind layoutKind, VectorType srcVectorTy, VectorType resVectorTy, DistributeLayoutAttr consumerLayout, const uArch::uArch *uArch)
Setup the result layout attribute for a bitcast operation based on element type bitwidths.
void removeLayoutAttr(const T &operandOrResult)
Removes the LayoutAttr for a given OpOperand or OpResult if it exists.
DistributeLayoutAttr inferMaskOffsetLayoutForScatterIO(DistributeLayoutAttr payloadLayout, int chunkSize)
Infers the layout attribute for mask and offset operand for Chunked load and store,...
DistributeLayoutAttr getDistributeLayoutAttr(const Value value)
Retrieves the DistributeLayoutAttr associated with a given Value.
SmallVector< NamedAttribute > dropSgLayoutAndDataOnAttrs(ArrayRef< NamedAttribute > attrs)
Updates the NamedAttribute sequence by dropping sg-layout and sg-data information from any Distribute...
DistributeLayoutAttr setupPrefetchNdAnchorLayout(LayoutKind layoutKind, TensorDescType tdescTy, int numSg, const uArch::uArch *uArch)
Sets up the anchor layout for a prefetch_nd operation.
LogicalResult propagateYieldOperandsToRegionResults(RegionBranchTerminatorOpInterface terminator, GetLayoutFnTy getLayoutOfValue)
Propagate layouts from a region branch terminator's forwarded operands to the matching region results...
DistributeLayoutAttr inferShapeCastResultLayout(DistributeLayoutAttr srcLayout, ArrayRef< int64_t > srcShape, ArrayRef< int64_t > resShape)
Infers the result layout attribute for a shape cast operation given the source layout attribute,...
DistributeLayoutAttr inferExtractSourceLayout(DistributeLayoutAttr resLayout, ArrayRef< int64_t > resShape, ArrayRef< int64_t > srcShape)
Infers the source layout attribute for an extract operation.
std::string getTemporaryLayoutName(const OpOperand &operand)
Return the attribute name for the OpOperand to attach DistributeLayoutAttr.
DistributeLayoutAttr inferBitCastSourceLayout(DistributeLayoutAttr resLayout, int resElemTyBitWidth, int srcElemTyBitWidth)
Infers the source layout attribute for a bitcast operation given the result layout attribute,...
DistributeLayoutAttr setupInsertStridedSliceResultLayout(LayoutKind layoutKind, VectorType srcVectorTy, VectorType resVectorTy, DistributeLayoutAttr consumerLayout, const uArch::uArch *uArch)
Sets up the result layout for an insert strided slice operation.
DistributeLayoutAttr inferReductionSourceLayout(DistributeLayoutAttr resLayout)
Infers the source layout attribute for a reduction operation given the result layout attribute and re...
std::optional< DistributeLayoutAttr > completeScatterStoreLaneLayoutFromInstData(DistributeLayoutAttr specifiedLayout, Type elemTy, const xegpu::uArch::StoreScatterInstruction *uArchInstruction, const int subgroupSize)
Like completeScatterLoadLaneLayoutFromInstData, but for scatter stores (store_scatter / store_matrix)...
std::optional< DistributeLayoutAttr > completeBlockStoreLaneLayoutFromInstData(DistributeLayoutAttr specifiedLayout, Type elemTy, const xegpu::uArch::BlockIOInstructionInterface *uArchInstruction, const int subgroupSize)
Completes a user-provided 2D-block store_nd / prefetch_nd anchor that has only inst_data.
DistributeLayoutAttr inferDeinterleaveSourceLayout(DistributeLayoutAttr resLayout)
Infers the source layout attribute for a deinterleave operation given the result layout attribute.
DistributeLayoutAttr getConsumerLayoutAt(OpOperand &operand)
Gets the expected layout for a given consumer operand.
void removeLayoutAttrs(Operation *op)
Removes the DistributeLayoutAttr for each OpOperand and OpResult of the given operation if they exist...
DistributeLayoutAttr inferMultiReductionSourceLayout(DistributeLayoutAttr resLayout, SmallVector< int64_t > reduceDims)
Infers the source layout attribute for a reduction operation given the result layout attribute and re...
bool isTriviallyRematerializable(Operation *op)
Returns true if op is safe and cheap to clone: it has no side effects, no regions,...
DistributeLayoutAttr setupStoreNdAnchorLayout(LayoutKind layoutKind, VectorType vectorTy, int numSg, const uArch::uArch *uArch)
Sets up the anchor layout for a store_nd operation.
DistributeLayoutAttr inferTransposeResultLayout(DistributeLayoutAttr srcLayout, ArrayRef< int64_t > permutation)
Infers the result layout attribute for a transpose operation given the source layout attribute and pe...
std::optional< DistributeLayoutAttr > completeBlockLoadLaneLayoutFromInstData(DistributeLayoutAttr specifiedLayout, DistributeLayoutAttr consumerLayout, Type elemTy, const xegpu::uArch::BlockIOInstructionInterface *uArchInstruction, const int subgroupSize)
Like completeBlockStoreLaneLayoutFromInstData, but for load_nd.
LogicalResult propagateRegionArgsToInits(RegionBranchOpInterface regionOp, GetLayoutFnTy getLayoutOfValue)
Propagate layouts from a region branch op's region entry block arguments back to its init operands.
std::optional< std::tuple< DistributeLayoutAttr, DistributeLayoutAttr, DistributeLayoutAttr > > setupDpasLayout(LayoutKind layoutKind, VectorType aTy, VectorType bTy, VectorType cdTy, DistributeLayoutAttr consumerLayout, int numSg, const uArch::uArch *uArch)
Sets up the anchor layouts for a dpas operands (A, B, and C/D).
SliceAttr setupReductionResultLayout(LayoutKind layoutKind, VectorType srcVectorTy, const uArch::uArch *uArch)
Sets up layout for Reduction operations by creating a SliceAttr for the result.
Include the generated interface declarations.
DenseMap< OpOperand *, SmallVector< Value > > RegionBranchSuccessorMapping
A mapping from successor operands to successor inputs.
AffineMap inversePermutation(AffineMap map)
Returns a map of codomain to domain dimensions such that the first codomain dimension for a particula...
bool isMemoryEffectFree(Operation *op)
Returns true if the given operation is free of memory effects.
detail::DenseArrayAttrImpl< int32_t > DenseI32ArrayAttr
std::optional< SmallVector< int64_t > > computeShapeRatio(ArrayRef< int64_t > shape, ArrayRef< int64_t > subShape)
Return the multi-dimensional integral ratio of subShape to the trailing dimensions of shape.
SmallVector< int64_t > invertPermutationVector(ArrayRef< int64_t > permutation)
Helper method to apply to inverse a permutation.
virtual int32_t getPackedFormatBitSize() const =0
std::optional< BlockShapes > getBlockWidthHeightCount(Type elemTy, bool hasTransform=false, bool hasTranspose=false, bool upConv=false) const
int32_t getMaxLaneAccessSizeBytes() const override
virtual llvm::SmallVector< uint32_t, 8 > getSupportedN(Type type) const =0
virtual llvm::SmallVector< uint32_t, 8 > getSupportedK(Type type) const =0
virtual llvm::SmallVector< uint32_t, 8 > getSupportedM(Type type) const =0
int32_t getMaxLaneAccessSizeBytes() const override
virtual int getSubgroupSize() const =0
const Instruction * getInstruction(InstructionKind instKind) const