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 "mlir/IR/BlockAndValueMapping.h"
16 #include "mlir/IR/Builders.h"
17 #include "mlir/IR/BuiltinOps.h"
18 #include "mlir/IR/BuiltinTypes.h"
19 #include "mlir/IR/OpImplementation.h"
20 #include "mlir/IR/PatternMatch.h"
21 #include "mlir/IR/TypeRange.h"
22
23 using namespace mlir;
24
25 //===----------------------------------------------------------------------===//
26 // Builtin Dialect
27 //===----------------------------------------------------------------------===//
28
29 #include "mlir/IR/BuiltinDialect.cpp.inc"
30
31 namespace {
32 struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface {
33 using OpAsmDialectInterface::OpAsmDialectInterface;
34
getAlias__anon9e1f13f00111::BuiltinOpAsmDialectInterface35 AliasResult getAlias(Attribute attr, raw_ostream &os) const override {
36 if (attr.isa<AffineMapAttr>()) {
37 os << "map";
38 return AliasResult::OverridableAlias;
39 }
40 if (attr.isa<IntegerSetAttr>()) {
41 os << "set";
42 return AliasResult::OverridableAlias;
43 }
44 if (attr.isa<LocationAttr>()) {
45 os << "loc";
46 return AliasResult::OverridableAlias;
47 }
48 return AliasResult::NoAlias;
49 }
50
getAlias__anon9e1f13f00111::BuiltinOpAsmDialectInterface51 AliasResult getAlias(Type type, raw_ostream &os) const final {
52 if (auto tupleType = type.dyn_cast<TupleType>()) {
53 if (tupleType.size() > 16) {
54 os << "tuple";
55 return AliasResult::OverridableAlias;
56 }
57 }
58 return AliasResult::NoAlias;
59 }
60 };
61 } // namespace
62
initialize()63 void BuiltinDialect::initialize() {
64 registerTypes();
65 registerAttributes();
66 registerLocationAttributes();
67 addOperations<
68 #define GET_OP_LIST
69 #include "mlir/IR/BuiltinOps.cpp.inc"
70 >();
71 addInterfaces<BuiltinOpAsmDialectInterface>();
72 }
73
74 //===----------------------------------------------------------------------===//
75 // ModuleOp
76 //===----------------------------------------------------------------------===//
77
build(OpBuilder & builder,OperationState & state,Optional<StringRef> name)78 void ModuleOp::build(OpBuilder &builder, OperationState &state,
79 Optional<StringRef> name) {
80 state.addRegion()->emplaceBlock();
81 if (name) {
82 state.attributes.push_back(builder.getNamedAttr(
83 mlir::SymbolTable::getSymbolAttrName(), builder.getStringAttr(*name)));
84 }
85 }
86
87 /// Construct a module from the given context.
create(Location loc,Optional<StringRef> name)88 ModuleOp ModuleOp::create(Location loc, Optional<StringRef> name) {
89 OpBuilder builder(loc->getContext());
90 return builder.create<ModuleOp>(loc, name);
91 }
92
getDataLayoutSpec()93 DataLayoutSpecInterface ModuleOp::getDataLayoutSpec() {
94 // Take the first and only (if present) attribute that implements the
95 // interface. This needs a linear search, but is called only once per data
96 // layout object construction that is used for repeated queries.
97 for (NamedAttribute attr : getOperation()->getAttrs())
98 if (auto spec = attr.getValue().dyn_cast<DataLayoutSpecInterface>())
99 return spec;
100 return {};
101 }
102
verify()103 LogicalResult ModuleOp::verify() {
104 // Check that none of the attributes are non-dialect attributes, except for
105 // the symbol related attributes.
106 for (auto attr : (*this)->getAttrs()) {
107 if (!attr.getName().strref().contains('.') &&
108 !llvm::is_contained(
109 ArrayRef<StringRef>{mlir::SymbolTable::getSymbolAttrName(),
110 mlir::SymbolTable::getVisibilityAttrName()},
111 attr.getName().strref()))
112 return emitOpError() << "can only contain attributes with "
113 "dialect-prefixed names, found: '"
114 << attr.getName().getValue() << "'";
115 }
116
117 // Check that there is at most one data layout spec attribute.
118 StringRef layoutSpecAttrName;
119 DataLayoutSpecInterface layoutSpec;
120 for (const NamedAttribute &na : (*this)->getAttrs()) {
121 if (auto spec = na.getValue().dyn_cast<DataLayoutSpecInterface>()) {
122 if (layoutSpec) {
123 InFlightDiagnostic diag =
124 emitOpError() << "expects at most one data layout attribute";
125 diag.attachNote() << "'" << layoutSpecAttrName
126 << "' is a data layout attribute";
127 diag.attachNote() << "'" << na.getName().getValue()
128 << "' is a data layout attribute";
129 }
130 layoutSpecAttrName = na.getName().strref();
131 layoutSpec = spec;
132 }
133 }
134
135 return success();
136 }
137
138 //===----------------------------------------------------------------------===//
139 // UnrealizedConversionCastOp
140 //===----------------------------------------------------------------------===//
141
142 LogicalResult
fold(ArrayRef<Attribute> attrOperands,SmallVectorImpl<OpFoldResult> & foldResults)143 UnrealizedConversionCastOp::fold(ArrayRef<Attribute> attrOperands,
144 SmallVectorImpl<OpFoldResult> &foldResults) {
145 OperandRange operands = getInputs();
146 ResultRange results = getOutputs();
147
148 if (operands.getType() == results.getType()) {
149 foldResults.append(operands.begin(), operands.end());
150 return success();
151 }
152
153 if (operands.empty())
154 return failure();
155
156 // Check that the input is a cast with results that all feed into this
157 // operation, and operand types that directly match the result types of this
158 // operation.
159 Value firstInput = operands.front();
160 auto inputOp = firstInput.getDefiningOp<UnrealizedConversionCastOp>();
161 if (!inputOp || inputOp.getResults() != operands ||
162 inputOp.getOperandTypes() != results.getTypes())
163 return failure();
164
165 // If everything matches up, we can fold the passthrough.
166 foldResults.append(inputOp->operand_begin(), inputOp->operand_end());
167 return success();
168 }
169
areCastCompatible(TypeRange inputs,TypeRange outputs)170 bool UnrealizedConversionCastOp::areCastCompatible(TypeRange inputs,
171 TypeRange outputs) {
172 // `UnrealizedConversionCastOp` is agnostic of the input/output types.
173 return true;
174 }
175
176 //===----------------------------------------------------------------------===//
177 // TableGen'd op method definitions
178 //===----------------------------------------------------------------------===//
179
180 #define GET_OP_CLASSES
181 #include "mlir/IR/BuiltinOps.cpp.inc"
182