//===- BuiltinDialect.cpp - MLIR Builtin Dialect --------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains the Builtin dialect that contains all of the attributes, // operations, and types that are necessary for the validity of the IR. // //===----------------------------------------------------------------------===// #include "mlir/IR/BuiltinDialect.h" #include "mlir/IR/BlockAndValueMapping.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/PatternMatch.h" #include "mlir/IR/TypeRange.h" using namespace mlir; //===----------------------------------------------------------------------===// // Builtin Dialect //===----------------------------------------------------------------------===// #include "mlir/IR/BuiltinDialect.cpp.inc" namespace { struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface { using OpAsmDialectInterface::OpAsmDialectInterface; AliasResult getAlias(Attribute attr, raw_ostream &os) const override { if (attr.isa()) { os << "map"; return AliasResult::OverridableAlias; } if (attr.isa()) { os << "set"; return AliasResult::OverridableAlias; } if (attr.isa()) { os << "loc"; return AliasResult::OverridableAlias; } return AliasResult::NoAlias; } AliasResult getAlias(Type type, raw_ostream &os) const final { if (auto tupleType = type.dyn_cast()) { if (tupleType.size() > 16) { os << "tuple"; return AliasResult::OverridableAlias; } } return AliasResult::NoAlias; } }; } // namespace void BuiltinDialect::initialize() { registerTypes(); registerAttributes(); registerLocationAttributes(); addOperations< #define GET_OP_LIST #include "mlir/IR/BuiltinOps.cpp.inc" >(); addInterfaces(); } //===----------------------------------------------------------------------===// // ModuleOp //===----------------------------------------------------------------------===// void ModuleOp::build(OpBuilder &builder, OperationState &state, Optional name) { state.addRegion()->emplaceBlock(); if (name) { state.attributes.push_back(builder.getNamedAttr( mlir::SymbolTable::getSymbolAttrName(), builder.getStringAttr(*name))); } } /// Construct a module from the given context. ModuleOp ModuleOp::create(Location loc, Optional name) { OpBuilder builder(loc->getContext()); return builder.create(loc, name); } DataLayoutSpecInterface ModuleOp::getDataLayoutSpec() { // Take the first and only (if present) attribute that implements the // interface. This needs a linear search, but is called only once per data // layout object construction that is used for repeated queries. for (NamedAttribute attr : getOperation()->getAttrs()) if (auto spec = attr.getValue().dyn_cast()) return spec; return {}; } LogicalResult ModuleOp::verify() { // Check that none of the attributes are non-dialect attributes, except for // the symbol related attributes. for (auto attr : (*this)->getAttrs()) { if (!attr.getName().strref().contains('.') && !llvm::is_contained( ArrayRef{mlir::SymbolTable::getSymbolAttrName(), mlir::SymbolTable::getVisibilityAttrName()}, attr.getName().strref())) return emitOpError() << "can only contain attributes with " "dialect-prefixed names, found: '" << attr.getName().getValue() << "'"; } // Check that there is at most one data layout spec attribute. StringRef layoutSpecAttrName; DataLayoutSpecInterface layoutSpec; for (const NamedAttribute &na : (*this)->getAttrs()) { if (auto spec = na.getValue().dyn_cast()) { if (layoutSpec) { InFlightDiagnostic diag = emitOpError() << "expects at most one data layout attribute"; diag.attachNote() << "'" << layoutSpecAttrName << "' is a data layout attribute"; diag.attachNote() << "'" << na.getName().getValue() << "' is a data layout attribute"; } layoutSpecAttrName = na.getName().strref(); layoutSpec = spec; } } return success(); } //===----------------------------------------------------------------------===// // UnrealizedConversionCastOp //===----------------------------------------------------------------------===// LogicalResult UnrealizedConversionCastOp::fold(ArrayRef attrOperands, SmallVectorImpl &foldResults) { OperandRange operands = getInputs(); ResultRange results = getOutputs(); if (operands.getType() == results.getType()) { foldResults.append(operands.begin(), operands.end()); return success(); } if (operands.empty()) return failure(); // Check that the input is a cast with results that all feed into this // operation, and operand types that directly match the result types of this // operation. Value firstInput = operands.front(); auto inputOp = firstInput.getDefiningOp(); if (!inputOp || inputOp.getResults() != operands || inputOp.getOperandTypes() != results.getTypes()) return failure(); // If everything matches up, we can fold the passthrough. foldResults.append(inputOp->operand_begin(), inputOp->operand_end()); return success(); } bool UnrealizedConversionCastOp::areCastCompatible(TypeRange inputs, TypeRange outputs) { // `UnrealizedConversionCastOp` is agnostic of the input/output types. return true; } //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// #define GET_OP_CLASSES #include "mlir/IR/BuiltinOps.cpp.inc"