MLIR 23.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 {
30 using DialectInlinerInterface::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 mlir::LogicalResult verifyCompatibleBufferType(
43 mlir::Type tensor, BufferLikeType bufferType,
44 llvm::function_ref<mlir::InFlightDiagnostic()> emitError) const {
45 auto tensorType = cast<ShapedType>(tensor);
46 auto memrefType = cast<ShapedType>(bufferType);
47
48 if (tensorType.getShape() != memrefType.getShape())
49 return emitError() << "shapes do not match";
50
51 if (tensorType.getElementType() != memrefType.getElementType())
52 return emitError() << "element types do not match";
53
54 return mlir::success();
55 }
56};
57
58template <typename MemRef>
59struct BuiltinMemRefExternalModel
60 : BufferLikeType::ExternalModel<BuiltinMemRefExternalModel<MemRef>,
61 MemRef> {};
62} // namespace
63
64//===----------------------------------------------------------------------===//
65// Bufferization Dialect
66//===----------------------------------------------------------------------===//
67
68void mlir::bufferization::BufferizationDialect::initialize() {
69 addOperations<
70#define GET_OP_LIST
71#include "mlir/Dialect/Bufferization/IR/BufferizationOps.cpp.inc"
72 >();
73 addInterfaces<BufferizationInlinerInterface>();
74
75 // Note: Unlike with other external models, declaring bufferization's
76 // "promised interfaces" in builtins for TensorLike and BufferLike type
77 // interfaces is not possible (due to builtins being independent of
78 // bufferization). Thus, the compromise is to attach these interfaces directly
79 // during dialect initialization.
80 RankedTensorType::attachInterface<
81 BuiltinTensorExternalModel<RankedTensorType>>(*getContext());
82 UnrankedTensorType::attachInterface<
83 BuiltinTensorExternalModel<UnrankedTensorType>>(*getContext());
84 MemRefType::attachInterface<BuiltinMemRefExternalModel<MemRefType>>(
85 *getContext());
86 UnrankedMemRefType::attachInterface<
87 BuiltinMemRefExternalModel<UnrankedMemRefType>>(*getContext());
88}
89
90LogicalResult BufferizationDialect::verifyRegionArgAttribute(
91 Operation *op, unsigned /*regionIndex*/, unsigned argIndex,
92 NamedAttribute attr) {
93 if (attr.getName() == kWritableAttrName) {
94 if (!llvm::isa<BoolAttr>(attr.getValue())) {
95 return op->emitError() << "'" << kWritableAttrName
96 << "' is expected to be a boolean attribute";
97 }
98 if (!isa<FunctionOpInterface>(op))
99 return op->emitError() << "expected '" << kWritableAttrName
100 << "' to be used on function-like operations";
101 if (cast<FunctionOpInterface>(op).isExternal())
102 return op->emitError() << "'" << kWritableAttrName
103 << "' is invalid on external functions";
104 return success();
105 }
106 if (attr.getName() == kBufferAccessAttrName) {
107 if (!llvm::isa<StringAttr>(attr.getValue())) {
108 return op->emitError() << "'" << kBufferAccessAttrName
109 << "' is expected to be a string attribute";
110 }
111 StringRef str = llvm::cast<StringAttr>(attr.getValue()).getValue();
112 if (str != "none" && str != "read" && str != "write" && str != "read-write")
113 return op->emitError()
114 << "invalid value for '" << kBufferAccessAttrName << "'";
115 if (!isa<FunctionOpInterface>(op))
116 return op->emitError() << "expected '" << kBufferAccessAttrName
117 << "' to be used on function-like operations";
118 return success();
119 }
120 if (attr.getName() == kBufferLayoutAttrName) {
121 if (!llvm::isa<MemRefLayoutAttrInterface>(attr.getValue())) {
122 return op->emitError() << "'" << kBufferLayoutAttrName
123 << "' is expected to be a memref layout attribute";
124 }
125 if (!isa<FunctionOpInterface>(op))
126 return op->emitError() << "expected '" << kBufferLayoutAttrName
127 << "' to be used on function-like operations";
128 return success();
129 }
130 return op->emitError() << "attribute '" << kBufferLayoutAttrName
131 << "' not supported as a region arg attribute by the "
132 "bufferization dialect";
133}
134
135LogicalResult
136BufferizationDialect::verifyOperationAttribute(Operation *op,
137 NamedAttribute attr) {
138 using bufferization::BufferizableOpInterface;
139
140 if (attr.getName() == kManualDeallocation) {
143 return op->emitOpError("attribute '")
144 << kManualDeallocation
145 << "' can be used only on ops that have an allocation and/or free "
146 "side effect";
147 return success();
148 }
149
150 return op->emitError()
151 << "attribute '" << attr.getName()
152 << "' not supported as an op attribute by the bufferization dialect";
153}
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())
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:87
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.
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.