20#include "llvm/ADT/ScopeExit.h"
21#include "llvm/ADT/SmallVectorExtras.h"
30#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.cpp.inc"
37#define DEBUG_TYPE "bufferizable-op-interface"
45 if (
auto bufferizableOp =
options.dynCastBufferizableOp(op))
51Region *AnalysisState::getEnclosingRepetitiveRegion(
55 if (
auto iter = enclosingRepetitiveRegionCache.find_as(op);
56 iter != enclosingRepetitiveRegionCache.end())
58 return enclosingRepetitiveRegionCache[op] =
62Region *AnalysisState::getEnclosingRepetitiveRegion(
64 if (
auto iter = enclosingRepetitiveRegionCache.find_as(value);
65 iter != enclosingRepetitiveRegionCache.end())
71 SmallVector<Region *> visitedRegions;
73 visitedRegions.push_back(region);
78 enclosingRepetitiveRegionCache[value] = region;
79 for (Region *r : visitedRegions)
80 enclosingRepetitiveRegionCache[r] = region;
84Region *AnalysisState::getEnclosingRepetitiveRegion(
86 if (
auto iter = enclosingRepetitiveRegionCache.find_as(block);
87 iter != enclosingRepetitiveRegionCache.end())
91 Operation *op =
nullptr;
94 SmallVector<Region *> visitedRegions;
101 enclosingRepetitiveRegionCache[block] = region;
102 for (Region *r : visitedRegions)
103 enclosingRepetitiveRegionCache[r] = region;
107bool AnalysisState::insideMutuallyExclusiveRegions(
Operation *op0,
109 auto key = std::make_pair(op0, op1);
110 if (
auto iter = insideMutuallyExclusiveRegionsCache.find(key);
111 iter != insideMutuallyExclusiveRegionsCache.end())
115 insideMutuallyExclusiveRegionsCache[key] =
result;
116 insideMutuallyExclusiveRegionsCache[std::make_pair(op1, op0)] =
result;
120void AnalysisState::resetCache() {
121 enclosingRepetitiveRegionCache.clear();
122 insideMutuallyExclusiveRegionsCache.clear();
133Region *bufferization::getNextEnclosingRepetitiveRegion(
144 const BufferizationOptions &
options) {
147 if (bufferizableOp &&
150 "expected that all parallel regions are also repetitive regions");
159 if (
auto opResult = llvm::dyn_cast<OpResult>(value))
160 return opResult.getDefiningOp();
161 return llvm::cast<BlockArgument>(value).getOwner()->
getParentOp();
169FailureOr<Value> bufferization::allocateTensorForShapedValue(
171 const BufferizationOptions &
options,
const BufferizationState &state,
174 if (llvm::isa<RankedTensorType>(shapedValue.
getType())) {
176 }
else if (llvm::isa<MemRefType>(shapedValue.
getType())) {
177 tensor = ToTensorOp::create(
180 }
else if (llvm::isa<UnrankedTensorType>(shapedValue.
getType()) ||
181 llvm::isa<UnrankedMemRefType>(shapedValue.
getType())) {
183 ->
emitError(
"copying of unranked tensors is not implemented");
185 llvm_unreachable(
"expected RankedTensorType or MemRefType");
187 RankedTensorType tensorType = llvm::cast<RankedTensorType>(
tensor.getType());
192 bool reifiedShapes =
false;
193 if (llvm::isa<RankedTensorType>(shapedValue.
getType()) &&
194 llvm::isa<OpResult>(shapedValue)) {
198 reifiedShapes =
true;
200 resultDims[llvm::cast<OpResult>(shapedValue).getResultNumber()];
201 for (
const auto &dim :
enumerate(tensorType.getShape())) {
202 if (ShapedType::isDynamic(dim.value())) {
203 dynamicSizes.push_back(
216 auto allocTensorOp = AllocTensorOp::create(
b, loc, tensorType, dynamicSizes,
221 return allocTensorOp.getResult();
222 auto copyBufferType =
224 if (
failed(copyBufferType))
226 std::optional<Attribute> memorySpace = copyBufferType->getMemorySpace();
229 options.defaultMemorySpaceFn(cast<TensorLikeType>(tensorType));
230 if (memorySpace.has_value())
231 allocTensorOp.setMemorySpaceAttr(memorySpace.value());
232 return allocTensorOp.getResult();
237LogicalResult BufferizableOpInterface::resolveTensorOpOperandConflicts(
239 const BufferizationState &bufferizationState) {
249 Type operandType = opOperand.get().getType();
250 if (!llvm::isa<TensorType>(operandType))
252 if (analysisState.isInPlace(opOperand))
254 if (llvm::isa<UnrankedTensorType>(operandType))
255 return op->
emitError(
"copying of unranked tensors is not implemented");
257 AliasingValueList aliasingValues =
258 analysisState.getAliasingValues(opOperand);
259 if (aliasingValues.getNumAliases() == 1 &&
260 isa<OpResult>(aliasingValues.getAliases()[0].value) &&
261 !analysisState.bufferizesToMemoryWrite(opOperand) &&
263 .getAliasingOpOperands(aliasingValues.getAliases()[0].value)
264 .getNumAliases() == 1 &&
265 !isa<UnrankedTensorType>(
266 aliasingValues.getAliases()[0].value.getType())) {
273 Value value = aliasingValues.getAliases()[0].value;
274 outOfPlaceValues.push_back(value);
275 if (!analysisState.canOmitTensorCopy(opOperand))
276 copiedOpValues.insert(value);
279 outOfPlaceOpOperands.push_back(&opOperand);
280 if (!analysisState.canOmitTensorCopy(opOperand))
281 copiedOpOperands.insert(&opOperand);
287 for (
OpOperand *opOperand : outOfPlaceOpOperands) {
288 FailureOr<Value>
copy = allocateTensorForShapedValue(
289 rewriter, op->
getLoc(), opOperand->get(), analysisState.getOptions(),
290 bufferizationState, copiedOpOperands.contains(opOperand));
298 for (
Value value : outOfPlaceValues) {
299 FailureOr<Value>
copy = allocateTensorForShapedValue(
300 rewriter, op->
getLoc(), value, analysisState.getOptions(),
301 bufferizationState, copiedOpValues.count(value));
308 if (use->getOwner() ==
copy->getDefiningOp())
312 if (isa<tensor::DimOp>(use->getOwner()))
325bool OpFilter::isOpAllowed(
Operation *op)
const {
327 bool isAllowed = !hasAllowRule();
328 for (
const Entry &entry : entries) {
329 bool filterResult = entry.fn(op);
330 switch (entry.type) {
332 isAllowed |= filterResult;
352 mlir::Type elementType,
354 int64_t dynamicOffset = ShapedType::kDynamic;
356 auto stridedLayout = StridedLayoutAttr::get(elementType.
getContext(),
357 dynamicOffset, dynamicStrides);
358 return MemRefType::get(
shape, elementType, stridedLayout, memorySpace);
364 unsigned int bufferAlignment) {
366 if (bufferAlignment != 0)
367 return memref::AllocOp::create(
b, loc, type, dynShape,
368 b.getI64IntegerAttr(bufferAlignment))
370 return memref::AllocOp::create(
b, loc, type, dynShape).getResult();
376 memref::CopyOp::create(
b, loc, from, to);
382 assert(isa<BaseMemRefType>(dest) &&
"expected BaseMemRefType");
383 assert(isa<BaseMemRefType>(value.
getType()) &&
"expected BaseMemRefType");
384 assert(memref::CastOp::areCastCompatible(value.
getType(), dest) &&
385 "cast incompatible");
386 return memref::CastOp::create(
b, loc, dest, value).getResult();
391defaultFunctionArgTypeConverter(TensorLikeType type,
Attribute memorySpace,
393 const BufferizationOptions &
options) {
394 if (
auto tensorType = mlir::dyn_cast<TensorType>(type)) {
395 return cast<BufferLikeType>(
396 bufferization::getMemRefTypeWithFullyDynamicLayout(tensorType,
401 return options.unknownTypeConverterFn(type, memorySpace,
options);
405defaultUnknownTypeConverter(TensorLikeType tensorType,
Attribute memorySpace,
406 const BufferizationOptions &
options) {
407 return cast<BufferLikeType>(
408 bufferization::getMemRefTypeWithFullyDynamicLayout(
409 cast<TensorType>(tensorType), memorySpace));
414FailureOr<BufferLikeType>
415defaultReconcileBufferTypeMismatch(BufferLikeType x, BufferLikeType y,
416 const BufferizationOptions &) {
417 const auto xMemRef = cast<BaseMemRefType>(x);
418 const auto yMemRef = cast<BaseMemRefType>(y);
420 if (xMemRef.getMemorySpace() != yMemRef.getMemorySpace())
423 if (isa<UnrankedMemRefType>(xMemRef)) {
428 return cast<BufferLikeType>(::getMemRefTypeWithFullyDynamicLayout(
429 xMemRef.getShape(), xMemRef.getElementType(), xMemRef.getMemorySpace()));
435BufferizationOptions::BufferizationOptions()
436 : allocationFn(defaultCreateAlloc), memCpyFn(defaultCreateMemCpy),
437 castFn(defaultCreateCast),
438 functionArgTypeConverterFn(defaultFunctionArgTypeConverter),
439 unknownTypeConverterFn(defaultUnknownTypeConverter),
440 reconcileBufferTypeMismatchFn(defaultReconcileBufferTypeMismatch) {}
442bool BufferizationOptions::isOpAllowed(
Operation *op)
const {
445 bool isFuncBoundaryOp = isa_and_nonnull<func::FuncDialect>(op->
getDialect());
446 if (!bufferizeFunctionBoundaries && isFuncBoundaryOp)
449 return opFilter.isOpAllowed(op);
452BufferizableOpInterface
453BufferizationOptions::dynCastBufferizableOp(
Operation *op)
const {
454 if (!isOpAllowed(op))
456 auto bufferizableOp = dyn_cast<BufferizableOpInterface>(op);
459 return bufferizableOp;
462BufferizableOpInterface
463BufferizationOptions::dynCastBufferizableOp(
Value value)
const {
467void BufferizationOptions::setFunctionBoundaryTypeConversion(
468 LayoutMapOption layoutMapOption) {
469 functionArgTypeConverterFn = [=](TensorLikeType type, Attribute memorySpace,
471 const BufferizationOptions &
options) {
472 if (
auto tensorType = mlir::dyn_cast<TensorType>(type)) {
473 if (layoutMapOption == LayoutMapOption::IdentityLayoutMap)
474 return cast<BufferLikeType>(
475 bufferization::getMemRefTypeWithStaticIdentityLayout(tensorType,
477 return cast<BufferLikeType>(
478 bufferization::getMemRefTypeWithFullyDynamicLayout(tensorType,
483 return options.unknownTypeConverterFn(type, memorySpace,
options);
485 inferFunctionResultLayout =
486 layoutMapOption == LayoutMapOption::InferLayoutMap;
494 if (
auto bbArg = llvm::dyn_cast<BlockArgument>(value)) {
495 b.setInsertionPointToStart(bbArg.getOwner());
503AliasingOpOperandList AnalysisState::getAliasingOpOperands(
Value value)
const {
505 if (
auto bufferizableOp = getOptions().dynCastBufferizableOp(op))
506 return bufferizableOp.getAliasingOpOperands(value, *
this);
509 return detail::unknownGetAliasingOpOperands(value);
514AliasingValueList AnalysisState::getAliasingValues(
OpOperand &opOperand)
const {
515 if (
auto bufferizableOp =
516 getOptions().dynCastBufferizableOp(opOperand.
getOwner()))
517 return bufferizableOp.getAliasingValues(opOperand, *
this);
520 return detail::unknownGetAliasingValues(opOperand);
525bool AnalysisState::bufferizesToMemoryRead(
OpOperand &opOperand)
const {
526 if (
auto bufferizableOp =
527 getOptions().dynCastBufferizableOp(opOperand.
getOwner()))
528 return bufferizableOp.bufferizesToMemoryRead(opOperand, *
this);
537bool AnalysisState::bufferizesToMemoryWrite(
OpOperand &opOperand)
const {
538 if (
auto bufferizableOp =
539 getOptions().dynCastBufferizableOp(opOperand.
getOwner()))
540 return bufferizableOp.bufferizesToMemoryWrite(opOperand, *
this);
549bool AnalysisState::bufferizesToAliasOnly(
OpOperand &opOperand)
const {
550 if (
auto bufferizableOp =
551 getOptions().dynCastBufferizableOp(opOperand.
getOwner()))
552 return bufferizableOp.bufferizesToAliasOnly(opOperand, *
this);
559bool AnalysisState::bufferizesToMemoryWrite(
Value value)
const {
560 auto opResult = llvm::dyn_cast<OpResult>(value);
563 auto bufferizableOp = getOptions().dynCastBufferizableOp(value);
566 return bufferizableOp.resultBufferizesToMemoryWrite(opResult, *
this);
572bool AnalysisState::isValueRead(
Value value)
const {
573 assert(llvm::isa<TensorLikeType>(value.
getType()) &&
574 "expected TensorLikeType");
575 SmallVector<OpOperand *> workingSet;
577 for (OpOperand &use : value.
getUses())
578 workingSet.push_back(&use);
580 while (!workingSet.empty()) {
581 OpOperand *uMaybeReading = workingSet.pop_back_val();
582 if (!visited.insert(uMaybeReading).second)
586 if (bufferizesToAliasOnly(*uMaybeReading))
587 for (AliasingValue alias : getAliasingValues(*uMaybeReading))
588 for (OpOperand &use : alias.value.getUses())
589 workingSet.push_back(&use);
590 if (bufferizesToMemoryRead(*uMaybeReading))
602llvm::SetVector<Value> AnalysisState::findValueInReverseUseDefChain(
604 TraversalConfig config,
605 llvm::DenseSet<OpOperand *> *visitedOpOperands)
const {
606 llvm::DenseSet<Value> visited;
607 llvm::SetVector<Value>
result, workingSet;
608 workingSet.insert(opOperand->
get());
610 if (visitedOpOperands)
611 visitedOpOperands->insert(opOperand);
613 while (!workingSet.empty()) {
614 Value value = workingSet.pop_back_val();
616 if (!config.revisitAlreadyVisitedValues && visited.contains(value)) {
618 if (config.alwaysIncludeLeaves)
622 visited.insert(value);
624 if (condition(value)) {
629 if (!config.followUnknownOps && !
options.dynCastBufferizableOp(value)) {
632 if (config.alwaysIncludeLeaves)
637 AliasingOpOperandList aliases = getAliasingOpOperands(value);
638 if (aliases.getNumAliases() == 0) {
641 if (config.alwaysIncludeLeaves)
646 for (AliasingOpOperand a : aliases) {
647 if (config.followEquivalentOnly &&
648 a.relation != BufferRelation::Equivalent) {
651 if (config.alwaysIncludeLeaves)
656 if (config.followInPlaceOnly && !isInPlace(*a.opOperand)) {
659 if (config.alwaysIncludeLeaves)
664 if (config.followSameTypeOrCastsOnly &&
665 a.opOperand->get().getType() != value.
getType() &&
669 if (config.alwaysIncludeLeaves)
674 workingSet.insert(a.opOperand->get());
675 if (visitedOpOperands)
676 visitedOpOperands->insert(a.opOperand);
684llvm::SetVector<Value>
685AnalysisState::findDefinitions(
OpOperand *opOperand)
const {
686 TraversalConfig config;
687 config.alwaysIncludeLeaves =
false;
688 return findValueInReverseUseDefChain(
689 opOperand, [&](Value v) {
return this->bufferizesToMemoryWrite(v); },
698 for (
const BufferizationOptions::AnalysisStateInitFn &fn :
703bool AnalysisState::canOmitTensorCopy(
OpOperand &opOperand)
const {
705 if (hasUndefinedContents(&opOperand))
710 if (bufferizesToMemoryWrite(opOperand) && !bufferizesToMemoryRead(opOperand))
714 AliasingValueList aliases = getAliasingValues(opOperand);
715 if (!bufferizesToMemoryRead(opOperand) &&
716 llvm::none_of(aliases,
717 [&](AliasingValue a) {
return isValueRead(a.value); }))
724bool AnalysisState::isInPlace(
OpOperand &opOperand)
const {
726 if (isa<ToBufferOp>(opOperand.
getOwner()))
731 return !bufferizesToMemoryWrite(opOperand);
734bool AnalysisState::areEquivalentBufferizedValues(
Value v1,
Value v2)
const {
740bool AnalysisState::areAliasingBufferizedValues(
Value v1,
Value v2)
const {
746bool AnalysisState::hasUndefinedContents(
OpOperand *opOperand)
const {
752 const BufferizationOptions &
options,
753 const BufferizationState &state) {
755 auto tensorType = llvm::dyn_cast<TensorLikeType>(value.
getType());
756 assert(tensorType &&
"unexpected non-tensor type");
760 if (
auto toTensorOp = value.
getDefiningOp<bufferization::ToTensorOp>())
761 return toTensorOp.getBuffer();
770 return bufferization::ToBufferOp::create(rewriter, value.
getLoc(),
776FailureOr<BufferLikeType>
777bufferization::getBufferType(
Value value,
const BufferizationOptions &
options,
778 const BufferizationState &state) {
784FailureOr<BufferLikeType>
785bufferization::getBufferType(
Value value,
const BufferizationOptions &
options,
786 const BufferizationState &state,
788 assert(llvm::isa<TensorLikeType>(value.
getType()) &&
789 "unexpected non-tensor type");
790 invocationStack.push_back(value);
791 llvm::scope_exit popFromStack([&]() { invocationStack.pop_back(); });
795 auto bufferizableOp =
options.dynCastBufferizableOp(op);
797 return bufferizableOp.getBufferType(value,
options, state, invocationStack);
801 options.defaultMemorySpaceFn(cast<TensorLikeType>(value.
getType()));
802 if (!memSpace.has_value())
803 return op->emitError(
"could not infer memory space");
805 return options.unknownTypeConverterFn(cast<TensorLikeType>(value.
getType()),
809bool bufferization::hasTensorSemantics(
Operation *op) {
810 if (
auto bufferizableOp = dyn_cast<BufferizableOpInterface>(op))
811 return bufferizableOp.hasTensorSemantics();
812 return detail::defaultHasTensorSemantics(op);
815void bufferization::replaceOpWithBufferizedValues(
RewriterBase &rewriter,
819 "expected one value per OpResult");
826 if (llvm::isa<TensorLikeType>(opResult.getType())) {
829 assert(llvm::isa<BufferLikeType>(
replacement.getType()) &&
830 "tensor op result should be replaced with a buffer value");
849bufferization::getMemRefTypeWithFullyDynamicLayout(
TensorType tensorType,
852 if (
auto unrankedTensorType =
853 llvm::dyn_cast<UnrankedTensorType>(tensorType)) {
854 return UnrankedMemRefType::get(unrankedTensorType.getElementType(),
859 return ::getMemRefTypeWithFullyDynamicLayout(
866bufferization::getMemRefTypeWithStaticIdentityLayout(
TensorType tensorType,
869 if (
auto unrankedTensorType =
870 llvm::dyn_cast<UnrankedTensorType>(tensorType)) {
871 return UnrankedMemRefType::get(unrankedTensorType.getElementType(),
876 auto rankedTensorType = llvm::cast<RankedTensorType>(tensorType);
877 MemRefLayoutAttrInterface layout = {};
878 return MemRefType::get(rankedTensorType.getShape(),
879 rankedTensorType.getElementType(), layout,
887bool bufferization::detail::defaultResultBufferizesToMemoryWrite(
889 auto bufferizableOp = cast<BufferizableOpInterface>(opResult.
getDefiningOp());
890 AliasingOpOperandList opOperands =
891 bufferizableOp.getAliasingOpOperands(opResult, state);
895 if (opOperands.getAliases().empty())
900 if (llvm::any_of(opOperands, [&](AliasingOpOperand alias) {
901 return state.bufferizesToMemoryWrite(*alias.opOperand);
934 auto isMemoryWriteInsideOp = [&](
Value v) {
938 return state.bufferizesToMemoryWrite(v);
940 TraversalConfig config;
941 config.alwaysIncludeLeaves =
false;
942 for (AliasingOpOperand alias : opOperands) {
944 .findValueInReverseUseDefChain(alias.opOperand,
945 isMemoryWriteInsideOp, config)
954AliasingOpOperandList bufferization::detail::defaultGetAliasingOpOperands(
959 if (!llvm::isa<TensorLikeType>(opOperand.
get().
getType()))
961 AliasingValueList aliasingValues = state.getAliasingValues(opOperand);
962 for (
const auto &it : aliasingValues)
963 if (it.value == value)
964 result.emplace_back(&opOperand, it.relation, it.isDefinite);
966 return AliasingOpOperandList(std::move(
result));
969FailureOr<BufferLikeType> bufferization::detail::defaultGetBufferType(
971 const BufferizationState &bufferizationState,
973 assert(llvm::isa<TensorType>(value.
getType()) &&
"expected tensor type");
974 auto tensorType = cast<TensorType>(value.
getType());
980 <<
"cannot bufferize value of type " << tensorType
981 <<
": element type " << elementType
982 <<
" is not a valid memref element type";
985 if (llvm::isa<BlockArgument>(value)) {
986 return options.unknownTypeConverterFn(cast<TensorLikeType>(tensorType),
992 auto opResult = llvm::cast<OpResult>(value);
994 AliasingOpOperandList aliases = analysisState.getAliasingOpOperands(opResult);
995 if (aliases.getNumAliases() > 0 &&
996 aliases.getAliases()[0].relation == BufferRelation::Equivalent) {
999 Value equivalentOperand = aliases.getAliases().front().opOperand->get();
1007 options.defaultMemorySpaceFn(cast<TensorLikeType>(tensorType));
1008 if (!memSpace.has_value())
1009 return op->
emitError(
"could not infer memory space");
1011 return options.unknownTypeConverterFn(cast<TensorLikeType>(tensorType),
1015bool bufferization::detail::defaultIsRepetitiveRegion(
1016 BufferizableOpInterface bufferizableOp,
unsigned index) {
1017 assert(index < bufferizableOp->getNumRegions() &&
"invalid region index");
1018 auto regionInterface =
1019 dyn_cast<RegionBranchOpInterface>(bufferizableOp.getOperation());
1020 if (!regionInterface)
1022 return regionInterface.isRepetitiveRegion(
index);
1025AliasingOpOperandList
1026bufferization::detail::unknownGetAliasingOpOperands(
Value value) {
1029 if (
auto bbArg = dyn_cast<BlockArgument>(value))
1030 if (bbArg.getOwner() != &bbArg.getOwner()->getParent()->getBlocks().front())
1036 AliasingOpOperandList r;
1038 if (isa<TensorLikeType>(operand.get().getType()))
1039 r.addAlias({&operand, BufferRelation::Unknown,
false});
1044bufferization::detail::unknownGetAliasingValues(
OpOperand &opOperand) {
1049 AliasingValueList r;
1051 if (llvm::isa<TensorLikeType>(
result.getType()))
1052 r.addAlias({
result, BufferRelation::Unknown,
false});
1056 if (isa<TensorLikeType>(bbArg.getType()))
1057 r.addAlias({bbArg, BufferRelation::Unknown,
false});
1061bool bufferization::detail::defaultHasTensorSemantics(
Operation *op) {
1062 auto isaTensor = [](
Type t) {
return isa<TensorLikeType>(t); };
1064 return any_of(r.getBlocks(), [&](Block &b) {
1065 return any_of(b.getArguments(), [&](BlockArgument bbArg) {
1066 return isaTensor(bbArg.getType());
1070 if (hasTensorBlockArgument)
1078FailureOr<BaseMemRefType>
1079bufferization::detail::asMemRefType(FailureOr<BufferLikeType> bufferType) {
1082 return cast<BaseMemRefType>(*bufferType);
1085bool bufferization::detail::typesMatchAfterBufferization(
Operation &op,
1088 return mlir::succeeded(
1089 cast<TensorLikeType>(
tensor.getType())
1090 .verifyCompatibleBufferType(cast<BufferLikeType>(buffer.
getType()),
1091 [&]() { return op.emitError(); }));
static void setInsertionPointAfter(OpBuilder &b, Value value)
static bool isRepetitiveRegion(Region *region, const BufferizationOptions &options)
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 bool isaTensor(Type t)
static llvm::ManagedStatic< PassManagerOptions > options
static RankedTensorType getBufferType(const SparseTensorType &stt, bool needTmpCOO)
#define MLIR_DEFINE_EXPLICIT_TYPE_ID(CLASS_NAME)
static Operation * getOwnerOfValue(Value value)
Base class for generic analysis states.
AnalysisState(LatticeAnchor anchor)
Create the analysis state on the given lattice anchor.
Attributes are known-constant values of operations.
This class provides a shared interface for ranked and unranked memref types.
static bool isValidElementType(Type type)
Return true if the specified element type is ok in a memref.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
IRValueT get() const
Return the current value being used by this operand.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
This class represents an operand of an operation.
This is a value defined by a result of an operation.
Operation is the basic unit of execution within MLIR.
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Block * getBlock()
Returns the operation block that contains this operation.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
MutableArrayRef< OpOperand > getOpOperands()
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
operand_type_range getOperandTypes()
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
result_type_range getResultTypes()
bool isAncestor(Operation *other)
Return true if this operation is an ancestor of the other operation.
result_range getOpResults()
Region * getParentRegion()
Returns the region to which the instruction belongs.
unsigned getNumResults()
Return the number of results held by this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Region * getParentRegion()
Return the region containing this region or nullptr if the region is attached to a top-level operatio...
unsigned getRegionNumber()
Return the number of this region in the parent operation.
Operation * getParentOp()
Return the parent operation this region is attached to.
BlockListType & getBlocks()
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...
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
This class represents a collection of SymbolTables.
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.
Type getElementType() const
Returns the element type of this tensor type.
This class provides an efficient unique identifier for a specific C++ type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
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.
use_range getUses() const
Returns a range of all uses, which is useful for iterating over all uses.
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.
Region * getParentRegion()
Return the Region in which this Value is defined.
Operation * getOwner() const
Return the owner of this operand.
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...
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Type getTensorTypeFromMemRefType(Type type)
Return an unranked/ranked tensor type for the given unranked/ranked memref type.
Include the generated interface declarations.
LogicalResult reifyResultShapes(OpBuilder &b, Operation *op, ReifiedRankedShapedTypeDims &reifiedReturnShapes)
Reify the shape of the result of an operation (typically in terms of the shape of its operands).
bool insideMutuallyExclusiveRegions(Operation *a, Operation *b)
Return true if a and b are in mutually exclusive regions as per RegionBranchOpInterface.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
Region * getEnclosingRepetitiveRegion(Operation *op)
Return the first enclosing region of the given op that may be executed repetitively as per RegionBran...
SmallVector< SmallVector< OpFoldResult > > ReifiedRankedShapedTypeDims
Value getValueOrCreateConstantIndexOp(OpBuilder &b, Location loc, OpFoldResult ofr)
Converts an OpFoldResult to a Value.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...