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);
1081 int64_t rank = wgShape.size();
1082 assert(rank > 0 &&
"wgShape must be non-empty");
1083 assert(
static_cast<int64_t>(instData.size()) == rank &&
1084 "instData rank must match wgShape rank");
1091 for (
const auto &sgLayout : allFactorizations) {
1093 for (
int64_t dim = 0; dim < rank; ++dim) {
1097 if (dim == broadcastDim) {
1098 sgData = wgShape[dim];
1100 if (wgShape[dim] % sgLayout[dim] != 0) {
1104 sgData = wgShape[dim] / sgLayout[dim];
1106 if (sgData % instData[dim] != 0) {
1112 candidates.push_back(sgLayout);
1118 int64_t spreadLhs = *llvm::max_element(
lhs) - *llvm::min_element(
lhs);
1119 int64_t spreadRhs = *llvm::max_element(
rhs) - *llvm::min_element(
rhs);
1120 if (spreadLhs != spreadRhs)
1121 return spreadLhs < spreadRhs;
1132 bool transform =
false,
bool transpose =
false) {
1133 int rank = dataShape.size();
1137 return std::nullopt;
1138 auto [bWidths, bHeights, bCounts] = blockWHC.value();
1144 assert(rank >= 2 &&
"dataShape must be at least 2D for 2D-block IO");
1149 instData.back() = instWidth;
1150 instData[rank - 2] = instHeight;
1161 VectorType aTy, VectorType bTy, VectorType cdTy,
1165 const unsigned dataALen = aTy.getShape()[aTy.getRank() - 2];
1166 auto supportedALen = uArchInstruction->
getSupportedM(aTy.getElementType());
1171 const unsigned dataBLen = bTy.getShape().back();
1172 auto supportedBLen = uArchInstruction->
getSupportedN(bTy.getElementType());
1176 auto supportedCLen = uArchInstruction->
getSupportedN(cdTy.getElementType());
1179 if (maxALen == -1 || maxBLen == -1 || maxCLen == -1)
1180 return std::nullopt;
1182 auto supportedKLen = uArchInstruction->
getSupportedK(aTy.getElementType());
1183 if (supportedKLen.empty())
1184 return std::nullopt;
1185 auto kDimSize = supportedKLen[0];
1188 instDataA[aTy.getRank() - 2] = maxALen;
1189 instDataA[aTy.getRank() - 1] = kDimSize;
1191 instDataB[bTy.getRank() - 2] = kDimSize;
1192 instDataB[bTy.getRank() - 1] = maxBLen;
1194 instDataCD[cdTy.getRank() - 2] = maxALen;
1195 instDataCD[cdTy.getRank() - 1] = maxCLen;
1196 return std::make_tuple(instDataA, instDataB, instDataCD);
1209 int64_t rank = instShape.size();
1212 laneLayout[innermost] = std::min(subgroupSize, instShape[innermost]);
1213 laneData[innermost] =
1214 std::min(instShape[innermost] / laneLayout[innermost], maxChunkSize);
1215 return {laneLayout, laneData};
1225 int64_t rank = instShape.size();
1227 int kDim =
transform ? rank - 2 : rank - 1;
1228 unsigned vnniFactor = packingSize / bitwidth;
1229 laneData[kDim] = bitwidth < packingSize ? vnniFactor : 1;
1231 std::min(subgroupSize, instShape.back() / laneData.back());
1234 for (
int64_t i = 0; i < rank; ++i) {
1235 int64_t laneProduct = laneLayout[i] * laneData[i];
1236 assert(instShape[i] % laneProduct == 0 &&
1237 "lane_layout * lane_data must evenly divide the inst shape");
1240 return {laneLayout, laneData};
1259 int subgroupSize,
int64_t maxReduceVectorSize,
1260 bool verticalLaneLayout =
false) {
1261 int srcRank = srcShape.size();
1264 int innermost = srcRank - 1;
1265 int secondInnermost = srcRank - 2;
1267 if (verticalLaneLayout && secondInnermost >= 0) {
1268 std::swap(innermost, secondInnermost);
1270 int laneDim = innermost;
1271 int vectorDim = secondInnermost;
1273 laneLayout[laneDim] =
1274 std::min(
static_cast<int64_t>(subgroupSize), srcShape[laneDim]);
1276 laneData[vectorDim] = std::min(maxReduceVectorSize, srcShape[vectorDim]);
1278 return {laneLayout, laneData};
1344static std::optional<
1345 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
1346 xegpu::DistributeLayoutAttr>>
1349 xegpu::DistributeLayoutAttr consumerLayout,
int numSg,
1352 auto [instDataA, instDataB, instDataCD] = instDataVecs;
1354 std::optional<LayoutRepresentation> consumerSgLayout = std::nullopt;
1355 if (consumerLayout && consumerLayout.isForWorkgroup()) {
1356 consumerSgLayout = consumerLayout.getEffectiveSgLayoutAsInt();
1365 if (layoutsA.empty() || layoutsB.empty() || layoutsCD.empty())
1366 return std::nullopt;
1369 std::optional<LayoutRepresentation> bestPick;
1370 for (
auto &sgLayout : layoutsB) {
1371 if (llvm::is_contained(layoutsA, sgLayout) &&
1372 llvm::is_contained(layoutsCD, sgLayout)) {
1374 if (consumerSgLayout.has_value() && sgLayout == *consumerSgLayout) {
1375 bestPick = sgLayout;
1383 bestPick = sgLayout;
1387 return std::nullopt;
1389 const auto &picked = *bestPick;
1391 auto dpasALayout =
buildSgLayout(context, aTy.getShape(), picked,
1393 auto dpasBLayout =
buildSgLayout(context, bTy.getShape(), picked,
1395 auto dpasCDLayout =
buildSgLayout(context, cdTy.getShape(), picked);
1396 return std::make_tuple(dpasALayout, dpasBLayout, dpasCDLayout);
1403 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
1404 xegpu::DistributeLayoutAttr>>
1406 VectorType bTy, VectorType cdTy,
1407 xegpu::DistributeLayoutAttr consumerLayout,
int numSg,
1409 auto context = aTy.getContext();
1410 const auto *uArchInstruction =
1411 dyn_cast<xegpu::uArch::SubgroupMatrixMultiplyAcc>(uArch->
getInstruction(
1413 if (!uArchInstruction)
1414 return std::nullopt;
1418 aTy.getShape(), subgroupSize,
1419 aTy.getElementType().getIntOrFloatBitWidth(),
1420 uArchInstruction->getPackedFormatBitSizeA());
1422 bTy.getShape(), subgroupSize,
1423 bTy.getElementType().getIntOrFloatBitWidth(),
1424 uArchInstruction->getPackedFormatBitSizeB(),
true);
1426 cdTy.getShape(), subgroupSize,
1427 cdTy.getElementType().getIntOrFloatBitWidth(),
1428 cdTy.getElementType().getIntOrFloatBitWidth());
1432 return std::nullopt;
1436 "Number of subgroups must be provided for sg layout creation.");
1438 numSg, *instDataVecs);
1440 auto [instDataA, instDataB, instDataCD] = *instDataVecs;
1441 return std::make_tuple(
1450 return std::make_tuple(aLayout, bLayout, cdLayout);
1452 return std::nullopt;
1459static xegpu::DistributeLayoutAttr
1461 VectorType scaleTy, xegpu::DistributeLayoutAttr matrixLayout,
1463 if (!scaleTy || !matrixLayout)
1471 if (scaleShape.empty())
1474 auto uArchInstruction =
1475 dyn_cast<xegpu::uArch::SubgroupScaledMatrixMultiplyAcc>(
1479 int64_t rank = matrixLayout.getRank();
1480 assert(rank >= 2 &&
"dpas layouts must be at least two dimensions");
1487 auto order = matrixLayout.getOrder();
1491 if (!sgLayout.empty() && !sgData.empty()) {
1492 scaleSgLayout.assign(sgLayout.begin(), sgLayout.end());
1493 scaleSgData.assign(sgData.begin(), sgData.end());
1494 scaleSgData[rank - 2] = std::max<int64_t>(
1495 scaleShape[rank - 2] / (matrixShape[rank - 2] / sgData[rank - 2]), 1);
1496 scaleSgData[rank - 1] = std::max<int64_t>(
1497 scaleShape[rank - 1] / (matrixShape[rank - 1] / sgData[rank - 1]), 1);
1504 if (!instData.empty()) {
1505 scaleInstData.assign(instData.begin(), instData.end());
1507 scaleInstData[rank - 2] = std::max<int64_t>(
1508 scaleShape[rank - 2] / (matrixShape[rank - 2] / instData[rank - 2]),
1511 scaleInstData[rank - 1] = std::max<int64_t>(
1512 scaleShape[rank - 1] / (matrixShape[rank - 1] / instData[rank - 1]),
1518 if (!laneLayout.empty() && !laneData.empty()) {
1519 scaleLaneLayout.assign(laneLayout.begin(), laneLayout.end());
1520 scaleLaneData.assign(laneData.size(), 1);
1522 bool isRowMajor = uArchInstruction->isLaneLayoutRowMajorOrder();
1523 if (isBScale ^ isRowMajor)
1524 std::swap(scaleLaneLayout[rank - 2], scaleLaneLayout[rank - 1]);
1529 auto layoutCap = scaleInstData.empty() ? scaleShape : scaleInstData;
1530 for (
int64_t d = rank - 2; d < rank; ++d)
1531 scaleLaneLayout[d] = std::min<int64_t>(layoutCap[d], scaleLaneLayout[d]);
1533 return buildLayout(context, scaleSgLayout, scaleSgData, scaleInstData,
1534 scaleLaneLayout, scaleLaneData, order);
1541 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
1542 xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
1543 xegpu::DistributeLayoutAttr>>
1545 VectorType bTy, VectorType cdTy, VectorType aScaleTy,
1546 VectorType bScaleTy,
1547 xegpu::DistributeLayoutAttr consumerLayout,
int numSg,
1549 auto context = aTy.getContext();
1550 const auto *uArchInstruction =
1551 dyn_cast<xegpu::uArch::SubgroupMatrixMultiplyAcc>(uArch->
getInstruction(
1553 if (!uArchInstruction)
1554 return std::nullopt;
1558 aTy.getShape(), subgroupSize,
1559 aTy.getElementType().getIntOrFloatBitWidth(),
1560 uArchInstruction->getPackedFormatBitSizeA());
1562 bTy.getShape(), subgroupSize,
1563 bTy.getElementType().getIntOrFloatBitWidth(),
1564 uArchInstruction->getPackedFormatBitSizeB(),
true);
1566 cdTy.getShape(), subgroupSize,
1567 cdTy.getElementType().getIntOrFloatBitWidth(),
1568 cdTy.getElementType().getIntOrFloatBitWidth());
1571 return std::nullopt;
1575 "Number of subgroups must be provided for sg layout creation.");
1577 context, aTy, bTy, cdTy, consumerLayout, numSg, *instDataVecs);
1579 return std::nullopt;
1581 auto [dpasALayout, dpasBLayout, dpasCDLayout] = *dpasLayouts;
1590 return std::make_tuple(dpasALayout, dpasBLayout, dpasCDLayout, aScaleLayout,
1594 auto [instDataA, instDataB, instDataCD] = *instDataVecs;
1601 laneLayoutCD, laneDataCD);
1608 return std::make_tuple(dpasALayout, dpasBLayout, dpasCDLayout, aScaleLayout,
1613 auto dpasCDLayout =
buildLaneLayout(context, laneLayoutCD, laneDataCD);
1620 return std::make_tuple(dpasALayout, dpasBLayout, dpasCDLayout, aScaleLayout,
1623 return std::nullopt;
1629xegpu::DistributeLayoutAttr
1631 VectorType srcVecTy,
int numSg,
1633 const auto *uArchInstruction =
1634 dyn_cast<xegpu::uArch::Subgroup2DBlockStoreInstruction>(
1635 uArch->getInstruction(
1637 if (!uArchInstruction)
1640 auto context = srcVecTy.getContext();
1641 Type elemTy = srcVecTy.getElementType();
1642 auto subgroupSize =
uArch->getSubgroupSize();
1643 auto dataShape = srcVecTy.getShape();
1644 [[maybe_unused]]
int rank = srcVecTy.getRank();
1645 assert(rank >= 2 &&
"Expected at least 2D shape for ND op");
1650 dataShape, subgroupSize, bitwidth,
1651 uArchInstruction->getPackedFormatBitSize());
1661 "Expected the store layout to satisfy uArch block constraints");
1668 "Number of subgroups must be provided for sg layout creation.");
1670 if (sgLayouts.empty())
1672 return buildSgLayout(context, dataShape, sgLayouts.front(), -1);
1681xegpu::DistributeLayoutAttr
1683 xegpu::TensorDescType tdescTy,
int numSg,
1686 const auto *uArchInstruction =
1687 dyn_cast<xegpu::uArch::Subgroup2DBlockPrefetchInstruction>(
1690 if (!uArchInstruction)
1693 auto context = tdescTy.getContext();
1694 Type elemTy = tdescTy.getElementType();
1696 auto dataShape = tdescTy.getShape();
1697 [[maybe_unused]]
int rank = tdescTy.getRank();
1698 assert(rank >= 2 &&
"Expected at least 2D shape for ND op");
1703 dataShape, subgroupSize, bitwidth,
1704 uArchInstruction->getPackedFormatBitSize());
1714 "Expected the prefetch layout to satisfy uArch block constraints");
1721 "Number of subgroups must be provided for sg layout creation.");
1723 if (sgLayouts.empty())
1725 return buildSgLayout(context, dataShape, sgLayouts.front(), -1);
1736xegpu::DistributeLayoutAttr
1738 VectorType resVecTy,
1739 xegpu::DistributeLayoutAttr consumerLayout,
1742 assert(consumerLayout &&
"Expected a valid consumer layout");
1744 assert(consumerLayout.isForWorkgroup() &&
1745 "Expected consumer layout to be a complete workgroup-level layout");
1746 return consumerLayout;
1749 auto context = resVecTy.getContext();
1750 Type elemTy = resVecTy.getElementType();
1752 auto dataShape = resVecTy.getShape();
1753 const auto *uArchInstruction =
1754 dyn_cast<xegpu::uArch::Subgroup2DBlockLoadInstruction>(
1757 if (!uArchInstruction)
1760 int rank = resVecTy.getRank();
1762 consumerLayout.getEffectiveInstDataAsInt();
1764 consumerLayout.getEffectiveLaneLayoutAsInt();
1766 consumerLayout.getEffectiveLaneDataAsInt();
1767 auto consumerOrderAttr = consumerLayout.getOrder();
1769 assert(!consumerLaneLayout.empty() && !consumerLaneData.empty() &&
1770 "Expected consumer layout to have lane_layout and lane_data");
1776 consumerLaneLayout[rank - 2] > 1 && consumerLaneLayout[rank - 1] == 1;
1777 bool hasTransform = !hasTranspose && consumerLaneData[rank - 2] > 1 &&
1778 consumerLaneData[rank - 1] == 1;
1779 assert((consumerLaneData[rank - 2] == 1 || consumerLaneData[rank - 1] == 1) &&
1780 "Expected consumer lane data to have at most one non-unit dim");
1783 auto blockWHC = uArchInstruction->getBlockWidthHeightCount(
1784 elemTy, hasTransform, hasTranspose,
1788 auto [bWidths, bHeights, bCounts] = blockWHC.value();
1794 for (
int i = 0; i < rank; i++) {
1795 if (consumerLaneLayout[i] > 1)
1796 laneLayout.push_back(std::max(
static_cast<int64_t>(subgroupSize),
1797 consumerLaneLayout[i]));
1799 laneLayout.push_back(1);
1803 int64_t height = consumerInstData[rank - 2];
1804 int64_t width = consumerInstData[rank - 1];
1805 auto maxBlockCount = *llvm::max_element(bCounts);
1806 auto maxWidth = *llvm::max_element(bWidths);
1807 if (llvm::is_contained(bWidths,
static_cast<int>(width)) ||
1808 (width % maxWidth == 0 && width / maxWidth < maxBlockCount)) {
1809 if (llvm::is_contained(bHeights,
static_cast<int>(height))) {
1811 laneLayout, consumerLaneData,
1819 dataShape, elemTy, uArchInstruction, hasTransform, hasTranspose);
1824 "Expected the load layout to satisfy uArch block constraints");
1826 consumerLaneData, consumerOrderAttr);
1830 "Expected the lane layout to satisfy uArch block constraints");
1831 return consumerLayout;
1851 xegpu::DistributeLayoutAttr consumerLayout,
int maxChunkSize,
1855 return consumerLayout;
1858 consumerLayout.getEffectiveInstDataAsInt();
1860 consumerLayout.getEffectiveLaneLayoutAsInt();
1862 consumerLayout.getEffectiveLaneDataAsInt();
1866 assert(!consumerLaneLayout.empty() && !consumerLaneData.empty() &&
1867 "Expected consumer layout to have lane_layout and lane_data");
1868 laneLayout.assign(consumerLaneLayout.begin(), consumerLaneLayout.end());
1869 laneData.assign(consumerLaneData.begin(), consumerLaneData.end());
1873 instData.resize(resShape.size());
1874 for (
size_t i = 0; i < resShape.size(); ++i)
1875 instData[i] = laneLayout[i] * laneData[i];
1886 xegpu::DistributeLayoutAttr consumerLayout,
const uArch::uArch *uArch) {
1888 const int subgroupSize = uArch->getSubgroupSize();
1890 auto context = resVecTy.getContext();
1892 const auto *uArchInstruction = dyn_cast<xegpu::uArch::LoadGatherInstruction>(
1895 std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
1898 maxChunkSize, resShape, subgroupSize);
1903xegpu::DistributeLayoutAttr
1905 VectorType resVecTy,
int contigChunkSize,
1906 xegpu::DistributeLayoutAttr consumerLayout,
1911 auto context = resVecTy.getContext();
1913 const auto *uArchInstruction = dyn_cast<xegpu::uArch::LoadGatherInstruction>(
1916 std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
1918 maxChunkSize, resShape, subgroupSize);
1924static xegpu::DistributeLayoutAttr
1928 if (candidates.empty())
1931 return buildSgLayout(context, wgShape, candidates.front(), -1);
1941 auto [laneLayout, laneData] =
1945 for (
size_t i = 0; i < srcShape.size(); ++i)
1946 instData[i] = laneLayout[i] * laneData[i];
1950 "Number of subgroups must be provided for sg layout creation.");
1963xegpu::DistributeLayoutAttr
1965 VectorType srcVecTy,
int contigChunkSize,
1968 const int subgroupSize =
uArch->getSubgroupSize();
1970 auto context = srcVecTy.getContext();
1972 const auto *uArchInstruction =
1973 dyn_cast<xegpu::uArch::StoreScatterInstruction>(
1976 std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
1978 srcShape, subgroupSize, numSg);
1986 const int subgroupSize =
uArch->getSubgroupSize();
1988 auto context = srcVecTy.getContext();
1990 const auto *uArchInstruction =
1991 dyn_cast<xegpu::uArch::StoreScatterInstruction>(
1994 std::min(uArchInstruction->getMaxLaneAccessSizeBytes(), contigChunkSize);
1997 srcShape, subgroupSize, numSg);
2015std::optional<xegpu::DistributeLayoutAttr>
2017 xegpu::DistributeLayoutAttr specifiedLayout,
2018 xegpu::DistributeLayoutAttr consumerLayout,
Type elemTy,
2020 const int subgroupSize) {
2021 if (!specifiedLayout)
2022 return specifiedLayout;
2024 specifiedLayout.getEffectiveInstDataAsInt();
2025 if (specifiedInstData.empty())
2026 return specifiedLayout;
2027 if (!specifiedLayout.getEffectiveLaneLayoutAsInt().empty() &&
2028 !specifiedLayout.getEffectiveLaneDataAsInt().empty())
2029 return specifiedLayout;
2032 auto *context = specifiedLayout.getContext();
2034 if (consumerLayout) {
2035 auto consumerLaneLayout = consumerLayout.getEffectiveLaneLayoutAsInt();
2036 auto consumerLaneData = consumerLayout.getEffectiveLaneDataAsInt();
2037 if (!consumerLaneLayout.empty() && !consumerLaneData.empty() &&
2041 consumerLaneLayout, consumerLaneData);
2044 specifiedInstData, subgroupSize, maxChunkSize);
2046 return std::nullopt;
2054std::optional<xegpu::DistributeLayoutAttr>
2056 xegpu::DistributeLayoutAttr specifiedLayout,
Type elemTy,
2058 const int subgroupSize) {
2059 if (!specifiedLayout)
2060 return specifiedLayout;
2062 specifiedLayout.getEffectiveInstDataAsInt();
2063 if (specifiedInstData.empty())
2064 return specifiedLayout;
2065 if (!specifiedLayout.getEffectiveLaneLayoutAsInt().empty() &&
2066 !specifiedLayout.getEffectiveLaneDataAsInt().empty())
2067 return specifiedLayout;
2070 auto *context = specifiedLayout.getContext();
2073 specifiedInstData, subgroupSize, maxChunkSize);
2075 return std::nullopt;
2084std::optional<xegpu::DistributeLayoutAttr>
2086 xegpu::DistributeLayoutAttr specifiedLayout,
Type elemTy,
2088 const int subgroupSize) {
2089 if (!specifiedLayout)
2090 return specifiedLayout;
2092 specifiedLayout.getEffectiveInstDataAsInt();
2093 if (specifiedInstData.empty())
2094 return specifiedLayout;
2095 if (!specifiedLayout.getEffectiveLaneLayoutAsInt().empty() &&
2096 !specifiedLayout.getEffectiveLaneDataAsInt().empty())
2097 return specifiedLayout;
2099 auto *context = specifiedLayout.getContext();
2104 return std::nullopt;
2113std::optional<xegpu::DistributeLayoutAttr>
2115 xegpu::DistributeLayoutAttr specifiedLayout,
2116 xegpu::DistributeLayoutAttr consumerLayout,
Type elemTy,
2118 const int subgroupSize) {
2119 if (!specifiedLayout)
2120 return specifiedLayout;
2122 specifiedLayout.getEffectiveInstDataAsInt();
2123 if (specifiedInstData.empty())
2124 return specifiedLayout;
2125 if (!specifiedLayout.getEffectiveLaneLayoutAsInt().empty() &&
2126 !specifiedLayout.getEffectiveLaneDataAsInt().empty())
2127 return specifiedLayout;
2128 if (!consumerLayout)
2129 return specifiedLayout;
2131 consumerLayout.getEffectiveLaneLayoutAsInt();
2133 consumerLayout.getEffectiveLaneDataAsInt();
2134 if (consumerLaneLayout.empty() || consumerLaneData.empty())
2135 return specifiedLayout;
2137 auto *context = specifiedLayout.getContext();
2138 int rank = specifiedInstData.size();
2143 for (
int i = 0; i < rank; i++) {
2144 if (consumerLaneLayout[i] > 1) {
2145 laneLayout.push_back(
2146 std::max(
static_cast<int64_t>(subgroupSize), consumerLaneLayout[i]));
2148 laneLayout.push_back(1);
2153 return std::nullopt;
2156 consumerLayout.getOrder());
2164 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
2165 xegpu::DistributeLayoutAttr>>
2167 xegpu::DistributeLayoutAttr bLayout,
2168 xegpu::DistributeLayoutAttr cdLayout,
2169 VectorType aTy, VectorType bTy,
2172 auto context = aTy.getContext();
2173 const auto *uArchInstruction =
2174 dyn_cast<xegpu::uArch::SubgroupMatrixMultiplyAcc>(uArch->
getInstruction(
2176 if (!uArchInstruction)
2177 return std::nullopt;
2180 laneLayoutCD, laneDataCD;
2185 if (isa<xegpu::uArch::Xe2, xegpu::uArch::Xe3>(uArch)) {
2187 aTy.getShape(), subgroupSize,
2188 aTy.getElementType().getIntOrFloatBitWidth(),
2189 uArchInstruction->getPackedFormatBitSizeA());
2191 bTy.getShape(), subgroupSize,
2192 bTy.getElementType().getIntOrFloatBitWidth(),
2193 uArchInstruction->getPackedFormatBitSizeB(),
true);
2195 cdTy.getShape(), subgroupSize,
2196 cdTy.getElementType().getIntOrFloatBitWidth(),
2197 cdTy.getElementType().getIntOrFloatBitWidth());
2199 assert(
false &&
"Unsupported uArch for DPAS lane layout completion");
2205 return std::nullopt;
2206 return std::make_tuple(
2208 aLayout.getOrder()),
2210 bLayout.getOrder()),
2212 cdLayout.getOrder()));
2219 std::tuple<xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
2220 xegpu::DistributeLayoutAttr, xegpu::DistributeLayoutAttr,
2221 xegpu::DistributeLayoutAttr>>
2223 xegpu::DistributeLayoutAttr aLayout, xegpu::DistributeLayoutAttr bLayout,
2224 xegpu::DistributeLayoutAttr cdLayout, VectorType aTy, VectorType bTy,
2225 VectorType cdTy, VectorType aScaleTy, VectorType bScaleTy,
2228 aLayout, bLayout, cdLayout, aTy, bTy, cdTy, uArch);
2230 return std::nullopt;
2231 auto context = aTy.getContext();
2232 auto [completedA, completedB, completedCD] = *completed;
2239 return std::make_tuple(completedA, completedB, completedCD, aScaleLayout,
2371 auto srcShape = srcVecTy.getShape();
2372 int srcRank = srcShape.size();
2373 auto context = srcVecTy.getContext();
2375 const int subgroupSize =
uArch->getSubgroupSize();
2376 int64_t maxReduceVectorSize = 1;
2377 xegpu::DistributeLayoutAttr srcLayout;
2379 xegpu::SliceAttr consumerSliceLayout =
2380 dyn_cast_if_present<xegpu::SliceAttr>(consumerLayout);
2381 if (consumerSliceLayout &&
2382 consumerSliceLayout.getDims().asArrayRef().equals(reductionDims)) {
2383 srcLayout = consumerSliceLayout.getParent();
2385 srcLayout.getEffectiveSgLayoutAsInt();
2388 for (
int dim = 0; dim < srcRank; dim++) {
2389 if (llvm::is_contained(reductionDims, dim))
2391 srcLayout.setDimData(dim, srcSgData.value()[dim], -1, -1);
2395 consumerLayout ? consumerLayout.getEffectiveSgLayoutAsInt()
2398 consumerLayout ? consumerLayout.getEffectiveSgDataAsInt()
2401 consumerLayout ? consumerLayout.getEffectiveOrderAsInt()
2404 consumerLayout ? consumerLayout.getOrder() :
nullptr;
2406 int remainingSgCount =
2407 consumerLayout ? consumerLayout.getNumSubgroups() : numSg;
2408 int consumerIdx = 0;
2411 for (
int i = 0; i < srcRank; i++) {
2412 if (!llvm::is_contained(reductionDims, i) &&
2413 consumerIdx <
static_cast<int>(consumerSgLayout.size())) {
2414 sgLayout[i] = consumerSgLayout[consumerIdx];
2415 sgData[i] = consumerSgData[consumerIdx];
2416 remainingSgCount /= sgLayout[i];
2417 order[i] = consumerOrder[consumerIdx];
2424 int64_t remainOrder = consumerSgLayout.size();
2425 for (
int i = 0; i < srcRank; i++) {
2426 if (llvm::is_contained(reductionDims, i)) {
2428 std::min(srcShape[i],
static_cast<int64_t>(remainingSgCount));
2429 assert((srcShape[i] % sgLayout[i] == 0) &&
2430 "source shape not divisible by sg_layout");
2431 sgData[i] = srcShape[i] / sgLayout[i];
2432 remainingSgCount /= sgLayout[i];
2433 order[i] = remainOrder++;
2438 if (!orderAttr || orderAttr.empty())
2439 resOrderAttr =
nullptr;
2440 assert(remainingSgCount == 1 &&
"not all subgroups distributed");
2441 srcLayout =
buildLayout(context, sgLayout, sgData,
2446 xegpu::SliceAttr consumerSliceLayout =
2447 dyn_cast_if_present<xegpu::SliceAttr>(consumerLayout);
2448 auto consumerReductionDims =
2454 bool verticalLaneLayout = consumerReductionDims.empty() &&
2455 reductionDims.size() == 1 &&
2456 reductionDims[0] == (srcRank - 1);
2458 srcShape, reductionDims, subgroupSize, maxReduceVectorSize,
2459 verticalLaneLayout);
2463 for (
int i = 0; i < srcRank; i++)
2464 instData[i] = laneLayout[i] * laneData[i];
2471 "Lane reduction layout assumes all leading (non-innermost-two) "
2472 "dimensions are unit dimensions");
2473 xegpu::SliceAttr consumerSliceLayout =
2474 dyn_cast_if_present<xegpu::SliceAttr>(consumerLayout);
2475 auto consumerReductionDims =
2479 if (consumerSliceLayout &&
2480 consumerSliceLayout.getDims().asArrayRef().equals(reductionDims)) {
2484 srcLayout = consumerSliceLayout.getParent();
2486 bool verticalLaneLayout = consumerReductionDims.empty() &&
2487 reductionDims.size() == 1 &&
2488 reductionDims[0] == (srcRank - 1);
2490 srcShape, reductionDims, subgroupSize, maxReduceVectorSize,
2491 verticalLaneLayout);
2496 return xegpu::SliceAttr::get(context, srcLayout,
2504 VectorType srcVecTy,
2507 auto srcShape = srcVecTy.getShape();
2508 auto context = srcVecTy.getContext();
2509 auto subgroupSize =
uArch->getSubgroupSize();
2510 xegpu::LayoutAttr srcLayout;
2514 "subgroup layout assignment not supported for reduction (op "
2515 "is not expected at this level).");
2518 "instData layout assignment not supported for reduction (op "
2519 "is not expected at this level).");
2522 laneLayout[0] = std::min(
static_cast<int64_t>(subgroupSize), srcShape[0]);
2527 auto result = xegpu::SliceAttr::get(context, srcLayout,
2545static xegpu::DistributeLayoutAttr
2548 size_t innerMostDim,
int ratio,
int64_t bound,
2554 consumerLayout.getEffectiveLaneLayoutAsInt();
2561 sgDataValue = sgData[innerMostDim];
2562 while ((sgDataValue <= bound) && (sgDataValue % ratio) != 0)
2565 instDataValue = instData[innerMostDim];
2566 const int innermostDimLaneLayout = laneLayout.empty()
2568 : laneLayout[innerMostDim];
2569 while ((instDataValue <= bound) &&
2570 (instDataValue % (innermostDimLaneLayout * ratio) != 0))
2572 assert((bound % instDataValue) == 0 &&
2573 "bound, instData, and laneLayout for innermost must be 2^n!");
2575 laneDataValue = laneData[innerMostDim];
2576 while ((laneDataValue <= bound) && (laneDataValue % ratio) != 0)
2580 return consumerLayout.setDimData(innerMostDim, sgDataValue, instDataValue,
2610 int srcElemTyBitWidth = srcVecTy.getElementType().getIntOrFloatBitWidth();
2611 int resElemTyBitWidth = resVecTy.getElementType().getIntOrFloatBitWidth();
2616 assert(consumerLayout.getRank() ==
static_cast<int64_t>(srcShape.size()) &&
2617 "laneData must be available for all dimensions");
2621 if (srcElemTyBitWidth <= resElemTyBitWidth)
2622 return consumerLayout;
2627 size_t innerMostDim = srcShape.size() - 1;
2628 int bitWidthRatio = srcElemTyBitWidth / resElemTyBitWidth;
2630 innerMostDim, bitWidthRatio,
2631 resShape[innerMostDim],
uArch);
2654 assert(consumerLayout.getRank() ==
static_cast<int64_t>(resShape.size()) &&
2655 "consumer layout rank must match source shape rank");
2660 const size_t innerMostDim = resShape.size() - 1;
2661 constexpr int ratio = 2;
2663 innerMostDim, ratio,
2664 resShape[innerMostDim],
uArch);
2672 VectorType resVectorTy, xegpu::DistributeLayoutAttr consumerLayout,
2675 xegpu::DistributeLayoutAttr requiredResLayout;
2677 consumerLayout.getEffectiveInstDataAsInt();
2679 consumerLayout.getEffectiveLaneDataAsInt();
2681 consumerLayout.getEffectiveLaneLayoutAsInt();
2685 requiredResLayout = consumerLayout;
2686 int srcRank = srcShape.size();
2690 assert(
false &&
"subgroup/instData layout assignment not supported for "
2691 "insertStridedSlice.");
2693 for (
int dim = 0; dim < srcRank; dim++) {
2695 if (srcShape[dim] == 1) {
2698 assert(srcShape[dim] % consumerLaneLayout[dim] == 0 &&
2699 "srcShape must be divisible by laneLayout for all dimensions");
2700 laneDataValue = std::min(srcShape[dim] / consumerLaneLayout[dim],
2701 consumerLaneData[dim]);
2704 requiredResLayout.setDimData(dim, -1, -1, laneDataValue);
2707 return requiredResLayout;
2717 OpOperand &operand, xegpu::DistributeLayoutAttr resLayout) {
2724 if (
auto broadcast = dyn_cast<vector::BroadcastOp>(op)) {
2725 auto srcTy = dyn_cast<VectorType>(
broadcast.getSourceType());
2729 resLayout,
broadcast.getResultVectorType().getShape(),
2736 if (
auto reduction = dyn_cast<vector::MultiDimReductionOp>(op)) {
2745 if (
auto reduction = dyn_cast<vector::ReductionOp>(op))
2750 if (
auto bitcast = dyn_cast<vector::BitCastOp>(op)) {
2751 int resElemBitWidth =
2752 bitcast.getResultVectorType().getElementType().getIntOrFloatBitWidth();
2753 int srcElemBitWidth =
2754 bitcast.getSourceVectorType().getElementType().getIntOrFloatBitWidth();
2761 if (
auto shapeCast = dyn_cast<vector::ShapeCastOp>(op)) {
2763 resLayout, shapeCast.getResultVectorType().getShape(),
2764 shapeCast.getSourceVectorType().getShape());
2769 if (
auto insertSlice = dyn_cast<vector::InsertStridedSliceOp>(op)) {
2772 resLayout, insertSlice.getDestVectorType().getShape(),
2773 insertSlice.getSourceVectorType().getShape());
2781 if (
auto insert = dyn_cast<vector::InsertOp>(op)) {
2782 VectorType resVecTy = dyn_cast<VectorType>(insert.getResult().getType());
2783 VectorType valueToStoreTy =
2784 dyn_cast<VectorType>(insert.getValueToStore().getType());
2786 if ((idx == 0) && valueToStoreTy) {
2788 valueToStoreTy.getShape());
2796 if (
auto extract = dyn_cast<vector::ExtractOp>(op)) {
2797 VectorType srcVecTy = dyn_cast<VectorType>(extract.getSource().getType());
2798 VectorType resVecTy = dyn_cast<VectorType>(extract.getResult().getType());
2799 if (!srcVecTy || !resVecTy)
2802 srcVecTy.getShape());
2807 if (
auto transpose = dyn_cast<vector::TransposeOp>(op)) {
2809 transpose.getPermutation());
2814 if (
auto bitcast = dyn_cast<vector::BitCastOp>(op)) {
2815 int resElemBitWidth =
2816 bitcast.getResultVectorType().getElementType().getIntOrFloatBitWidth();
2817 int srcElemBitWidth =
2818 bitcast.getSourceVectorType().getElementType().getIntOrFloatBitWidth();
2824 if (
auto interleave = dyn_cast<vector::InterleaveOp>(op)) {
2829 if (
auto deinterleave = dyn_cast<vector::DeinterleaveOp>(op)) {
2834 if (dyn_cast<vector::ExtractStridedSliceOp>(op))
2853 if (isa<xegpu::AnchorLayoutInterface>(op))
2857 xegpu::DistributeLayoutAttr resLayout;
2858 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 SmallVector< LayoutRepresentation > getSgLayoutCandidates(ArrayRef< int64_t > wgShape, ArrayRef< int64_t > instData, int64_t sgCount, int64_t broadcastDim=-1)
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 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