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())
302 if (AllocTensorOp::genericParseProperties(parser, parsedProperties))
304 auto propertyDictionary = dyn_cast_or_null<DictionaryAttr>(parsedProperties);
305 if (parsedProperties && !propertyDictionary)
307 "expected properties dictionary");
312 for (StringRef attrName : AllocTensorOp::getAttributeNames()) {
313 if (
result.attributes.get(attrName))
315 <<
"inherent attribute '" << attrName
316 <<
"' cannot be parsed from attr-dict when strict properties in "
317 "assembly format is enabled";
330 if (copyKeyword.succeeded())
333 if (sizeHintKeyword.succeeded())
337 NamedAttrList properties(propertyDictionary ? propertyDictionary
339 properties.set(AllocTensorOp::getOperandSegmentSizeAttr(),
341 {static_cast<int32_t>(dynamicSizesOperands.size()),
342 static_cast<int32_t>(copyKeyword.succeeded()),
343 static_cast<int32_t>(sizeHintKeyword.succeeded())}));
344 propertyDictionary = properties.getDictionary(builder.
getContext());
347 << propertyDictionary <<
" for op " <<
result.name.getStringRef()
350 if (
failed(AllocTensorOp::setPropertiesFromParsedAttr(
351 result.getOrAddProperties<Properties>(), propertyDictionary,
360 p <<
" copy(" << getCopy() <<
")";
362 p <<
" size_hint=" << getSizeHint();
363 AllocTensorOp::printProperties(
getContext(), p, getProperties(),
364 getOperandSegmentSizeAttr());
367 auto type = getResult().getType();
368 if (
auto validType = llvm::dyn_cast<::mlir::TensorType>(type))
375 assert(isDynamicDim(idx) &&
"expected dynamic dim");
377 return tensor::DimOp::create(
b, getLoc(), getCopy(), idx);
378 return getOperand(getIndexOfDynamicSize(idx));
394 using OpRewritePattern<CloneOp>::OpRewritePattern;
396 LogicalResult matchAndRewrite(CloneOp cloneOp,
397 PatternRewriter &rewriter)
const override {
398 if (cloneOp.use_empty()) {
403 Value source = cloneOp.getInput();
404 if (source.
getType() != cloneOp.getType() &&
405 !memref::CastOp::areCastCompatible({source.getType()},
406 {cloneOp.getType()}))
411 Value canonicalSource = source;
412 while (
auto iface = dyn_cast_or_null<ViewLikeOpInterface>(
414 if (canonicalSource != iface.getViewDest()) {
417 canonicalSource = iface.getViewSource();
420 std::optional<Operation *> maybeCloneDeallocOp =
423 if (!maybeCloneDeallocOp.has_value())
425 std::optional<Operation *> maybeSourceDeallocOp =
427 if (!maybeSourceDeallocOp.has_value())
429 Operation *cloneDeallocOp = *maybeCloneDeallocOp;
430 Operation *sourceDeallocOp = *maybeSourceDeallocOp;
434 if (cloneDeallocOp && sourceDeallocOp &&
438 Block *currentBlock = cloneOp->getBlock();
439 Operation *redundantDealloc =
nullptr;
440 if (cloneDeallocOp && cloneDeallocOp->
getBlock() == currentBlock) {
441 redundantDealloc = cloneDeallocOp;
442 }
else if (sourceDeallocOp && sourceDeallocOp->
getBlock() == currentBlock) {
443 redundantDealloc = sourceDeallocOp;
446 if (!redundantDealloc)
454 for (Operation *pos = cloneOp->getNextNode(); pos != redundantDealloc;
455 pos = pos->getNextNode()) {
459 auto effectInterface = dyn_cast<MemoryEffectOpInterface>(pos);
460 if (!effectInterface)
462 if (effectInterface.hasEffect<MemoryEffects::Free>())
466 if (source.
getType() != cloneOp.getType())
467 source = memref::CastOp::create(rewriter, cloneOp.getLoc(),
468 cloneOp.getType(), source);
470 rewriter.
eraseOp(redundantDealloc);
479 results.
add<SimplifyClones>(context);
486LogicalResult MaterializeInDestinationOp::reifyResultShapes(
488 if (getOperation()->getNumResults() == 1) {
489 assert(isa<TensorType>(getDest().
getType()) &&
"expected tensor type");
490 reifiedReturnShapes.resize(1,
492 reifiedReturnShapes[0] =
498Value MaterializeInDestinationOp::buildSubsetExtraction(
OpBuilder &builder,
500 if (isa<TensorType>(getDest().
getType())) {
513 assert(isa<BaseMemRefType>(getDest().
getType()) &&
"expected memref type");
514 assert(getRestrict() &&
515 "expected that ops with memrefs dest have 'restrict'");
517 return ToTensorOp::create(
520 true, getWritable());
523bool MaterializeInDestinationOp::isEquivalentSubset(
525 return equivalenceFn(getDest(), candidate);
529MaterializeInDestinationOp::getValuesNeededToBuildSubsetExtraction() {
533OpOperand &MaterializeInDestinationOp::getSourceOperand() {
534 return getOperation()->getOpOperand(0) ;
537bool MaterializeInDestinationOp::operatesOnEquivalentSubset(
538 SubsetOpInterface subsetOp,
543bool MaterializeInDestinationOp::operatesOnDisjointSubset(
544 SubsetOpInterface subsetOp,
549LogicalResult MaterializeInDestinationOp::verify() {
550 if (!isa<TensorType, BaseMemRefType>(getDest().
getType()))
551 return emitOpError(
"'dest' must be a tensor or a memref");
552 if (
auto destType = dyn_cast<TensorType>(getDest().
getType())) {
553 if (getOperation()->getNumResults() != 1)
554 return emitOpError(
"tensor 'dest' implies exactly one tensor result");
555 if (destType != getResult().
getType())
556 return emitOpError(
"result and 'dest' types must match");
558 if (isa<BaseMemRefType>(getDest().
getType()) &&
559 getOperation()->getNumResults() != 0)
560 return emitOpError(
"memref 'dest' implies zero results");
561 if (getRestrict() && !isa<BaseMemRefType>(getDest().
getType()))
562 return emitOpError(
"'restrict' is valid only for memref destinations");
563 if (getWritable() != isa<BaseMemRefType>(getDest().
getType()))
564 return emitOpError(
"'writable' must be specified if and only if the "
565 "destination is of memref type");
567 ShapedType destType = cast<ShapedType>(getDest().
getType());
568 if (srcType.
hasRank() != destType.hasRank())
569 return emitOpError(
"source/destination shapes are incompatible");
574 for (
auto [src, dest] :
575 llvm::zip(srcType.
getShape(), destType.getShape())) {
576 if (src == ShapedType::kDynamic || dest == ShapedType::kDynamic) {
582 return emitOpError(
"source/destination shapes are incompatible");
588void MaterializeInDestinationOp::build(
OpBuilder &builder,
591 auto destTensorType = dyn_cast<TensorType>(dest.
getType());
592 build(builder, state, destTensorType ? destTensorType :
Type(),
597 return getDestMutable();
600void MaterializeInDestinationOp::getEffects(
603 if (isa<BaseMemRefType>(getDest().
getType()))
613 if (
auto toBuffer = getBuffer().getDefiningOp<ToBufferOp>())
616 if (toBuffer->getBlock() == this->getOperation()->getBlock() &&
617 toBuffer->getNextNode() == this->getOperation())
618 return toBuffer.getTensor();
624 using OpRewritePattern<tensor::DimOp>::OpRewritePattern;
626 LogicalResult matchAndRewrite(tensor::DimOp dimOp,
627 PatternRewriter &rewriter)
const override {
628 auto memrefToTensorOp = dimOp.getSource().getDefiningOp<ToTensorOp>();
629 if (!memrefToTensorOp)
633 dimOp, memrefToTensorOp.getBuffer(), dimOp.getIndex());
641 results.
add<DimOfToTensorFolder>(context);
649 if (
auto memrefToTensor = getTensor().getDefiningOp<ToTensorOp>())
650 if (memrefToTensor.getBuffer().getType() ==
getType())
651 return memrefToTensor.getBuffer();
659 using OpRewritePattern<ToBufferOp>::OpRewritePattern;
661 LogicalResult matchAndRewrite(ToBufferOp toBuffer,
662 PatternRewriter &rewriter)
const final {
663 auto tensorCastOperand =
664 toBuffer.getOperand().getDefiningOp<tensor::CastOp>();
665 if (!tensorCastOperand)
667 auto srcTensorType = llvm::dyn_cast<RankedTensorType>(
668 tensorCastOperand.getOperand().getType());
671 auto currentOutputMemRefType =
672 dyn_cast<BaseMemRefType>(toBuffer.getResult().getType());
673 if (!currentOutputMemRefType)
676 auto memrefType = currentOutputMemRefType.cloneWith(
677 srcTensorType.getShape(), srcTensorType.getElementType());
678 Value memref = ToBufferOp::create(rewriter, toBuffer.getLoc(), memrefType,
679 tensorCastOperand.getOperand(),
680 toBuffer.getReadOnly());
690 using OpRewritePattern<ToBufferOp>::OpRewritePattern;
692 LogicalResult matchAndRewrite(ToBufferOp toBuffer,
693 PatternRewriter &rewriter)
const final {
703 using OpRewritePattern<memref::LoadOp>::OpRewritePattern;
705 LogicalResult matchAndRewrite(memref::LoadOp
load,
706 PatternRewriter &rewriter)
const override {
707 auto toBuffer =
load.getMemref().getDefiningOp<ToBufferOp>();
708 if (!toBuffer || !toBuffer.getReadOnly())
719 using OpRewritePattern<memref::DimOp>::OpRewritePattern;
721 LogicalResult matchAndRewrite(memref::DimOp dimOp,
722 PatternRewriter &rewriter)
const override {
723 auto castOp = dimOp.getSource().getDefiningOp<ToBufferOp>();
726 Value newSource = castOp.getOperand();
737 results.
add<DimOfCastOp, LoadOfToBuffer, ToBufferOfCast,
738 ToBufferToTensorFolding>(context);
741std::optional<Operation *> CloneOp::buildDealloc(
OpBuilder &builder,
743 return memref::DeallocOp::create(builder, alloc.
getLoc(), alloc)
747std::optional<Value> CloneOp::buildClone(
OpBuilder &builder,
Value alloc) {
748 return CloneOp::create(builder, alloc.
getLoc(), alloc).getResult();
755LogicalResult DeallocOp::inferReturnTypes(
756 MLIRContext *context, std::optional<::mlir::Location> location,
759 DeallocOpAdaptor adaptor(operands, attributes, properties, regions);
761 IntegerType::get(context, 1));
765LogicalResult DeallocOp::verify() {
766 if (getMemrefs().size() != getConditions().size())
768 "must have the same number of conditions as memrefs to deallocate");
769 if (getRetained().size() != getUpdatedConditions().size())
770 return emitOpError(
"must have the same number of updated conditions "
771 "(results) as retained operands");
779 if (deallocOp.getMemrefs() == memrefs &&
780 deallocOp.getConditions() == conditions)
784 deallocOp.getMemrefsMutable().assign(memrefs);
785 deallocOp.getConditionsMutable().assign(conditions);
805struct DeallocRemoveDuplicateDeallocMemrefs
807 using OpRewritePattern<DeallocOp>::OpRewritePattern;
809 LogicalResult matchAndRewrite(DeallocOp deallocOp,
810 PatternRewriter &rewriter)
const override {
813 SmallVector<Value> newMemrefs, newConditions;
814 for (
auto [i, memref, cond] :
815 llvm::enumerate(deallocOp.getMemrefs(), deallocOp.getConditions())) {
816 if (memrefToCondition.count(memref)) {
819 Value &newCond = newConditions[memrefToCondition[memref]];
822 arith::OrIOp::create(rewriter, deallocOp.getLoc(), newCond, cond);
824 memrefToCondition.insert({memref, newConditions.size()});
825 newMemrefs.push_back(memref);
826 newConditions.push_back(cond);
847struct DeallocRemoveDuplicateRetainedMemrefs
849 using OpRewritePattern<DeallocOp>::OpRewritePattern;
851 LogicalResult matchAndRewrite(DeallocOp deallocOp,
852 PatternRewriter &rewriter)
const override {
855 SmallVector<Value> newRetained;
856 SmallVector<unsigned> resultReplacementIdx;
858 for (
auto retained : deallocOp.getRetained()) {
859 if (seen.count(retained)) {
860 resultReplacementIdx.push_back(seen[retained]);
865 newRetained.push_back(retained);
866 resultReplacementIdx.push_back(i++);
871 if (newRetained.size() == deallocOp.getRetained().size())
877 DeallocOp::create(rewriter, deallocOp.getLoc(), deallocOp.getMemrefs(),
878 deallocOp.getConditions(), newRetained);
879 SmallVector<Value> replacements(
880 llvm::map_range(resultReplacementIdx, [&](
unsigned idx) {
881 return newDeallocOp.getUpdatedConditions()[idx];
883 rewriter.
replaceOp(deallocOp, replacements);
894 using OpRewritePattern<DeallocOp>::OpRewritePattern;
896 LogicalResult matchAndRewrite(DeallocOp deallocOp,
897 PatternRewriter &rewriter)
const override {
898 if (deallocOp.getMemrefs().empty()) {
899 Value constFalse = arith::ConstantOp::create(rewriter, deallocOp.getLoc(),
902 deallocOp, SmallVector<Value>(deallocOp.getUpdatedConditions().size(),
923 using OpRewritePattern<DeallocOp>::OpRewritePattern;
925 LogicalResult matchAndRewrite(DeallocOp deallocOp,
926 PatternRewriter &rewriter)
const override {
927 SmallVector<Value> newMemrefs, newConditions;
928 for (
auto [memref, cond] :
929 llvm::zip(deallocOp.getMemrefs(), deallocOp.getConditions())) {
931 newMemrefs.push_back(memref);
932 newConditions.push_back(cond);
960 using OpRewritePattern<DeallocOp>::OpRewritePattern;
962 LogicalResult matchAndRewrite(DeallocOp deallocOp,
963 PatternRewriter &rewriter)
const override {
964 SmallVector<Value> newMemrefs(
965 llvm::map_range(deallocOp.getMemrefs(), [&](Value memref) {
966 auto extractStridedOp =
967 memref.getDefiningOp<memref::ExtractStridedMetadataOp>();
968 if (!extractStridedOp)
970 Value allocMemref = extractStridedOp.getOperand();
971 auto allocOp = allocMemref.getDefiningOp<MemoryEffectOpInterface>();
974 if (allocOp.getEffectOnValue<MemoryEffects::Allocate>(allocMemref))
980 deallocOp.getConditions(), rewriter);
998struct RemoveAllocDeallocPairWhenNoOtherUsers
1000 using OpRewritePattern<DeallocOp>::OpRewritePattern;
1002 LogicalResult matchAndRewrite(DeallocOp deallocOp,
1003 PatternRewriter &rewriter)
const override {
1004 SmallVector<Value> newMemrefs, newConditions;
1005 SmallVector<Operation *> toDelete;
1006 for (
auto [memref, cond] :
1007 llvm::zip(deallocOp.getMemrefs(), deallocOp.getConditions())) {
1008 if (
auto allocOp = memref.getDefiningOp<MemoryEffectOpInterface>()) {
1012 if (allocOp.getEffectOnValue<MemoryEffects::Allocate>(memref) &&
1014 memref.hasOneUse()) {
1015 toDelete.push_back(allocOp);
1020 newMemrefs.push_back(memref);
1021 newConditions.push_back(cond);
1028 for (Operation *op : toDelete)
1044 patterns.
add<DeallocRemoveDuplicateDeallocMemrefs,
1045 DeallocRemoveDuplicateRetainedMemrefs, EraseEmptyDealloc,
1046 EraseAlwaysFalseDealloc, SkipExtractMetadataOfAlloc,
1047 RemoveAllocDeallocPairWhenNoOtherUsers>(context);
1054#define GET_OP_CLASSES
1055#include "mlir/Dialect/Bufferization/IR/BufferizationOps.cpp.inc"
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 InFlightDiagnostic emitError(SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
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 SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
virtual ParseResult parseColon()=0
Parse a : token.
virtual SMLoc getNameLoc() const =0
Return the location of the original name 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...
Attributes are known-constant values of operations.
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getIndexAttr(int64_t value)
DenseI32ArrayAttr getDenseI32ArrayAttr(ArrayRef< int32_t > values)
BoolAttr getBoolAttr(bool value)
MLIRContext * getContext() const
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > 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.
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
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.