26#include "llvm/ADT/TypeSwitch.h"
32#define GEN_PASS_DEF_CONVERTVECTORTOXEGPU
33#include "mlir/Conversion/Passes.h.inc"
41static bool isZeroConstant(
Value val) {
47 .Case([](FloatAttr floatAttr) {
return floatAttr.getValue().isZero(); })
48 .Case([](IntegerAttr intAttr) {
return intAttr.getValue().isZero(); })
57 unsigned vecRank = vecTy.getRank();
58 if (!(vecRank == 1 || vecRank == 2))
61 if (!vecTy.getElementType().isIntOrFloat())
63 op,
"Expected scalar type with known bitwidth");
69 if (!memTy.getElementType().isIntOrFloat())
71 op,
"Unsupported memref element type: expected integer or float");
77 VectorTransferOpInterface xferOp) {
80 "Masked transfer is not supported");
82 auto srcTy = dyn_cast<MemRefType>(xferOp.getShapedType());
89 if (
failed(srcTy.getStridesAndOffset(strides, offset)))
91 "The memref strides cannot be inferred");
94 if (strides.back() != 1)
96 xferOp,
"Buffer must be contiguous in the innermost dimension");
98 VectorType vecTy = xferOp.getVectorType();
99 unsigned vecRank = vecTy.getRank();
102 if (xferOp.hasOutOfBoundsDim() && vecRank < 2)
104 xferOp,
"Boundary check is available only for block instructions.");
111 auto dim = dyn_cast<AffineDimExpr>(expr);
112 if (dim.getPosition() < (numInputDims - vecRank))
114 xferOp,
"Only the innermost dimensions can be accessed");
120static xegpu::CreateNdDescOp createNdDescriptor(
PatternRewriter &rewriter,
122 xegpu::TensorDescType descType,
124 MemRefType srcTy = src.getType();
125 assert(srcTy.isStrided() &&
"Expected strided memref type");
126 auto [strides, offset] = srcTy.getStridesAndOffset();
127 bool isStatic =
true;
130 if (!srcTy.hasStaticShape())
133 if (!ShapedType::isStatic(offset))
136 for (
auto stride : strides) {
137 if (!ShapedType::isStatic(stride)) {
143 xegpu::CreateNdDescOp ndDesc;
145 ndDesc = xegpu::CreateNdDescOp::create(rewriter, loc, descType, src);
150 auto meta = memref::ExtractStridedMetadataOp::create(rewriter, loc, src);
151 auto baseAddrIndex = memref::ExtractAlignedPointerAsIndexOp::create(
152 rewriter, loc, meta.getBaseBuffer());
153 auto offset = meta.getOffset();
154 auto elemByteSize = srcTy.getElementTypeBitWidth() / 8;
155 auto offsetInBytes = arith::MulIOp::create(
156 rewriter, loc, offset,
158 auto adjustedBaseAddr = arith::AddIOp::create(
159 rewriter, loc, baseAddrIndex.getResult(), offsetInBytes);
160 auto adjustedAddrI64 = arith::IndexCastOp::create(
161 rewriter, loc, rewriter.
getI64Type(), adjustedBaseAddr);
162 ndDesc = xegpu::CreateNdDescOp::create(
163 rewriter, loc, descType, adjustedAddrI64,
164 meta.getConstifiedMixedSizes(), meta.getConstifiedMixedStrides());
187static void adjustStridesForPermutation(
AffineMap permMap,
202 typename = std::enable_if_t<llvm::is_one_of<
203 std::decay_t<OpType>, vector::TransferReadOp, vector::TransferWriteOp,
204 vector::GatherOp, vector::ScatterOp>::value>>
205static std::pair<SmallVector<Value>,
Value>
208 Value baseMemref = xferOp.getBase();
209 MemRefType memrefType = dyn_cast<MemRefType>(baseMemref.
getType());
212 Value offsetVal =
nullptr;
213 if (memrefType.hasStaticShape()) {
216 if (
failed(memrefType.getStridesAndOffset(intStrides, offset)))
217 return {{}, offsetVal};
218 bool hasDynamicStrides = llvm::any_of(intStrides, [](
int64_t strideVal) {
219 return ShapedType::isDynamic(strideVal);
222 if (!hasDynamicStrides)
226 if (!ShapedType::isDynamic(offset))
230 if (strides.empty() || !offsetVal) {
233 unsigned rank = memrefType.getRank();
239 resultTypes.push_back(MemRefType::get(
240 {}, memrefType.getElementType()));
241 resultTypes.push_back(indexType);
243 for (
unsigned i = 0; i < rank; ++i)
244 resultTypes.push_back(indexType);
246 for (
unsigned i = 0; i < rank; ++i)
247 resultTypes.push_back(indexType);
249 auto meta = memref::ExtractStridedMetadataOp::create(
250 rewriter, loc, resultTypes, baseMemref);
253 strides.append(meta.getStrides().begin(), meta.getStrides().end());
256 offsetVal = meta.getOffset();
261 return {strides, offsetVal};
292static Value computeOffsets(VectorTransferOpInterface xferOp,
296 VectorType vectorType = xferOp.getVectorType();
298 xferOp.getIndices().end());
304 auto stepType = VectorType::get({dim}, rewriter.
getIndexType());
305 auto stepOp = vector::StepOp::create(rewriter, loc, stepType);
306 stepVectors.push_back(stepOp);
313 adjustStridesForPermutation(xferOp.getPermutationMap(), permutedStrides);
316 size_t memrefRank = permutedStrides.size();
319 for (
size_t i = 0; i < vectorRank; ++i) {
320 size_t memrefDim = memrefRank - vectorRank + i;
321 Value strideValue = permutedStrides[memrefDim];
322 auto mulType = dyn_cast<VectorType>(stepVectors[i].
getType());
324 vector::BroadcastOp::create(rewriter, loc, mulType, strideValue);
325 auto mulOp = arith::MulIOp::create(rewriter, loc, stepVectors[i], bcastOp);
326 strideMultiplied.push_back(mulOp);
331 for (
size_t i = 0; i < vectorRank; ++i) {
334 auto newType = VectorType::get(newShape, rewriter.
getIndexType());
335 auto castOp = vector::ShapeCastOp::create(rewriter, loc, newType,
336 strideMultiplied[i]);
337 shapeCasted.push_back(castOp);
342 auto fullIndexVectorType =
344 for (
Value shapeCastVal : shapeCasted) {
345 auto broadcastOp = vector::BroadcastOp::create(
346 rewriter, loc, fullIndexVectorType, shapeCastVal);
347 broadcasted.push_back(broadcastOp);
351 Value localOffsets = broadcasted[0];
352 for (
size_t i = 1; i < broadcasted.size(); ++i)
354 arith::AddIOp::create(rewriter, loc, localOffsets, broadcasted[i]);
357 for (
size_t i = 0; i <
indices.size(); ++i) {
358 Value strideVal = strides[i];
359 Value offsetContrib =
360 arith::MulIOp::create(rewriter, loc,
indices[i], strideVal);
362 arith::AddIOp::create(rewriter, loc, baseOffset, offsetContrib);
365 Value bcastBase = vector::BroadcastOp::create(
366 rewriter, loc, fullIndexVectorType, baseOffset);
367 localOffsets = arith::AddIOp::create(rewriter, loc, bcastBase, localOffsets);
378 typename = std::enable_if_t<llvm::is_one_of<
379 std::decay_t<OpType>, vector::GatherOp, vector::ScatterOp>::value>>
384 for (
size_t i = 0; i < offsets.size(); ++i) {
385 Value offsetContrib =
386 arith::MulIOp::create(rewriter, loc, offsets[i], strides[i]);
388 arith::AddIOp::create(rewriter, loc, baseOffset, offsetContrib);
391 VectorType vecType = cast<VectorType>(
indices.getType());
394 vector::BroadcastOp::create(rewriter, loc, vecType, strides.back())
396 Value stridedIndices =
397 arith::MulIOp::create(rewriter, loc, strideVector,
indices).getResult();
400 vector::BroadcastOp::create(
402 VectorType::get(vecType.getShape(), rewriter.
getIndexType()),
405 return arith::AddIOp::create(rewriter, loc, baseVector, stridedIndices)
414static std::pair<Value, SmallVector<OpFoldResult>>
419 auto memrefType = cast<MemRefType>(
memref.getType());
420 unsigned rank = memrefType.getRank();
422 if (rank <= targetRank)
425 int64_t numCombinedDims = rank - targetRank;
431 for (
unsigned i = 0; i < numCombinedDims; ++i) {
432 subviewOffsets.push_back(offsets[i]);
439 auto originalShape = memrefType.getShape();
440 auto meta = memref::ExtractStridedMetadataOp::create(rewriter, loc,
memref);
441 for (
unsigned i = numCombinedDims; i < rank; ++i) {
443 if (ShapedType::isDynamic(originalShape[i])) {
444 subviewSizes.push_back(meta.getSizes()[i]);
445 resultShape.push_back(ShapedType::kDynamic);
448 resultShape.push_back(originalShape[i]);
453 auto resultType = memref::SubViewOp::inferRankReducedResultType(
454 resultShape, memrefType, subviewOffsets, subviewSizes, subviewStrides);
456 memref::SubViewOp::create(rewriter, loc, resultType,
memref,
457 subviewOffsets, subviewSizes, subviewStrides);
462 return {subviewOp.getResult(), newOffsets};
467 typename = std::enable_if_t<llvm::is_one_of<
468 std::decay_t<OpType>, vector::TransferReadOp, vector::TransferWriteOp,
469 vector::GatherOp, vector::ScatterOp>::value>>
473 auto indexPtr = memref::ExtractAlignedPointerAsIndexOp::create(
474 rewriter, loc, xferOp.getBase())
476 return arith::IndexCastOp::create(rewriter, loc, rewriter.
getI64Type(),
481static LogicalResult lowerToScatteredLoadOp(vector::TransferReadOp readOp,
485 VectorType vectorType = readOp.getVectorType();
487 auto memrefType = dyn_cast<MemRefType>(readOp.getShapedType());
491 auto meta = computeMemrefMeta(readOp, rewriter);
492 if (meta.first.empty())
496 computeOffsets(readOp, rewriter, meta.first, meta.second);
498 Value flatMemref = memrefToIndexPtr(readOp, rewriter);
500 Value mask = vector::ConstantMaskOp::create(
503 auto gatherOp = xegpu::LoadGatherOp::create(
504 rewriter, loc, vectorType, flatMemref, localOffsets, mask,
506 xegpu::CachePolicyAttr{},
507 xegpu::CachePolicyAttr{},
508 xegpu::CachePolicyAttr{},
511 rewriter.
replaceOp(readOp, gatherOp.getResult());
515static LogicalResult lowerToScatteredStoreOp(vector::TransferWriteOp writeOp,
519 VectorType vectorType = writeOp.getVectorType();
522 auto memrefType = dyn_cast<MemRefType>(writeOp.getShapedType());
526 auto meta = computeMemrefMeta(writeOp, rewriter);
527 if (meta.first.empty())
531 computeOffsets(writeOp, rewriter, meta.first, meta.second);
533 Value flatMemref = memrefToIndexPtr(writeOp, rewriter);
535 Value mask = vector::ConstantMaskOp::create(
538 xegpu::StoreScatterOp::create(rewriter, loc, writeOp.getVector(), flatMemref,
541 xegpu::CachePolicyAttr{},
542 xegpu::CachePolicyAttr{},
543 xegpu::CachePolicyAttr{},
549struct TransferReadLowering :
public OpRewritePattern<vector::TransferReadOp> {
552 LogicalResult matchAndRewrite(vector::TransferReadOp readOp,
553 PatternRewriter &rewriter)
const override {
554 Location loc = readOp.getLoc();
556 if (
failed(transferPreconditions(rewriter, readOp)))
558 auto readMemTy = cast<MemRefType>(readOp.getShapedType());
559 VectorType loadedVecTy = readOp.getVectorType();
560 bool isOutOfBounds = readOp.hasOutOfBoundsDim();
562 bool isSharedMemory = xegpu::XeGPUDialect::isSharedMemory(readMemTy);
566 if (loadedVecTy.getRank() != 1 && loadedVecTy.getRank() != 2)
568 readOp,
"Only 1D and 2D vector loads are supported for SLM");
569 AffineMap readMap = readOp.getPermutationMap();
573 "Non identity transposition is not supported for SLM loads.");
577 readOp,
"Out-of-bounds access is not supported for SLM loads");
581 xegpu::MemDescType::get(rewriter.
getContext(), readMemTy.getShape(),
582 readMemTy.getElementType(),
584 auto createMemDescOp = xegpu::CreateMemDescOp::create(
585 rewriter, loc, memDescType, readOp.getBase());
587 SmallVector<OpFoldResult>
indices =
589 auto loadMatrixOp = xegpu::LoadMatrixOp::create(
590 rewriter, loc, loadedVecTy, createMemDescOp.getResult(),
indices,
593 rewriter.
replaceOp(readOp, loadMatrixOp.getResult());
601 if ((chip !=
"pvc" && chip !=
"bmg" && chip !=
"cri") ||
602 readOp.getVectorType().getRank() > 2) {
607 return lowerToScatteredLoadOp(readOp, rewriter);
611 if (loadedVecTy.getRank() == 1 && !isOutOfBounds)
612 return lowerToScatteredLoadOp(readOp, rewriter);
617 storeLoadPreconditions(rewriter, readOp, loadedVecTy, readMemTy)))
620 if (isOutOfBounds && !isZeroConstant(readOp.getPadding()))
622 readOp,
"Unsupported non-zero padded out-of-bounds read");
631 bool isTransposeLoad =
false;
635 if (numInputs >= 2) {
640 (results[0] == lastDim && results[1] == secondLastDim);
643 auto elementType = loadedVecTy.getElementType();
645 SmallVector<int64_t> descShape(loadedVecTy.getShape());
646 if (isTransposeLoad) {
649 size_t rank = descShape.size();
650 assert(rank >= 2 &&
"Transpose requires at least 2 dimensions");
651 std::swap(descShape[rank - 1], descShape[rank - 2]);
652 loadedVecTy = VectorType::get(descShape, elementType);
654 auto descType = xegpu::TensorDescType::get(
655 descShape, elementType, 1,
656 isOutOfBounds, xegpu::MemorySpace::Global);
657 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
659 loadedVecTy.getRank());
661 xegpu::CachePolicyAttr hint =
nullptr;
662 xegpu::CreateNdDescOp ndDesc = createNdDescriptor(
665 Operation *loadedOp =
666 xegpu::LoadNdOp::create(rewriter, loc, loadedVecTy, ndDesc,
indices,
671 if (isTransposeLoad) {
674 auto range = llvm::seq<int64_t>(0, readMap.
getResults().size());
675 SmallVector<int64_t> perm(
676 range.rbegin(), range.rend());
677 loadedOp = vector::TransposeOp::create(rewriter, loc,
686struct TransferWriteLowering
690 LogicalResult matchAndRewrite(vector::TransferWriteOp writeOp,
691 PatternRewriter &rewriter)
const override {
692 Location loc = writeOp.getLoc();
694 if (
failed(transferPreconditions(rewriter, writeOp)))
697 VectorType vecTy = writeOp.getVectorType();
698 auto writeMemTy = cast<MemRefType>(writeOp.getShapedType());
700 bool isSharedMemory = xegpu::XeGPUDialect::isSharedMemory(writeMemTy);
706 if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
708 writeOp,
"Only 1D and 2D vector stores are supported for SLM");
711 xegpu::MemDescType::get(rewriter.
getContext(), writeMemTy.getShape(),
712 writeMemTy.getElementType(),
715 auto createMemDescOp = xegpu::CreateMemDescOp::create(
716 rewriter, loc, memDescType, writeOp.getBase());
719 SmallVector<OpFoldResult>
indices =
722 xegpu::StoreMatrixOp::create(rewriter, loc, writeOp.getVector(),
723 createMemDescOp.getResult(),
indices,
734 if ((chip !=
"pvc" && chip !=
"bmg" && chip !=
"cri") ||
735 writeOp.getVectorType().getRank() > 2) {
738 if (writeOp.hasOutOfBoundsDim())
740 return lowerToScatteredStoreOp(writeOp, rewriter);
743 if (
failed(storeLoadPreconditions(rewriter, writeOp, vecTy, writeMemTy)))
750 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
751 rewriter, loc, writeOp.getBase(),
754 auto descType = xegpu::TensorDescType::get(
755 vecTy.getShape(), vecTy.getElementType(),
756 1, writeOp.hasOutOfBoundsDim(),
757 xegpu::MemorySpace::Global);
759 xegpu::CachePolicyAttr hint =
nullptr;
760 xegpu::CreateNdDescOp ndDesc = createNdDescriptor(
763 auto storeOp = xegpu::StoreNdOp::create(rewriter, loc, writeOp.getVector(),
777 LogicalResult matchAndRewrite(vector::GatherOp gatherOp,
778 PatternRewriter &rewriter)
const override {
779 auto srcTy = dyn_cast<MemRefType>(gatherOp.getBase().getType());
783 Location loc = gatherOp.getLoc();
784 VectorType vectorType = gatherOp.getVectorType();
786 auto meta = computeMemrefMeta(gatherOp, rewriter);
787 if (meta.first.empty())
791 computeOffsets(rewriter, gatherOp, meta.first, meta.second);
792 Value flatMemref = memrefToIndexPtr(gatherOp, rewriter);
794 auto xeGatherOp = xegpu::LoadGatherOp::create(
795 rewriter, loc, vectorType, flatMemref, localOffsets, gatherOp.getMask(),
797 xegpu::CachePolicyAttr{},
798 xegpu::CachePolicyAttr{},
799 xegpu::CachePolicyAttr{},
803 arith::SelectOp::create(rewriter, loc, gatherOp.getMask(),
804 xeGatherOp.getResult(), gatherOp.getPassThru());
805 rewriter.
replaceOp(gatherOp, selectOp.getResult());
813 LogicalResult matchAndRewrite(vector::ScatterOp scatterOp,
814 PatternRewriter &rewriter)
const override {
815 auto srcTy = dyn_cast<MemRefType>(scatterOp.getBase().getType());
819 Location loc = scatterOp.getLoc();
820 auto meta = computeMemrefMeta(scatterOp, rewriter);
821 if (meta.first.empty())
823 "Failed to compute strides");
826 computeOffsets(rewriter, scatterOp, meta.first, meta.second);
827 Value flatMemref = memrefToIndexPtr(scatterOp, rewriter);
829 xegpu::StoreScatterOp::create(rewriter, loc, scatterOp.getValueToStore(),
830 flatMemref, localOffsets, scatterOp.getMask(),
832 xegpu::CachePolicyAttr{},
833 xegpu::CachePolicyAttr{},
834 xegpu::CachePolicyAttr{},
845 LogicalResult matchAndRewrite(vector::LoadOp loadOp,
846 PatternRewriter &rewriter)
const override {
847 Location loc = loadOp.getLoc();
849 VectorType vecTy = loadOp.getResult().getType();
850 MemRefType memTy = loadOp.getBase().getType();
851 if (
failed(storeLoadPreconditions(rewriter, loadOp, vecTy, memTy)))
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();
891 if (
failed(storeLoadPreconditions(rewriter, storeOp, vecTy, memTy)))
895 bool boundaryCheck = vecTy.getRank() > 1;
897 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
898 rewriter, loc, storeOp.getBase(),
901 auto descType = xegpu::TensorDescType::get(
902 vecTy.getShape(), vecTy.getElementType(),
903 1, boundaryCheck, xegpu::MemorySpace::Global);
906 xegpu::CachePolicyAttr hint =
nullptr;
907 xegpu::CreateNdDescOp ndDesc = createNdDescriptor(
911 xegpu::StoreNdOp::create(rewriter, loc, vector, ndDesc,
indices,
922struct ContractionLowering :
public OpRewritePattern<vector::ContractionOp> {
925 LogicalResult matchAndRewrite(vector::ContractionOp contractOp,
926 PatternRewriter &rewriter)
const override {
927 Location loc = contractOp.getLoc();
929 if (contractOp.getKind() != vector::CombiningKind::ADD)
931 "Expects add combining kind");
934 VectorType accType = dyn_cast<VectorType>(acc.getType());
935 if (!accType || accType.getRank() != 2)
942 if (
lhs.getType().getRank() != 2 ||
rhs.getType().getRank() != 2)
944 "Expects lhs and rhs 2D vectors");
949 auto dpasOp = xegpu::DpasOp::create(rewriter, loc,
959static MemRefType withMemorySpace(MemRefType memrefTy,
Attribute newMemSpace) {
960 return MemRefType::get(memrefTy.getShape(), memrefTy.getElementType(),
961 memrefTy.getLayout(), newMemSpace);
974static void promoteAllocasToSLM(
Operation *root) {
976 Attribute slmAttr = IntegerAttr::get(IntegerType::get(ctx, 64), 3);
982 auto isMemrefResultOp = [](
Operation *op) {
986 [](
Type t) { return isa<MemRefType>(t); });
992 auto memrefTy = dyn_cast<MemRefType>(v.getType());
993 if (!memrefTy || xegpu::XeGPUDialect::isSharedMemory(memrefTy))
995 v.setType(withMemorySpace(memrefTy, slmAttr));
997 if (!isMemrefResultOp(user))
1005 root->
walk([&](memref::AllocaOp op) {
1006 auto memrefTy = dyn_cast<MemRefType>(op.getResult().getType());
1007 if (!memrefTy || xegpu::XeGPUDialect::isSharedMemory(memrefTy))
1009 allocas.push_back(op);
1012 for (memref::AllocaOp alloca : allocas) {
1014 auto memrefTy = cast<MemRefType>(alloca.getResult().getType());
1015 auto newTy = withMemorySpace(memrefTy, slmAttr);
1016 auto newOp = memref::AllocaOp::create(
1017 builder, alloca.getLoc(), newTy, alloca.getDynamicSizes(),
1018 alloca.getSymbolOperands(), alloca.getAlignmentAttr());
1019 alloca.getResult().replaceAllUsesWith(newOp.getResult());
1023 if (!isMemrefResultOp(user))
1031struct ConvertVectorToXeGPUPass
1032 :
public impl::ConvertVectorToXeGPUBase<ConvertVectorToXeGPUPass> {
1033 void runOnOperation()
override {
1036 promoteAllocasToSLM(getOperation());
1042 return signalPassFailure();
1051 .
add<TransferReadLowering, TransferWriteLowering, LoadLowering,
1052 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
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.
result_type_range getResultTypes()
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...