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 35 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 51 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 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 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. 88 ModuleOp ModuleOp::create(Location loc, Optional<StringRef> name) { 89 OpBuilder builder(loc->getContext()); 90 return builder.create<ModuleOp>(loc, name); 91 } 92 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 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 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 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