MLIR  20.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 
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"
20 #include "mlir/IR/IRMapping.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 
39 
40 //===----------------------------------------------------------------------===//
41 // BuiltinOpAsmDialectInterface
42 //===----------------------------------------------------------------------===//
43 
44 namespace {
45 struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface {
46  BuiltinOpAsmDialectInterface(Dialect *dialect,
48  : OpAsmDialectInterface(dialect), blobManager(mgr) {}
49 
50  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 
71  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
86  getResourceKey(const AsmDialectResourceHandle &handle) const override {
87  return cast<DenseResourceElementsHandle>(handle).getKey().str();
88  }
89  FailureOr<AsmDialectResourceHandle>
90  declareResource(StringRef key) const final {
91  return blobManager.insert(key);
92  }
93  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
103  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 
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);
127 }
128 
129 //===----------------------------------------------------------------------===//
130 // ModuleOp
131 //===----------------------------------------------------------------------===//
132 
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(
139  }
140 }
141 
142 /// Construct a module from the given context.
143 ModuleOp ModuleOp::create(Location loc, std::optional<StringRef> name) {
144  OpBuilder builder(loc->getContext());
145  return builder.create<ModuleOp>(loc, name);
146 }
147 
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 
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 
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) {
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
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 
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"
static TargetSystemSpecInterface getTargetSystemSpec(Operation *operation)
static std::string diag(const llvm::Value &value)
The possible results of an alias query.
Definition: AliasAnalysis.h:26
@ NoAlias
The two locations do not alias at all.
Definition: AliasAnalysis.h:34
This class represents an opaque handle to a dialect resource entry.
This class represents a single parsed resource entry.
Definition: AsmState.h:290
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:246
Attributes are known-constant values of operations.
Definition: Attributes.h:25
MLIRContext * getContext() const
Return the context this attribute belongs to.
Definition: Attributes.cpp:37
StringAttr getStringAttr(const Twine &bytes)
Definition: Builders.cpp:302
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Definition: Builders.cpp:134
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:38
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:314
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:66
NamedAttribute represents a combination of a name and an Attribute value.
Definition: Attributes.h:207
This class helps build Operations.
Definition: Builders.h:215
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
Definition: Builders.cpp:497
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:42
type_range getType() const
Definition: ValueRange.cpp:30
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:88
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:242
type_range getTypes() const
Definition: ValueRange.cpp:35
type_range getType() const
Definition: ValueRange.cpp:39
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
Definition: SymbolTable.h:76
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:20
void addBytecodeInterface(BuiltinDialect *dialect)
Add the interfaces necessary for encoding the builtin dialect components in bytecode.
DataLayoutSpecInterface getDataLayoutSpec(Operation *op)
Definition: Traits.cpp:26
Include the generated interface declarations.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:426
This represents an operation in an abstracted form, suitable for use with the builder APIs.