MLIR 24.0.0git
BuiltinDialect.cpp
Go to the documentation of this file.
1//===- BuiltinDialect.cpp - MLIR Builtin Dialect --------------------------===//
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// This file contains the Builtin dialect that contains all of the attributes,
10// operations, and types that are necessary for the validity of the IR.
11//
12//===----------------------------------------------------------------------===//
13
16#include "mlir/IR/Builders.h"
17#include "mlir/IR/BuiltinOps.h"
21#include "mlir/IR/TypeRange.h"
22
23using namespace mlir;
24
25//===----------------------------------------------------------------------===//
26// TableGen'erated dialect
27//===----------------------------------------------------------------------===//
28
29#include "mlir/IR/BuiltinDialect.cpp.inc"
30
31//===----------------------------------------------------------------------===//
32// BuiltinBlobManagerInterface
33//===----------------------------------------------------------------------===//
34
37
38//===----------------------------------------------------------------------===//
39// BuiltinOpAsmDialectInterface
40//===----------------------------------------------------------------------===//
41
42namespace {
43struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface {
44 BuiltinOpAsmDialectInterface(Dialect *dialect,
46 : OpAsmDialectInterface(dialect), blobManager(mgr) {}
47
48 AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
49 if (llvm::isa<LocationAttr>(attr)) {
50 os << "loc";
51 return AliasResult::OverridableAlias;
52 }
53 if (auto distinct = llvm::dyn_cast<DistinctAttr>(attr))
54 if (!llvm::isa<UnitAttr>(distinct.getReferencedAttr())) {
55 os << "distinct";
56 return AliasResult::OverridableAlias;
57 }
59 }
60
61 AliasResult getAlias(Type type, raw_ostream &os) const final {
62 if (auto tupleType = llvm::dyn_cast<TupleType>(type)) {
63 if (tupleType.size() > 16) {
64 os << "tuple";
65 return AliasResult::OverridableAlias;
66 }
67 }
69 }
70
71 //===------------------------------------------------------------------===//
72 // Resources
73 //===------------------------------------------------------------------===//
74
75 std::string
76 getResourceKey(const AsmDialectResourceHandle &handle) const override {
77 return cast<DenseResourceElementsHandle>(handle).getKey().str();
78 }
79 FailureOr<AsmDialectResourceHandle>
80 declareResource(StringRef key) const final {
81 return blobManager.insert(key);
82 }
83 LogicalResult parseResource(AsmParsedResourceEntry &entry) const final {
84 FailureOr<AsmResourceBlob> blob = entry.parseAsBlob();
85 if (failed(blob))
86 return failure();
87
88 // Update the blob for this entry.
89 blobManager.update(entry.getKey(), std::move(*blob));
90 return success();
91 }
92 void
93 buildResources(Operation *op,
94 const SetVector<AsmDialectResourceHandle> &referencedResources,
95 AsmResourceBuilder &provider) const final {
96 blobManager.buildResources(provider, referencedResources.getArrayRef());
97 }
98
99private:
100 /// The blob manager for the dialect.
101 BuiltinBlobManagerInterface &blobManager;
102};
103} // namespace
104
105void BuiltinDialect::initialize() {
107 registerTypes();
108 registerAttributes();
109 registerLocationAttributes();
110 addOperations<
111#define GET_OP_LIST
112#include "mlir/IR/BuiltinOps.cpp.inc"
113 >();
114
115 auto &blobInterface = addInterface<BuiltinBlobManagerInterface>();
116 addInterface<BuiltinOpAsmDialectInterface>(blobInterface);
118}
119
120//===----------------------------------------------------------------------===//
121// ModuleOp
122//===----------------------------------------------------------------------===//
123
124void ModuleOp::build(OpBuilder &builder, OperationState &state,
125 std::optional<StringRef> name) {
126 state.addRegion()->emplaceBlock();
127 if (name) {
128 state.attributes.push_back(builder.getNamedAttr(
129 getSymNameAttrName(state.name), builder.getStringAttr(*name)));
130 }
131}
132
133/// Construct a module from the given context.
134ModuleOp ModuleOp::create(Location loc, std::optional<StringRef> name) {
135 OpBuilder builder(loc->getContext());
136 return ModuleOp::create(builder, loc, name);
137}
138
139LogicalResult ModuleOp::readProperties(DialectBytecodeReader &reader,
140 OperationState &state) {
141 auto &properties = state.getOrAddProperties<Properties>();
142 if (failed(reader.readOptionalAttribute(properties.sym_name)) ||
143 failed(reader.readOptionalAttribute(properties.sym_visibility)))
144 return failure();
145
146 FailureOr<const DialectVersion *> maybeVersion =
147 reader.getDialectVersion<BuiltinDialect>();
148 if (failed(maybeVersion) ||
149 static_cast<const BuiltinDialectVersion *>(*maybeVersion)->getVersion() <
150 1)
151 return success();
152 return reader.readOptionalAttribute(properties.dlti);
153}
154
155void ModuleOp::writeProperties(DialectBytecodeWriter &writer) {
156 Properties &properties = getProperties();
157 writer.writeOptionalAttribute(properties.sym_name);
158 writer.writeOptionalAttribute(properties.sym_visibility);
159
160 FailureOr<const DialectVersion *> maybeVersion =
161 writer.getDialectVersion<BuiltinDialect>();
162 if (succeeded(maybeVersion) &&
163 static_cast<const BuiltinDialectVersion *>(*maybeVersion)->getVersion() <
164 1)
165 return;
166 writer.writeOptionalAttribute(properties.dlti);
167}
168
169DataLayoutSpecInterface ModuleOp::getDataLayoutSpec() {
170 // Take the first and only (if present) attribute that implements the
171 // interface. This needs a linear search, but is called only once per data
172 // layout object construction that is used for repeated queries.
173 for (NamedAttribute attr :
174 getOperation()->getDiscardableAttrDictionary().getValue())
175 if (auto spec = llvm::dyn_cast<DataLayoutSpecInterface>(attr.getValue()))
176 return spec;
177 return {};
178}
179
180TargetSystemSpecInterface ModuleOp::getTargetSystemSpec() {
181 // Take the first and only (if present) attribute that implements the
182 // interface. This needs a linear search, but is called only once per data
183 // layout object construction that is used for repeated queries.
184 for (NamedAttribute attr :
185 getOperation()->getDiscardableAttrDictionary().getValue())
186 if (auto spec = llvm::dyn_cast<TargetSystemSpecInterface>(attr.getValue()))
187 return spec;
188 return {};
189}
190
191LogicalResult ModuleOp::verify() {
192 // Check that none of the attributes are non-dialect attributes, except for
193 // the symbol related attributes.
194 for (auto attr : (*this)->getDiscardableAttrDictionary().getValue()) {
195 if (!attr.getName().strref().contains('.') &&
196 !llvm::is_contained(
197 ArrayRef<StringRef>{
198 getSymNameAttrName().getValue(),
199 mlir::SymbolOpInterface::getDefaultVisibilityAttrName()},
200 attr.getName().strref()))
201 return emitOpError() << "can only contain attributes with "
202 "dialect-prefixed names, found: '"
203 << attr.getName().getValue() << "'";
204 }
205
206 // Check that there is at most one data layout spec attribute.
207 StringRef layoutSpecAttrName;
208 DataLayoutSpecInterface layoutSpec;
209 for (const NamedAttribute &na :
210 (*this)->getDiscardableAttrDictionary().getValue()) {
211 if (auto spec = llvm::dyn_cast<DataLayoutSpecInterface>(na.getValue())) {
212 if (layoutSpec) {
213 InFlightDiagnostic diag =
214 emitOpError() << "expects at most one data layout attribute";
215 diag.attachNote() << "'" << layoutSpecAttrName
216 << "' is a data layout attribute";
217 diag.attachNote() << "'" << na.getName().getValue()
218 << "' is a data layout attribute";
219 }
220 layoutSpecAttrName = na.getName().strref();
221 layoutSpec = spec;
222 }
223 }
224
225 return success();
226}
227
228//===----------------------------------------------------------------------===//
229// UnrealizedConversionCastOp
230//===----------------------------------------------------------------------===//
231
232LogicalResult
233UnrealizedConversionCastOp::fold(FoldAdaptor adaptor,
234 SmallVectorImpl<OpFoldResult> &foldResults) {
235 OperandRange operands = getInputs();
236 ResultRange results = getOutputs();
237
238 if (operands.getType() == results.getType()) {
239 foldResults.append(operands.begin(), operands.end());
240 return success();
241 }
242
243 if (operands.empty())
244 return failure();
245
246 // Check that the input is a cast with results that all feed into this
247 // operation, and operand types that directly match the result types of this
248 // operation.
249 Value firstInput = operands.front();
250 auto inputOp = firstInput.getDefiningOp<UnrealizedConversionCastOp>();
251 if (!inputOp || inputOp.getResults() != operands ||
252 inputOp.getOperandTypes() != results.getTypes())
253 return failure();
254
255 // If everything matches up, we can fold the passthrough.
256 foldResults.append(inputOp->operand_begin(), inputOp->operand_end());
257 return success();
258}
259
260LogicalResult UnrealizedConversionCastOp::verify() {
261 // TODO: The verifier of external models is not called. This op verifier can
262 // be removed when that is fixed.
263 if (getNumResults() == 0)
264 return emitOpError() << "expected at least one result for cast operation";
265 return success();
266}
267
268//===----------------------------------------------------------------------===//
269// TableGen'd op method definitions
270//===----------------------------------------------------------------------===//
271
272#define GET_OP_CLASSES
273#include "mlir/IR/BuiltinOps.cpp.inc"
return success()
ResourceBlobManagerDialectInterfaceBase< DenseResourceElementsHandle > BuiltinBlobManagerInterface
The possible results of an alias query.
@ NoAlias
The two locations do not alias at all.
This class represents an opaque handle to a dialect resource entry.
This class represents a single parsed resource entry.
Definition AsmState.h:291
virtual FailureOr< AsmResourceBlob > parseAsBlob(BlobAllocatorFn allocator) const =0
Parse the resource entry represented by a binary blob.
virtual StringRef getKey() const =0
Return the key of the resource entry.
This class is used to build resource entries for use by the printer.
Definition AsmState.h:247
Attributes are known-constant values of operations.
Definition Attributes.h:25
MLIRContext * getContext() const
Return the context this attribute belongs to.
StringAttr getStringAttr(const Twine &bytes)
Definition Builders.cpp:271
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Definition Builders.cpp:102
This class defines a virtual interface for reading a bytecode stream, providing hooks into the byteco...
virtual FailureOr< const DialectVersion * > getDialectVersion(StringRef dialectName) const =0
Retrieve the dialect version by name if available.
virtual LogicalResult readOptionalAttribute(Attribute &attr)=0
Read an optional reference to the given attribute.
This class defines a virtual interface for writing to a bytecode stream, providing hooks into the byt...
virtual FailureOr< const DialectVersion * > getDialectVersion(StringRef dialectName) const =0
Retrieve the dialect version by name if available.
virtual void writeOptionalAttribute(Attribute attr)=0
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition Dialect.h:38
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
void push_back(NamedAttribute newAttribute)
Add an attribute with the specified name.
This class helps build Operations.
Definition Builders.h:210
This class implements the operand iterators for the Operation class.
Definition ValueRange.h:44
type_range getType() const
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
Block & emplaceBlock()
Definition Region.h:46
This class provides a base class for dialects implementing the resource blob interface.
This class implements the result iterators for the Operation class.
Definition ValueRange.h:248
type_range getTypes() const
type_range getType() const
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition Value.cpp:18
void addBytecodeInterface(BuiltinDialect *dialect)
Add the interfaces necessary for encoding the builtin dialect components in bytecode.
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:734
Include the generated interface declarations.
llvm::SetVector< T, Vector, Set, N > SetVector
Definition LLVM.h:128
static BuiltinDialectVersion getCurrentVersion()
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) the properties of the provided type to be set on the operation on creation.
Region * addRegion()
Create a region that should be attached to the operation.