MLIR 22.0.0git
BufferizationDialect.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
18
19using namespace mlir;
20using namespace mlir::bufferization;
21
22#include "mlir/Dialect/Bufferization/IR/BufferizationOpsDialect.cpp.inc"
23
24//===----------------------------------------------------------------------===//
25// Bufferization Dialect Interfaces
26//===----------------------------------------------------------------------===//
27
28namespace {
29struct BufferizationInlinerInterface : public DialectInlinerInterface {
31
32 /// Operations in Bufferization dialect are always legal to inline.
33 bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
34 return true;
35 }
36};
37
38template <typename Tensor>
39struct BuiltinTensorExternalModel
40 : TensorLikeType::ExternalModel<BuiltinTensorExternalModel<Tensor>,
41 Tensor> {
42 llvm::FailureOr<BufferLikeType> getBufferType(
43 mlir::Type tensor, const BufferizationOptions &options,
44 llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
45 auto tensorType = cast<TensorType>(tensor);
46 auto memSpace = options.defaultMemorySpaceFn(tensorType);
47 if (!memSpace.has_value())
48 return emitError() << "could not infer memory space";
49
50 return cast<BufferLikeType>(
51 getMemRefType(tensorType, options, /*layout=*/{}, *memSpace));
52 }
53
54 mlir::LogicalResult verifyCompatibleBufferType(
55 mlir::Type tensor, BufferLikeType bufferType,
56 llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
57 auto tensorType = cast<ShapedType>(tensor);
58 auto memrefType = cast<ShapedType>(bufferType);
59
60 if (tensorType.getShape() != memrefType.getShape())
61 return emitError() << "shapes do not match";
62
63 if (tensorType.getElementType() != memrefType.getElementType())
64 return emitError() << "element types do not match";
65
66 return mlir::success();
67 }
68};
69
70template <typename MemRef>
71struct BuiltinMemRefExternalModel
72 : BufferLikeType::ExternalModel<BuiltinMemRefExternalModel<MemRef>,
73 MemRef> {};
74} // namespace
75
76//===----------------------------------------------------------------------===//
77// Bufferization Dialect
78//===----------------------------------------------------------------------===//
79
80void mlir::bufferization::BufferizationDialect::initialize() {
81 addOperations<
82#define GET_OP_LIST
83#include "mlir/Dialect/Bufferization/IR/BufferizationOps.cpp.inc"
84 >();
85 addInterfaces<BufferizationInlinerInterface>();
86
87 // Note: Unlike with other external models, declaring bufferization's
88 // "promised interfaces" in builtins for TensorLike and BufferLike type
89 // interfaces is not possible (due to builtins being independent of
90 // bufferization). Thus, the compromise is to attach these interfaces directly
91 // during dialect initialization.
92 RankedTensorType::attachInterface<
93 BuiltinTensorExternalModel<RankedTensorType>>(*getContext());
94 UnrankedTensorType::attachInterface<
95 BuiltinTensorExternalModel<UnrankedTensorType>>(*getContext());
96 MemRefType::attachInterface<BuiltinMemRefExternalModel<MemRefType>>(
97 *getContext());
98 UnrankedMemRefType::attachInterface<
99 BuiltinMemRefExternalModel<UnrankedMemRefType>>(*getContext());
100}
101
102LogicalResult BufferizationDialect::verifyRegionArgAttribute(
103 Operation *op, unsigned /*regionIndex*/, unsigned argIndex,
104 NamedAttribute attr) {
105 if (attr.getName() == kWritableAttrName) {
106 if (!llvm::isa<BoolAttr>(attr.getValue())) {
107 return op->emitError() << "'" << kWritableAttrName
108 << "' is expected to be a boolean attribute";
109 }
110 if (!isa<FunctionOpInterface>(op))
111 return op->emitError() << "expected '" << kWritableAttrName
112 << "' to be used on function-like operations";
113 if (cast<FunctionOpInterface>(op).isExternal())
114 return op->emitError() << "'" << kWritableAttrName
115 << "' is invalid on external functions";
116 return success();
117 }
118 if (attr.getName() == kBufferAccessAttrName) {
119 if (!llvm::isa<StringAttr>(attr.getValue())) {
120 return op->emitError() << "'" << kBufferAccessAttrName
121 << "' is expected to be a string attribute";
122 }
123 StringRef str = llvm::cast<StringAttr>(attr.getValue()).getValue();
124 if (str != "none" && str != "read" && str != "write" && str != "read-write")
125 return op->emitError()
126 << "invalid value for '" << kBufferAccessAttrName << "'";
127 if (!isa<FunctionOpInterface>(op))
128 return op->emitError() << "expected '" << kBufferAccessAttrName
129 << "' to be used on function-like operations";
130 return success();
131 }
132 if (attr.getName() == kBufferLayoutAttrName) {
133 if (!llvm::isa<MemRefLayoutAttrInterface>(attr.getValue())) {
134 return op->emitError() << "'" << kBufferLayoutAttrName
135 << "' is expected to be a memref layout attribute";
136 }
137 if (!isa<FunctionOpInterface>(op))
138 return op->emitError() << "expected '" << kBufferLayoutAttrName
139 << "' to be used on function-like operations";
140 return success();
141 }
142 return op->emitError() << "attribute '" << kBufferLayoutAttrName
143 << "' not supported as a region arg attribute by the "
144 "bufferization dialect";
145}
146
147LogicalResult
148BufferizationDialect::verifyOperationAttribute(Operation *op,
149 NamedAttribute attr) {
150 using bufferization::BufferizableOpInterface;
151
152 if (attr.getName() == kManualDeallocation) {
155 return op->emitOpError("attribute '")
156 << kManualDeallocation
157 << "' can be used only on ops that have an allocation and/or free "
158 "side effect";
159 return success();
160 }
161
162 return op->emitError()
163 << "attribute '" << attr.getName()
164 << "' not supported as an op attribute by the bufferization dialect";
165}
return success()
static bool isLegalToInline(InlinerInterface &interface, Region *src, Region *insertRegion, bool shouldCloneInlinedRegion, IRMapping &valueMapping)
Utility to check that all of the operations within 'src' can be inlined.
b getContext())
static llvm::ManagedStatic< PassManagerOptions > options
static RankedTensorType getBufferType(const SparseTensorType &stt, bool needTmpCOO)
This is the interface that must be implemented by the dialects of operations to be inlined.
DialectInlinerInterface(Dialect *dialect)
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
Definition Attributes.h:179
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
MemRefType getMemRefType(T &&t)
Convenience method to abbreviate casting getType().
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool hasEffect(Operation *op)
Returns "true" if op has an effect of type EffectTy.