xref: /llvm-project/mlir/lib/IR/BuiltinDialect.cpp (revision abd95342f0b94e140b36ac954b8f8c29b1393861)
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 
14 #include "mlir/IR/BuiltinDialect.h"
15 #include "BuiltinDialectBytecode.h"
16 #include "mlir/IR/Builders.h"
17 #include "mlir/IR/BuiltinOps.h"
18 #include "mlir/IR/BuiltinTypes.h"
19 #include "mlir/IR/DialectResourceBlobManager.h"
20 #include "mlir/IR/IRMapping.h"
21 #include "mlir/IR/OpImplementation.h"
22 #include "mlir/IR/PatternMatch.h"
23 #include "mlir/IR/TypeRange.h"
24 
25 using namespace mlir;
26 
27 //===----------------------------------------------------------------------===//
28 // TableGen'erated dialect
29 //===----------------------------------------------------------------------===//
30 
31 #include "mlir/IR/BuiltinDialect.cpp.inc"
32 
33 //===----------------------------------------------------------------------===//
34 // BuiltinBlobManagerInterface
35 //===----------------------------------------------------------------------===//
36 
37 using BuiltinBlobManagerInterface =
38     ResourceBlobManagerDialectInterfaceBase<DenseResourceElementsHandle>;
39 
40 //===----------------------------------------------------------------------===//
41 // BuiltinOpAsmDialectInterface
42 //===----------------------------------------------------------------------===//
43 
44 namespace {
45 struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface {
BuiltinOpAsmDialectInterface__anon246efb530111::BuiltinOpAsmDialectInterface46   BuiltinOpAsmDialectInterface(Dialect *dialect,
47                                BuiltinBlobManagerInterface &mgr)
48       : OpAsmDialectInterface(dialect), blobManager(mgr) {}
49 
getAlias__anon246efb530111::BuiltinOpAsmDialectInterface50   AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
51     if (llvm::isa<AffineMapAttr>(attr)) {
52       os << "map";
53       return AliasResult::OverridableAlias;
54     }
55     if (llvm::isa<IntegerSetAttr>(attr)) {
56       os << "set";
57       return AliasResult::OverridableAlias;
58     }
59     if (llvm::isa<LocationAttr>(attr)) {
60       os << "loc";
61       return AliasResult::OverridableAlias;
62     }
63     if (auto distinct = llvm::dyn_cast<DistinctAttr>(attr))
64       if (!llvm::isa<UnitAttr>(distinct.getReferencedAttr())) {
65         os << "distinct";
66         return AliasResult::OverridableAlias;
67       }
68     return AliasResult::NoAlias;
69   }
70 
getAlias__anon246efb530111::BuiltinOpAsmDialectInterface71   AliasResult getAlias(Type type, raw_ostream &os) const final {
72     if (auto tupleType = llvm::dyn_cast<TupleType>(type)) {
73       if (tupleType.size() > 16) {
74         os << "tuple";
75         return AliasResult::OverridableAlias;
76       }
77     }
78     return AliasResult::NoAlias;
79   }
80 
81   //===------------------------------------------------------------------===//
82   // Resources
83   //===------------------------------------------------------------------===//
84 
85   std::string
getResourceKey__anon246efb530111::BuiltinOpAsmDialectInterface86   getResourceKey(const AsmDialectResourceHandle &handle) const override {
87     return cast<DenseResourceElementsHandle>(handle).getKey().str();
88   }
89   FailureOr<AsmDialectResourceHandle>
declareResource__anon246efb530111::BuiltinOpAsmDialectInterface90   declareResource(StringRef key) const final {
91     return blobManager.insert(key);
92   }
parseResource__anon246efb530111::BuiltinOpAsmDialectInterface93   LogicalResult parseResource(AsmParsedResourceEntry &entry) const final {
94     FailureOr<AsmResourceBlob> blob = entry.parseAsBlob();
95     if (failed(blob))
96       return failure();
97 
98     // Update the blob for this entry.
99     blobManager.update(entry.getKey(), std::move(*blob));
100     return success();
101   }
102   void
buildResources__anon246efb530111::BuiltinOpAsmDialectInterface103   buildResources(Operation *op,
104                  const SetVector<AsmDialectResourceHandle> &referencedResources,
105                  AsmResourceBuilder &provider) const final {
106     blobManager.buildResources(provider, referencedResources.getArrayRef());
107   }
108 
109 private:
110   /// The blob manager for the dialect.
111   BuiltinBlobManagerInterface &blobManager;
112 };
113 } // namespace
114 
initialize()115 void BuiltinDialect::initialize() {
116   registerTypes();
117   registerAttributes();
118   registerLocationAttributes();
119   addOperations<
120 #define GET_OP_LIST
121 #include "mlir/IR/BuiltinOps.cpp.inc"
122       >();
123 
124   auto &blobInterface = addInterface<BuiltinBlobManagerInterface>();
125   addInterface<BuiltinOpAsmDialectInterface>(blobInterface);
126   builtin_dialect_detail::addBytecodeInterface(this);
127 }
128 
129 //===----------------------------------------------------------------------===//
130 // ModuleOp
131 //===----------------------------------------------------------------------===//
132 
build(OpBuilder & builder,OperationState & state,std::optional<StringRef> name)133 void ModuleOp::build(OpBuilder &builder, OperationState &state,
134                      std::optional<StringRef> name) {
135   state.addRegion()->emplaceBlock();
136   if (name) {
137     state.attributes.push_back(builder.getNamedAttr(
138         mlir::SymbolTable::getSymbolAttrName(), builder.getStringAttr(*name)));
139   }
140 }
141 
142 /// Construct a module from the given context.
create(Location loc,std::optional<StringRef> name)143 ModuleOp ModuleOp::create(Location loc, std::optional<StringRef> name) {
144   OpBuilder builder(loc->getContext());
145   return builder.create<ModuleOp>(loc, name);
146 }
147 
getDataLayoutSpec()148 DataLayoutSpecInterface ModuleOp::getDataLayoutSpec() {
149   // Take the first and only (if present) attribute that implements the
150   // interface. This needs a linear search, but is called only once per data
151   // layout object construction that is used for repeated queries.
152   for (NamedAttribute attr : getOperation()->getAttrs())
153     if (auto spec = llvm::dyn_cast<DataLayoutSpecInterface>(attr.getValue()))
154       return spec;
155   return {};
156 }
157 
getTargetSystemSpec()158 TargetSystemSpecInterface ModuleOp::getTargetSystemSpec() {
159   // Take the first and only (if present) attribute that implements the
160   // interface. This needs a linear search, but is called only once per data
161   // layout object construction that is used for repeated queries.
162   for (NamedAttribute attr : getOperation()->getAttrs())
163     if (auto spec = llvm::dyn_cast<TargetSystemSpecInterface>(attr.getValue()))
164       return spec;
165   return {};
166 }
167 
verify()168 LogicalResult ModuleOp::verify() {
169   // Check that none of the attributes are non-dialect attributes, except for
170   // the symbol related attributes.
171   for (auto attr : (*this)->getAttrs()) {
172     if (!attr.getName().strref().contains('.') &&
173         !llvm::is_contained(
174             ArrayRef<StringRef>{mlir::SymbolTable::getSymbolAttrName(),
175                                 mlir::SymbolTable::getVisibilityAttrName()},
176             attr.getName().strref()))
177       return emitOpError() << "can only contain attributes with "
178                               "dialect-prefixed names, found: '"
179                            << attr.getName().getValue() << "'";
180   }
181 
182   // Check that there is at most one data layout spec attribute.
183   StringRef layoutSpecAttrName;
184   DataLayoutSpecInterface layoutSpec;
185   for (const NamedAttribute &na : (*this)->getAttrs()) {
186     if (auto spec = llvm::dyn_cast<DataLayoutSpecInterface>(na.getValue())) {
187       if (layoutSpec) {
188         InFlightDiagnostic diag =
189             emitOpError() << "expects at most one data layout attribute";
190         diag.attachNote() << "'" << layoutSpecAttrName
191                           << "' is a data layout attribute";
192         diag.attachNote() << "'" << na.getName().getValue()
193                           << "' is a data layout attribute";
194       }
195       layoutSpecAttrName = na.getName().strref();
196       layoutSpec = spec;
197     }
198   }
199 
200   return success();
201 }
202 
203 //===----------------------------------------------------------------------===//
204 // UnrealizedConversionCastOp
205 //===----------------------------------------------------------------------===//
206 
207 LogicalResult
fold(FoldAdaptor adaptor,SmallVectorImpl<OpFoldResult> & foldResults)208 UnrealizedConversionCastOp::fold(FoldAdaptor adaptor,
209                                  SmallVectorImpl<OpFoldResult> &foldResults) {
210   OperandRange operands = getInputs();
211   ResultRange results = getOutputs();
212 
213   if (operands.getType() == results.getType()) {
214     foldResults.append(operands.begin(), operands.end());
215     return success();
216   }
217 
218   if (operands.empty())
219     return failure();
220 
221   // Check that the input is a cast with results that all feed into this
222   // operation, and operand types that directly match the result types of this
223   // operation.
224   Value firstInput = operands.front();
225   auto inputOp = firstInput.getDefiningOp<UnrealizedConversionCastOp>();
226   if (!inputOp || inputOp.getResults() != operands ||
227       inputOp.getOperandTypes() != results.getTypes())
228     return failure();
229 
230   // If everything matches up, we can fold the passthrough.
231   foldResults.append(inputOp->operand_begin(), inputOp->operand_end());
232   return success();
233 }
234 
verify()235 LogicalResult UnrealizedConversionCastOp::verify() {
236   // TODO: The verifier of external models is not called. This op verifier can
237   // be removed when that is fixed.
238   if (getNumResults() == 0)
239     return emitOpError() << "expected at least one result for cast operation";
240   return success();
241 }
242 
243 //===----------------------------------------------------------------------===//
244 // TableGen'd op method definitions
245 //===----------------------------------------------------------------------===//
246 
247 #define GET_OP_CLASSES
248 #include "mlir/IR/BuiltinOps.cpp.inc"
249