27#include "llvm/ADT/TypeSwitch.h"
33#define GEN_PASS_DEF_CONVERTVECTORTOXEGPU
34#include "mlir/Conversion/Passes.h.inc"
42static bool isZeroConstant(
Value val) {
48 .Case([](FloatAttr floatAttr) {
return floatAttr.getValue().isZero(); })
49 .Case([](IntegerAttr intAttr) {
return intAttr.getValue().isZero(); })
58static bool isZeroOrPoisonPadding(
Value val) {
59 return isZeroConstant(val) || val.
getDefiningOp<ub::PoisonOp>();
69static bool isInnermostTwoDimsTransposed(
AffineMap map) {
76 for (
unsigned i = 0; i + 2 < numResults; ++i)
86 VectorTransferOpInterface xferOp) {
89 "Masked transfer is not supported");
91 auto srcTy = dyn_cast<MemRefType>(xferOp.getShapedType());
98 if (
failed(srcTy.getStridesAndOffset(strides, offset)))
100 "The memref strides cannot be inferred");
103 if (strides.back() != 1)
105 xferOp,
"Buffer must be contiguous in the innermost dimension");
107 VectorType vecTy = xferOp.getVectorType();
108 unsigned vecRank = vecTy.getRank();
111 if (xferOp.hasOutOfBoundsDim() && vecRank < 2)
113 xferOp,
"Boundary check is available only for block instructions.");
120 auto dim = dyn_cast<AffineDimExpr>(expr);
121 if (dim.getPosition() < (numInputDims - vecRank))
123 xferOp,
"Only the innermost dimensions can be accessed");
129static xegpu::CreateNdDescOp createNdDescriptor(
PatternRewriter &rewriter,
131 xegpu::TensorDescType descType,
133 MemRefType srcTy = src.getType();
134 assert(srcTy.isStrided() &&
"Expected strided memref type");
135 auto [strides, offset] = srcTy.getStridesAndOffset();
136 bool isStatic =
true;
139 if (!srcTy.hasStaticShape())
142 if (!ShapedType::isStatic(offset))
145 for (
auto stride : strides) {
146 if (!ShapedType::isStatic(stride)) {
152 xegpu::CreateNdDescOp ndDesc;
154 ndDesc = xegpu::CreateNdDescOp::create(rewriter, loc, descType, src);
159 auto meta = memref::ExtractStridedMetadataOp::create(rewriter, loc, src);
160 auto baseAddrIndex = memref::ExtractAlignedPointerAsIndexOp::create(
161 rewriter, loc, meta.getBaseBuffer());
162 auto offset = meta.getOffset();
163 auto elemByteSize = srcTy.getElementTypeBitWidth() / 8;
164 auto offsetInBytes = arith::MulIOp::create(
165 rewriter, loc, offset,
167 auto adjustedBaseAddr = arith::AddIOp::create(
168 rewriter, loc, baseAddrIndex.getResult(), offsetInBytes);
169 auto adjustedAddrI64 = arith::IndexCastOp::create(
170 rewriter, loc, rewriter.
getI64Type(), adjustedBaseAddr);
171 ndDesc = xegpu::CreateNdDescOp::create(
172 rewriter, loc, descType, adjustedAddrI64,
173 meta.getConstifiedMixedSizes(), meta.getConstifiedMixedStrides());
196static void adjustStridesForPermutation(
AffineMap permMap,
211 typename = std::enable_if_t<llvm::is_one_of<
212 std::decay_t<OpType>, vector::TransferReadOp, vector::TransferWriteOp,
213 vector::GatherOp, vector::ScatterOp>::value>>
214static std::pair<SmallVector<Value>,
Value>
217 Value baseMemref = xferOp.getBase();
218 MemRefType memrefType = dyn_cast<MemRefType>(baseMemref.
getType());
221 Value offsetVal =
nullptr;
222 if (memrefType.hasStaticShape()) {
225 if (
failed(memrefType.getStridesAndOffset(intStrides, offset)))
226 return {{}, offsetVal};
227 bool hasDynamicStrides = llvm::any_of(intStrides, [](
int64_t strideVal) {
228 return ShapedType::isDynamic(strideVal);
231 if (!hasDynamicStrides)
235 if (!ShapedType::isDynamic(offset))
239 if (strides.empty() || !offsetVal) {
242 unsigned rank = memrefType.getRank();
248 resultTypes.push_back(MemRefType::get(
249 {}, memrefType.getElementType()));
250 resultTypes.push_back(indexType);
252 for (
unsigned i = 0; i < rank; ++i)
253 resultTypes.push_back(indexType);
255 for (
unsigned i = 0; i < rank; ++i)
256 resultTypes.push_back(indexType);
258 auto meta = memref::ExtractStridedMetadataOp::create(
259 rewriter, loc, resultTypes, baseMemref);
262 strides.append(meta.getStrides().begin(), meta.getStrides().end());
265 offsetVal = meta.getOffset();
270 return {strides, offsetVal};
301static Value computeOffsets(VectorTransferOpInterface xferOp,
305 VectorType vectorType = xferOp.getVectorType();
307 xferOp.getIndices().end());
313 auto stepType = VectorType::get({dim}, rewriter.
getIndexType());
314 auto stepOp = vector::StepOp::create(rewriter, loc, stepType);
315 stepVectors.push_back(stepOp);
322 adjustStridesForPermutation(xferOp.getPermutationMap(), permutedStrides);
325 size_t memrefRank = permutedStrides.size();
328 for (
size_t i = 0; i < vectorRank; ++i) {
329 size_t memrefDim = memrefRank - vectorRank + i;
330 Value strideValue = permutedStrides[memrefDim];
331 auto mulType = dyn_cast<VectorType>(stepVectors[i].
getType());
333 vector::BroadcastOp::create(rewriter, loc, mulType, strideValue);
334 auto mulOp = arith::MulIOp::create(rewriter, loc, stepVectors[i], bcastOp);
335 strideMultiplied.push_back(mulOp);
340 for (
size_t i = 0; i < vectorRank; ++i) {
343 auto newType = VectorType::get(newShape, rewriter.
getIndexType());
344 auto castOp = vector::ShapeCastOp::create(rewriter, loc, newType,
345 strideMultiplied[i]);
346 shapeCasted.push_back(castOp);
351 auto fullIndexVectorType =
353 for (
Value shapeCastVal : shapeCasted) {
354 auto broadcastOp = vector::BroadcastOp::create(
355 rewriter, loc, fullIndexVectorType, shapeCastVal);
356 broadcasted.push_back(broadcastOp);
360 Value localOffsets = broadcasted[0];
361 for (
size_t i = 1; i < broadcasted.size(); ++i)
363 arith::AddIOp::create(rewriter, loc, localOffsets, broadcasted[i]);
366 for (
size_t i = 0; i <
indices.size(); ++i) {
367 Value strideVal = strides[i];
368 Value offsetContrib =
369 arith::MulIOp::create(rewriter, loc,
indices[i], strideVal);
371 arith::AddIOp::create(rewriter, loc, baseOffset, offsetContrib);
374 Value bcastBase = vector::BroadcastOp::create(
375 rewriter, loc, fullIndexVectorType, baseOffset);
376 localOffsets = arith::AddIOp::create(rewriter, loc, bcastBase, localOffsets);
387 typename = std::enable_if_t<llvm::is_one_of<
388 std::decay_t<OpType>, vector::GatherOp, vector::ScatterOp>::value>>
393 for (
size_t i = 0; i < offsets.size(); ++i) {
394 Value offsetContrib =
395 arith::MulIOp::create(rewriter, loc, offsets[i], strides[i]);
397 arith::AddIOp::create(rewriter, loc, baseOffset, offsetContrib);
400 VectorType vecType = cast<VectorType>(
indices.getType());
403 vector::BroadcastOp::create(rewriter, loc, vecType, strides.back())
405 Value stridedIndices =
406 arith::MulIOp::create(rewriter, loc, strideVector,
indices).getResult();
409 vector::BroadcastOp::create(
411 VectorType::get(vecType.getShape(), rewriter.
getIndexType()),
414 return arith::AddIOp::create(rewriter, loc, baseVector, stridedIndices)
423static std::pair<Value, SmallVector<OpFoldResult>>
428 auto memrefType = cast<MemRefType>(
memref.getType());
429 unsigned rank = memrefType.getRank();
431 if (rank <= targetRank)
434 int64_t numCombinedDims = rank - targetRank;
440 for (
unsigned i = 0; i < numCombinedDims; ++i) {
441 subviewOffsets.push_back(offsets[i]);
448 auto originalShape = memrefType.getShape();
449 auto meta = memref::ExtractStridedMetadataOp::create(rewriter, loc,
memref);
450 for (
unsigned i = numCombinedDims; i < rank; ++i) {
452 if (ShapedType::isDynamic(originalShape[i])) {
453 subviewSizes.push_back(meta.getSizes()[i]);
454 resultShape.push_back(ShapedType::kDynamic);
457 resultShape.push_back(originalShape[i]);
462 auto resultType = memref::SubViewOp::inferRankReducedResultType(
463 resultShape, memrefType, subviewOffsets, subviewSizes, subviewStrides);
465 memref::SubViewOp::create(rewriter, loc, resultType,
memref,
466 subviewOffsets, subviewSizes, subviewStrides);
471 return {subviewOp.getResult(), newOffsets};
476 typename = std::enable_if_t<llvm::is_one_of<
477 std::decay_t<OpType>, vector::TransferReadOp, vector::TransferWriteOp,
478 vector::GatherOp, vector::ScatterOp>::value>>
482 auto indexPtr = memref::ExtractAlignedPointerAsIndexOp::create(
483 rewriter, loc, xferOp.getBase())
485 return arith::IndexCastOp::create(rewriter, loc, rewriter.
getI64Type(),
490static LogicalResult lowerToScatteredLoadOp(vector::TransferReadOp readOp,
494 VectorType vectorType = readOp.getVectorType();
496 auto memrefType = dyn_cast<MemRefType>(readOp.getShapedType());
500 auto meta = computeMemrefMeta(readOp, rewriter);
501 if (meta.first.empty())
505 computeOffsets(readOp, rewriter, meta.first, meta.second);
507 Value flatMemref = memrefToIndexPtr(readOp, rewriter);
509 Value mask = vector::ConstantMaskOp::create(
512 auto gatherOp = xegpu::LoadGatherOp::create(
513 rewriter, loc, vectorType, flatMemref, localOffsets, mask,
515 xegpu::CachePolicyAttr{},
516 xegpu::CachePolicyAttr{},
517 xegpu::CachePolicyAttr{},
520 rewriter.
replaceOp(readOp, gatherOp.getResult());
524static LogicalResult lowerToScatteredStoreOp(vector::TransferWriteOp writeOp,
528 VectorType vectorType = writeOp.getVectorType();
531 auto memrefType = dyn_cast<MemRefType>(writeOp.getShapedType());
535 auto meta = computeMemrefMeta(writeOp, rewriter);
536 if (meta.first.empty())
540 computeOffsets(writeOp, rewriter, meta.first, meta.second);
542 Value flatMemref = memrefToIndexPtr(writeOp, rewriter);
544 Value mask = vector::ConstantMaskOp::create(
547 xegpu::StoreScatterOp::create(rewriter, loc, writeOp.getVector(), flatMemref,
550 xegpu::CachePolicyAttr{},
551 xegpu::CachePolicyAttr{},
552 xegpu::CachePolicyAttr{},
558struct TransferReadLowering :
public OpRewritePattern<vector::TransferReadOp> {
561 LogicalResult matchAndRewrite(vector::TransferReadOp readOp,
562 PatternRewriter &rewriter)
const override {
563 Location loc = readOp.getLoc();
565 if (
failed(transferPreconditions(rewriter, readOp)))
567 auto readMemTy = cast<MemRefType>(readOp.getShapedType());
568 VectorType loadedVecTy = readOp.getVectorType();
569 bool isOutOfBounds = readOp.hasOutOfBoundsDim();
571 bool isSharedMemory = xegpu::XeGPUDialect::isSharedMemory(readMemTy);
575 if (loadedVecTy.getRank() != 1 && loadedVecTy.getRank() != 2)
577 readOp,
"Only 1D and 2D vector loads are supported for SLM");
578 AffineMap readMap = readOp.getPermutationMap();
582 "Non identity transposition is not supported for SLM loads.");
586 readOp,
"Out-of-bounds access is not supported for SLM loads");
590 xegpu::MemDescType::get(rewriter.
getContext(), readMemTy.getShape(),
591 readMemTy.getElementType(),
593 auto createMemDescOp = xegpu::CreateMemDescOp::create(
594 rewriter, loc, memDescType, readOp.getBase());
596 SmallVector<OpFoldResult>
indices =
598 auto loadMatrixOp = xegpu::LoadMatrixOp::create(
599 rewriter, loc, loadedVecTy, createMemDescOp.getResult(),
indices,
602 rewriter.
replaceOp(readOp, loadMatrixOp.getResult());
608 bool hasBlockLoadSupport =
609 (chip ==
"pvc" || chip ==
"bmg" || chip ==
"cri");
616 bool isTransposeLoad = isInnermostTwoDimsTransposed(readMap);
622 bool canLowerToLoadNd =
623 hasBlockLoadSupport && loadedVecTy.getRank() > 0 &&
625 readMemTy.getElementType().isIntOrFloat() &&
626 (!isOutOfBounds || isZeroOrPoisonPadding(readOp.getPadding()));
628 if (canLowerToLoadNd) {
629 auto elementType = loadedVecTy.getElementType();
631 SmallVector<int64_t> descShape(loadedVecTy.getShape());
632 if (isTransposeLoad) {
635 size_t rank = descShape.size();
636 assert(rank >= 2 &&
"Transpose requires at least 2 dimensions");
637 std::swap(descShape[rank - 1], descShape[rank - 2]);
638 loadedVecTy = VectorType::get(descShape, elementType);
640 auto descType = xegpu::TensorDescType::get(
641 descShape, elementType, 1,
642 isOutOfBounds, xegpu::MemorySpace::Global);
643 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
644 rewriter, loc, readOp.getBase(),
647 xegpu::CachePolicyAttr hint =
nullptr;
648 xegpu::CreateNdDescOp ndDesc = createNdDescriptor(
651 Operation *loadedOp =
652 xegpu::LoadNdOp::create(rewriter, loc, loadedVecTy, ndDesc,
indices,
657 if (isTransposeLoad) {
661 int64_t rank = loadedVecTy.getRank();
662 SmallVector<int64_t> perm(llvm::to_vector(llvm::seq<int64_t>(0, rank)));
663 std::swap(perm[rank - 1], perm[rank - 2]);
664 loadedOp = vector::TransposeOp::create(rewriter, loc,
676 return lowerToScatteredLoadOp(readOp, rewriter);
680struct TransferWriteLowering
684 LogicalResult matchAndRewrite(vector::TransferWriteOp writeOp,
685 PatternRewriter &rewriter)
const override {
686 Location loc = writeOp.getLoc();
688 if (
failed(transferPreconditions(rewriter, writeOp)))
691 VectorType vecTy = writeOp.getVectorType();
692 auto writeMemTy = cast<MemRefType>(writeOp.getShapedType());
694 bool isSharedMemory = xegpu::XeGPUDialect::isSharedMemory(writeMemTy);
700 if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
702 writeOp,
"Only 1D and 2D vector stores are supported for SLM");
705 xegpu::MemDescType::get(rewriter.
getContext(), writeMemTy.getShape(),
706 writeMemTy.getElementType(),
709 auto createMemDescOp = xegpu::CreateMemDescOp::create(
710 rewriter, loc, memDescType, writeOp.getBase());
713 SmallVector<OpFoldResult>
indices =
716 xegpu::StoreMatrixOp::create(rewriter, loc, writeOp.getVector(),
717 createMemDescOp.getResult(),
indices,
726 bool hasBlockStoreSupport =
727 (chip ==
"pvc" || chip ==
"bmg" || chip ==
"cri");
734 bool canLowerToStoreNd = hasBlockStoreSupport && vecTy.getRank() > 0 &&
736 writeMemTy.getElementType().isIntOrFloat();
738 if (canLowerToStoreNd) {
739 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
740 rewriter, loc, writeOp.getBase(),
743 auto descType = xegpu::TensorDescType::get(
744 vecTy.getShape(), vecTy.getElementType(),
745 1, writeOp.hasOutOfBoundsDim(),
746 xegpu::MemorySpace::Global);
748 xegpu::CachePolicyAttr hint =
nullptr;
749 xegpu::CreateNdDescOp ndDesc = createNdDescriptor(
752 auto storeOp = xegpu::StoreNdOp::create(
753 rewriter, loc, writeOp.getVector(), ndDesc,
indices,
764 if (writeOp.hasOutOfBoundsDim())
766 return lowerToScatteredStoreOp(writeOp, rewriter);
773 LogicalResult matchAndRewrite(vector::GatherOp gatherOp,
774 PatternRewriter &rewriter)
const override {
775 auto srcTy = dyn_cast<MemRefType>(gatherOp.getBase().getType());
779 Location loc = gatherOp.getLoc();
780 VectorType vectorType = gatherOp.getVectorType();
782 auto meta = computeMemrefMeta(gatherOp, rewriter);
783 if (meta.first.empty())
787 computeOffsets(rewriter, gatherOp, meta.first, meta.second);
788 Value flatMemref = memrefToIndexPtr(gatherOp, rewriter);
790 auto xeGatherOp = xegpu::LoadGatherOp::create(
791 rewriter, loc, vectorType, flatMemref, localOffsets, gatherOp.getMask(),
793 xegpu::CachePolicyAttr{},
794 xegpu::CachePolicyAttr{},
795 xegpu::CachePolicyAttr{},
799 arith::SelectOp::create(rewriter, loc, gatherOp.getMask(),
800 xeGatherOp.getResult(), gatherOp.getPassThru());
801 rewriter.
replaceOp(gatherOp, selectOp.getResult());
809 LogicalResult matchAndRewrite(vector::ScatterOp scatterOp,
810 PatternRewriter &rewriter)
const override {
811 auto srcTy = dyn_cast<MemRefType>(scatterOp.getBase().getType());
815 Location loc = scatterOp.getLoc();
816 auto meta = computeMemrefMeta(scatterOp, rewriter);
817 if (meta.first.empty())
819 "Failed to compute strides");
822 computeOffsets(rewriter, scatterOp, meta.first, meta.second);
823 Value flatMemref = memrefToIndexPtr(scatterOp, rewriter);
825 xegpu::StoreScatterOp::create(rewriter, loc, scatterOp.getValueToStore(),
826 flatMemref, localOffsets, scatterOp.getMask(),
828 xegpu::CachePolicyAttr{},
829 xegpu::CachePolicyAttr{},
830 xegpu::CachePolicyAttr{},
841 LogicalResult matchAndRewrite(vector::LoadOp loadOp,
842 PatternRewriter &rewriter)
const override {
843 Location loc = loadOp.getLoc();
845 VectorType vecTy = loadOp.getResult().getType();
846 MemRefType memTy = loadOp.getBase().getType();
848 if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
850 if (!memTy.getElementType().isIntOrFloat())
852 loadOp,
"Unsupported memref element type: expected integer or float");
855 bool boundaryCheck = vecTy.getRank() > 1;
857 xegpu::CachePolicyAttr hint =
nullptr;
859 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
863 auto descType = xegpu::TensorDescType::get(
864 vecTy.getShape(), vecTy.getElementType(), 1,
865 boundaryCheck, xegpu::MemorySpace::Global);
867 xegpu::CreateNdDescOp ndDesc = createNdDescriptor(
870 xegpu::LoadNdOp::create(rewriter, loc, vecTy, ndDesc,
indices,
884 LogicalResult matchAndRewrite(vector::StoreOp storeOp,
885 PatternRewriter &rewriter)
const override {
886 Location loc = storeOp.getLoc();
889 VectorType vecTy = vector.getType();
890 MemRefType memTy = storeOp.getBase().getType();
892 if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
894 if (!memTy.getElementType().isIntOrFloat())
897 "Unsupported memref element type: expected integer or float");
900 bool boundaryCheck = vecTy.getRank() > 1;
902 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
903 rewriter, loc, storeOp.getBase(),
906 auto descType = xegpu::TensorDescType::get(
907 vecTy.getShape(), vecTy.getElementType(),
908 1, boundaryCheck, xegpu::MemorySpace::Global);
911 xegpu::CachePolicyAttr hint =
nullptr;
912 xegpu::CreateNdDescOp ndDesc = createNdDescriptor(
916 xegpu::StoreNdOp::create(rewriter, loc, vector, ndDesc,
indices,
927struct ContractionLowering :
public OpRewritePattern<vector::ContractionOp> {
930 LogicalResult matchAndRewrite(vector::ContractionOp contractOp,
931 PatternRewriter &rewriter)
const override {
932 Location loc = contractOp.getLoc();
934 if (contractOp.getKind() != vector::CombiningKind::ADD)
936 "Expects add combining kind");
939 VectorType accType = dyn_cast<VectorType>(acc.getType());
940 if (!accType || accType.getRank() != 2)
947 if (
lhs.getType().getRank() != 2 ||
rhs.getType().getRank() != 2)
949 "Expects lhs and rhs 2D vectors");
954 auto dpasOp = xegpu::DpasOp::create(rewriter, loc,
964static MemRefType withMemorySpace(MemRefType memrefTy,
Attribute newMemSpace) {
965 return MemRefType::get(memrefTy.getShape(), memrefTy.getElementType(),
966 memrefTy.getLayout(), newMemSpace);
979static void promoteAllocasToSLM(
Operation *root) {
981 Attribute slmAttr = IntegerAttr::get(IntegerType::get(ctx, 64), 3);
987 auto isMemrefResultOp = [](
Operation *op) {
990 return llvm::any_of(op->getResultTypes(),
991 [](
Type t) { return isa<MemRefType>(t); });
997 auto memrefTy = dyn_cast<MemRefType>(v.getType());
998 if (!memrefTy || xegpu::XeGPUDialect::isSharedMemory(memrefTy))
1000 v.setType(withMemorySpace(memrefTy, slmAttr));
1002 if (!isMemrefResultOp(user))
1010 root->
walk([&](memref::AllocaOp op) {
1011 auto memrefTy = dyn_cast<MemRefType>(op.getResult().getType());
1012 if (!memrefTy || xegpu::XeGPUDialect::isSharedMemory(memrefTy))
1014 allocas.push_back(op);
1017 for (memref::AllocaOp alloca : allocas) {
1019 auto memrefTy = cast<MemRefType>(alloca.getResult().getType());
1020 auto newTy = withMemorySpace(memrefTy, slmAttr);
1021 auto newOp = memref::AllocaOp::create(
1022 builder, alloca.getLoc(), newTy, alloca.getDynamicSizes(),
1023 alloca.getSymbolOperands(), alloca.getAlignmentAttr());
1024 alloca.getResult().replaceAllUsesWith(newOp.getResult());
1028 if (!isMemrefResultOp(user))
1036struct ConvertVectorToXeGPUPass
1038 void runOnOperation()
override {
1041 promoteAllocasToSLM(getOperation());
1047 return signalPassFailure();
1056 .
add<TransferReadLowering, TransferWriteLowering, LoadLowering,
1057 ScatterLowering, GatherLowering, StoreLowering, ContractionLowering>(
static std::optional< VectorShape > vectorShape(Type type)
static bool isSharedMemory(MemRefType type)
Return true if this is a shared memory memref type.
Base type for affine expression.
A multi-dimensional affine map Affine map's are immutable like Type's, and they are uniqued.
MLIRContext * getContext() const
bool isMinorIdentity() const
Returns true if this affine map is a minor identity, i.e.
bool isProjectedPermutation(bool allowZeroInResults=false) const
Returns true if the AffineMap represents a subset (i.e.
ArrayRef< AffineExpr > getResults() const
bool isPermutationOfMinorIdentityWithBroadcasting(SmallVectorImpl< unsigned > &permutedDims) const
Return true if this affine map can be converted to a minor identity with broadcast by doing a permute...
unsigned getNumResults() const
unsigned getNumInputs() const
AffineExpr getResult(unsigned idx) const
static AffineMap getPermutationMap(ArrayRef< unsigned > permutation, MLIRContext *context)
Returns an AffineMap representing a permutation.
Attributes are known-constant values of operations.
IntegerAttr getI64IntegerAttr(int64_t value)
MLIRContext * getContext() const
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.
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
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),...
user_range getUsers()
Returns a range of all users.
MLIRContext * getContext()
Return the context this operation is associated with.
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,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
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.
user_range getUsers() const
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
std::optional< std::string > getChipStr(Operation *op)
Retrieves the chip string from the XeVM target attribute of the parent GPU module operation.
Include the generated interface declarations.
void populatePrepareVectorToMMAPatterns(RewritePatternSet &patterns, bool useNvGpu=false)
Patterns to transform vector ops into a canonical form to convert to MMA matrix operations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
AffineMap inverseAndBroadcastProjectedPermutation(AffineMap map)
Return the reverse map of a projected permutation where the projected dimensions are transformed into...
SmallVector< T > applyPermutation(ArrayRef< T > input, ArrayRef< int64_t > permutation)
LogicalResult applyPatternsGreedily(Region ®ion, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig(), bool *changed=nullptr)
Rewrite ops in the given region, which must be isolated from above, by repeatedly applying the highes...
bool isMemoryEffectFree(Operation *op)
Returns true if the given operation is free of memory effects.
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.
void populateVectorToXeGPUConversionPatterns(RewritePatternSet &patterns)
Collect a set of patterns to convert from the vector to XeGPU ops.
llvm::TypeSwitch< T, ResultT > TypeSwitch
OpFoldResult getAsOpFoldResult(Value val)
Given a value, try to extract a constant Attribute.
AffineExpr getAffineDimExpr(unsigned position, MLIRContext *context)
These free functions allow clients of the API to not use classes in detail.
bool isRowMajorMatmul(ArrayAttr indexingMaps)
Tests whether the given maps describe a row major matmul.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...