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)))
60 if (!source.getLayout().isIdentity() &&
target.getLayout().isIdentity())
68 if (memref::CastOp::areCastCompatible(srcType, destType) &&
69 isGuaranteedCastCompatible(srcType, destType)) {
76 for (
int i = 0; i < destType.getRank(); ++i) {
77 if (destType.getShape()[i] != ShapedType::kDynamic)
79 Value size = memref::DimOp::create(
b, loc, value, i);
80 dynamicOperands.push_back(size);
84 b, loc, destType, dynamicOperands,
options.bufferAlignment);
97 auto bufferToTensor = toBuffer.getTensor().getDefiningOp<ToTensorOp>();
101 Type srcType = bufferToTensor.getBuffer().getType();
102 Type destType = toBuffer.getType();
105 if (srcType == destType) {
106 rewriter.
replaceOp(toBuffer, bufferToTensor.getBuffer());
110 if (!llvm::isa<BaseMemRefType>(srcType) ||
111 !llvm::isa<BaseMemRefType>(destType)) {
114 options.castFn(rewriter, bufferToTensor.getBuffer().getLoc(), destType,
115 bufferToTensor.getBuffer());
122 auto rankedSrcType = llvm::dyn_cast<MemRefType>(srcType);
123 auto rankedDestType = llvm::dyn_cast<MemRefType>(destType);
124 auto unrankedSrcType = llvm::dyn_cast<UnrankedMemRefType>(srcType);
127 if (rankedSrcType && rankedDestType) {
129 rewriter, bufferToTensor.getBuffer(), rankedDestType,
options);
139 if (unrankedSrcType && rankedDestType)
144 if (!memref::CastOp::areCastCompatible(srcType, destType))
148 bufferToTensor.getBuffer());
155 auto shapedType = llvm::cast<ShapedType>(shapedValue.
getType());
156 for (
int64_t i = 0; i < shapedType.getRank(); ++i) {
157 if (shapedType.isDynamicDim(i)) {
158 if (llvm::isa<MemRefType>(shapedType)) {
159 dynamicDims.push_back(memref::DimOp::create(
b, loc, shapedValue, i));
161 assert(llvm::isa<RankedTensorType>(shapedType) &&
"expected tensor");
162 dynamicDims.push_back(tensor::DimOp::create(
b, loc, shapedValue, i));
172LogicalResult AllocTensorOp::verify() {
173 auto type = dyn_cast<RankedTensorType>(
getType());
175 return emitError(
"takes dynamic sizes and a size hint only for a ranked "
178 return emitError(
"dynamic sizes not needed when copying a tensor");
179 if (type && !getCopy() &&
184 return emitError(
"expected that `copy` and return type match");
189 RankedTensorType type,
ValueRange dynamicSizes) {
190 build(builder,
result, llvm::cast<TensorLikeType>(type), dynamicSizes,
197 RankedTensorType type,
ValueRange dynamicSizes,
199 build(builder,
result, llvm::cast<TensorLikeType>(type), dynamicSizes,
copy);
204 IntegerAttr memorySpace) {
205 build(builder,
result, llvm::cast<TensorLikeType>(type), dynamicSizes,
copy,
206 Value(), memorySpace);
219 build(builder,
result,
Type(type), dynamicSizes,
copy, sizeHint, memorySpace);
235 using OpRewritePattern<AllocTensorOp>::OpRewritePattern;
237 LogicalResult matchAndRewrite(AllocTensorOp op,
238 PatternRewriter &rewriter)
const override {
241 auto type = dyn_cast<RankedTensorType>(op.getType());
242 if (!type || op.getCopy())
244 SmallVector<int64_t> newShape = llvm::to_vector(type.getShape());
245 SmallVector<Value> newDynamicSizes;
246 unsigned int dynValCounter = 0;
247 for (int64_t i = 0; i < type.getRank(); ++i) {
248 if (!type.isDynamicDim(i))
250 Value value = op.getDynamicSizes()[dynValCounter++];
253 int64_t dim = intVal.getSExtValue();
255 newShape[i] = intVal.getSExtValue();
257 newDynamicSizes.push_back(value);
259 newDynamicSizes.push_back(value);
262 RankedTensorType newType = RankedTensorType::get(
263 newShape, type.getElementType(), type.getEncoding());
266 auto newOp = AllocTensorOp::create(rewriter, op.getLoc(), newType,
267 newDynamicSizes, Value());
274 using OpRewritePattern<tensor::DimOp>::OpRewritePattern;
276 LogicalResult matchAndRewrite(tensor::DimOp dimOp,
277 PatternRewriter &rewriter)
const override {
278 std::optional<int64_t> maybeConstantIndex = dimOp.getConstantIndex();
279 auto allocTensorOp = dimOp.getSource().getDefiningOp<AllocTensorOp>();
280 if (!allocTensorOp || !maybeConstantIndex)
284 auto type = dyn_cast<RankedTensorType>(allocTensorOp.getType());
285 if (!type || *maybeConstantIndex < 0 ||
286 *maybeConstantIndex >= type.getRank())
288 if (!type.isDynamicDim(*maybeConstantIndex))
291 dimOp, allocTensorOp.getDynamicSize(rewriter, *maybeConstantIndex));
299 results.
add<FoldDimOfAllocTensorOp, ReplaceStaticShapeDims>(ctx);
302LogicalResult AllocTensorOp::reifyResultShapes(
306 auto type = dyn_cast<RankedTensorType>(
getType());
309 auto shapes = llvm::map_to_vector<4>(
311 if (type.isDynamicDim(dim))
312 return getDynamicSize(builder, dim);
313 return builder.getIndexAttr(type.getDimSize(dim));
315 reifiedReturnShapes.emplace_back(std::move(shapes));
326 if (copyKeyword.succeeded())
332 if (sizeHintKeyword.succeeded())
337 if (AllocTensorOp::genericParseProperties(parser, parsedProperties))
339 auto propertyDictionary = dyn_cast_or_null<DictionaryAttr>(parsedProperties);
340 if (parsedProperties && !propertyDictionary)
342 "expected properties dictionary");
347 for (StringRef attrName : AllocTensorOp::getAttributeNames()) {
348 if (
result.attributes.get(attrName))
350 <<
"inherent attribute '" << attrName
351 <<
"' cannot be parsed from attr-dict when strict properties in "
352 "assembly format is enabled";
365 if (copyKeyword.succeeded())
368 if (sizeHintKeyword.succeeded())
372 NamedAttrList properties(propertyDictionary ? propertyDictionary
374 properties.set(AllocTensorOp::getOperandSegmentSizeAttr(),
376 {static_cast<int32_t>(dynamicSizesOperands.size()),
377 static_cast<int32_t>(copyKeyword.succeeded()),
378 static_cast<int32_t>(sizeHintKeyword.succeeded())}));
379 propertyDictionary = properties.getDictionary(builder.
getContext());
382 << propertyDictionary <<
" for op " <<
result.name.getStringRef()
385 if (
failed(AllocTensorOp::setPropertiesFromParsedAttr(
386 result.getOrAddProperties<Properties>(), propertyDictionary,
395 p <<
" copy(" << getCopy() <<
")";
397 p <<
" size_hint=" << getSizeHint();
398 AllocTensorOp::printProperties(
getContext(), p, getProperties(),
399 getOperandSegmentSizeAttr());
402 auto type = getResult().getType();
403 if (
auto validType = llvm::dyn_cast<::mlir::TensorType>(type))
410 assert(isDynamicDim(idx) &&
"expected dynamic dim");
412 return tensor::DimOp::create(
b, getLoc(), getCopy(), idx);
413 return getOperand(getIndexOfDynamicSize(idx));
429 using OpRewritePattern<CloneOp>::OpRewritePattern;
431 LogicalResult matchAndRewrite(CloneOp cloneOp,
432 PatternRewriter &rewriter)
const override {
433 if (cloneOp.use_empty()) {
438 Value source = cloneOp.getInput();
439 if (source.
getType() != cloneOp.getType() &&
440 !memref::CastOp::areCastCompatible({source.getType()},
441 {cloneOp.getType()}))
446 Value canonicalSource = source;
447 while (
auto iface = dyn_cast_or_null<ViewLikeOpInterface>(
449 if (canonicalSource != iface.getViewDest()) {
452 canonicalSource = iface.getViewSource();
455 std::optional<Operation *> maybeCloneDeallocOp =
458 if (!maybeCloneDeallocOp.has_value())
460 std::optional<Operation *> maybeSourceDeallocOp =
462 if (!maybeSourceDeallocOp.has_value())
464 Operation *cloneDeallocOp = *maybeCloneDeallocOp;
465 Operation *sourceDeallocOp = *maybeSourceDeallocOp;
469 if (cloneDeallocOp && sourceDeallocOp &&
473 Block *currentBlock = cloneOp->getBlock();
474 Operation *redundantDealloc =
nullptr;
475 if (cloneDeallocOp && cloneDeallocOp->
getBlock() == currentBlock) {
476 redundantDealloc = cloneDeallocOp;
477 }
else if (sourceDeallocOp && sourceDeallocOp->
getBlock() == currentBlock) {
478 redundantDealloc = sourceDeallocOp;
481 if (!redundantDealloc)
489 for (Operation *pos = cloneOp->getNextNode(); pos != redundantDealloc;
490 pos = pos->getNextNode()) {
494 auto effectInterface = dyn_cast<MemoryEffectOpInterface>(pos);
495 if (!effectInterface)
497 if (effectInterface.hasEffect<MemoryEffects::Free>())
501 if (source.
getType() != cloneOp.getType())
502 source = memref::CastOp::create(rewriter, cloneOp.getLoc(),
503 cloneOp.getType(), source);
505 rewriter.
eraseOp(redundantDealloc);
514 results.
add<SimplifyClones>(context);
521LogicalResult MaterializeInDestinationOp::reifyResultShapes(
523 if (getOperation()->getNumResults() == 1) {
524 assert(isa<TensorType>(getDest().
getType()) &&
"expected tensor type");
525 reifiedReturnShapes.resize(1,
527 reifiedReturnShapes[0] =
533Value MaterializeInDestinationOp::buildSubsetExtraction(
OpBuilder &builder,
535 if (isa<TensorType>(getDest().
getType())) {
548 assert(isa<BaseMemRefType>(getDest().
getType()) &&
"expected memref type");
549 assert(getRestrict() &&
550 "expected that ops with memrefs dest have 'restrict'");
552 return ToTensorOp::create(
555 true, getWritable());
558bool MaterializeInDestinationOp::isEquivalentSubset(
560 return equivalenceFn(getDest(), candidate);
564MaterializeInDestinationOp::getValuesNeededToBuildSubsetExtraction() {
568OpOperand &MaterializeInDestinationOp::getSourceOperand() {
569 return getOperation()->getOpOperand(0) ;
572bool MaterializeInDestinationOp::operatesOnEquivalentSubset(
573 SubsetOpInterface subsetOp,
578bool MaterializeInDestinationOp::operatesOnDisjointSubset(
579 SubsetOpInterface subsetOp,
584LogicalResult MaterializeInDestinationOp::verify() {
585 if (!isa<TensorType, BaseMemRefType>(getDest().
getType()))
586 return emitOpError(
"'dest' must be a tensor or a memref");
587 if (
auto destType = dyn_cast<TensorType>(getDest().
getType())) {
588 if (getOperation()->getNumResults() != 1)
589 return emitOpError(
"tensor 'dest' implies exactly one tensor result");
590 if (destType != getResult().
getType())
591 return emitOpError(
"result and 'dest' types must match");
593 if (isa<BaseMemRefType>(getDest().
getType()) &&
594 getOperation()->getNumResults() != 0)
595 return emitOpError(
"memref 'dest' implies zero results");
596 if (getRestrict() && !isa<BaseMemRefType>(getDest().
getType()))
597 return emitOpError(
"'restrict' is valid only for memref destinations");
598 if (getWritable() != isa<BaseMemRefType>(getDest().
getType()))
599 return emitOpError(
"'writable' must be specified if and only if the "
600 "destination is of memref type");
602 ShapedType destType = cast<ShapedType>(getDest().
getType());
603 if (srcType.
hasRank() != destType.hasRank())
604 return emitOpError(
"source/destination shapes are incompatible");
609 for (
auto [src, dest] :
610 llvm::zip(srcType.
getShape(), destType.getShape())) {
611 if (src == ShapedType::kDynamic || dest == ShapedType::kDynamic) {
617 return emitOpError(
"source/destination shapes are incompatible");
623void MaterializeInDestinationOp::build(
OpBuilder &builder,
626 auto destTensorType = dyn_cast<TensorType>(dest.
getType());
627 build(builder, state, destTensorType ? destTensorType :
Type(),
632 return getDestMutable();
635void MaterializeInDestinationOp::getEffects(
638 if (isa<BaseMemRefType>(getDest().
getType()))
648 if (
auto toBuffer = getBuffer().getDefiningOp<ToBufferOp>())
651 if (toBuffer->getBlock() == this->getOperation()->getBlock() &&
652 toBuffer->getNextNode() == this->getOperation())
653 return toBuffer.getTensor();
659 using OpRewritePattern<tensor::DimOp>::OpRewritePattern;
661 LogicalResult matchAndRewrite(tensor::DimOp dimOp,
662 PatternRewriter &rewriter)
const override {
663 auto memrefToTensorOp = dimOp.getSource().getDefiningOp<ToTensorOp>();
664 if (!memrefToTensorOp)
668 dimOp, memrefToTensorOp.getBuffer(), dimOp.getIndex());
676 results.
add<DimOfToTensorFolder>(context);
684 if (
auto memrefToTensor = getTensor().getDefiningOp<ToTensorOp>())
685 if (memrefToTensor.getBuffer().getType() ==
getType())
686 return memrefToTensor.getBuffer();
694 using OpRewritePattern<ToBufferOp>::OpRewritePattern;
696 LogicalResult matchAndRewrite(ToBufferOp toBuffer,
697 PatternRewriter &rewriter)
const final {
698 auto tensorCastOperand =
699 toBuffer.getOperand().getDefiningOp<tensor::CastOp>();
700 if (!tensorCastOperand)
702 auto srcTensorType = llvm::dyn_cast<RankedTensorType>(
703 tensorCastOperand.getOperand().getType());
706 auto currentOutputMemRefType =
707 dyn_cast<BaseMemRefType>(toBuffer.getResult().getType());
708 if (!currentOutputMemRefType)
711 auto memrefType = currentOutputMemRefType.cloneWith(
712 srcTensorType.getShape(), srcTensorType.getElementType());
713 Value memref = ToBufferOp::create(rewriter, toBuffer.getLoc(), memrefType,
714 tensorCastOperand.getOperand(),
715 toBuffer.getReadOnly());
725 using OpRewritePattern<ToBufferOp>::OpRewritePattern;
727 LogicalResult matchAndRewrite(ToBufferOp toBuffer,
728 PatternRewriter &rewriter)
const final {
738 using OpRewritePattern<memref::LoadOp>::OpRewritePattern;
740 LogicalResult matchAndRewrite(memref::LoadOp
load,
741 PatternRewriter &rewriter)
const override {
742 auto toBuffer =
load.getMemref().getDefiningOp<ToBufferOp>();
743 if (!toBuffer || !toBuffer.getReadOnly())
754 using OpRewritePattern<memref::DimOp>::OpRewritePattern;
756 LogicalResult matchAndRewrite(memref::DimOp dimOp,
757 PatternRewriter &rewriter)
const override {
758 auto castOp = dimOp.getSource().getDefiningOp<ToBufferOp>();
761 Value newSource = castOp.getOperand();
772 results.
add<DimOfCastOp, LoadOfToBuffer, ToBufferOfCast,
773 ToBufferToTensorFolding>(context);
776std::optional<Operation *> CloneOp::buildDealloc(
OpBuilder &builder,
778 return memref::DeallocOp::create(builder, alloc.
getLoc(), alloc)
782std::optional<Value> CloneOp::buildClone(
OpBuilder &builder,
Value alloc) {
783 return CloneOp::create(builder, alloc.
getLoc(), alloc).getResult();
790LogicalResult DeallocOp::inferReturnTypes(
791 MLIRContext *context, std::optional<::mlir::Location> location,
794 DeallocOpAdaptor adaptor(operands, attributes, properties, regions);
796 IntegerType::get(context, 1));
800LogicalResult DeallocOp::verify() {
801 if (getMemrefs().size() != getConditions().size())
803 "must have the same number of conditions as memrefs to deallocate");
804 if (getRetained().size() != getUpdatedConditions().size())
805 return emitOpError(
"must have the same number of updated conditions "
806 "(results) as retained operands");
814 if (deallocOp.getMemrefs() == memrefs &&
815 deallocOp.getConditions() == conditions)
819 deallocOp.getMemrefsMutable().assign(memrefs);
820 deallocOp.getConditionsMutable().assign(conditions);
840struct DeallocRemoveDuplicateDeallocMemrefs
842 using OpRewritePattern<DeallocOp>::OpRewritePattern;
844 LogicalResult matchAndRewrite(DeallocOp deallocOp,
845 PatternRewriter &rewriter)
const override {
848 SmallVector<Value> newMemrefs, newConditions;
849 for (
auto [i, memref, cond] :
850 llvm::enumerate(deallocOp.getMemrefs(), deallocOp.getConditions())) {
851 if (memrefToCondition.count(memref)) {
854 Value &newCond = newConditions[memrefToCondition[memref]];
857 arith::OrIOp::create(rewriter, deallocOp.getLoc(), newCond, cond);
859 memrefToCondition.insert({memref, newConditions.size()});
860 newMemrefs.push_back(memref);
861 newConditions.push_back(cond);
882struct DeallocRemoveDuplicateRetainedMemrefs
884 using OpRewritePattern<DeallocOp>::OpRewritePattern;
886 LogicalResult matchAndRewrite(DeallocOp deallocOp,
887 PatternRewriter &rewriter)
const override {
890 SmallVector<Value> newRetained;
891 SmallVector<unsigned> resultReplacementIdx;
893 for (
auto retained : deallocOp.getRetained()) {
894 if (seen.count(retained)) {
895 resultReplacementIdx.push_back(seen[retained]);
900 newRetained.push_back(retained);
901 resultReplacementIdx.push_back(i++);
906 if (newRetained.size() == deallocOp.getRetained().size())
912 DeallocOp::create(rewriter, deallocOp.getLoc(), deallocOp.getMemrefs(),
913 deallocOp.getConditions(), newRetained);
914 SmallVector<Value> replacements(
915 llvm::map_range(resultReplacementIdx, [&](
unsigned idx) {
916 return newDeallocOp.getUpdatedConditions()[idx];
918 rewriter.
replaceOp(deallocOp, replacements);
929 using OpRewritePattern<DeallocOp>::OpRewritePattern;
931 LogicalResult matchAndRewrite(DeallocOp deallocOp,
932 PatternRewriter &rewriter)
const override {
933 if (deallocOp.getMemrefs().empty()) {
934 Value constFalse = arith::ConstantOp::create(rewriter, deallocOp.getLoc(),
937 deallocOp, SmallVector<Value>(deallocOp.getUpdatedConditions().size(),
958 using OpRewritePattern<DeallocOp>::OpRewritePattern;
960 LogicalResult matchAndRewrite(DeallocOp deallocOp,
961 PatternRewriter &rewriter)
const override {
962 SmallVector<Value> newMemrefs, newConditions;
963 for (
auto [memref, cond] :
964 llvm::zip(deallocOp.getMemrefs(), deallocOp.getConditions())) {
966 newMemrefs.push_back(memref);
967 newConditions.push_back(cond);
995 using OpRewritePattern<DeallocOp>::OpRewritePattern;
997 LogicalResult matchAndRewrite(DeallocOp deallocOp,
998 PatternRewriter &rewriter)
const override {
999 SmallVector<Value> newMemrefs(
1000 llvm::map_range(deallocOp.getMemrefs(), [&](Value memref) {
1001 auto extractStridedOp =
1002 memref.getDefiningOp<memref::ExtractStridedMetadataOp>();
1003 if (!extractStridedOp)
1005 Value allocMemref = extractStridedOp.getOperand();
1006 auto allocOp = allocMemref.getDefiningOp<MemoryEffectOpInterface>();
1009 if (allocOp.getEffectOnValue<MemoryEffects::Allocate>(allocMemref))
1015 deallocOp.getConditions(), rewriter);
1033struct RemoveAllocDeallocPairWhenNoOtherUsers
1035 using OpRewritePattern<DeallocOp>::OpRewritePattern;
1037 LogicalResult matchAndRewrite(DeallocOp deallocOp,
1038 PatternRewriter &rewriter)
const override {
1039 SmallVector<Value> newMemrefs, newConditions;
1040 SmallVector<Operation *> toDelete;
1041 for (
auto [memref, cond] :
1042 llvm::zip(deallocOp.getMemrefs(), deallocOp.getConditions())) {
1043 if (
auto allocOp = memref.getDefiningOp<MemoryEffectOpInterface>()) {
1047 if (allocOp.getEffectOnValue<MemoryEffects::Allocate>(memref) &&
1049 memref.hasOneUse()) {
1050 toDelete.push_back(allocOp);
1055 newMemrefs.push_back(memref);
1056 newConditions.push_back(cond);
1063 for (Operation *op : toDelete)
1079 patterns.
add<DeallocRemoveDuplicateDeallocMemrefs,
1080 DeallocRemoveDuplicateRetainedMemrefs, EraseEmptyDealloc,
1081 EraseAlwaysFalseDealloc, SkipExtractMetadataOfAlloc,
1082 RemoveAllocDeallocPairWhenNoOtherUsers>(context);
1089#define GET_OP_CLASSES
1090#include "mlir/Dialect/Bufferization/IR/BufferizationOps.cpp.inc"
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,...
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.