23#include "llvm/ADT/STLExtras.h"
24#include "llvm/Support/DebugLog.h"
28#define GEN_PASS_DEF_XEGPUUNROLL
29#include "mlir/Dialect/XeGPU/Transforms/Passes.h.inc"
33#define DEBUG_TYPE "xegpu-unroll"
46template <
typename SourceOp>
56 LDBG() <<
"Get unroll shape for: " << *op;
58 if (
options.filterConstraint && failed(
options.filterConstraint(op))) {
59 LDBG() <<
"--no filter constraint -> BAIL";
64 "expects the native shape for native shape call back function.");
65 auto nativeShape =
options.nativeShape(op);
71 return options.getUnrolledTypes(type, tileShape);
78 if (
auto vecTy = dyn_cast<VectorType>(destTy)) {
79 auto shape = vecTy.getShape();
83 if (isa<xegpu::TensorDescType>(destTy)) {
88 auto castOp = UnrealizedConversionCastOp::create(
89 rewriter, loc, destTy, srcs,
91 return castOp.getResult(0);
94 llvm_unreachable(
"Unexpected destTy.");
103 if (
auto vecTy = dyn_cast<VectorType>(src.
getType())) {
108 if (isa<xegpu::TensorDescType>(src.
getType())) {
113 auto castOp = UnrealizedConversionCastOp::create(
114 rewriter, loc, destTypes, src,
116 return castOp.getResults();
119 llvm_unreachable(
"Unexpected src type.");
129 auto vecType = cast<VectorType>(operand.
getType());
130 std::optional<SmallVector<int64_t>> grids =
132 assert(grids &&
"Expecting grids to be computed.");
136 VectorType newVecTy =
137 vecType.cloneWith(blockSize, vecType.getElementType());
139 return pack(operand, convertedTypes, blockSize, loc, rewriter);
143 const char *
const packAttrName =
"__xegpu_blocking_pack__";
144 const char *
const unpackAttrName =
"__xegpu_blocking_unpack__";
145 const char *
const blockAttrName =
"__xegpu_blocking_tile_shape__";
159 int64_t rank = tdescTy.getRank();
167 auto aV = llvm::cast<Value>(a);
169 return rewriter.
createOrFold<arith::AddIOp>(loc, aV, bV);
174 llvm::drop_begin(mixedOffsets, mixedOffsets.size() - rank));
176 llvm::seq<int64_t>(mixedOffsets.size() - rank, mixedOffsets.size());
182 for (
auto [idx, oldOff, offset] :
183 llvm::zip(validIdxes, oldOffsets, offsets))
184 mixedOffsets[idx] = addi(oldOff, offset);
186 auto newOp = createOp(mixedOffsets);
187 newOps.push_back(newOp);
192struct UnrollCreateNdOp :
public UnrollPattern<xegpu::CreateNdDescOp> {
193 using UnrollPattern<xegpu::CreateNdDescOp>::UnrollPattern;
194 LogicalResult matchAndRewrite(xegpu::CreateNdDescOp op,
197 xegpu::TensorDescType tdescTy = op.getType();
199 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
204 Value src = op.getSource();
205 auto makeCreateNd = [&](
Type tdesc) ->
Value {
206 auto ndTy = cast<xegpu::TensorDescType>(tdesc);
207 if (isa<MemRefType>(src.
getType()))
208 return xegpu::CreateNdDescOp::create(rewriter, loc, ndTy,
210 return xegpu::CreateNdDescOp::create(
211 rewriter, loc, ndTy, src, op.getMixedSizes(), op.getMixedStrides());
216 if (tdescTy.getRank() <= 2) {
218 newOps.push_back(makeCreateNd(newTdescTys[0]));
221 for (
Type t : newTdescTys)
222 newOps.push_back(makeCreateNd(t));
224 Value castOp = unpack(newOps, tdescTy, *targetShape, loc, rewriter);
230struct UnrollPrefetchNdOp :
public UnrollPattern<xegpu::PrefetchNdOp> {
231 using UnrollPattern<xegpu::PrefetchNdOp>::UnrollPattern;
232 LogicalResult matchAndRewrite(xegpu::PrefetchNdOp op,
235 xegpu::TensorDescType tdescTy = op.getTensorDescType();
237 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
241 xegpu::DistributeLayoutAttr layout = op.getLayoutAttr();
243 layout = layout.dropInstData();
247 getUnrolledTypes(tdescTy, *targetShape);
249 op.getTensorDesc(), convertedTdescTypes, *targetShape, loc, rewriter);
252 xegpu::PrefetchNdOp::create(rewriter, loc, convertedTdesc[0], offsets,
253 op.getL1HintAttr(), op.getL2HintAttr(),
254 op.getL3HintAttr(), layout);
257 unrollByTile(op.getMixedOffsets(), tdescTy, *targetShape, createPrefetch,
265struct UnrollLoadNdOp :
public UnrollPattern<xegpu::LoadNdOp> {
266 using UnrollPattern<xegpu::LoadNdOp>::UnrollPattern;
267 LogicalResult matchAndRewrite(xegpu::LoadNdOp op,
271 VectorType valueTy = op.getType();
272 xegpu::TensorDescType tdescTy = op.getTensorDescType();
274 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
278 xegpu::DistributeLayoutAttr layout = op.getLayoutAttr();
280 layout = layout.dropInstData();
282 Type elemTy = tdescTy.getElementType();
283 VectorType newValueTy = valueTy.cloneWith(*targetShape, elemTy);
289 getUnrolledTypes(tdescTy, *targetShape);
291 op.getTensorDesc(), convertedTdescTypes, *targetShape, loc, rewriter);
294 return xegpu::LoadNdOp::create(
295 rewriter, loc, newValueTy, convertedTdescs[0], offsets,
296 op.getPackedAttr(), op.getTransposeAttr(), op.getL1HintAttr(),
297 op.getL2HintAttr(), op.getL3HintAttr(), layout);
299 newOps = unrollByTile(op.getMixedOffsets(), tdescTy, *targetShape,
300 createLoad, loc, rewriter);
302 Value castOp = unpack(newOps, op.getType(), *targetShape, loc, rewriter);
308struct UnrollStoreNdOp :
public UnrollPattern<xegpu::StoreNdOp> {
309 using UnrollPattern<xegpu::StoreNdOp>::UnrollPattern;
310 LogicalResult matchAndRewrite(xegpu::StoreNdOp op,
313 VectorType valueTy = op.getValueType();
314 xegpu::TensorDescType tdescTy = op.getTensorDescType();
316 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
320 xegpu::DistributeLayoutAttr layout = op.getLayoutAttr();
322 layout = layout.dropInstData();
325 getUnrolledTypes(valueTy, *targetShape);
328 pack(op.getValue(), convertedValTypes, *targetShape, loc, rewriter);
330 size_t valueIndex = 0;
336 getUnrolledTypes(tdescTy, *targetShape);
338 op.getTensorDesc(), convertedTdescTypes, *targetShape, loc, rewriter);
341 xegpu::StoreNdOp::create(rewriter, loc, convertedValues[valueIndex++],
342 convertedTdescs[0], offsets, op.getL1HintAttr(),
343 op.getL2HintAttr(), op.getL3HintAttr(), layout);
344 return (
Value)
nullptr;
346 unrollByTile(op.getMixedOffsets(), tdescTy, *targetShape, createStore, loc,
354struct UnrollDpasOp :
public UnrollPattern<xegpu::DpasOp> {
355 using UnrollPattern<xegpu::DpasOp>::UnrollPattern;
356 LogicalResult matchAndRewrite(xegpu::DpasOp op,
360 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
361 if (!targetShape || targetShape->size() < 3)
365 int64_t tsRank = targetShape->size();
366 auto M = (*targetShape)[tsRank - 3];
367 auto K = (*targetShape)[tsRank - 2];
368 auto N = (*targetShape)[tsRank - 1];
373 aBlockSize.push_back(M);
374 aBlockSize.push_back(K);
376 bBlockSize.push_back(K);
377 bBlockSize.push_back(N);
379 cBlockSize.push_back(M);
380 cBlockSize.push_back(N);
382 auto a = op.getLhs();
383 auto b = op.getRhs();
384 auto c = op.getAcc();
390 cVals = packOperandForDpas(c, cBlockSize, loc, rewriter);
394 if (llvm::any_of(ranges, [](
auto &v) {
return v.size() == 0; }) ||
395 llvm::all_of(ranges, [](
auto &v) {
return v.size() == 1; }))
398 VectorType resultTy = op.getResult().getType();
399 auto vecTy = VectorType::get(cBlockSize, resultTy.getElementType());
401 auto aShape = a.getType().getShape();
402 auto bShape =
b.getType().getShape();
406 int64_t batchRank = batchDims.size();
407 int64_t mIters = aShape[batchRank] / M;
408 int64_t kIters = aShape[batchRank + 1] / K;
409 int64_t nIters = bShape[batchRank + 1] / N;
413 for (
int64_t d = 0; d < batchRank; ++d)
414 batchIters *= aShape[d] / batchDims[d];
417 for (
int64_t batch = 0; batch < batchIters; ++batch) {
418 for (
int64_t i = 0; i < mIters; ++i) {
422 tmpC = cVals[batch * (mIters * nIters) + i * nIters +
j];
424 for (
int64_t k = 0; k < kIters; ++k) {
425 Value aVec = aVals[batch * (mIters * kIters) + i * kIters + k];
426 Value bVec = bVals[batch * (kIters * nIters) + k * nIters +
j];
429 operands.push_back(tmpC);
431 auto newDpasOp = xegpu::DpasOp::create(
432 rewriter, loc,
TypeRange{vecTy}, operands, op.getProperties(),
434 op->getDiscardableAttrDictionary().getValue()));
436 tmpC = newDpasOp.getResult();
438 newOps.push_back(tmpC);
442 Value castOp = unpack(newOps, resultTy, cBlockSize, loc, rewriter);
448struct UnrollDpasMxOp :
public UnrollPattern<xegpu::DpasMxOp> {
449 using UnrollPattern<xegpu::DpasMxOp>::UnrollPattern;
450 LogicalResult matchAndRewrite(xegpu::DpasMxOp op,
454 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
455 if (!targetShape || targetShape->size() < 4)
459 int64_t tsRank = targetShape->size();
460 auto M = (*targetShape)[tsRank - 4];
461 auto K = (*targetShape)[tsRank - 3];
462 auto N = (*targetShape)[tsRank - 2];
463 auto S = (*targetShape)[tsRank - 1];
467 aBlockSize.push_back(M);
468 aBlockSize.push_back(K);
470 bBlockSize.push_back(K);
471 bBlockSize.push_back(N);
473 cBlockSize.push_back(M);
474 cBlockSize.push_back(N);
476 aScaleBlockSize.push_back(M);
477 aScaleBlockSize.push_back(S);
479 bScaleBlockSize.push_back(S);
480 bScaleBlockSize.push_back(N);
484 auto c = op.getAcc();
485 auto ascale = dyn_cast<TypedValue<VectorType>>(op.getScaleA());
486 auto bscale = dyn_cast<TypedValue<VectorType>>(op.getScaleB());
492 cVals = packOperandForDpas(c, cBlockSize, loc, rewriter);
495 aScaleVals = packOperandForDpas(ascale, aScaleBlockSize, loc, rewriter);
498 bScaleVals = packOperandForDpas(bscale, bScaleBlockSize, loc, rewriter);
500 VectorType resultTy = op.getResult().getType();
501 auto vecTy = VectorType::get(cBlockSize, resultTy.getElementType());
503 auto aShape = a.getType().getShape();
504 auto bShape =
b.getType().getShape();
505 int64_t batchRank = batchDims.size();
506 int64_t mIters = aShape[batchRank] / M;
507 int64_t kIters = aShape[batchRank + 1] / K;
508 int64_t nIters = bShape[batchRank + 1] / N;
511 for (
int64_t d = 0; d < batchRank; ++d)
512 batchIters *= aShape[d] / batchDims[d];
515 xegpu::DpasMxOp newDpasMxOp;
516 for (
int64_t batch = 0; batch < batchIters; ++batch) {
517 for (
int64_t i = 0; i < mIters; ++i) {
521 tmpC = cVals[batch * (mIters * nIters) + i * nIters +
j];
523 for (
int64_t k = 0; k < kIters; ++k) {
524 Value aVec = aVals[batch * (mIters * kIters) + i * kIters + k];
525 Value bVec = bVals[batch * (kIters * nIters) + k * nIters +
j];
528 operands.push_back(tmpC);
531 aScaleVals[batch * (mIters * kIters) + i * kIters + k]);
534 bScaleVals[batch * (kIters * nIters) + k * nIters +
j]);
536 newDpasMxOp = xegpu::DpasMxOp::create(
537 rewriter, loc,
TypeRange{vecTy}, operands, op.getProperties(),
539 op->getDiscardableAttrDictionary().getValue()));
541 tmpC = newDpasMxOp.getResult();
543 newOps.push_back(newDpasMxOp);
547 Value castOp = unpack(newOps, resultTy, cBlockSize, loc, rewriter);
557struct UnrollLoadGatherOp :
public UnrollPattern<xegpu::LoadGatherOp> {
558 using UnrollPattern<xegpu::LoadGatherOp>::UnrollPattern;
559 LogicalResult matchAndRewrite(xegpu::LoadGatherOp op,
562 VectorType valueTy = llvm::dyn_cast<VectorType>(op.getType());
563 Value offsets = op.getOffsets();
564 Value mask = op.getMask();
566 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
573 VectorType maskTy = llvm::dyn_cast<VectorType>(mask.getType());
574 VectorType offsetsTy = llvm::dyn_cast<VectorType>(offsets.
getType());
575 Type elemTy = valueTy.getElementType();
576 VectorType newValueTy = VectorType::get(*targetShape, elemTy);
579 getUnrolledTypes(maskTy, targetMaskShape);
581 pack(mask, convertedMaskTypes, targetMaskShape, loc, rewriter);
584 getUnrolledTypes(offsetsTy, *targetShape);
586 pack(offsets, convertedOffsetTypes, *targetShape, loc, rewriter);
588 auto layout = op.getLayoutAttr();
590 layout = layout.dropInstData();
593 for (
auto [o, m] : llvm::zip(convertedOffsets, convertedMasks)) {
594 auto newOp = xegpu::LoadGatherOp::create(
595 rewriter, loc, newValueTy, op.getSource(), o, m, op.getL1HintAttr(),
596 op.getL2HintAttr(), op.getL3HintAttr(), layout,
598 newOps.push_back(newOp);
601 Value castOp = unpack(newOps, op.getType(), *targetShape, loc, rewriter);
611struct UnrollStoreScatterOp :
public UnrollPattern<xegpu::StoreScatterOp> {
612 using UnrollPattern<xegpu::StoreScatterOp>::UnrollPattern;
613 LogicalResult matchAndRewrite(xegpu::StoreScatterOp op,
616 VectorType valueTy = llvm::dyn_cast<VectorType>(op.getValue().getType());
617 Value offsets = op.getOffsets();
618 Value mask = op.getMask();
620 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
625 VectorType maskTy = llvm::dyn_cast<VectorType>(mask.getType());
626 VectorType offsetsTy = llvm::dyn_cast<VectorType>(offsets.
getType());
629 getUnrolledTypes(maskTy, targetMaskShape);
631 pack(mask, convertedMaskTypes, targetMaskShape, loc, rewriter);
634 getUnrolledTypes(offsetsTy, *targetShape);
636 pack(offsets, convertedOffsetTypes, *targetShape, loc, rewriter);
639 getUnrolledTypes(valueTy, *targetShape);
641 pack(op.getValue(), convertedValTypes, *targetShape, loc, rewriter);
643 auto layout = op.getLayoutAttr();
645 layout = layout.dropInstData();
647 for (
auto [v, o, m] :
648 llvm::zip(convertedValues, convertedOffsets, convertedMasks)) {
649 xegpu::StoreScatterOp::create(rewriter, loc, v, op.getDest(), o, m,
650 op.getL1HintAttr(), op.getL2HintAttr(),
651 op.getL3HintAttr(), layout,
660struct UnrollLoadMatrixOp :
public UnrollPattern<xegpu::LoadMatrixOp> {
661 using UnrollPattern<xegpu::LoadMatrixOp>::UnrollPattern;
662 LogicalResult matchAndRewrite(xegpu::LoadMatrixOp op,
665 VectorType valueTy = llvm::dyn_cast<VectorType>(op.getType());
666 assert(valueTy &&
"the value type must be vector type!");
668 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
669 if (!targetShape || targetShape->size() != (
size_t)valueTy.getRank())
672 Type elemTy = valueTy.getElementType();
674 xegpu::DistributeLayoutAttr layout = op.getLayoutAttr();
676 VectorType newValueTy = valueTy.cloneWith(*targetShape, elemTy);
683 rewriter, loc, mixedOffsets,
685 offsetsList.push_back(adds);
690 layout = layout.dropInstData();
692 auto newOp = xegpu::LoadMatrixOp::create(
693 rewriter, op.getLoc(), newValueTy, op.getMemDesc(), offsets, layout);
694 newOps.push_back(newOp);
696 Value castOp = unpack(newOps, op.getType(), *targetShape, loc, rewriter);
702struct UnrollStoreMatrixOp :
public UnrollPattern<xegpu::StoreMatrixOp> {
703 using UnrollPattern<xegpu::StoreMatrixOp>::UnrollPattern;
704 LogicalResult matchAndRewrite(xegpu::StoreMatrixOp op,
706 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
711 VectorType valueTy = llvm::dyn_cast<VectorType>(op.getData().getType());
712 assert(valueTy &&
"the value type must be vector type!");
714 xegpu::DistributeLayoutAttr layout = op.getLayoutAttr();
716 layout = layout.dropInstData();
719 getUnrolledTypes(valueTy, *targetShape);
721 pack(op.getData(), convertedValTypes, *targetShape, loc, rewriter);
728 rewriter, loc, mixedOffsets,
730 offsetsList.push_back(adds);
733 for (
auto [v, offsets] : llvm::zip_equal(convertedValues, offsetsList))
734 xegpu::StoreMatrixOp::create(rewriter, loc, v, op.getMemDesc(), offsets,
752struct UnrollConvertLayoutOp :
public UnrollPattern<xegpu::ConvertLayoutOp> {
753 using UnrollPattern<xegpu::ConvertLayoutOp>::UnrollPattern;
759 rewriteWithRegrouping(xegpu::ConvertLayoutOp op, VectorType valueTy,
762 xegpu::DistributeLayoutAttr inputLayout,
763 xegpu::DistributeLayoutAttr targetLayout,
Location loc,
771 Type elemTy = valueTy.getElementType();
772 int64_t rank = valueTy.getRank();
773 VectorType convTy = VectorType::get(convTile, elemTy);
776 Value source = op.getSource();
777 auto zeroOf = [&](VectorType ty) ->
Value {
778 return arith::ConstantOp::create(
785 for (
auto [r, v] : llvm::zip_equal(res,
b))
795 if (convTile == inTile) {
796 conv = vector::ExtractStridedSliceOp::create(
797 rewriter, loc, source, convOff, convTile, strides);
799 conv = zeroOf(convTy);
802 Value piece = vector::ExtractStridedSliceOp::create(
803 rewriter, loc, source, addOffsets(convOff, inLocal), inTile,
805 conv = vector::InsertStridedSliceOp::create(rewriter, loc, piece,
806 conv, inLocal, strides);
810 conv = xegpu::ConvertLayoutOp::create(rewriter, loc, convTy, conv,
811 inputLayout, targetLayout);
814 if (convTile == outTile) {
815 result = vector::InsertStridedSliceOp::create(rewriter, loc, conv,
816 result, convOff, strides);
820 Value piece = vector::ExtractStridedSliceOp::create(
821 rewriter, loc, conv, outLocal, outTile, strides);
822 result = vector::InsertStridedSliceOp::create(
823 rewriter, loc, piece,
result, addOffsets(convOff, outLocal),
833 LogicalResult matchAndRewrite(xegpu::ConvertLayoutOp op,
836 Type valType = op.getType();
838 xegpu::DistributeLayoutAttr inputLayout = op.getEffectiveInputLayout();
839 xegpu::DistributeLayoutAttr targetLayout = op.getTargetLayoutAttr();
840 if (!inputLayout || !targetLayout)
851 if (inTile.empty() || outTile.empty())
854 inputLayout = inputLayout.dropInstData();
855 targetLayout = targetLayout.dropInstData();
857 VectorType valueTy = llvm::dyn_cast<VectorType>(op.getType());
858 assert(valueTy &&
"the value type must be vector type!");
860 std::optional<SmallVector<int64_t>> targetShape =
getTargetShape(op);
861 if (!targetShape || targetShape->size() != (
size_t)valueTy.getRank())
865 if (!inputLayout || !targetLayout || inputLayout.isEqualTo(targetLayout)) {
871 if (succeeded(rewriteWithRegrouping(op, valueTy, *targetShape, inTile,
872 outTile, inputLayout, targetLayout, loc,
878 getUnrolledTypes(valueTy, *targetShape);
880 pack(op.getOperand(), convertedValTypes, *targetShape, loc, rewriter);
882 for (
auto [v, t] : llvm::zip(convertedValues, convertedValTypes)) {
883 auto newOp = xegpu::ConvertLayoutOp::create(rewriter, loc, t, v,
884 inputLayout, targetLayout);
885 newOps.push_back(newOp);
887 Value newSource = unpack(newOps, op.getType(), *targetShape, loc, rewriter);
908struct UnrollMultiReductionOp
909 :
public UnrollPattern<vector::MultiDimReductionOp> {
913 : UnrollPattern<vector::MultiDimReductionOp>(context,
options, benefit) {}
915 LogicalResult matchAndRewrite(vector::MultiDimReductionOp reductionOp,
917 VectorType srcTy = reductionOp.getSourceVectorType();
919 int64_t srcRank = srcTy.getRank();
921 Location loc = reductionOp.getLoc();
922 Value source = reductionOp.getSource();
924 vector::CombiningKind kind = reductionOp.getKind();
927 auto resultType = dyn_cast<VectorType>(reductionOp.getDestType());
931 std::optional<SmallVector<int64_t>> targetShapeOpt =
933 if (!targetShapeOpt ||
934 static_cast<int64_t>(targetShapeOpt->size()) != srcRank)
940 for (
int64_t i = 0; i < srcRank; ++i) {
941 if (srcShape[i] % targetShape[i] != 0)
948 for (
int64_t i = 0; i < srcRank; ++i) {
949 if (reductionMask[i])
950 reducedDims.push_back(i);
952 keptDims.push_back(i);
959 numReducedTilesPerDim.push_back(srcShape[d] / targetShape[d]);
964 keptShape.push_back(srcShape[d]);
965 keptTileShape.push_back(targetShape[d]);
969 Value result = arith::ConstantOp::create(rewriter, loc, resultType,
982 for (
auto [idx, dim] : llvm::enumerate(keptDims))
983 baseOffsets[dim] = keptOffsets[idx];
999 for (
auto [idx, dim] : llvm::enumerate(reducedDims))
1000 offsets[dim] = reducedTileIdx[idx] * targetShape[dim];
1002 Value tile = vector::ExtractStridedSliceOp::create(
1003 rewriter, loc, source, offsets, targetShape, strides);
1004 tiles.push_back(
tile);
1008 Value reduced = tiles[0];
1009 for (
size_t i = 1; i < tiles.size(); ++i)
1015 Value accSlice = vector::ExtractStridedSliceOp::create(
1016 rewriter, loc,
acc, keptOffsets, keptTileShape, accStrides);
1018 auto newReduction = vector::MultiDimReductionOp::create(
1019 rewriter, loc, reduced, accSlice, reductionMask, kind);
1023 result = vector::InsertStridedSliceOp::create(
1024 rewriter, loc, newReduction,
result, keptOffsets, dstStrides);
1037 .
add<UnrollCreateNdOp, UnrollPrefetchNdOp, UnrollLoadNdOp,
1038 UnrollStoreNdOp, UnrollDpasOp, UnrollDpasMxOp, UnrollLoadMatrixOp,
1039 UnrollStoreMatrixOp, UnrollLoadGatherOp, UnrollStoreScatterOp,
1040 UnrollConvertLayoutOp, UnrollMultiReductionOp>(patterns.
getContext(),
static llvm::ManagedStatic< PassManagerOptions > options
static std::optional< SmallVector< int64_t > > getTargetShape(const vector::UnrollVectorOptions &options, Operation *op)
Return the target shape for unrolling for the given op.
DenseI64ArrayAttr getDenseI64ArrayAttr(ArrayRef< int64_t > values)
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
NamedAttribute represents a combination of a name and an Attribute value.
void createOrFold(SmallVectorImpl< Value > &results, Location location, Args &&...args)
Create an operation of specific op type at the current insertion point, and immediately try to fold i...
This class represents a single result from folding an operation.
Operation is the basic unit of execution within MLIR.
This class represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
MLIRContext * getContext() const
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
A range-style iterator that allows for iterating over the offsets of all potential tiles of size tile...
This class provides an abstraction over the various different ranges of value types.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
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...
Type getType() const
Return the type of this value.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
Value makeArithReduction(OpBuilder &b, Location loc, CombiningKind kind, Value v1, Value acc, arith::FastMathFlagsAttr fastmath=nullptr, Value mask=nullptr)
Returns the result value of reducing two scalar/vector values with the corresponding arith operation.
Value createVectorWithShapeFromValues(OpBuilder &builder, Location loc, ValueRange values, ArrayRef< int64_t > shape)
Create a vector of shape from a set of values using vector.insert_stride_slice.
void populateXeGPUUnrollPatterns(RewritePatternSet &patterns, const UnrollOptions &options)
Collect a set of patterns to unroll xegpu operations to a smaller shapes.
SmallVector< NamedAttribute > dropInstDataOnAttrs(ArrayRef< NamedAttribute > attrs)
Updates the NamedAttribute sequence by dropping inst-data information from any DistributeLayoutAttr f...
void dropInstDataOnInherentAttrs(Operation *op)
Drops inst-data information from DistributeLayoutAttrs stored as inherent attributes on the operation...
SmallVector< Value > extractVectorsWithShapeFromValue(OpBuilder &builder, Location loc, Value value, ArrayRef< int64_t > shape)
Extract a set of small vectors from a value with a given shape using vector.extract_stride_slice.
SmallVector< OpFoldResult > addElementwise(OpBuilder &builder, Location loc, ArrayRef< OpFoldResult > lhs, ArrayRef< OpFoldResult > rhs)
Generates element-wise addition ops of two arrays with same length.
Include the generated interface declarations.
OpFoldResult getAsIndexOpFoldResult(MLIRContext *ctx, int64_t val)
Convert int64_t to integer attributes of index type and return them as OpFoldResult.
std::optional< int64_t > getConstantIntValue(OpFoldResult ofr)
If ofr is a constant integer or an IntegerAttr, return the integer.
int64_t computeProduct(ArrayRef< int64_t > basis)
Self-explicit.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.
SmallVector< Loops, 8 > tile(ArrayRef< scf::ForOp > forOps, ArrayRef< Value > sizes, ArrayRef< scf::ForOp > targets)
Performs tiling fo imperfectly nested loops (with interchange) by strip-mining the forOps by sizes an...
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.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
Options to control the XeGPU unrolling.
Eliminates variable at the specified position using Fourier-Motzkin variable elimination.