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
9#include "mlir/Dialect/Affine/IR/AffineOps.h"
10#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
11#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
12#include "mlir/Dialect/MemRef/IR/MemRef.h"
13#include "mlir/Dialect/Tensor/IR/Tensor.h"
14#include "mlir/Interfaces/FunctionInterfaces.h"
15#include "mlir/Transforms/InliningUtils.h"
16
17using namespace mlir;
18using namespace mlir::bufferization;
19
20#include "mlir/Dialect/Bufferization/IR/BufferizationOpsDialect.cpp.inc"
21
22/// Attribute name used to mark function arguments who's buffers can be written
23/// to during One-Shot Module Bufferize.
24constexpr const ::llvm::StringLiteral BufferizationDialect::kWritableAttrName;
25
26/// Attribute name used to mark the bufferization layout for region arguments
27/// during One-Shot Module Bufferize.
28constexpr const ::llvm::StringLiteral
29 BufferizationDialect::kBufferLayoutAttrName;
30
31/// An attribute that can be attached to ops with an allocation and/or
32/// deallocation side effect. It indicates that the op is under a "manual
33/// deallocation" scheme. In the case of an allocation op, the returned
34/// value is *not* an automatically managed allocation and assigned an
35/// ownership of "false". Furthermore, only deallocation ops that are
36/// guaranteed to deallocate a buffer under "manual deallocation" are
37/// allowed to have this attribute. (Deallocation ops without this
38/// attribute are rejected by the ownership-based buffer deallocation pass.)
39constexpr const ::llvm::StringLiteral BufferizationDialect::kManualDeallocation;
40
41//===----------------------------------------------------------------------===//
42// Bufferization Dialect Interfaces
43//===----------------------------------------------------------------------===//
44
45namespace {
46struct BufferizationInlinerInterface : public DialectInlinerInterface {
47 using DialectInlinerInterface::DialectInlinerInterface;
48
49 /// Operations in Bufferization dialect are always legal to inline.
50 bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
51 return true;
52 }
53};
54} // namespace
55
56//===----------------------------------------------------------------------===//
57// Bufferization Dialect
58//===----------------------------------------------------------------------===//
59
60void mlir::bufferization::BufferizationDialect::initialize() {
61 addOperations<
62#define GET_OP_LIST
63#include "mlir/Dialect/Bufferization/IR/BufferizationOps.cpp.inc"
64 >();
65 addInterfaces<BufferizationInlinerInterface>();
66}
67
68LogicalResult BufferizationDialect::verifyRegionArgAttribute(
69 Operation *op, unsigned /*regionIndex*/, unsigned argIndex,
70 NamedAttribute attr) {
71 if (attr.getName() == kWritableAttrName) {
72 if (!llvm::isa<BoolAttr>(attr.getValue())) {
73 return op->emitError() << "'" << kWritableAttrName
74 << "' is expected to be a boolean attribute";
75 }
76 if (!isa<FunctionOpInterface>(op))
77 return op->emitError() << "expected '" << kWritableAttrName
78 << "' to be used on function-like operations";
79 if (cast<FunctionOpInterface>(op).isExternal())
80 return op->emitError() << "'" << kWritableAttrName
81 << "' is invalid on external functions";
82 return success();
83 }
84 if (attr.getName() == kBufferAccessAttrName) {
85 if (!llvm::isa<StringAttr>(attr.getValue())) {
86 return op->emitError() << "'" << kBufferAccessAttrName
87 << "' is expected to be a string attribute";
88 }
89 StringRef str = llvm::cast<StringAttr>(attr.getValue()).getValue();
90 if (str != "none" && str != "read" && str != "write" && str != "read-write")
91 return op->emitError()
92 << "invalid value for '" << kBufferAccessAttrName << "'";
93 if (!isa<FunctionOpInterface>(op))
94 return op->emitError() << "expected '" << kBufferAccessAttrName
95 << "' to be used on function-like operations";
96 return success();
97 }
98 if (attr.getName() == kBufferLayoutAttrName) {
99 if (!llvm::isa<AffineMapAttr>(attr.getValue())) {
100 return op->emitError() << "'" << kBufferLayoutAttrName
101 << "' is expected to be a affine map attribute";
102 }
103 if (!isa<FunctionOpInterface>(op))
104 return op->emitError() << "expected '" << kBufferLayoutAttrName
105 << "' to be used on function-like operations";
106 return success();
107 }
108 return op->emitError() << "attribute '" << kBufferLayoutAttrName
109 << "' not supported as a region arg attribute by the "
110 "bufferization dialect";
111}
112
113LogicalResult
114BufferizationDialect::verifyOperationAttribute(Operation *op,
115 NamedAttribute attr) {
116 using bufferization::BufferizableOpInterface;
117
118 if (attr.getName() == kManualDeallocation) {
119 if (!mlir::hasEffect<MemoryEffects::Allocate>(op) &&
120 !mlir::hasEffect<MemoryEffects::Free>(op))
121 return op->emitOpError("attribute '")
122 << kManualDeallocation
123 << "' can be used only on ops that have an allocation and/or free "
124 "side effect";
125 return success();
126 }
127
128 return op->emitError()
129 << "attribute '" << attr.getName()
130 << "' not supported as an op attribute by the bufferization dialect";
131}
132

source code of mlir/lib/Dialect/Bufferization/IR/BufferizationDialect.cpp