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();
167FailureOr<Value> bufferization::allocateTensorForShapedValue(
169 const BufferizationOptions &
options,
const BufferizationState &state,
172 if (llvm::isa<MemRefType>(shapedValue.
getType())) {
173 tensor = ToTensorOp::create(
176 }
else if (llvm::isa<UnrankedTensorType>(shapedValue.
getType()) ||
177 llvm::isa<UnrankedMemRefType>(shapedValue.
getType())) {
179 ->
emitError(
"copying of unranked tensors is not implemented");
181 auto tensorType = llvm::cast<TensorLikeType>(
tensor.getType());
185 auto rankedTensorType = dyn_cast<RankedTensorType>(tensorType);
186 if (!
copy && rankedTensorType) {
189 bool reifiedShapes =
false;
190 if (llvm::isa<RankedTensorType>(shapedValue.
getType()) &&
191 llvm::isa<OpResult>(shapedValue)) {
195 reifiedShapes =
true;
197 resultDims[llvm::cast<OpResult>(shapedValue).getResultNumber()];
198 for (
const auto &dim :
enumerate(rankedTensorType.getShape())) {
199 if (ShapedType::isDynamic(dim.value())) {
200 dynamicSizes.push_back(
213 auto allocTensorOp = AllocTensorOp::create(
b, loc, tensorType, dynamicSizes,
218 return allocTensorOp.getResult();
220 if (
failed(copyBufferType))
223 std::optional<Attribute> memorySpace;
224 if (
auto copyMemRefType = dyn_cast<BaseMemRefType>(*copyBufferType))
225 memorySpace = copyMemRefType.getMemorySpace();
228 options.defaultMemorySpaceFn(cast<TensorLikeType>(tensorType));
229 if (memorySpace.has_value())
230 allocTensorOp.setMemorySpaceAttr(memorySpace.value());
231 return allocTensorOp.getResult();
234LogicalResult BufferizableOpInterface::resolveTensorOpOperandConflicts(
236 const BufferizationState &bufferizationState) {
246 Type operandType = opOperand.get().getType();
247 if (!llvm::isa<TensorLikeType>(operandType))
249 if (analysisState.isInPlace(opOperand))
251 if (llvm::isa<UnrankedTensorType>(operandType))
252 return op->
emitError(
"copying of unranked tensors is not implemented");
254 AliasingValueList aliasingValues =
255 analysisState.getAliasingValues(opOperand);
256 if (aliasingValues.getNumAliases() == 1 &&
257 isa<OpResult>(aliasingValues.getAliases()[0].value) &&
258 !analysisState.bufferizesToMemoryWrite(opOperand) &&
260 .getAliasingOpOperands(aliasingValues.getAliases()[0].value)
261 .getNumAliases() == 1 &&
262 !isa<UnrankedTensorType>(
263 aliasingValues.getAliases()[0].value.getType())) {
270 Value value = aliasingValues.getAliases()[0].value;
271 outOfPlaceValues.push_back(value);
272 if (!analysisState.canOmitTensorCopy(opOperand))
273 copiedOpValues.insert(value);
276 outOfPlaceOpOperands.push_back(&opOperand);
277 if (!analysisState.canOmitTensorCopy(opOperand))
278 copiedOpOperands.insert(&opOperand);
284 for (
OpOperand *opOperand : outOfPlaceOpOperands) {
285 FailureOr<Value>
copy = allocateTensorForShapedValue(
286 rewriter, op->
getLoc(), opOperand->get(), analysisState.getOptions(),
287 bufferizationState, copiedOpOperands.contains(opOperand));
295 for (
Value value : outOfPlaceValues) {
296 FailureOr<Value>
copy = allocateTensorForShapedValue(
297 rewriter, op->
getLoc(), value, analysisState.getOptions(),
298 bufferizationState, copiedOpValues.count(value));
305 if (use->getOwner() ==
copy->getDefiningOp())
309 if (isa<tensor::DimOp>(use->getOwner()))
322bool OpFilter::isOpAllowed(
Operation *op)
const {
324 bool isAllowed = !hasAllowRule();
325 for (
const Entry &entry : entries) {
326 bool filterResult = entry.fn(op);
327 switch (entry.type) {
329 isAllowed |= filterResult;
349 mlir::Type elementType,
351 int64_t dynamicOffset = ShapedType::kDynamic;
353 auto stridedLayout = StridedLayoutAttr::get(elementType.
getContext(),
354 dynamicOffset, dynamicStrides);
355 return MemRefType::get(
shape, elementType, stridedLayout, memorySpace);
361 unsigned int bufferAlignment) {
363 if (bufferAlignment != 0)
364 return memref::AllocOp::create(
b, loc, type, dynShape,
365 b.getI64IntegerAttr(bufferAlignment))
367 return memref::AllocOp::create(
b, loc, type, dynShape).getResult();
373 memref::CopyOp::create(
b, loc, from, to);
379 assert(isa<BaseMemRefType>(dest) &&
"expected BaseMemRefType");
380 assert(isa<BaseMemRefType>(value.
getType()) &&
"expected BaseMemRefType");
381 assert(memref::CastOp::areCastCompatible(value.
getType(), dest) &&
382 "cast incompatible");
383 return memref::CastOp::create(
b, loc, dest, value).getResult();
388defaultFunctionArgTypeConverter(TensorLikeType type,
Attribute memorySpace,
390 const BufferizationOptions &
options) {
391 if (
auto tensorType = mlir::dyn_cast<TensorType>(type)) {
392 return cast<BufferLikeType>(
393 bufferization::getMemRefTypeWithFullyDynamicLayout(tensorType,
398 return options.unknownTypeConverterFn(type, memorySpace,
options);
402defaultUnknownTypeConverter(TensorLikeType tensorType,
Attribute memorySpace,
403 const BufferizationOptions &
options) {
404 return cast<BufferLikeType>(
405 bufferization::getMemRefTypeWithFullyDynamicLayout(
406 cast<TensorType>(tensorType), memorySpace));
411FailureOr<BufferLikeType>
412defaultReconcileBufferTypeMismatch(BufferLikeType x, BufferLikeType y,
413 const BufferizationOptions &) {
414 const auto xMemRef = cast<BaseMemRefType>(x);
415 const auto yMemRef = cast<BaseMemRefType>(y);
417 if (xMemRef.getMemorySpace() != yMemRef.getMemorySpace())
420 if (isa<UnrankedMemRefType>(xMemRef)) {
425 return cast<BufferLikeType>(::getMemRefTypeWithFullyDynamicLayout(
426 xMemRef.getShape(), xMemRef.getElementType(), xMemRef.getMemorySpace()));
432BufferizationOptions::BufferizationOptions()
433 : allocationFn(defaultCreateAlloc), memCpyFn(defaultCreateMemCpy),
434 castFn(defaultCreateCast),
435 functionArgTypeConverterFn(defaultFunctionArgTypeConverter),
436 unknownTypeConverterFn(defaultUnknownTypeConverter),
437 reconcileBufferTypeMismatchFn(defaultReconcileBufferTypeMismatch) {}
439bool BufferizationOptions::isOpAllowed(
Operation *op)
const {
442 bool isFuncBoundaryOp = isa_and_nonnull<func::FuncDialect>(op->
getDialect());
443 if (!bufferizeFunctionBoundaries && isFuncBoundaryOp)
446 return opFilter.isOpAllowed(op);
449BufferizableOpInterface
450BufferizationOptions::dynCastBufferizableOp(
Operation *op)
const {
451 if (!isOpAllowed(op))
453 auto bufferizableOp = dyn_cast<BufferizableOpInterface>(op);
456 return bufferizableOp;
459BufferizableOpInterface
460BufferizationOptions::dynCastBufferizableOp(
Value value)
const {
464void BufferizationOptions::setFunctionBoundaryTypeConversion(
465 LayoutMapOption layoutMapOption) {
466 functionArgTypeConverterFn = [=](TensorLikeType type, Attribute memorySpace,
468 const BufferizationOptions &
options) {
469 if (
auto tensorType = mlir::dyn_cast<TensorType>(type)) {
470 if (layoutMapOption == LayoutMapOption::IdentityLayoutMap)
471 return cast<BufferLikeType>(
472 bufferization::getMemRefTypeWithStaticIdentityLayout(tensorType,
474 return cast<BufferLikeType>(
475 bufferization::getMemRefTypeWithFullyDynamicLayout(tensorType,
480 return options.unknownTypeConverterFn(type, memorySpace,
options);
482 inferFunctionResultLayout =
483 layoutMapOption == LayoutMapOption::InferLayoutMap;
491 if (
auto bbArg = llvm::dyn_cast<BlockArgument>(value)) {
492 b.setInsertionPointToStart(bbArg.getOwner());
500AliasingOpOperandList AnalysisState::getAliasingOpOperands(
Value value)
const {
502 if (
auto bufferizableOp = getOptions().dynCastBufferizableOp(op))
503 return bufferizableOp.getAliasingOpOperands(value, *
this);
506 return detail::unknownGetAliasingOpOperands(value);
511AliasingValueList AnalysisState::getAliasingValues(
OpOperand &opOperand)
const {
512 if (
auto bufferizableOp =
513 getOptions().dynCastBufferizableOp(opOperand.
getOwner()))
514 return bufferizableOp.getAliasingValues(opOperand, *
this);
517 return detail::unknownGetAliasingValues(opOperand);
522bool AnalysisState::bufferizesToMemoryRead(
OpOperand &opOperand)
const {
523 if (
auto bufferizableOp =
524 getOptions().dynCastBufferizableOp(opOperand.
getOwner()))
525 return bufferizableOp.bufferizesToMemoryRead(opOperand, *
this);
534bool AnalysisState::bufferizesToMemoryWrite(
OpOperand &opOperand)
const {
535 if (
auto bufferizableOp =
536 getOptions().dynCastBufferizableOp(opOperand.
getOwner()))
537 return bufferizableOp.bufferizesToMemoryWrite(opOperand, *
this);
546bool AnalysisState::bufferizesToAliasOnly(
OpOperand &opOperand)
const {
547 if (
auto bufferizableOp =
548 getOptions().dynCastBufferizableOp(opOperand.
getOwner()))
549 return bufferizableOp.bufferizesToAliasOnly(opOperand, *
this);
556bool AnalysisState::bufferizesToMemoryWrite(
Value value)
const {
557 auto opResult = llvm::dyn_cast<OpResult>(value);
560 auto bufferizableOp = getOptions().dynCastBufferizableOp(value);
563 return bufferizableOp.resultBufferizesToMemoryWrite(opResult, *
this);
569bool AnalysisState::isValueRead(
Value value)
const {
570 assert(llvm::isa<TensorLikeType>(value.
getType()) &&
571 "expected TensorLikeType");
572 SmallVector<OpOperand *> workingSet;
574 for (OpOperand &use : value.
getUses())
575 workingSet.push_back(&use);
577 while (!workingSet.empty()) {
578 OpOperand *uMaybeReading = workingSet.pop_back_val();
579 if (!visited.insert(uMaybeReading).second)
583 if (bufferizesToAliasOnly(*uMaybeReading))
584 for (AliasingValue alias : getAliasingValues(*uMaybeReading))
585 for (OpOperand &use : alias.value.getUses())
586 workingSet.push_back(&use);
587 if (bufferizesToMemoryRead(*uMaybeReading))
599llvm::SetVector<Value> AnalysisState::findValueInReverseUseDefChain(
601 TraversalConfig config,
602 llvm::DenseSet<OpOperand *> *visitedOpOperands)
const {
603 llvm::DenseSet<Value> visited;
604 llvm::SetVector<Value>
result, workingSet;
605 workingSet.insert(opOperand->
get());
607 if (visitedOpOperands)
608 visitedOpOperands->insert(opOperand);
610 while (!workingSet.empty()) {
611 Value value = workingSet.pop_back_val();
613 if (!config.revisitAlreadyVisitedValues && visited.contains(value)) {
615 if (config.alwaysIncludeLeaves)
619 visited.insert(value);
621 if (condition(value)) {
626 if (!config.followUnknownOps && !
options.dynCastBufferizableOp(value)) {
629 if (config.alwaysIncludeLeaves)
634 AliasingOpOperandList aliases = getAliasingOpOperands(value);
635 if (aliases.getNumAliases() == 0) {
638 if (config.alwaysIncludeLeaves)
643 for (AliasingOpOperand a : aliases) {
644 if (config.followEquivalentOnly &&
645 a.relation != BufferRelation::Equivalent) {
648 if (config.alwaysIncludeLeaves)
653 if (config.followInPlaceOnly && !isInPlace(*a.opOperand)) {
656 if (config.alwaysIncludeLeaves)
661 if (config.followSameTypeOrCastsOnly &&
662 a.opOperand->get().getType() != value.
getType() &&
666 if (config.alwaysIncludeLeaves)
671 workingSet.insert(a.opOperand->get());
672 if (visitedOpOperands)
673 visitedOpOperands->insert(a.opOperand);
681llvm::SetVector<Value>
682AnalysisState::findDefinitions(
OpOperand *opOperand)
const {
683 TraversalConfig config;
684 config.alwaysIncludeLeaves =
false;
685 return findValueInReverseUseDefChain(
686 opOperand, [&](Value v) {
return this->bufferizesToMemoryWrite(v); },
695 for (
const BufferizationOptions::AnalysisStateInitFn &fn :
700bool AnalysisState::canOmitTensorCopy(
OpOperand &opOperand)
const {
702 if (hasUndefinedContents(&opOperand))
707 if (bufferizesToMemoryWrite(opOperand) && !bufferizesToMemoryRead(opOperand))
711 AliasingValueList aliases = getAliasingValues(opOperand);
712 if (!bufferizesToMemoryRead(opOperand) &&
713 llvm::none_of(aliases,
714 [&](AliasingValue a) {
return isValueRead(a.value); }))
721bool AnalysisState::isInPlace(
OpOperand &opOperand)
const {
723 if (isa<ToBufferOp>(opOperand.
getOwner()))
728 return !bufferizesToMemoryWrite(opOperand);
731bool AnalysisState::areEquivalentBufferizedValues(
Value v1,
Value v2)
const {
737bool AnalysisState::areAliasingBufferizedValues(
Value v1,
Value v2)
const {
743bool AnalysisState::hasUndefinedContents(
OpOperand *opOperand)
const {
749 const BufferizationOptions &
options,
750 const BufferizationState &state) {
752 auto tensorType = llvm::dyn_cast<TensorLikeType>(value.
getType());
753 assert(tensorType &&
"unexpected non-tensor type");
757 if (
auto toTensorOp = value.
getDefiningOp<bufferization::ToTensorOp>())
758 return toTensorOp.getBuffer();
767 return bufferization::ToBufferOp::create(rewriter, value.
getLoc(),
773FailureOr<BufferLikeType>
774bufferization::getBufferType(
Value value,
const BufferizationOptions &
options,
775 const BufferizationState &state) {
781FailureOr<BufferLikeType>
782bufferization::getBufferType(
Value value,
const BufferizationOptions &
options,
783 const BufferizationState &state,
785 assert(llvm::isa<TensorLikeType>(value.
getType()) &&
786 "unexpected non-tensor type");
787 invocationStack.push_back(value);
788 llvm::scope_exit popFromStack([&]() { invocationStack.pop_back(); });
792 auto bufferizableOp =
options.dynCastBufferizableOp(op);
794 return bufferizableOp.getBufferType(value,
options, state, invocationStack);
798 options.defaultMemorySpaceFn(cast<TensorLikeType>(value.
getType()));
799 if (!memSpace.has_value())
800 return op->emitError(
"could not infer memory space");
802 return options.unknownTypeConverterFn(cast<TensorLikeType>(value.
getType()),
806bool bufferization::hasTensorSemantics(
Operation *op) {
807 if (
auto bufferizableOp = dyn_cast<BufferizableOpInterface>(op))
808 return bufferizableOp.hasTensorSemantics();
809 return detail::defaultHasTensorSemantics(op);
812void bufferization::replaceOpWithBufferizedValues(
RewriterBase &rewriter,
816 "expected one value per OpResult");
823 if (llvm::isa<TensorLikeType>(opResult.getType())) {
826 assert(llvm::isa<BufferLikeType>(
replacement.getType()) &&
827 "tensor op result should be replaced with a buffer value");
846bufferization::getMemRefTypeWithFullyDynamicLayout(
TensorType tensorType,
849 if (
auto unrankedTensorType =
850 llvm::dyn_cast<UnrankedTensorType>(tensorType)) {
851 return UnrankedMemRefType::get(unrankedTensorType.getElementType(),
856 return ::getMemRefTypeWithFullyDynamicLayout(
863bufferization::getMemRefTypeWithStaticIdentityLayout(
TensorType tensorType,
866 if (
auto unrankedTensorType =
867 llvm::dyn_cast<UnrankedTensorType>(tensorType)) {
868 return UnrankedMemRefType::get(unrankedTensorType.getElementType(),
873 auto rankedTensorType = llvm::cast<RankedTensorType>(tensorType);
874 MemRefLayoutAttrInterface layout = {};
875 return MemRefType::get(rankedTensorType.getShape(),
876 rankedTensorType.getElementType(), layout,
884bool bufferization::detail::defaultResultBufferizesToMemoryWrite(
886 auto bufferizableOp = cast<BufferizableOpInterface>(opResult.
getDefiningOp());
887 AliasingOpOperandList opOperands =
888 bufferizableOp.getAliasingOpOperands(opResult, state);
892 if (opOperands.getAliases().empty())
897 if (llvm::any_of(opOperands, [&](AliasingOpOperand alias) {
898 return state.bufferizesToMemoryWrite(*alias.opOperand);
931 auto isMemoryWriteInsideOp = [&](
Value v) {
935 return state.bufferizesToMemoryWrite(v);
937 TraversalConfig config;
938 config.alwaysIncludeLeaves =
false;
939 for (AliasingOpOperand alias : opOperands) {
941 .findValueInReverseUseDefChain(alias.opOperand,
942 isMemoryWriteInsideOp, config)
951AliasingOpOperandList bufferization::detail::defaultGetAliasingOpOperands(
956 if (!llvm::isa<TensorLikeType>(opOperand.
get().
getType()))
958 AliasingValueList aliasingValues = state.getAliasingValues(opOperand);
959 for (
const auto &it : aliasingValues)
960 if (it.value == value)
961 result.emplace_back(&opOperand, it.relation, it.isDefinite);
963 return AliasingOpOperandList(std::move(
result));
966FailureOr<BufferLikeType> bufferization::detail::defaultGetBufferType(
968 const BufferizationState &bufferizationState,
970 assert(llvm::isa<TensorType>(value.
getType()) &&
"expected tensor type");
971 auto tensorType = cast<TensorType>(value.
getType());
977 <<
"cannot bufferize value of type " << tensorType
978 <<
": element type " << elementType
979 <<
" is not a valid memref element type";
982 if (llvm::isa<BlockArgument>(value)) {
983 return options.unknownTypeConverterFn(cast<TensorLikeType>(tensorType),
989 auto opResult = llvm::cast<OpResult>(value);
991 AliasingOpOperandList aliases = analysisState.getAliasingOpOperands(opResult);
992 if (aliases.getNumAliases() > 0 &&
993 aliases.getAliases()[0].relation == BufferRelation::Equivalent) {
996 Value equivalentOperand = aliases.getAliases().front().opOperand->get();
1004 options.defaultMemorySpaceFn(cast<TensorLikeType>(tensorType));
1005 if (!memSpace.has_value())
1006 return op->
emitError(
"could not infer memory space");
1008 return options.unknownTypeConverterFn(cast<TensorLikeType>(tensorType),
1012bool bufferization::detail::defaultIsRepetitiveRegion(
1013 BufferizableOpInterface bufferizableOp,
unsigned index) {
1014 assert(index < bufferizableOp->getNumRegions() &&
"invalid region index");
1015 auto regionInterface =
1016 dyn_cast<RegionBranchOpInterface>(bufferizableOp.getOperation());
1017 if (!regionInterface)
1019 return regionInterface.isRepetitiveRegion(
index);
1022AliasingOpOperandList
1023bufferization::detail::unknownGetAliasingOpOperands(
Value value) {
1026 if (
auto bbArg = dyn_cast<BlockArgument>(value))
1027 if (bbArg.getOwner() != &bbArg.getOwner()->getParent()->getBlocks().front())
1033 AliasingOpOperandList r;
1035 if (isa<TensorLikeType>(operand.get().getType()))
1036 r.addAlias({&operand, BufferRelation::Unknown,
false});
1041bufferization::detail::unknownGetAliasingValues(
OpOperand &opOperand) {
1046 AliasingValueList r;
1048 if (llvm::isa<TensorLikeType>(
result.getType()))
1049 r.addAlias({
result, BufferRelation::Unknown,
false});
1053 if (isa<TensorLikeType>(bbArg.getType()))
1054 r.addAlias({bbArg, BufferRelation::Unknown,
false});
1058bool bufferization::detail::defaultHasTensorSemantics(
Operation *op) {
1059 auto isaTensor = [](
Type t) {
return isa<TensorLikeType>(t); };
1061 return any_of(r.getBlocks(), [&](Block &b) {
1062 return any_of(b.getArguments(), [&](BlockArgument bbArg) {
1063 return isaTensor(bbArg.getType());
1067 if (hasTensorBlockArgument)
1075FailureOr<BaseMemRefType>
1076bufferization::detail::asMemRefType(FailureOr<BufferLikeType> bufferType) {
1079 return cast<BaseMemRefType>(*bufferType);
1082bool bufferization::detail::typesMatchAfterBufferization(
Operation &op,
1085 return mlir::succeeded(
1086 cast<TensorLikeType>(
tensor.getType())
1087 .verifyCompatibleBufferType(cast<BufferLikeType>(buffer.
getType()),
1088 [&]() { 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...