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