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