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");
146static void adjustStridesForPermutation(
AffineMap permMap,
161 typename = std::enable_if_t<llvm::is_one_of<
162 std::decay_t<OpType>, vector::TransferReadOp, vector::TransferWriteOp,
163 vector::GatherOp, vector::ScatterOp>::value>>
164static std::pair<SmallVector<Value>,
Value>
167 Value baseMemref = xferOp.getBase();
168 MemRefType memrefType = dyn_cast<MemRefType>(baseMemref.
getType());
171 Value offsetVal =
nullptr;
172 if (memrefType.hasStaticShape()) {
175 if (
failed(memrefType.getStridesAndOffset(intStrides, offset)))
176 return {{}, offsetVal};
177 bool hasDynamicStrides = llvm::any_of(intStrides, [](
int64_t strideVal) {
178 return ShapedType::isDynamic(strideVal);
181 if (!hasDynamicStrides)
185 if (!ShapedType::isDynamic(offset))
189 if (strides.empty() || !offsetVal) {
192 unsigned rank = memrefType.getRank();
198 resultTypes.push_back(MemRefType::get(
199 {}, memrefType.getElementType()));
200 resultTypes.push_back(indexType);
202 for (
unsigned i = 0; i < rank; ++i)
203 resultTypes.push_back(indexType);
205 for (
unsigned i = 0; i < rank; ++i)
206 resultTypes.push_back(indexType);
208 auto meta = memref::ExtractStridedMetadataOp::create(
209 rewriter, loc, resultTypes, baseMemref);
212 strides.append(meta.getStrides().begin(), meta.getStrides().end());
215 offsetVal = meta.getOffset();
220 return {strides, offsetVal};
251static Value computeOffsets(VectorTransferOpInterface xferOp,
255 VectorType vectorType = xferOp.getVectorType();
257 xferOp.getIndices().end());
263 auto stepType = VectorType::get({dim}, rewriter.
getIndexType());
264 auto stepOp = vector::StepOp::create(rewriter, loc, stepType);
265 stepVectors.push_back(stepOp);
272 adjustStridesForPermutation(xferOp.getPermutationMap(), permutedStrides);
275 size_t memrefRank = permutedStrides.size();
278 for (
size_t i = 0; i < vectorRank; ++i) {
279 size_t memrefDim = memrefRank - vectorRank + i;
280 Value strideValue = permutedStrides[memrefDim];
281 auto mulType = dyn_cast<VectorType>(stepVectors[i].
getType());
283 vector::BroadcastOp::create(rewriter, loc, mulType, strideValue);
284 auto mulOp = arith::MulIOp::create(rewriter, loc, stepVectors[i], bcastOp);
285 strideMultiplied.push_back(mulOp);
290 for (
size_t i = 0; i < vectorRank; ++i) {
293 auto newType = VectorType::get(newShape, rewriter.
getIndexType());
294 auto castOp = vector::ShapeCastOp::create(rewriter, loc, newType,
295 strideMultiplied[i]);
296 shapeCasted.push_back(castOp);
301 auto fullIndexVectorType =
303 for (
Value shapeCastVal : shapeCasted) {
304 auto broadcastOp = vector::BroadcastOp::create(
305 rewriter, loc, fullIndexVectorType, shapeCastVal);
306 broadcasted.push_back(broadcastOp);
310 Value localOffsets = broadcasted[0];
311 for (
size_t i = 1; i < broadcasted.size(); ++i)
313 arith::AddIOp::create(rewriter, loc, localOffsets, broadcasted[i]);
316 for (
size_t i = 0; i <
indices.size(); ++i) {
317 Value strideVal = strides[i];
318 Value offsetContrib =
319 arith::MulIOp::create(rewriter, loc,
indices[i], strideVal);
321 arith::AddIOp::create(rewriter, loc, baseOffset, offsetContrib);
324 Value bcastBase = vector::BroadcastOp::create(
325 rewriter, loc, fullIndexVectorType, baseOffset);
326 localOffsets = arith::AddIOp::create(rewriter, loc, bcastBase, localOffsets);
337 typename = std::enable_if_t<llvm::is_one_of<
338 std::decay_t<OpType>, vector::GatherOp, vector::ScatterOp>::value>>
343 for (
size_t i = 0; i < offsets.size(); ++i) {
344 Value offsetContrib =
345 arith::MulIOp::create(rewriter, loc, offsets[i], strides[i]);
347 arith::AddIOp::create(rewriter, loc, baseOffset, offsetContrib);
350 VectorType vecType = cast<VectorType>(
indices.getType());
353 vector::BroadcastOp::create(rewriter, loc, vecType, strides.back())
355 Value stridedIndices =
356 arith::MulIOp::create(rewriter, loc, strideVector,
indices).getResult();
359 vector::BroadcastOp::create(
361 VectorType::get(vecType.getShape(), rewriter.
getIndexType()),
364 return arith::AddIOp::create(rewriter, loc, baseVector, stridedIndices)
373static std::pair<Value, SmallVector<OpFoldResult>>
378 auto memrefType = cast<MemRefType>(
memref.getType());
379 unsigned rank = memrefType.getRank();
381 if (rank <= targetRank)
384 int64_t numCombinedDims = rank - targetRank;
390 for (
unsigned i = 0; i < numCombinedDims; ++i) {
391 subviewOffsets.push_back(offsets[i]);
398 auto originalShape = memrefType.getShape();
399 auto meta = memref::ExtractStridedMetadataOp::create(rewriter, loc,
memref);
400 for (
unsigned i = numCombinedDims; i < rank; ++i) {
402 if (ShapedType::isDynamic(originalShape[i])) {
403 subviewSizes.push_back(meta.getSizes()[i]);
404 resultShape.push_back(ShapedType::kDynamic);
407 resultShape.push_back(originalShape[i]);
412 auto resultType = memref::SubViewOp::inferRankReducedResultType(
413 resultShape, memrefType, subviewOffsets, subviewSizes, subviewStrides);
415 memref::SubViewOp::create(rewriter, loc, resultType,
memref,
416 subviewOffsets, subviewSizes, subviewStrides);
421 return {subviewOp.getResult(), newOffsets};
426 typename = std::enable_if_t<llvm::is_one_of<
427 std::decay_t<OpType>, vector::TransferReadOp, vector::TransferWriteOp,
428 vector::GatherOp, vector::ScatterOp>::value>>
432 auto indexPtr = memref::ExtractAlignedPointerAsIndexOp::create(
433 rewriter, loc, xferOp.getBase())
435 return arith::IndexCastOp::create(rewriter, loc, rewriter.
getI64Type(),
440static LogicalResult lowerToScatteredLoadOp(vector::TransferReadOp readOp,
444 VectorType vectorType = readOp.getVectorType();
446 auto memrefType = dyn_cast<MemRefType>(readOp.getShapedType());
450 auto meta = computeMemrefMeta(readOp, rewriter);
451 if (meta.first.empty())
455 computeOffsets(readOp, rewriter, meta.first, meta.second);
457 Value flatMemref = memrefToIndexPtr(readOp, rewriter);
459 Value mask = vector::ConstantMaskOp::create(
462 auto gatherOp = xegpu::LoadGatherOp::create(
463 rewriter, loc, vectorType, flatMemref, localOffsets, mask,
465 xegpu::CachePolicyAttr{},
466 xegpu::CachePolicyAttr{},
467 xegpu::CachePolicyAttr{},
470 rewriter.
replaceOp(readOp, gatherOp.getResult());
474static LogicalResult lowerToScatteredStoreOp(vector::TransferWriteOp writeOp,
478 VectorType vectorType = writeOp.getVectorType();
481 auto memrefType = dyn_cast<MemRefType>(writeOp.getShapedType());
485 auto meta = computeMemrefMeta(writeOp, rewriter);
486 if (meta.first.empty())
490 computeOffsets(writeOp, rewriter, meta.first, meta.second);
492 Value flatMemref = memrefToIndexPtr(writeOp, rewriter);
494 Value mask = vector::ConstantMaskOp::create(
497 xegpu::StoreScatterOp::create(rewriter, loc, writeOp.getVector(), flatMemref,
500 xegpu::CachePolicyAttr{},
501 xegpu::CachePolicyAttr{},
502 xegpu::CachePolicyAttr{},
508struct TransferReadLowering :
public OpRewritePattern<vector::TransferReadOp> {
511 LogicalResult matchAndRewrite(vector::TransferReadOp readOp,
512 PatternRewriter &rewriter)
const override {
513 Location loc = readOp.getLoc();
515 if (
failed(transferPreconditions(rewriter, readOp)))
517 auto readMemTy = cast<MemRefType>(readOp.getShapedType());
518 VectorType loadedVecTy = readOp.getVectorType();
519 bool isOutOfBounds = readOp.hasOutOfBoundsDim();
521 bool isSharedMemory = xegpu::XeGPUDialect::isSharedMemory(readMemTy);
525 if (loadedVecTy.getRank() != 1 && loadedVecTy.getRank() != 2)
527 readOp,
"Only 1D and 2D vector loads are supported for SLM");
528 AffineMap readMap = readOp.getPermutationMap();
532 "Non identity transposition is not supported for SLM loads.");
536 readOp,
"Out-of-bounds access is not supported for SLM loads");
540 xegpu::MemDescType::get(rewriter.
getContext(), readMemTy.getShape(),
541 readMemTy.getElementType(),
543 auto createMemDescOp = xegpu::CreateMemDescOp::create(
544 rewriter, loc, memDescType, readOp.getBase());
546 SmallVector<OpFoldResult>
indices =
548 auto loadMatrixOp = xegpu::LoadMatrixOp::create(
549 rewriter, loc, loadedVecTy, createMemDescOp.getResult(),
indices,
552 rewriter.
replaceOp(readOp, loadMatrixOp.getResult());
558 bool hasBlockLoadSupport =
559 (chip ==
"pvc" || chip ==
"bmg" || chip ==
"cri");
566 bool isTransposeLoad = isInnermostTwoDimsTransposed(readMap);
573 bool canLowerToLoadNd =
574 hasBlockLoadSupport && loadedVecTy.getRank() > 1 &&
576 readMemTy.getElementType().isIntOrFloat() &&
577 (!isOutOfBounds || isZeroOrPoisonPadding(readOp.getPadding()));
579 if (canLowerToLoadNd) {
580 auto elementType = loadedVecTy.getElementType();
582 SmallVector<int64_t> descShape(loadedVecTy.getShape());
583 if (isTransposeLoad) {
586 size_t rank = descShape.size();
587 assert(rank >= 2 &&
"Transpose requires at least 2 dimensions");
588 std::swap(descShape[rank - 1], descShape[rank - 2]);
589 loadedVecTy = VectorType::get(descShape, elementType);
591 auto descType = xegpu::TensorDescType::get(
592 descShape, elementType, 1,
593 isOutOfBounds, xegpu::MemorySpace::Global);
594 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
595 rewriter, loc, readOp.getBase(),
598 xegpu::CachePolicyAttr hint =
nullptr;
599 xegpu::CreateNdDescOp ndDesc = xegpu::CreateNdDescOp::create(
602 Operation *loadedOp =
603 xegpu::LoadNdOp::create(rewriter, loc, loadedVecTy, ndDesc,
indices,
608 if (isTransposeLoad) {
612 int64_t rank = loadedVecTy.getRank();
613 SmallVector<int64_t> perm(llvm::to_vector(llvm::seq<int64_t>(0, rank)));
614 std::swap(perm[rank - 1], perm[rank - 2]);
615 loadedOp = vector::TransposeOp::create(rewriter, loc,
627 return lowerToScatteredLoadOp(readOp, rewriter);
631struct TransferWriteLowering
635 LogicalResult matchAndRewrite(vector::TransferWriteOp writeOp,
636 PatternRewriter &rewriter)
const override {
637 Location loc = writeOp.getLoc();
639 if (
failed(transferPreconditions(rewriter, writeOp)))
642 VectorType vecTy = writeOp.getVectorType();
643 auto writeMemTy = cast<MemRefType>(writeOp.getShapedType());
645 bool isSharedMemory = xegpu::XeGPUDialect::isSharedMemory(writeMemTy);
651 if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
653 writeOp,
"Only 1D and 2D vector stores are supported for SLM");
656 xegpu::MemDescType::get(rewriter.
getContext(), writeMemTy.getShape(),
657 writeMemTy.getElementType(),
660 auto createMemDescOp = xegpu::CreateMemDescOp::create(
661 rewriter, loc, memDescType, writeOp.getBase());
664 SmallVector<OpFoldResult>
indices =
667 xegpu::StoreMatrixOp::create(rewriter, loc, writeOp.getVector(),
668 createMemDescOp.getResult(),
indices,
677 bool hasBlockStoreSupport =
678 (chip ==
"pvc" || chip ==
"bmg" || chip ==
"cri");
686 bool canLowerToStoreNd = hasBlockStoreSupport && vecTy.getRank() > 1 &&
688 writeMemTy.getElementType().isIntOrFloat();
690 if (canLowerToStoreNd) {
691 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
692 rewriter, loc, writeOp.getBase(),
695 auto descType = xegpu::TensorDescType::get(
696 vecTy.getShape(), vecTy.getElementType(),
697 1, writeOp.hasOutOfBoundsDim(),
698 xegpu::MemorySpace::Global);
700 xegpu::CachePolicyAttr hint =
nullptr;
701 xegpu::CreateNdDescOp ndDesc = xegpu::CreateNdDescOp::create(
704 auto storeOp = xegpu::StoreNdOp::create(
705 rewriter, loc, writeOp.getVector(), ndDesc,
indices,
716 if (writeOp.hasOutOfBoundsDim())
718 return lowerToScatteredStoreOp(writeOp, rewriter);
725 LogicalResult matchAndRewrite(vector::GatherOp gatherOp,
726 PatternRewriter &rewriter)
const override {
727 auto srcTy = dyn_cast<MemRefType>(gatherOp.getBase().getType());
731 Location loc = gatherOp.getLoc();
732 VectorType vectorType = gatherOp.getVectorType();
734 auto meta = computeMemrefMeta(gatherOp, rewriter);
735 if (meta.first.empty())
739 computeOffsets(rewriter, gatherOp, meta.first, meta.second);
740 Value flatMemref = memrefToIndexPtr(gatherOp, rewriter);
742 auto xeGatherOp = xegpu::LoadGatherOp::create(
743 rewriter, loc, vectorType, flatMemref, localOffsets, gatherOp.getMask(),
745 xegpu::CachePolicyAttr{},
746 xegpu::CachePolicyAttr{},
747 xegpu::CachePolicyAttr{},
751 arith::SelectOp::create(rewriter, loc, gatherOp.getMask(),
752 xeGatherOp.getResult(), gatherOp.getPassThru());
753 rewriter.
replaceOp(gatherOp, selectOp.getResult());
761 LogicalResult matchAndRewrite(vector::ScatterOp scatterOp,
762 PatternRewriter &rewriter)
const override {
763 auto srcTy = dyn_cast<MemRefType>(scatterOp.getBase().getType());
767 Location loc = scatterOp.getLoc();
768 auto meta = computeMemrefMeta(scatterOp, rewriter);
769 if (meta.first.empty())
771 "Failed to compute strides");
774 computeOffsets(rewriter, scatterOp, meta.first, meta.second);
775 Value flatMemref = memrefToIndexPtr(scatterOp, rewriter);
777 xegpu::StoreScatterOp::create(rewriter, loc, scatterOp.getValueToStore(),
778 flatMemref, localOffsets, scatterOp.getMask(),
780 xegpu::CachePolicyAttr{},
781 xegpu::CachePolicyAttr{},
782 xegpu::CachePolicyAttr{},
793 LogicalResult matchAndRewrite(vector::LoadOp loadOp,
794 PatternRewriter &rewriter)
const override {
795 Location loc = loadOp.getLoc();
797 VectorType vecTy = loadOp.getResult().getType();
798 MemRefType memTy = loadOp.getBase().getType();
800 if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
802 if (!memTy.getElementType().isIntOrFloat())
804 loadOp,
"Unsupported memref element type: expected integer or float");
807 bool boundaryCheck = vecTy.getRank() > 1;
809 xegpu::CachePolicyAttr hint =
nullptr;
811 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
815 auto descType = xegpu::TensorDescType::get(
816 vecTy.getShape(), vecTy.getElementType(), 1,
817 boundaryCheck, xegpu::MemorySpace::Global);
819 xegpu::CreateNdDescOp ndDesc = xegpu::CreateNdDescOp::create(
822 xegpu::LoadNdOp::create(rewriter, loc, vecTy, ndDesc,
indices,
836 LogicalResult matchAndRewrite(vector::StoreOp storeOp,
837 PatternRewriter &rewriter)
const override {
838 Location loc = storeOp.getLoc();
841 VectorType vecTy = vector.getType();
842 MemRefType memTy = storeOp.getBase().getType();
844 if (vecTy.getRank() != 1 && vecTy.getRank() != 2)
846 if (!memTy.getElementType().isIntOrFloat())
849 "Unsupported memref element type: expected integer or float");
852 bool boundaryCheck = vecTy.getRank() > 1;
854 auto [src,
indices] = convertMemrefAndOffsetsToTargetRank(
855 rewriter, loc, storeOp.getBase(),
858 auto descType = xegpu::TensorDescType::get(
859 vecTy.getShape(), vecTy.getElementType(),
860 1, boundaryCheck, xegpu::MemorySpace::Global);
863 xegpu::CachePolicyAttr hint =
nullptr;
864 xegpu::CreateNdDescOp ndDesc = xegpu::CreateNdDescOp::create(
868 xegpu::StoreNdOp::create(rewriter, loc, vector, ndDesc,
indices,
883static std::optional<int64_t>
884getRowMajorMatmulBatchRank(
ArrayAttr indexingMaps) {
885 if (indexingMaps.size() != 3)
888 AffineMap mapA = cast<AffineMapAttr>(indexingMaps[0]).getValue();
889 AffineMap mapB = cast<AffineMapAttr>(indexingMaps[1]).getValue();
890 AffineMap mapC = cast<AffineMapAttr>(indexingMaps[2]).getValue();
899 unsigned numDims =
static_cast<unsigned>(batchRank) + 3;
900 unsigned numOperandResults =
static_cast<unsigned>(batchRank) + 2;
926 auto expected = ArrayAttr::get(
931 if (indexingMaps != expected)
936struct ContractionLowering :
public OpRewritePattern<vector::ContractionOp> {
939 LogicalResult matchAndRewrite(vector::ContractionOp contractOp,
940 PatternRewriter &rewriter)
const override {
941 Location loc = contractOp.getLoc();
943 if (contractOp.getKind() != vector::CombiningKind::ADD)
945 "Expects add combining kind");
950 VectorType accType = dyn_cast<VectorType>(acc.getType());
954 std::optional<int64_t> batchRank =
955 getRowMajorMatmulBatchRank(contractOp.getIndexingMapsAttr());
959 "Expects a (batched) row-major matmul: leading dims must "
960 "be batch dims shared by lhs, rhs, and acc; innermost two "
961 "dims must be (M, K), (K, N), and (M, N)");
966 "Expects operands of rank 4 or less");
968 auto dpasOp = xegpu::DpasOp::create(rewriter, loc,
978static MemRefType withMemorySpace(MemRefType memrefTy,
Attribute newMemSpace) {
979 return MemRefType::get(memrefTy.getShape(), memrefTy.getElementType(),
980 memrefTy.getLayout(), newMemSpace);
993static void promoteAllocasToSLM(
Operation *root) {
995 Attribute slmAttr = IntegerAttr::get(IntegerType::get(ctx, 64), 3);
1001 auto isMemrefResultOp = [](
Operation *op) {
1004 return llvm::any_of(op->getResultTypes(),
1005 [](
Type t) { return isa<MemRefType>(t); });
1011 auto memrefTy = dyn_cast<MemRefType>(v.getType());
1012 if (!memrefTy || xegpu::XeGPUDialect::isSharedMemory(memrefTy))
1014 v.setType(withMemorySpace(memrefTy, slmAttr));
1016 if (!isMemrefResultOp(user))
1024 root->
walk([&](memref::AllocaOp op) {
1025 auto memrefTy = dyn_cast<MemRefType>(op.getResult().getType());
1026 if (!memrefTy || xegpu::XeGPUDialect::isSharedMemory(memrefTy))
1028 allocas.push_back(op);
1031 for (memref::AllocaOp alloca : allocas) {
1033 auto memrefTy = cast<MemRefType>(alloca.getResult().getType());
1034 auto newTy = withMemorySpace(memrefTy, slmAttr);
1035 auto newOp = memref::AllocaOp::create(
1036 builder, alloca.getLoc(), newTy, alloca.getDynamicSizes(),
1037 alloca.getSymbolOperands(), alloca.getAlignmentAttr());
1038 alloca.getResult().replaceAllUsesWith(newOp.getResult());
1042 if (!isMemrefResultOp(user))
1050struct ConvertVectorToXeGPUPass
1052 void runOnOperation()
override {
1055 promoteAllocasToSLM(getOperation());
1061 return signalPassFailure();
1070 .
add<TransferReadLowering, TransferWriteLowering, LoadLowering,
1071 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.
static AffineMap get(MLIRContext *context)
Returns a zero result affine map with no dimensions or symbols: () -> ().
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.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...