17#include "llvm/ADT/SmallVectorExtras.h"
30 auto srcType = llvm::cast<MemRefType>(value.
getType());
33 if (srcType.getElementType() != destType.getElementType())
35 if (srcType.getRank() != destType.getRank())
41 auto isGuaranteedCastCompatible = [](MemRefType source, MemRefType
target) {
42 int64_t sourceOffset, targetOffset;
44 if (failed(source.getStridesAndOffset(sourceStrides, sourceOffset)) ||
45 failed(
target.getStridesAndOffset(targetStrides, targetOffset)))
48 return ShapedType::isDynamic(a) && ShapedType::isStatic(
b);
50 if (dynamicToStatic(sourceOffset, targetOffset))
52 for (
auto it : zip(sourceStrides, targetStrides))
53 if (dynamicToStatic(std::get<0>(it), std::get<1>(it)))
61 if (memref::CastOp::areCastCompatible(srcType, destType) &&
62 isGuaranteedCastCompatible(srcType, destType)) {
69 for (
int i = 0; i < destType.getRank(); ++i) {
70 if (destType.getShape()[i] != ShapedType::kDynamic)
72 Value size = memref::DimOp::create(
b, loc, value, i);
73 dynamicOperands.push_back(size);
77 b, loc, destType, dynamicOperands,
options.bufferAlignment);
90 auto bufferToTensor = toBuffer.getTensor().getDefiningOp<ToTensorOp>();
94 Type srcType = bufferToTensor.getBuffer().getType();
95 Type destType = toBuffer.getType();
98 if (srcType == destType) {
99 rewriter.
replaceOp(toBuffer, bufferToTensor.getBuffer());
103 if (!llvm::isa<BaseMemRefType>(srcType) ||
104 !llvm::isa<BaseMemRefType>(destType)) {
107 options.castFn(rewriter, bufferToTensor.getBuffer().getLoc(), destType,
108 bufferToTensor.getBuffer());
115 auto rankedSrcType = llvm::dyn_cast<MemRefType>(srcType);
116 auto rankedDestType = llvm::dyn_cast<MemRefType>(destType);
117 auto unrankedSrcType = llvm::dyn_cast<UnrankedMemRefType>(srcType);
120 if (rankedSrcType && rankedDestType) {
122 rewriter, bufferToTensor.getBuffer(), rankedDestType,
options);
132 if (unrankedSrcType && rankedDestType)
137 if (!memref::CastOp::areCastCompatible(srcType, destType))
141 bufferToTensor.getBuffer());
148 auto shapedType = llvm::cast<ShapedType>(shapedValue.
getType());
149 for (
int64_t i = 0; i < shapedType.getRank(); ++i) {
150 if (shapedType.isDynamicDim(i)) {
151 if (llvm::isa<MemRefType>(shapedType)) {
152 dynamicDims.push_back(memref::DimOp::create(
b, loc, shapedValue, i));
154 assert(llvm::isa<RankedTensorType>(shapedType) &&
"expected tensor");
155 dynamicDims.push_back(tensor::DimOp::create(
b, loc, shapedValue, i));
165LogicalResult AllocTensorOp::verify() {
167 return emitError(
"dynamic sizes not needed when copying a tensor");
172 return emitError(
"expected that `copy` and return type match");
177 RankedTensorType type,
ValueRange dynamicSizes) {
178 build(builder,
result, type, dynamicSizes,
Value(),
184 RankedTensorType type,
ValueRange dynamicSizes,
192 IntegerAttr memorySpace) {
210 using OpRewritePattern<AllocTensorOp>::OpRewritePattern;
212 LogicalResult matchAndRewrite(AllocTensorOp op,
213 PatternRewriter &rewriter)
const override {
216 SmallVector<int64_t> newShape = llvm::to_vector(op.getType().getShape());
217 SmallVector<Value> newDynamicSizes;
218 unsigned int dynValCounter = 0;
219 for (int64_t i = 0; i < op.getType().getRank(); ++i) {
220 if (!op.isDynamicDim(i))
222 Value value = op.getDynamicSizes()[dynValCounter++];
225 int64_t dim = intVal.getSExtValue();
227 newShape[i] = intVal.getSExtValue();
229 newDynamicSizes.push_back(value);
231 newDynamicSizes.push_back(value);
234 RankedTensorType newType = RankedTensorType::get(
235 newShape, op.getType().getElementType(), op.getType().getEncoding());
236 if (newType == op.getType())
238 auto newOp = AllocTensorOp::create(rewriter, op.getLoc(), newType,
239 newDynamicSizes, Value());
246 using OpRewritePattern<tensor::DimOp>::OpRewritePattern;
248 LogicalResult matchAndRewrite(tensor::DimOp dimOp,
249 PatternRewriter &rewriter)
const override {
250 std::optional<int64_t> maybeConstantIndex = dimOp.getConstantIndex();
251 auto allocTensorOp = dimOp.getSource().getDefiningOp<AllocTensorOp>();
252 if (!allocTensorOp || !maybeConstantIndex)
254 if (*maybeConstantIndex < 0 ||
255 *maybeConstantIndex >= allocTensorOp.getType().getRank())
257 if (!allocTensorOp.getType().isDynamicDim(*maybeConstantIndex))
260 dimOp, allocTensorOp.getDynamicSize(rewriter, *maybeConstantIndex));
268 results.
add<FoldDimOfAllocTensorOp, ReplaceStaticShapeDims>(ctx);
271LogicalResult AllocTensorOp::reifyResultShapes(
274 llvm::map_to_vector<4>(llvm::seq<int64_t>(0,
getType().getRank()),
276 if (isDynamicDim(dim))
280 reifiedReturnShapes.emplace_back(std::move(shapes));
291 if (copyKeyword.succeeded())
297 if (sizeHintKeyword.succeeded())
311 if (copyKeyword.succeeded())
314 if (sizeHintKeyword.succeeded())
317 result.addAttribute(AllocTensorOp::getOperandSegmentSizeAttr(),
319 {static_cast<int32_t>(dynamicSizesOperands.size()),
320 static_cast<int32_t>(copyKeyword.succeeded()),
321 static_cast<int32_t>(sizeHintKeyword.succeeded())}));
328 p <<
" copy(" << getCopy() <<
")";
330 p <<
" size_hint=" << getSizeHint();
332 AllocTensorOp::getOperandSegmentSizeAttr()});
334 auto type = getResult().getType();
335 if (
auto validType = llvm::dyn_cast<::mlir::TensorType>(type))
342 assert(isDynamicDim(idx) &&
"expected dynamic dim");
344 return tensor::DimOp::create(
b, getLoc(), getCopy(), idx);
345 return getOperand(getIndexOfDynamicSize(idx));
361 using OpRewritePattern<CloneOp>::OpRewritePattern;
363 LogicalResult matchAndRewrite(CloneOp cloneOp,
364 PatternRewriter &rewriter)
const override {
365 if (cloneOp.use_empty()) {
370 Value source = cloneOp.getInput();
371 if (source.
getType() != cloneOp.getType() &&
372 !memref::CastOp::areCastCompatible({source.getType()},
373 {cloneOp.getType()}))
378 Value canonicalSource = source;
379 while (
auto iface = dyn_cast_or_null<ViewLikeOpInterface>(
381 if (canonicalSource != iface.getViewDest()) {
384 canonicalSource = iface.getViewSource();
387 std::optional<Operation *> maybeCloneDeallocOp =
390 if (!maybeCloneDeallocOp.has_value())
392 std::optional<Operation *> maybeSourceDeallocOp =
394 if (!maybeSourceDeallocOp.has_value())
396 Operation *cloneDeallocOp = *maybeCloneDeallocOp;
397 Operation *sourceDeallocOp = *maybeSourceDeallocOp;
401 if (cloneDeallocOp && sourceDeallocOp &&
405 Block *currentBlock = cloneOp->getBlock();
406 Operation *redundantDealloc =
nullptr;
407 if (cloneDeallocOp && cloneDeallocOp->
getBlock() == currentBlock) {
408 redundantDealloc = cloneDeallocOp;
409 }
else if (sourceDeallocOp && sourceDeallocOp->
getBlock() == currentBlock) {
410 redundantDealloc = sourceDeallocOp;
413 if (!redundantDealloc)
421 for (Operation *pos = cloneOp->getNextNode(); pos != redundantDealloc;
422 pos = pos->getNextNode()) {
426 auto effectInterface = dyn_cast<MemoryEffectOpInterface>(pos);
427 if (!effectInterface)
429 if (effectInterface.hasEffect<MemoryEffects::Free>())
433 if (source.
getType() != cloneOp.getType())
434 source = memref::CastOp::create(rewriter, cloneOp.getLoc(),
435 cloneOp.getType(), source);
437 rewriter.
eraseOp(redundantDealloc);
446 results.
add<SimplifyClones>(context);
453LogicalResult MaterializeInDestinationOp::reifyResultShapes(
455 if (getOperation()->getNumResults() == 1) {
456 assert(isa<TensorType>(getDest().
getType()) &&
"expected tensor type");
457 reifiedReturnShapes.resize(1,
459 reifiedReturnShapes[0] =
465Value MaterializeInDestinationOp::buildSubsetExtraction(
OpBuilder &builder,
467 if (isa<TensorType>(getDest().
getType())) {
480 assert(isa<BaseMemRefType>(getDest().
getType()) &&
"expected memref type");
481 assert(getRestrict() &&
482 "expected that ops with memrefs dest have 'restrict'");
484 return ToTensorOp::create(
487 true, getWritable());
490bool MaterializeInDestinationOp::isEquivalentSubset(
492 return equivalenceFn(getDest(), candidate);
496MaterializeInDestinationOp::getValuesNeededToBuildSubsetExtraction() {
500OpOperand &MaterializeInDestinationOp::getSourceOperand() {
501 return getOperation()->getOpOperand(0) ;
504bool MaterializeInDestinationOp::operatesOnEquivalentSubset(
505 SubsetOpInterface subsetOp,
510bool MaterializeInDestinationOp::operatesOnDisjointSubset(
511 SubsetOpInterface subsetOp,
516LogicalResult MaterializeInDestinationOp::verify() {
517 if (!isa<TensorType, BaseMemRefType>(getDest().
getType()))
518 return emitOpError(
"'dest' must be a tensor or a memref");
519 if (
auto destType = dyn_cast<TensorType>(getDest().
getType())) {
520 if (getOperation()->getNumResults() != 1)
521 return emitOpError(
"tensor 'dest' implies exactly one tensor result");
522 if (destType != getResult().
getType())
523 return emitOpError(
"result and 'dest' types must match");
525 if (isa<BaseMemRefType>(getDest().
getType()) &&
526 getOperation()->getNumResults() != 0)
527 return emitOpError(
"memref 'dest' implies zero results");
528 if (getRestrict() && !isa<BaseMemRefType>(getDest().
getType()))
529 return emitOpError(
"'restrict' is valid only for memref destinations");
530 if (getWritable() != isa<BaseMemRefType>(getDest().
getType()))
531 return emitOpError(
"'writable' must be specified if and only if the "
532 "destination is of memref type");
534 ShapedType destType = cast<ShapedType>(getDest().
getType());
535 if (srcType.
hasRank() != destType.hasRank())
536 return emitOpError(
"source/destination shapes are incompatible");
541 for (
auto [src, dest] :
542 llvm::zip(srcType.
getShape(), destType.getShape())) {
543 if (src == ShapedType::kDynamic || dest == ShapedType::kDynamic) {
549 return emitOpError(
"source/destination shapes are incompatible");
555void MaterializeInDestinationOp::build(
OpBuilder &builder,
558 auto destTensorType = dyn_cast<TensorType>(dest.
getType());
559 build(builder, state, destTensorType ? destTensorType :
Type(),
564 return getDestMutable();
567void MaterializeInDestinationOp::getEffects(
570 if (isa<BaseMemRefType>(getDest().
getType()))
580 if (
auto toBuffer = getBuffer().getDefiningOp<ToBufferOp>())
583 if (toBuffer->getBlock() == this->getOperation()->getBlock() &&
584 toBuffer->getNextNode() == this->getOperation())
585 return toBuffer.getTensor();
591 using OpRewritePattern<tensor::DimOp>::OpRewritePattern;
593 LogicalResult matchAndRewrite(tensor::DimOp dimOp,
594 PatternRewriter &rewriter)
const override {
595 auto memrefToTensorOp = dimOp.getSource().getDefiningOp<ToTensorOp>();
596 if (!memrefToTensorOp)
600 dimOp, memrefToTensorOp.getBuffer(), dimOp.getIndex());
608 results.
add<DimOfToTensorFolder>(context);
616 if (
auto memrefToTensor = getTensor().getDefiningOp<ToTensorOp>())
617 if (memrefToTensor.getBuffer().getType() ==
getType())
618 return memrefToTensor.getBuffer();
626 using OpRewritePattern<ToBufferOp>::OpRewritePattern;
628 LogicalResult matchAndRewrite(ToBufferOp toBuffer,
629 PatternRewriter &rewriter)
const final {
630 auto tensorCastOperand =
631 toBuffer.getOperand().getDefiningOp<tensor::CastOp>();
632 if (!tensorCastOperand)
634 auto srcTensorType = llvm::dyn_cast<RankedTensorType>(
635 tensorCastOperand.getOperand().getType());
638 auto currentOutputMemRefType =
639 dyn_cast<BaseMemRefType>(toBuffer.getResult().getType());
640 if (!currentOutputMemRefType)
643 auto memrefType = currentOutputMemRefType.cloneWith(
644 srcTensorType.getShape(), srcTensorType.getElementType());
645 Value memref = ToBufferOp::create(rewriter, toBuffer.getLoc(), memrefType,
646 tensorCastOperand.getOperand(),
647 toBuffer.getReadOnly());
657 using OpRewritePattern<ToBufferOp>::OpRewritePattern;
659 LogicalResult matchAndRewrite(ToBufferOp toBuffer,
660 PatternRewriter &rewriter)
const final {
670 using OpRewritePattern<memref::LoadOp>::OpRewritePattern;
672 LogicalResult matchAndRewrite(memref::LoadOp
load,
673 PatternRewriter &rewriter)
const override {
674 auto toBuffer =
load.getMemref().getDefiningOp<ToBufferOp>();
675 if (!toBuffer || !toBuffer.getReadOnly())
686 using OpRewritePattern<memref::DimOp>::OpRewritePattern;
688 LogicalResult matchAndRewrite(memref::DimOp dimOp,
689 PatternRewriter &rewriter)
const override {
690 auto castOp = dimOp.getSource().getDefiningOp<ToBufferOp>();
693 Value newSource = castOp.getOperand();
704 results.
add<DimOfCastOp, LoadOfToBuffer, ToBufferOfCast,
705 ToBufferToTensorFolding>(context);
708std::optional<Operation *> CloneOp::buildDealloc(
OpBuilder &builder,
710 return memref::DeallocOp::create(builder, alloc.
getLoc(), alloc)
714std::optional<Value> CloneOp::buildClone(
OpBuilder &builder,
Value alloc) {
715 return CloneOp::create(builder, alloc.
getLoc(), alloc).getResult();
722LogicalResult DeallocOp::inferReturnTypes(
723 MLIRContext *context, std::optional<::mlir::Location> location,
726 DeallocOpAdaptor adaptor(operands, attributes, properties, regions);
728 IntegerType::get(context, 1));
732LogicalResult DeallocOp::verify() {
733 if (getMemrefs().size() != getConditions().size())
735 "must have the same number of conditions as memrefs to deallocate");
736 if (getRetained().size() != getUpdatedConditions().size())
737 return emitOpError(
"must have the same number of updated conditions "
738 "(results) as retained operands");
746 if (deallocOp.getMemrefs() == memrefs &&
747 deallocOp.getConditions() == conditions)
751 deallocOp.getMemrefsMutable().assign(memrefs);
752 deallocOp.getConditionsMutable().assign(conditions);
772struct DeallocRemoveDuplicateDeallocMemrefs
774 using OpRewritePattern<DeallocOp>::OpRewritePattern;
776 LogicalResult matchAndRewrite(DeallocOp deallocOp,
777 PatternRewriter &rewriter)
const override {
780 SmallVector<Value> newMemrefs, newConditions;
781 for (
auto [i, memref, cond] :
782 llvm::enumerate(deallocOp.getMemrefs(), deallocOp.getConditions())) {
783 if (memrefToCondition.count(memref)) {
786 Value &newCond = newConditions[memrefToCondition[memref]];
789 arith::OrIOp::create(rewriter, deallocOp.getLoc(), newCond, cond);
791 memrefToCondition.insert({memref, newConditions.size()});
792 newMemrefs.push_back(memref);
793 newConditions.push_back(cond);
814struct DeallocRemoveDuplicateRetainedMemrefs
816 using OpRewritePattern<DeallocOp>::OpRewritePattern;
818 LogicalResult matchAndRewrite(DeallocOp deallocOp,
819 PatternRewriter &rewriter)
const override {
822 SmallVector<Value> newRetained;
823 SmallVector<unsigned> resultReplacementIdx;
825 for (
auto retained : deallocOp.getRetained()) {
826 if (seen.count(retained)) {
827 resultReplacementIdx.push_back(seen[retained]);
832 newRetained.push_back(retained);
833 resultReplacementIdx.push_back(i++);
838 if (newRetained.size() == deallocOp.getRetained().size())
844 DeallocOp::create(rewriter, deallocOp.getLoc(), deallocOp.getMemrefs(),
845 deallocOp.getConditions(), newRetained);
846 SmallVector<Value> replacements(
847 llvm::map_range(resultReplacementIdx, [&](
unsigned idx) {
848 return newDeallocOp.getUpdatedConditions()[idx];
850 rewriter.
replaceOp(deallocOp, replacements);
861 using OpRewritePattern<DeallocOp>::OpRewritePattern;
863 LogicalResult matchAndRewrite(DeallocOp deallocOp,
864 PatternRewriter &rewriter)
const override {
865 if (deallocOp.getMemrefs().empty()) {
866 Value constFalse = arith::ConstantOp::create(rewriter, deallocOp.getLoc(),
869 deallocOp, SmallVector<Value>(deallocOp.getUpdatedConditions().size(),
890 using OpRewritePattern<DeallocOp>::OpRewritePattern;
892 LogicalResult matchAndRewrite(DeallocOp deallocOp,
893 PatternRewriter &rewriter)
const override {
894 SmallVector<Value> newMemrefs, newConditions;
895 for (
auto [memref, cond] :
896 llvm::zip(deallocOp.getMemrefs(), deallocOp.getConditions())) {
898 newMemrefs.push_back(memref);
899 newConditions.push_back(cond);
927 using OpRewritePattern<DeallocOp>::OpRewritePattern;
929 LogicalResult matchAndRewrite(DeallocOp deallocOp,
930 PatternRewriter &rewriter)
const override {
931 SmallVector<Value> newMemrefs(
932 llvm::map_range(deallocOp.getMemrefs(), [&](Value memref) {
933 auto extractStridedOp =
934 memref.getDefiningOp<memref::ExtractStridedMetadataOp>();
935 if (!extractStridedOp)
937 Value allocMemref = extractStridedOp.getOperand();
938 auto allocOp = allocMemref.getDefiningOp<MemoryEffectOpInterface>();
941 if (allocOp.getEffectOnValue<MemoryEffects::Allocate>(allocMemref))
947 deallocOp.getConditions(), rewriter);
965struct RemoveAllocDeallocPairWhenNoOtherUsers
967 using OpRewritePattern<DeallocOp>::OpRewritePattern;
969 LogicalResult matchAndRewrite(DeallocOp deallocOp,
970 PatternRewriter &rewriter)
const override {
971 SmallVector<Value> newMemrefs, newConditions;
972 SmallVector<Operation *> toDelete;
973 for (
auto [memref, cond] :
974 llvm::zip(deallocOp.getMemrefs(), deallocOp.getConditions())) {
975 if (
auto allocOp = memref.getDefiningOp<MemoryEffectOpInterface>()) {
979 if (allocOp.getEffectOnValue<MemoryEffects::Allocate>(memref) &&
981 memref.hasOneUse()) {
982 toDelete.push_back(allocOp);
987 newMemrefs.push_back(memref);
988 newConditions.push_back(cond);
995 for (Operation *op : toDelete)
1011 patterns.
add<DeallocRemoveDuplicateDeallocMemrefs,
1012 DeallocRemoveDuplicateRetainedMemrefs, EraseEmptyDealloc,
1013 EraseAlwaysFalseDealloc, SkipExtractMetadataOfAlloc,
1014 RemoveAllocDeallocPairWhenNoOtherUsers>(context);
1021#define GET_OP_CLASSES
1022#include "mlir/Dialect/Bufferization/IR/BufferizationOps.cpp.inc"
p<< " : "<< getMemRefType()<< ", "<< getType();}static LogicalResult verifyVectorMemoryOp(Operation *op, MemRefType memrefType, VectorType vectorType) { if(memrefType.getElementType() !=vectorType.getElementType()) return op-> emitOpError("requires memref and vector types of the same elemental type")
Given a list of lists of parsed operands, populates uniqueOperands with unique operands.
static SmallVector< Value > getDynamicSize(Value memref, func::FuncOp funcOp)
Return the dynamic shapes of the memref based on the defining op.
static LogicalResult updateDeallocIfChanged(DeallocOp deallocOp, ValueRange memrefs, ValueRange conditions, PatternRewriter &rewriter)
static void copy(Location loc, Value dst, Value src, Value size, OpBuilder &builder)
Copies the given number of bytes from src to dst pointers.
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be the output argument nBegin is set to its * replacement(set to `begin` if no invalidation happens). Since outgoing *copies could have been inserted at `end`
static llvm::ManagedStatic< PassManagerOptions > options
template bool mlir::hasSingleEffect< MemoryEffects::Allocate >(Operation *)
static void getDynamicSizes(RankedTensorType tp, ValueRange sizes, SmallVectorImpl< Value > &dynSizes)
Collects the dynamic dimension sizes for tp with the assumption that sizes are the dimension sizes fo...
virtual Builder & getBuilder() const =0
Return a builder which provides useful access to MLIRContext, global objects like types and attribute...
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into 'result' if it is present.
virtual ParseResult parseOptionalKeyword(StringRef keyword)=0
Parse the given keyword if present.
virtual ParseResult parseRParen()=0
Parse a ) token.
virtual ParseResult parseEqual()=0
Parse a = token.
virtual ParseResult parseCustomTypeWithFallback(Type &result, function_ref< ParseResult(Type &result)> parseType)=0
Parse a custom type with the provided callback, unless the next token is #, in which case the generic...
virtual ParseResult parseColon()=0
Parse a : token.
virtual ParseResult parseLParen()=0
Parse a ( token.
void printStrippedAttrOrType(AttrOrType attrOrType)
Print the provided attribute in the context of an operation custom printer/parser: this will invoke d...
IntegerAttr getIndexAttr(int64_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
BoolAttr getBoolAttr(bool value)
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 provides a mutable adaptor for a range of operands.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
virtual ParseResult resolveOperand(const UnresolvedOperand &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
ParseResult resolveOperands(Operands &&operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
virtual ParseResult parseOperand(UnresolvedOperand &result, bool allowResultNumber=true)=0
Parse a single SSA value operand name along with a result number if allowResultNumber is true.
virtual ParseResult parseOperandList(SmallVectorImpl< UnresolvedOperand > &result, Delimiter delimiter=Delimiter::None, bool allowResultNumber=true, int requiredOperandCount=-1)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values.
This class helps build Operations.
This class represents a single result from folding an operation.
This class represents an operand of an operation.
Block * getBlock()
Returns the operation block that contains this operation.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Type-safe wrapper around a void* for passing properties, including the properties structs of operatio...
This class provides an abstraction over the different types of ranges over Regions.
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
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.
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
This class represents a specific instance of an effect.
static DerivedEffect * get()
static DefaultResource * get()
Tensor types represent multi-dimensional arrays, and have two variants: RankedTensorType and Unranked...
ArrayRef< int64_t > getShape() const
Returns the shape of this tensor type.
bool hasRank() const
Returns if this type is ranked, i.e. it has a known number of dimensions.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
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.
Location getLoc() const
Return the location of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
void populateDeallocOpCanonicalizationPatterns(RewritePatternSet &patterns, MLIRContext *context)
Add the canonicalization patterns for bufferization.dealloc to the given pattern set to make them ava...
FailureOr< Value > castOrReallocMemRefValue(OpBuilder &b, Value value, MemRefType type, const BufferizationOptions &options)
Try to cast the given ranked MemRef-typed value to the given ranked MemRef type.
LogicalResult foldToBufferToTensorPair(RewriterBase &rewriter, ToBufferOp toBuffer, const BufferizationOptions &options)
Try to fold to_buffer(to_tensor(x)).
void populateDynamicDimSizes(OpBuilder &b, Location loc, Value shapedValue, SmallVector< Value > &dynamicDims)
Populate dynamicDims with tensor::DimOp / memref::DimOp results for all dynamic dimensions of the giv...
Type getTensorTypeFromMemRefType(Type type)
Return an unranked/ranked tensor type for the given unranked/ranked memref type.
std::optional< Operation * > findDealloc(Value allocValue)
Finds a single dealloc operation for the given allocated value.
LogicalResult foldMemRefCast(Operation *op, Value inner=nullptr)
This is a common utility used for patterns of the form "someop(memref.cast) -> someop".
SmallVector< OpFoldResult > getMixedSizes(OpBuilder &builder, Location loc, Value value)
Return the dimensions of the given tensor value.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
detail::constant_int_value_binder m_ConstantInt(IntegerAttr::ValueType *bind_value)
Matches a constant holding a scalar/vector/tensor integer (splat) and writes the integer value to bin...
LogicalResult verifyDynamicDimensionCount(Operation *op, ShapedType type, ValueRange dynamicSizes)
Verify that the number of dynamic size operands matches the number of dynamic dimensions in the shape...
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
SmallVector< SmallVector< OpFoldResult > > ReifiedRankedShapedTypeDims
detail::constant_int_predicate_matcher m_Zero()
Matches a constant scalar / vector splat / tensor splat integer zero.
LogicalResult verifyRanksMatch(Operation *op, ShapedType lhs, ShapedType rhs, StringRef lhsName, StringRef rhsName)
Verify that two shaped types have matching ranks.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
llvm::function_ref< Fn > function_ref
This is the representation of an operand reference.
OpRewritePattern is a wrapper around RewritePattern that allows for matching and rewriting against an...
This represents an operation in an abstracted form, suitable for use with the builder APIs.