573 if (
auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
574 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
576 emitError(loc,
"expected an array attribute for a struct constant");
579 SmallVector<llvm::Constant *> structElements;
580 structElements.reserve(structType->getNumElements());
581 for (
auto [elemType, elemAttr] :
582 zip_equal(structType->elements(), arrayAttr)) {
583 llvm::Constant *element =
587 structElements.push_back(element);
589 return llvm::ConstantStruct::get(structType, structElements);
593 if (
auto intAttr = dyn_cast<IntegerAttr>(attr)) {
596 auto intTy = dyn_cast<IntegerType>(intAttr.getType());
598 if (intTy && (intTy.isUnsigned() || intTy.getWidth() == 1))
599 value = intAttr.getValue().zextOrTrunc(llvmType->getIntegerBitWidth());
601 value = intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth());
602 return llvm::ConstantInt::get(llvmType, value);
604 if (
auto floatAttr = dyn_cast<FloatAttr>(attr)) {
605 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
610 unsigned floatWidth = APFloat::getSizeInBits(sem);
611 if (llvmType->isIntegerTy(floatWidth))
612 return llvm::ConstantInt::get(llvmType,
613 floatAttr.getValue().bitcastToAPInt());
615 llvm::Type::getFloatingPointTy(llvmType->getContext(),
616 floatAttr.getValue().getSemantics())) {
617 emitError(loc,
"FloatAttr does not match expected type of the constant");
620 return llvm::ConstantFP::get(llvmType, floatAttr.getValue());
622 if (
auto symAttr = dyn_cast<FlatSymbolRefAttr>(attr)) {
623 StringRef name = symAttr.getValue();
624 if (llvm::Function *func = moduleTranslation.
lookupFunction(name))
625 return llvm::ConstantExpr::getBitCast(func, llvmType);
626 if (llvm::GlobalValue *global = moduleTranslation.
lookupGlobal(name))
627 return llvm::ConstantExpr::getBitCast(global, llvmType);
628 emitError(loc,
"unknown symbol reference '") << name <<
"' in constant";
631 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
632 llvm::Type *elementType;
633 uint64_t numElements;
634 bool isScalable =
false;
635 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
636 elementType = arrayTy->getElementType();
637 numElements = arrayTy->getNumElements();
638 }
else if (
auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
639 elementType = fVectorTy->getElementType();
640 numElements = fVectorTy->getNumElements();
641 }
else if (
auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
642 elementType = sVectorTy->getElementType();
643 numElements = sVectorTy->getMinNumElements();
646 llvm_unreachable(
"unrecognized constant vector type");
651 bool elementTypeSequential =
652 isa<llvm::ArrayType, llvm::VectorType>(elementType);
655 elementTypeSequential ? splatAttr
656 : splatAttr.getSplatValue<Attribute>(),
657 loc, moduleTranslation);
660 if (llvmType->isVectorTy())
661 return llvm::ConstantVector::getSplat(
662 llvm::ElementCount::get(numElements, isScalable), child);
663 if (llvmType->isArrayTy()) {
664 auto *arrayType = llvm::ArrayType::get(elementType, numElements);
665 if (child->isNullValue() && !elementType->isFPOrFPVectorTy()) {
666 return llvm::ConstantAggregateZero::get(arrayType);
668 if (llvm::ConstantDataSequential::isElementTypeCompatible(elementType)) {
669 if (isa<llvm::IntegerType>(elementType)) {
670 if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
671 if (ci->getBitWidth() == 8) {
672 SmallVector<int8_t> constants(numElements, ci->getZExtValue());
673 return llvm::ConstantDataArray::get(elementType->getContext(),
676 if (ci->getBitWidth() == 16) {
677 SmallVector<int16_t> constants(numElements, ci->getZExtValue());
678 return llvm::ConstantDataArray::get(elementType->getContext(),
681 if (ci->getBitWidth() == 32) {
682 SmallVector<int32_t> constants(numElements, ci->getZExtValue());
683 return llvm::ConstantDataArray::get(elementType->getContext(),
686 if (ci->getBitWidth() == 64) {
687 SmallVector<int64_t> constants(numElements, ci->getZExtValue());
688 return llvm::ConstantDataArray::get(elementType->getContext(),
693 if (elementType->isFloatingPointTy()) {
694 if (llvm::ConstantFP *cfp = dyn_cast<llvm::ConstantFP>(child)) {
695 APInt bitPattern = cfp->getValueAPF().bitcastToAPInt();
696 uint64_t value = bitPattern.getZExtValue();
699 if (bitPattern.getBitWidth() == 16) {
700 SmallVector<uint16_t> constants(numElements, value);
701 return llvm::ConstantDataArray::getFP(elementType, constants);
703 if (bitPattern.getBitWidth() == 32) {
704 SmallVector<uint32_t> constants(numElements, value);
705 return llvm::ConstantDataArray::getFP(elementType, constants);
707 if (bitPattern.getBitWidth() == 64) {
708 SmallVector<uint64_t> constants(numElements, value);
709 return llvm::ConstantDataArray::getFP(elementType, constants);
716 std::vector<llvm::Constant *> constants(numElements, child);
717 return llvm::ConstantArray::get(arrayType, constants);
722 if (llvm::Constant *
result =
724 llvmType, moduleTranslation)) {
728 if (
auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
734 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
735 assert(elementsAttr.getShapedType().hasStaticShape());
736 assert(!elementsAttr.getShapedType().getShape().empty() &&
737 "unexpected empty elements attribute shape");
739 SmallVector<llvm::Constant *, 8> constants;
740 constants.reserve(elementsAttr.getNumElements());
742 for (
auto n : elementsAttr.getValues<Attribute>()) {
745 if (!constants.back())
748 ArrayRef<llvm::Constant *> constantsRef = constants;
750 constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
751 assert(constantsRef.empty() &&
"did not consume all elemental constants");
755 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
756 return llvm::ConstantDataArray::get(moduleTranslation.
getLLVMContext(),
757 ArrayRef<char>{stringAttr.getValue()});
762 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
763 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
764 llvm::Type *elementType = arrayTy->getElementType();
765 Attribute previousElementAttr;
766 llvm::Constant *elementCst =
nullptr;
767 SmallVector<llvm::Constant *> constants;
768 constants.reserve(arrayTy->getNumElements());
769 for (Attribute elementAttr : arrayAttr) {
773 if (!previousElementAttr || previousElementAttr != elementAttr) {
774 previousElementAttr = elementAttr;
780 constants.push_back(elementCst);
782 return llvm::ConstantArray::get(arrayTy, constants);
786 emitError(loc,
"unsupported constant value");
790ModuleTranslation::ModuleTranslation(Operation *module,
791 std::unique_ptr<llvm::Module> llvmModule,
792 llvm::vfs::FileSystem *fs)
793 : mlirModule(module), llvmModule(std::move(llvmModule)),
795 std::make_unique<DebugTranslation>(module, *this->llvmModule)),
796 loopAnnotationTranslation(std::make_unique<LoopAnnotationTranslation>(
797 *this, *this->llvmModule)),
798 fileSystem(fs), typeTranslator(this->llvmModule->
getContext()),
801 "mlirModule should honor LLVM's module semantics.");
804ModuleTranslation::~ModuleTranslation() {
805 if (ompBuilder && !ompBuilder->isFinalized())
806 ompBuilder->finalize();
811 toProcess.push_back(®ion);
812 while (!toProcess.empty()) {
813 Region *current = toProcess.pop_back_val();
814 for (
Block &block : *current) {
815 blockMapping.erase(&block);
816 for (
Value arg : block.getArguments())
817 valueMapping.erase(arg);
819 for (
Value value : op.getResults())
820 valueMapping.erase(value);
821 if (op.hasSuccessors())
822 branchMapping.erase(&op);
823 if (isa<LLVM::GlobalOp>(op))
824 globalsMapping.erase(&op);
825 if (isa<LLVM::AliasOp>(op))
826 aliasesMapping.erase(&op);
827 if (isa<LLVM::IFuncOp>(op))
828 ifuncMapping.erase(&op);
829 if (isa<LLVM::CallOp>(op))
830 callMapping.erase(&op);
833 llvm::map_range(op.getRegions(), [](
Region &r) { return &r; }));
842 unsigned numArguments,
unsigned index) {
844 if (isa<LLVM::BrOp>(terminator))
851 auto branch = cast<BranchOpInterface>(terminator);
854 (!seenSuccessors.contains(successor) || successorOperands.
empty()) &&
855 "successors with arguments in LLVM branches must be different blocks");
856 seenSuccessors.insert(successor);
862 if (
auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
865 return condBranchOp.getSuccessor(0) == current
866 ? condBranchOp.getTrueDestOperands()[
index]
867 : condBranchOp.getFalseDestOperands()[
index];
870 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
873 if (switchOp.getDefaultDestination() == current)
874 return switchOp.getDefaultOperands()[
index];
875 for (
const auto &i : llvm::enumerate(switchOp.getCaseDestinations()))
876 if (i.value() == current)
877 return switchOp.getCaseOperands(i.index())[
index];
880 if (
auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(terminator)) {
882 for (
const auto &i : llvm::enumerate(indBrOp->getSuccessors())) {
883 if (indBrOp->getSuccessor(i.index()) == current)
884 return indBrOp.getSuccessorOperands(i.index())[
index];
888 if (
auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
889 return invokeOp.getNormalDest() == current
890 ? invokeOp.getNormalDestOperands()[
index]
891 : invokeOp.getUnwindDestOperands()[
index];
895 "only branch, switch or invoke operations can be terminators "
896 "of a block that has successors");
904 for (
Block &bb : llvm::drop_begin(region)) {
906 auto phis = llvmBB->phis();
907 auto numArguments = bb.getNumArguments();
908 assert(numArguments == std::distance(phis.begin(), phis.end()));
909 for (
auto [
index, phiNode] : llvm::enumerate(phis)) {
910 for (
auto *pred : bb.getPredecessors()) {
916 llvm::Instruction *terminator =
918 assert(terminator &&
"missing the mapping for a terminator");
920 &bb, pred, numArguments,
index)),
921 terminator->getParent());
928 llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic,
930 return builder.CreateIntrinsicWithoutFolding(intrinsic, tys, args);
934 llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic,
936 return builder.CreateIntrinsicWithoutFolding(retTy, intrinsic, args);
941 Operation *intrOp, llvm::Intrinsic::ID intrinsic,
unsigned numResults,
945 assert(immArgPositions.size() == immArgAttrNames.size() &&
946 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
950 size_t numOpBundleOperands = 0;
951 auto opBundleSizesAttr = cast_if_present<DenseI32ArrayAttr>(
952 intrOp->
getAttr(LLVMDialect::getOpBundleSizesAttrName()));
953 auto opBundleTagsAttr = cast_if_present<ArrayAttr>(
954 intrOp->
getAttr(LLVMDialect::getOpBundleTagsAttrName()));
956 if (opBundleSizesAttr && opBundleTagsAttr) {
957 ArrayRef<int> opBundleSizes = opBundleSizesAttr.asArrayRef();
958 assert(opBundleSizes.size() == opBundleTagsAttr.size() &&
959 "operand bundles and tags do not match");
961 numOpBundleOperands = llvm::sum_of(opBundleSizes);
962 assert(numOpBundleOperands <= intrOp->getNumOperands() &&
963 "operand bundle operands is more than the number of operands");
966 size_t nextOperandIdx = 0;
967 opBundles.reserve(opBundleSizesAttr.size());
969 for (
auto [opBundleTagAttr, bundleSize] :
970 llvm::zip(opBundleTagsAttr, opBundleSizes)) {
971 auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
973 operands.slice(nextOperandIdx, bundleSize));
974 opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
975 nextOperandIdx += bundleSize;
980 auto opOperands = intrOp->
getOperands().drop_back(numOpBundleOperands);
981 auto operands = moduleTranslation.
lookupValues(opOperands);
983 for (
auto [immArgPos, immArgName] :
984 llvm::zip(immArgPositions, immArgAttrNames)) {
986 if (
auto intrinsicIntegerAttr =
987 dyn_cast<LLVM::IntrinsicIntegerAttrInterface>(attr))
988 attr = intrinsicIntegerAttr.getIntegerAttr();
989 auto typedAttr = llvm::cast<TypedAttr>(attr);
990 assert(typedAttr.getType().isIntOrFloat() &&
991 "expected int or float immarg");
992 auto *type = moduleTranslation.
convertType(typedAttr.getType());
994 type, typedAttr, intrOp->
getLoc(), moduleTranslation);
997 for (
auto &arg : args) {
999 arg = operands[opArg++];
1004 for (
unsigned overloadedResultIdx : overloadedResults) {
1005 if (numResults > 1) {
1007 overloadedTypes.push_back(moduleTranslation.
convertType(
1009 .getBody()[overloadedResultIdx]));
1011 overloadedTypes.push_back(
1015 for (
unsigned overloadedOperandIdx : overloadedOperands)
1016 overloadedTypes.push_back(args[overloadedOperandIdx]->
getType());
1017 llvm::Module *module = builder.GetInsertBlock()->getModule();
1018 llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
1019 module, intrinsic, overloadedTypes);
1021 return builder.CreateCall(llvmIntr, args, opBundles);
1026LogicalResult ModuleTranslation::convertOperationImpl(
1027 Operation &op, llvm::IRBuilderBase &builder,
bool recordInsertions) {
1028 const LLVMTranslationDialectInterface *opIface = iface.
getInterfaceFor(&op);
1030 return op.
emitError(
"cannot be converted to LLVM IR: missing "
1031 "`LLVMTranslationDialectInterface` registration for "
1035 InstructionCapturingInserter::CollectionScope scope(builder,
1037 if (failed(opIface->convertOperation(&op, builder, *
this)))
1038 return op.
emitError(
"LLVM Translation failed for operation: ")
1041 return convertDialectAttributes(&op, scope.getCapturedInstructions());
1051LogicalResult ModuleTranslation::convertBlockImpl(
Block &bb,
1052 bool ignoreArguments,
1053 llvm::IRBuilderBase &builder,
1054 bool recordInsertions) {
1056 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
1064 if (!ignoreArguments) {
1066 unsigned numPredecessors =
1067 std::distance(predecessors.begin(), predecessors.end());
1069 auto wrappedType = arg.getType();
1072 "block argument does not have an LLVM type");
1073 builder.SetCurrentDebugLocation(
1074 debugTranslation->translateLoc(arg.getLoc(), subprogram));
1076 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
1082 for (
auto &op : bb) {
1084 builder.SetCurrentDebugLocation(
1085 debugTranslation->translateLoc(op.
getLoc(), subprogram));
1087 if (
failed(convertOperationImpl(op, builder, recordInsertions)))
1091 if (
auto iface = dyn_cast<WeightedBranchOpInterface>(op))
1101 return module->getRegion(0).front();
1110 llvm::Constant *cst) {
1111 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1112 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1118 llvm::GlobalValue *gv) {
1119 if (dsoLocalRequested)
1120 gv->setDSOLocal(
true);
1129static FailureOr<llvm::Attribute>
1131 StringRef value = StringRef()) {
1132 auto kind = llvm::Attribute::getAttrKindFromName(key);
1133 if (kind == llvm::Attribute::None)
1134 return llvm::Attribute::get(ctx, key, value);
1136 if (llvm::Attribute::isIntAttrKind(kind)) {
1138 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1141 if (!value.getAsInteger(0,
result))
1142 return llvm::Attribute::get(ctx, kind,
result);
1143 return llvm::Attribute::get(ctx, key, value);
1147 return emitError(loc) <<
"LLVM attribute '" << key
1148 <<
"' does not expect a value, found '" << value
1151 return llvm::Attribute::get(ctx, kind);
1162static FailureOr<llvm::AttrBuilder>
1164 ArrayAttr arrayAttr, StringRef arrayAttrName) {
1165 llvm::AttrBuilder attrBuilder(ctx);
1170 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1171 FailureOr<llvm::Attribute> llvmAttr =
1173 if (failed(llvmAttr))
1175 attrBuilder.addAttribute(*llvmAttr);
1179 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1180 if (!arrayAttr || arrayAttr.size() != 2)
1181 return emitError(loc) <<
"expected '" << arrayAttrName
1182 <<
"' to contain string or array attributes";
1184 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1185 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1186 if (!keyAttr || !valueAttr)
1187 return emitError(loc) <<
"expected arrays within '" << arrayAttrName
1188 <<
"' to contain two strings";
1191 loc, ctx, keyAttr.getValue(), valueAttr.getValue());
1192 if (failed(llvmAttr))
1194 attrBuilder.addAttribute(*llvmAttr);
1200LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
1211 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1213 llvm::Constant *cst =
nullptr;
1214 const bool deferValueAttrToPass2 = op.getValueOrNull() &&
1215 !op.getInitializerBlock() &&
1216 !isa<StringAttr>(op.getValueOrNull());
1217 if (op.getValueOrNull() && !deferValueAttrToPass2) {
1220 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1221 cst = llvm::ConstantDataArray::getString(
1222 llvmModule->getContext(), strAttr.getValue(),
false);
1223 type = cst->getType();
1227 auto linkage = convertLinkageToLLVM(op.getLinkage());
1233 if (!deferValueAttrToPass2) {
1234 if (!dropInitializer && !cst)
1235 cst = llvm::UndefValue::get(type);
1236 else if (dropInitializer && cst)
1242 auto *var =
new llvm::GlobalVariable(
1243 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1245 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1246 : llvm::GlobalValue::NotThreadLocal,
1247 op.getAddrSpace(), op.getExternallyInitialized());
1249 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1250 auto selectorOp = cast<ComdatSelectorOp>(
1252 var->setComdat(comdatMapping.lookup(selectorOp));
1255 if (op.getUnnamedAddr().has_value())
1256 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1258 if (op.getSection().has_value())
1259 var->setSection(*op.getSection());
1263 std::optional<uint64_t> alignment = op.getAlignment();
1264 if (alignment.has_value())
1265 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1267 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1269 globalsMapping.try_emplace(op, var);
1270 globalsByNameMapping.try_emplace(op.getSymName(), var);
1273 if (op.getDbgExprs()) {
1274 for (
auto exprAttr :
1275 op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1276 llvm::DIGlobalVariableExpression *diGlobalExpr =
1277 debugTranslation->translateGlobalVariableExpression(exprAttr);
1278 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1279 var->addDebugInfo(diGlobalExpr);
1298 llvm::DIScope *scope = diGlobalVar->getScope();
1299 if (
auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1300 scope = mod->getScope();
1301 else if (
auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1303 dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1304 scope = sp->getUnit();
1305 }
else if (
auto *lbb =
1306 dyn_cast_if_present<llvm::DILexicalBlockBase>(scope)) {
1307 scope = lbb->getSubprogram();
1312 if (llvm::DICompileUnit *compileUnit =
1313 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1316 globalGVars[compileUnit].push_back(diGlobalExpr);
1317 }
else if (llvm::DISubprogram *sp =
1318 dyn_cast_if_present<llvm::DISubprogram>(scope)) {
1321 staticLocals[sp].push_back(diGlobalExpr);
1327 FailureOr<llvm::AttrBuilder> convertedTargetSpecificAttrs =
1329 op.getTargetSpecificAttrsAttr(),
1330 op.getTargetSpecificAttrsAttrName());
1331 if (
failed(convertedTargetSpecificAttrs))
1333 var->addAttributes(*convertedTargetSpecificAttrs);
1338 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1339 if (!op.getValueOrNull() || op.getInitializerBlock() ||
1340 isa<StringAttr>(op.getValueOrNull()))
1344 llvm::Constant *cst =
1349 auto linkage = convertLinkageToLLVM(op.getLinkage());
1351 auto *var = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1352 if (dropInitializer)
1353 var->setInitializer(
nullptr);
1355 var->setInitializer(cst);
1359 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1361 llvm::Constant *cst =
nullptr;
1362 llvm::GlobalValue::LinkageTypes linkage =
1363 convertLinkageToLLVM(op.getLinkage());
1364 llvm::Module &llvmMod = *llvmModule;
1367 llvm::GlobalAlias *var = llvm::GlobalAlias::create(
1368 type, op.getAddrSpace(), linkage, op.getSymName(), cst,
1371 var->setThreadLocalMode(op.getThreadLocal_()
1372 ? llvm::GlobalAlias::GeneralDynamicTLSModel
1373 : llvm::GlobalAlias::NotThreadLocal);
1378 if (op.getUnnamedAddr().has_value())
1379 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1381 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1383 aliasesMapping.try_emplace(op, var);
1387 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1388 if (
Block *initializer = op.getInitializerBlock()) {
1389 llvm::IRBuilder<llvm::TargetFolder> builder(
1390 llvmModule->getContext(),
1391 llvm::TargetFolder(llvmModule->getDataLayout()));
1393 [[maybe_unused]]
int numConstantsHit = 0;
1394 [[maybe_unused]]
int numConstantsErased = 0;
1397 for (
auto &op : initializer->without_terminator()) {
1411 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1414 int numUsers = std::distance(
result.use_begin(),
result.use_end());
1416 constantAggregateUseMap.try_emplace(agg, numUsers);
1419 iterator->second += numUsers;
1425 auto *cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1428 auto iter = constantAggregateUseMap.find(cst);
1429 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1431 if (iter->second == 0) {
1434 if (cst->user_empty()) {
1435 cst->destroyConstant();
1436 numConstantsErased++;
1438 constantAggregateUseMap.erase(iter);
1443 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1444 llvm::Constant *cst =
1445 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1446 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1448 global->setInitializer(cst);
1452 for (
auto it : constantAggregateUseMap) {
1453 auto *cst = it.first;
1454 cst->removeDeadConstantUsers();
1455 if (cst->user_empty()) {
1456 cst->destroyConstant();
1457 numConstantsErased++;
1461 LLVM_DEBUG(llvm::dbgs()
1462 <<
"Convert initializer for " << op.
getName() <<
"\n";
1463 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1465 << numConstantsErased <<
" dangling constants erased\n";);
1471 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1472 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1473 if (!ctorOp && !dtorOp)
1479 if ((ctorOp && ctorOp.getCtors().empty()) ||
1480 (dtorOp && dtorOp.getDtors().empty())) {
1481 llvm::IRBuilder<llvm::TargetFolder> builder(
1482 llvmModule->getContext(),
1483 llvm::TargetFolder(llvmModule->getDataLayout()));
1484 llvm::Type *eltTy = llvm::StructType::get(
1485 builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1486 llvm::ArrayType *at = llvm::ArrayType::get(eltTy, 0);
1487 llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1488 (void)
new llvm::GlobalVariable(
1489 *llvmModule, zeroInit->getType(),
false,
1490 llvm::GlobalValue::AppendingLinkage, zeroInit,
1491 ctorOp ?
"llvm.global_ctors" :
"llvm.global_dtors");
1494 ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1495 : llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1496 auto appendGlobalFn =
1497 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1498 for (
const auto &[sym, prio] : range) {
1501 appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1507 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1508 if (
failed(convertDialectAttributes(op, {})))
1513 for (
const auto &[compileUnit, globals] : globalGVars)
1514 compileUnit->replaceGlobalVariables(
1519 for (
const auto &[sp, globals] : staticLocals)
1520 sp->retainNodes(globals.begin(), globals.end());
1523 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1524 Block &initializer = op.getInitializerBlock();
1525 llvm::IRBuilder<llvm::TargetFolder> builder(
1526 llvmModule->getContext(),
1527 llvm::TargetFolder(llvmModule->getDataLayout()));
1537 auto *cst = cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1538 assert(aliasesMapping.count(op));
1539 auto *alias = cast<llvm::GlobalAlias>(aliasesMapping[op]);
1540 alias->setAliasee(cst);
1543 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>())
1544 if (
failed(convertDialectAttributes(op, {})))
1552 const llvm::APInt &value) {
1553 llvm::Constant *constant = llvm::ConstantInt::get(context, value);
1554 return llvm::ConstantAsMetadata::get(constant);
1559 const llvm::APInt &value) {
1567 llvm::Metadata *typeMD =
1568 llvm::ConstantAsMetadata::get(llvm::UndefValue::get(type));
1569 llvm::Metadata *isSignedMD =
1571 return llvm::MDNode::get(context, {typeMD, isSignedMD});
1579 values, std::back_inserter(mdValues), [&context](int32_t value) {
1582 return llvm::MDNode::get(context, mdValues);
1590 .Case([&](MDStringAttr a) -> FailureOr<llvm::Metadata *> {
1591 return llvm::MDString::get(llvmContext, a.getValue().getValue());
1593 .Case([&](MDConstantAttr a) -> FailureOr<llvm::Metadata *> {
1594 IntegerAttr intAttr = llvm::dyn_cast<IntegerAttr>(a.getValue());
1597 <<
"expected integer attribute in metadata constant";
1599 return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
1600 llvm::Type::getIntNTy(llvmContext,
1601 intAttr.getType().getIntOrFloatBitWidth()),
1602 intAttr.getValue()));
1604 .Case([&](MDGlobalValueAttr a) -> FailureOr<llvm::Metadata *> {
1606 return llvm::ValueAsMetadata::get(fn);
1607 if (llvm::GlobalValue *global =
lookupGlobal(a.getName().getValue()))
1608 return llvm::ValueAsMetadata::get(global);
1611 if (
auto alias = dyn_cast_if_present<LLVM::AliasOp>(symbol)) {
1612 if (llvm::GlobalValue *global =
lookupAlias(alias))
1613 return llvm::ValueAsMetadata::get(global);
1615 if (
auto ifunc = dyn_cast_if_present<LLVM::IFuncOp>(symbol)) {
1616 if (llvm::GlobalValue *global =
lookupIFunc(ifunc))
1617 return llvm::ValueAsMetadata::get(global);
1619 return emitError() <<
"could not resolve metadata reference '"
1620 << a.getName() <<
"'";
1622 .Case([&](MDNodeAttr a) -> FailureOr<llvm::Metadata *> {
1624 for (
Attribute operand : a.getOperands()) {
1625 FailureOr<llvm::Metadata *> md =
1629 operands.push_back(*md);
1631 return llvm::MDNode::get(llvmContext, operands);
1633 .Default([&](
Attribute attr) -> FailureOr<llvm::Metadata *> {
1634 return emitError() <<
"unsupported LLVM metadata attribute " << attr;
1638LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp
func) {
1641 blockMapping.clear();
1642 valueMapping.clear();
1643 branchMapping.clear();
1645 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1648 for (
auto [mlirArg, llvmArg] :
1649 llvm::zip(
func.getArguments(), llvmFunc->args()))
1653 if (
func.getPersonality()) {
1654 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1656 func.getLoc(), *
this))
1657 llvmFunc->setPersonalityFn(pfunc);
1660 if (std::optional<StringRef> section =
func.getSection())
1661 llvmFunc->setSection(*section);
1663 if (
func.getArmStreaming())
1664 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1665 else if (
func.getArmLocallyStreaming())
1666 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1667 else if (
func.getArmStreamingCompatible())
1668 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1670 if (
func.getArmNewZa())
1671 llvmFunc->addFnAttr(
"aarch64_new_za");
1672 else if (
func.getArmInZa())
1673 llvmFunc->addFnAttr(
"aarch64_in_za");
1674 else if (
func.getArmOutZa())
1675 llvmFunc->addFnAttr(
"aarch64_out_za");
1676 else if (
func.getArmInoutZa())
1677 llvmFunc->addFnAttr(
"aarch64_inout_za");
1678 else if (
func.getArmPreservesZa())
1679 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1681 if (
auto targetCpu =
func.getTargetCpu())
1682 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1684 if (
auto tuneCpu =
func.getTuneCpu())
1685 llvmFunc->addFnAttr(
"tune-cpu", *tuneCpu);
1687 if (
auto reciprocalEstimates =
func.getReciprocalEstimates())
1688 llvmFunc->addFnAttr(
"reciprocal-estimates", *reciprocalEstimates);
1690 if (
auto preferVectorWidth =
func.getPreferVectorWidth())
1691 llvmFunc->addFnAttr(
"prefer-vector-width", *preferVectorWidth);
1693 if (
func.getUseSampleProfile())
1694 llvmFunc->addFnAttr(
"use-sample-profile");
1696 if (
auto attr =
func.getVscaleRange())
1697 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1699 attr->getMaxRange().getInt()));
1701 if (
auto noSignedZerosFpMath =
func.getNoSignedZerosFpMath())
1702 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1703 llvm::toStringRef(*noSignedZerosFpMath));
1705 if (
auto fpContract =
func.getFpContract())
1706 llvmFunc->addFnAttr(
"fp-contract", *fpContract);
1708 if (
auto instrumentFunctionEntry =
func.getInstrumentFunctionEntry())
1709 llvmFunc->addFnAttr(
"instrument-function-entry", *instrumentFunctionEntry);
1711 if (
auto instrumentFunctionExit =
func.getInstrumentFunctionExit())
1712 llvmFunc->addFnAttr(
"instrument-function-exit", *instrumentFunctionExit);
1715 for (
auto &bb :
func) {
1716 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1717 llvmBB->insertInto(llvmFunc);
1724 for (
Block *bb : blocks) {
1725 CapturingIRBuilder builder(llvmContext,
1726 llvm::TargetFolder(llvmModule->getDataLayout()));
1727 if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1737 return convertDialectAttributes(func, {});
1740LogicalResult ModuleTranslation::convertDialectAttributes(
1741 Operation *op, ArrayRef<llvm::Instruction *> instructions) {
1743 if (
failed(iface.amendOperation(op, instructions, attribute, *
this)))
1751 llvm::Function *llvmFunc) {
1752 if (!
func.getMemoryEffects())
1755 MemoryEffectsAttr memEffects =
func.getMemoryEffectsAttr();
1758 llvm::MemoryEffects newMemEffects =
1759 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1760 convertModRefInfoToLLVM(memEffects.getArgMem()));
1761 newMemEffects |= llvm::MemoryEffects(
1762 llvm::MemoryEffects::Location::InaccessibleMem,
1763 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1765 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1766 convertModRefInfoToLLVM(memEffects.getOther()));
1768 llvm::MemoryEffects(llvm::MemoryEffects::Location::ErrnoMem,
1769 convertModRefInfoToLLVM(memEffects.getErrnoMem()));
1771 llvm::MemoryEffects(llvm::MemoryEffects::Location::TargetMem0,
1772 convertModRefInfoToLLVM(memEffects.getTargetMem0()));
1774 llvm::MemoryEffects(llvm::MemoryEffects::Location::TargetMem1,
1775 convertModRefInfoToLLVM(memEffects.getTargetMem1()));
1776 llvmFunc->setMemoryEffects(newMemEffects);
1781 if (!allocSizeAttr || allocSizeAttr.empty())
1782 return llvm::Attribute{};
1784 unsigned elemSize =
static_cast<unsigned>(allocSizeAttr[0]);
1785 std::optional<unsigned> numElems;
1786 if (allocSizeAttr.size() > 1)
1787 numElems =
static_cast<unsigned>(allocSizeAttr[1]);
1789 return llvm::Attribute::getWithAllocSizeArgs(
getLLVMContext(), elemSize,
1793 llvm::AttrBuilder &Attrs) {
1794 std::optional<DenormalFPEnvAttr> denormalFpEnv =
func.getDenormalFpenv();
1798 llvm::DenormalMode DefaultMode(
1799 convertDenormalModeKindToLLVM(denormalFpEnv->getDefaultOutputMode()),
1800 convertDenormalModeKindToLLVM(denormalFpEnv->getDefaultInputMode()));
1801 llvm::DenormalMode FloatMode(
1802 convertDenormalModeKindToLLVM(denormalFpEnv->getFloatOutputMode()),
1803 convertDenormalModeKindToLLVM(denormalFpEnv->getFloatInputMode()));
1805 llvm::DenormalFPEnv FPEnv(DefaultMode, FloatMode);
1806 Attrs.addDenormalFPEnvAttr(FPEnv);
1811 llvm::Function *llvmFunc) {
1813 llvm::AttrBuilder AttrBuilder(llvmFunc->getContext());
1815 if (
func.getNoInlineAttr())
1816 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1817 if (
func.getAlwaysInlineAttr())
1818 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1819 if (
func.getInlineHintAttr())
1820 llvmFunc->addFnAttr(llvm::Attribute::InlineHint);
1821 if (
func.getOptimizeNoneAttr())
1822 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1823 if (
func.getReturnsTwiceAttr())
1824 llvmFunc->addFnAttr(llvm::Attribute::ReturnsTwice);
1825 if (
func.getColdAttr())
1826 llvmFunc->addFnAttr(llvm::Attribute::Cold);
1827 if (
func.getHotAttr())
1828 llvmFunc->addFnAttr(llvm::Attribute::Hot);
1829 if (
func.getNoduplicateAttr())
1830 llvmFunc->addFnAttr(llvm::Attribute::NoDuplicate);
1831 if (
func.getConvergentAttr())
1832 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1833 if (
func.getNoUnwindAttr())
1834 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1835 if (
func.getWillReturnAttr())
1836 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1837 if (
func.getNoreturnAttr())
1838 llvmFunc->addFnAttr(llvm::Attribute::NoReturn);
1839 if (
func.getOptsizeAttr())
1840 llvmFunc->addFnAttr(llvm::Attribute::OptimizeForSize);
1841 if (
func.getMinsizeAttr())
1842 llvmFunc->addFnAttr(llvm::Attribute::MinSize);
1843 if (
func.getSaveRegParamsAttr())
1844 llvmFunc->addFnAttr(
"save-reg-params");
1845 if (
func.getNoCallerSavedRegistersAttr())
1846 llvmFunc->addFnAttr(
"no_caller_saved_registers");
1847 if (
func.getNocallbackAttr())
1848 llvmFunc->addFnAttr(llvm::Attribute::NoCallback);
1849 if (StringAttr modFormat =
func.getModularFormatAttr())
1850 llvmFunc->addFnAttr(
"modular-format", modFormat.getValue());
1851 if (TargetFeaturesAttr targetFeatAttr =
func.getTargetFeaturesAttr())
1852 llvmFunc->addFnAttr(
"target-features", targetFeatAttr.getFeaturesString());
1853 if (FramePointerKindAttr fpAttr =
func.getFramePointerAttr())
1854 llvmFunc->addFnAttr(
"frame-pointer", stringifyFramePointerKind(
1855 fpAttr.getFramePointerKind()));
1856 if (UWTableKindAttr uwTableKindAttr =
func.getUwtableKindAttr())
1857 llvmFunc->setUWTableKind(
1858 convertUWTableKindToLLVM(uwTableKindAttr.getUwtableKind()));
1859 if (StringAttr zcsr =
func.getZeroCallUsedRegsAttr())
1860 llvmFunc->addFnAttr(
"zero-call-used-regs", zcsr.getValue());
1863 if (noBuiltins.empty())
1864 llvmFunc->addFnAttr(
"no-builtins");
1875 llvmFunc->addFnAttr(attr);
1880 llvmFunc->addFnAttrs(AttrBuilder);
1885 llvm::Function *llvmFunc,
1887 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1889 if (VecTypeHintAttr vecTypeHint =
func.getVecTypeHintAttr()) {
1890 Type type = vecTypeHint.getHint().getValue();
1891 llvm::Type *llvmType = translation.
convertType(type);
1892 bool isSigned = vecTypeHint.getIsSigned();
1893 llvmFunc->setMetadata(
1894 func.getVecTypeHintAttrName(),
1899 func.getWorkGroupSizeHint()) {
1900 llvmFunc->setMetadata(
1901 func.getWorkGroupSizeHintAttrName(),
1906 func.getReqdWorkGroupSize()) {
1907 llvmFunc->setMetadata(
1908 func.getReqdWorkGroupSizeAttrName(),
1912 if (std::optional<uint32_t> intelReqdSubGroupSize =
1913 func.getIntelReqdSubGroupSize()) {
1914 llvmFunc->setMetadata(
1915 func.getIntelReqdSubGroupSizeAttrName(),
1917 llvm::APInt(32, *intelReqdSubGroupSize)));
1922 llvm::Attribute::AttrKind llvmKind,
1927 .Case([&](TypeAttr typeAttr) {
1928 attrBuilder.addTypeAttr(
1929 llvmKind, moduleTranslation.
convertType(typeAttr.getValue()));
1932 .Case([&](IntegerAttr intAttr) {
1933 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1936 .Case([&](UnitAttr) {
1937 attrBuilder.addAttribute(llvmKind);
1940 .Case([&](LLVM::ConstantRangeAttr rangeAttr) {
1941 attrBuilder.addConstantRangeAttr(
1943 llvm::ConstantRange(rangeAttr.getLower(), rangeAttr.getUpper()));
1946 .Default([loc](
auto) {
1947 return emitError(loc,
"unsupported parameter attribute type");
1951FailureOr<llvm::AttrBuilder>
1952ModuleTranslation::convertParameterAttrs(LLVMFuncOp func,
int argIdx,
1953 DictionaryAttr paramAttrs) {
1954 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1956 Location loc = func.getLoc();
1958 for (
auto namedAttr : paramAttrs) {
1959 auto it = attrNameToKindMapping.find(namedAttr.getName());
1960 if (it != attrNameToKindMapping.end()) {
1961 llvm::Attribute::AttrKind llvmKind = it->second;
1965 }
else if (namedAttr.getNameDialect()) {
1966 if (
failed(iface.convertParameterAttr(func, argIdx, namedAttr, *
this)))
1975 ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call,
1978 if (ArrayAttr argAttrsArray = attrsOp.getArgAttrsAttr()) {
1979 unsigned argAttrIdx = 0;
1980 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
1981 immArgPositions.end());
1982 for (
unsigned argIdx : llvm::seq<unsigned>(call->arg_size())) {
1983 if (argAttrIdx >= argAttrsArray.size())
1986 if (immArgPositionsSet.contains(argIdx))
1989 auto argAttrs = cast<DictionaryAttr>(argAttrsArray[argAttrIdx++]);
1990 if (argAttrs.empty())
1993 FailureOr<llvm::AttrBuilder> attrBuilder =
1994 convertParameterAttrs(attrsOp->getLoc(), argAttrs);
1995 if (failed(attrBuilder))
1997 call->addParamAttrs(argIdx, *attrBuilder);
2002 if (ArrayAttr resAttrsArray = attrsOp.getResAttrsAttr()) {
2003 if (!resAttrsArray.empty()) {
2004 auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
2005 FailureOr<llvm::AttrBuilder> attrBuilder =
2006 convertParameterAttrs(attrsOp->getLoc(), resAttrs);
2007 if (failed(attrBuilder))
2009 call->addRetAttrs(*attrBuilder);
2016std::optional<llvm::Attribute>
2018 if (
auto str = dyn_cast<StringAttr>(a))
2019 return llvm::Attribute::get(ctx, (
"no-builtin-" + str.getValue()).str());
2020 return std::nullopt;
2023std::optional<llvm::Attribute>
2026 StringAttr name = namedAttr.
getName();
2029 if (
auto strVal = dyn_cast<StringAttr>(value))
2030 return llvm::Attribute::get(ctx, name.getValue(), strVal.getValue());
2031 if (mlir::isa<UnitAttr>(value))
2032 return llvm::Attribute::get(ctx, name.getValue());
2033 return std::nullopt;
2036FailureOr<llvm::AttrBuilder>
2037ModuleTranslation::convertParameterAttrs(
Location loc,
2038 DictionaryAttr paramAttrs) {
2039 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
2042 for (
auto namedAttr : paramAttrs) {
2043 auto it = attrNameToKindMapping.find(namedAttr.getName());
2044 if (it != attrNameToKindMapping.end()) {
2045 llvm::Attribute::AttrKind llvmKind = it->second;
2055LogicalResult ModuleTranslation::convertFunctionSignatures() {
2058 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
2059 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
2061 cast<llvm::FunctionType>(
convertType(function.getFunctionType())));
2062 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
2063 llvmFunc->setLinkage(convertLinkageToLLVM(function.getLinkage()));
2064 llvmFunc->setCallingConv(convertCConvToLLVM(function.getCConv()));
2075 if (
auto entryCount = function.getFunctionEntryCountAttr()) {
2076 ArrayRef<uint64_t> imports = entryCount.getImports();
2077 llvm::DenseSet<llvm::GlobalValue::GUID> importGUIDs;
2078 if (!imports.empty())
2079 importGUIDs.insert(imports.begin(), imports.end());
2080 llvm::MDBuilder metadataBuilder(llvmFunc->getContext());
2081 llvmFunc->setMetadata(
2082 llvm::LLVMContext::MD_prof,
2083 metadataBuilder.createFunctionEntryCount(
2084 entryCount.getEntryCount(),
2085 entryCount.getCountType() == ProfileCountType::Synthetic,
2086 imports.empty() ?
nullptr : &importGUIDs));
2090 if (
ArrayAttr allResultAttrs = function.getAllResultAttrs()) {
2091 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
2092 FailureOr<llvm::AttrBuilder> attrBuilder =
2093 convertParameterAttrs(function, -1, resultAttrs);
2096 llvmFunc->addRetAttrs(*attrBuilder);
2100 for (
auto [argIdx, llvmArg] : llvm::enumerate(llvmFunc->args())) {
2101 if (DictionaryAttr argAttrs = function.getArgAttrDict(argIdx)) {
2102 FailureOr<llvm::AttrBuilder> attrBuilder =
2103 convertParameterAttrs(function, argIdx, argAttrs);
2106 llvmArg.addAttrs(*attrBuilder);
2111 FailureOr<llvm::AttrBuilder> convertedPassthroughAttrs =
2113 function.getPassthroughAttr(),
2114 function.getPassthroughAttrName());
2115 if (
failed(convertedPassthroughAttrs))
2117 llvmFunc->addFnAttrs(*convertedPassthroughAttrs);
2120 llvmFunc->setVisibility(convertVisibilityToLLVM(function.getVisibility_()));
2123 if (std::optional<mlir::SymbolRefAttr> comdat = function.getComdat()) {
2124 auto selectorOp = cast<ComdatSelectorOp>(
2126 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
2129 if (
auto gc = function.getGarbageCollector())
2130 llvmFunc->setGC(gc->str());
2132 if (
auto unnamedAddr = function.getUnnamedAddr())
2133 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
2135 if (
auto alignment = function.getAlignment())
2136 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
2139 debugTranslation->translate(function, *llvmFunc);
2145LogicalResult ModuleTranslation::convertFunctions() {
2147 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
2150 if (function.isExternal()) {
2151 if (
failed(convertDialectAttributes(function, {})))
2156 if (
failed(convertOneFunction(function)))
2163LogicalResult ModuleTranslation::convertIFuncs() {
2164 for (
auto op :
getModuleBody(mlirModule).getOps<IFuncOp>()) {
2165 llvm::Type *type =
convertType(op.getIFuncType());
2166 llvm::GlobalValue::LinkageTypes linkage =
2167 convertLinkageToLLVM(op.getLinkage());
2168 llvm::Constant *resolver;
2170 resolver = cast<llvm::Constant>(resolverFn);
2173 op.getResolverAttr());
2174 resolver = cast<llvm::Constant>(
lookupAlias(aliasOp));
2178 llvm::GlobalIFunc::create(type, op.getAddressSpace(), linkage,
2179 op.getSymName(), resolver, llvmModule.get());
2181 ifunc->setUnnamedAddr(convertUnnamedAddrToLLVM(op.getUnnamedAddr()));
2182 ifunc->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
2184 ifuncMapping.try_emplace(op, ifunc);
2190LogicalResult ModuleTranslation::convertComdats() {
2191 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
2192 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
2194 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
2196 <<
"comdat selection symbols must be unique even in different "
2198 llvm::Comdat *comdat =
module->getOrInsertComdat(selectorOp.getSymName());
2199 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
2200 comdatMapping.try_emplace(selectorOp, comdat);
2206LogicalResult ModuleTranslation::convertUnresolvedBlockAddress() {
2207 for (
auto &[blockAddressOp, llvmCst] : unresolvedBlockAddressMapping) {
2208 BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
2210 assert(llvmBlock &&
"expected LLVM blocks to be already translated");
2213 auto *llvmBlockAddr = llvm::BlockAddress::get(
2214 lookupFunction(blockAddressAttr.getFunction().getValue()), llvmBlock);
2215 llvmCst->replaceAllUsesWith(llvmBlockAddr);
2216 assert(llvmCst->use_empty() &&
"expected all uses to be replaced");
2217 cast<llvm::GlobalVariable>(llvmCst)->eraseFromParent();
2219 unresolvedBlockAddressMapping.clear();
2224 llvm::Instruction *inst) {
2225 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
2226 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
2231 auto [scopeIt, scopeInserted] =
2232 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
2234 return scopeIt->second;
2235 llvm::LLVMContext &ctx = llvmModule->getContext();
2236 auto dummy = llvm::MDNode::getTemporary(ctx, {});
2238 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
2239 aliasScopeAttr.getDomain(),
nullptr);
2240 if (insertedDomain) {
2243 operands.push_back(dummy.get());
2244 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
2245 operands.push_back(llvm::MDString::get(ctx, description));
2246 domainIt->second = llvm::MDNode::get(ctx, operands);
2249 if (
auto stringAttr =
2250 dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId()))
2251 replacement = llvm::MDString::get(ctx, stringAttr.getValue());
2254 domainIt->second->replaceOperandWith(0,
replacement);
2257 assert(domainIt->second &&
"Scope's domain should already be valid");
2260 operands.push_back(dummy.get());
2261 operands.push_back(domainIt->second);
2262 if (StringAttr description = aliasScopeAttr.getDescription())
2263 operands.push_back(llvm::MDString::get(ctx, description));
2264 scopeIt->second = llvm::MDNode::get(ctx, operands);
2267 if (
auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId()))
2268 replacement = llvm::MDString::get(ctx, stringAttr.getValue());
2271 scopeIt->second->replaceOperandWith(0,
replacement);
2272 return scopeIt->second;
2278 nodes.reserve(aliasScopeAttrs.size());
2279 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
2285 llvm::Instruction *inst) {
2286 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
2287 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
2290 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
2291 inst->setMetadata(kind, node);
2294 populateScopeMetadata(op.getAliasScopesOrNull(),
2295 llvm::LLVMContext::MD_alias_scope);
2296 populateScopeMetadata(op.getNoAliasScopesOrNull(),
2297 llvm::LLVMContext::MD_noalias);
2300llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
2301 return tbaaMetadataMapping.lookup(tbaaAttr);
2305 llvm::Instruction *inst) {
2306 ArrayAttr tagRefs = op.getTBAATagsOrNull();
2307 if (!tagRefs || tagRefs.empty())
2314 if (tagRefs.size() > 1) {
2315 op.emitWarning() <<
"TBAA access tags were not translated, because LLVM "
2316 "IR only supports a single tag per instruction";
2320 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
2321 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
2325 DereferenceableOpInterface op, llvm::Instruction *inst) {
2326 DereferenceableAttr derefAttr = op.getDereferenceableOrNull();
2330 llvm::MDNode *derefSizeNode = llvm::MDNode::get(
2332 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
2333 llvm::IntegerType::get(
getLLVMContext(), 64), derefAttr.getBytes())));
2334 unsigned kindId = derefAttr.getMayBeNull()
2335 ? llvm::LLVMContext::MD_dereferenceable_or_null
2336 : llvm::LLVMContext::MD_dereferenceable;
2337 inst->setMetadata(kindId, derefSizeNode);
2342 llvm::transform(op.getWeights(), std::back_inserter(weights),
2343 [](int32_t value) { return static_cast<uint32_t>(value); });
2344 if (weights.empty())
2348 assert(inst &&
"expected the operation to have a mapping to an instruction");
2350 llvm::LLVMContext::MD_prof,
2354LogicalResult ModuleTranslation::createTBAAMetadata() {
2355 llvm::LLVMContext &ctx = llvmModule->getContext();
2356 llvm::IntegerType *offsetTy = llvm::IntegerType::get(ctx, 64);
2367 walker.
addWalk([&](TBAARootAttr root) {
2369 if (StringAttr
id = root.getId()) {
2370 node = llvm::MDNode::get(ctx, llvm::MDString::get(ctx,
id));
2373 auto selfRef = llvm::MDNode::getTemporary(ctx, {});
2374 node = llvm::MDNode::get(ctx, {selfRef.get()});
2375 node->replaceOperandWith(0, node);
2377 tbaaMetadataMapping.insert({root, node});
2380 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
2381 SmallVector<llvm::Metadata *> operands;
2382 operands.push_back(llvm::MDString::get(ctx, descriptor.getId()));
2383 for (TBAAMemberAttr member : descriptor.getMembers()) {
2384 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
2385 operands.push_back(llvm::ConstantAsMetadata::get(
2386 llvm::ConstantInt::get(offsetTy, member.getOffset())));
2389 tbaaMetadataMapping.insert({descriptor, llvm::MDNode::get(ctx, operands)});
2392 walker.
addWalk([&](TBAATagAttr tag) {
2393 SmallVector<llvm::Metadata *> operands;
2395 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
2396 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
2398 operands.push_back(llvm::ConstantAsMetadata::get(
2399 llvm::ConstantInt::get(offsetTy, tag.getOffset())));
2400 if (tag.getConstant())
2402 llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(offsetTy, 1)));
2404 tbaaMetadataMapping.insert({tag, llvm::MDNode::get(ctx, operands)});
2407 mlirModule->walk([&](AliasAnalysisOpInterface analysisOpInterface) {
2408 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
2415LogicalResult ModuleTranslation::createIdentMetadata() {
2416 if (
auto attr = mlirModule->getAttrOfType<StringAttr>(
2417 LLVMDialect::getIdentAttrName())) {
2418 StringRef ident = attr;
2419 llvm::LLVMContext &ctx = llvmModule->
getContext();
2420 llvm::NamedMDNode *namedMd =
2421 llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
2422 llvm::MDNode *md = llvm::MDNode::get(ctx, llvm::MDString::get(ctx, ident));
2423 namedMd->addOperand(md);
2429LogicalResult ModuleTranslation::createCommandlineMetadata() {
2430 if (
auto attr = mlirModule->getAttrOfType<StringAttr>(
2431 LLVMDialect::getCommandlineAttrName())) {
2432 StringRef cmdLine = attr;
2433 llvm::LLVMContext &ctx = llvmModule->
getContext();
2434 llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
2435 LLVMDialect::getCommandlineAttrName());
2437 llvm::MDNode::get(ctx, llvm::MDString::get(ctx, cmdLine));
2438 nmd->addOperand(md);
2444LogicalResult ModuleTranslation::createDependentLibrariesMetadata() {
2445 if (
auto dependentLibrariesAttr = mlirModule->getDiscardableAttr(
2446 LLVM::LLVMDialect::getDependentLibrariesAttrName())) {
2448 llvmModule->getOrInsertNamedMetadata(
"llvm.dependent-libraries");
2449 llvm::LLVMContext &ctx = llvmModule->getContext();
2451 cast<ArrayAttr>(dependentLibrariesAttr).getAsRange<StringAttr>()) {
2453 llvm::MDNode::get(ctx, llvm::MDString::get(ctx, libAttr.getValue()));
2454 nmd->addOperand(md);
2461 llvm::Instruction *inst) {
2462 LoopAnnotationAttr attr =
2464 .Case<LLVM::BrOp, LLVM::CondBrOp>(
2465 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
2468 llvm::MDNode *loopMD =
2469 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
2470 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
2474 auto iface = cast<DisjointFlagInterface>(op);
2476 if (
auto *disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
2477 disjointInst->setIsDisjoint(iface.getIsDisjoint());
2481 return typeTranslator.translateType(type);
2487 remapped.reserve(values.size());
2488 for (
Value v : values)
2495 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
2500 llvm::OpenMPIRBuilderConfig config(
2507 unsigned int defaultAS =
2508 llvmModule->getDataLayout().getProgramAddressSpace();
2509 config.setDefaultTargetAS(defaultAS);
2510 config.setRuntimeCC(llvmModule->getTargetTriple().isSPIRV()
2511 ? llvm::CallingConv::SPIR_FUNC
2512 : llvm::CallingConv::C);
2513 ompBuilder->setConfig(std::move(config));
2514 ompBuilder->initialize();
2516 return ompBuilder.get();
2522 return *llvm::vfs::getRealFileSystem();
2526 llvm::DILocalScope *scope) {
2527 return debugTranslation->translateLoc(loc, scope);
2532 return debugTranslation->translateExpression(attr);
2535llvm::DIGlobalVariableExpression *
2537 LLVM::DIGlobalVariableExpressionAttr attr) {
2538 return debugTranslation->translateGlobalVariableExpression(attr);
2542 return debugTranslation->translate(attr);
2547 return convertRoundingModeToLLVM(rounding);
2551 LLVM::FPExceptionBehavior exceptionBehavior) {
2552 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
2557 return llvmModule->getOrInsertNamedMetadata(name);
2560static std::unique_ptr<llvm::Module>
2564 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
2565 if (
auto dataLayoutAttr =
2567 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
2569 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(
""));
2570 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
2571 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2575 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
2576 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2581 if (failed(llvmDataLayout))
2583 llvmModule->setDataLayout(*llvmDataLayout);
2585 if (
auto targetTripleAttr =
2587 llvmModule->setTargetTriple(
2588 llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
2591 LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
2592 auto asmArrayAttr = dyn_cast<ArrayAttr>(asmAttr);
2593 if (!asmArrayAttr) {
2594 m->
emitError(
"expected an array attribute for a module level asm");
2599 auto asmStrAttr = dyn_cast<StringAttr>(elt);
2602 "expected a string attribute for each entry of a module level asm");
2605 llvmModule->appendModuleInlineAsm(asmStrAttr.getValue());
2612std::unique_ptr<llvm::Module>
2614 StringRef name,
bool disableVerification,
2615 llvm::vfs::FileSystem *fs) {
2617 module->emitOpError("can not be translated to an LLVMIR module");
2621 std::unique_ptr<llvm::Module> llvmModule =
2630 llvm::IRBuilder<llvm::TargetFolder> llvmBuilder(
2632 llvm::TargetFolder(translator.getLLVMModule()->getDataLayout()));
2638 if (
failed(translator.convertOperation(*module, llvmBuilder)))
2641 if (
failed(translator.convertComdats()))
2643 if (
failed(translator.convertFunctionSignatures()))
2645 if (
failed(translator.convertGlobalsAndAliases()))
2647 if (
failed(translator.convertIFuncs()))
2649 if (
failed(translator.createTBAAMetadata()))
2651 if (
failed(translator.createIdentMetadata()))
2653 if (
failed(translator.createCommandlineMetadata()))
2655 if (
failed(translator.createDependentLibrariesMetadata()))
2659 for (Operation &o :
getModuleBody(module).getOperations()) {
2660 if (!isa<LLVM::LLVMFuncOp, LLVM::AliasOp, LLVM::GlobalOp,
2661 LLVM::GlobalCtorsOp, LLVM::GlobalDtorsOp, LLVM::ComdatOp,
2662 LLVM::IFuncOp>(&o) &&
2663 !o.hasTrait<OpTrait::IsTerminator>() &&
2664 failed(translator.convertOperation(o, llvmBuilder))) {
2672 if (
failed(translator.convertFunctions()))
2677 if (
failed(translator.convertUnresolvedBlockAddress()))
2682 translator.debugTranslation->addModuleFlagsIfNotPresent();
2685 if (
auto *ompBuilder = translator.getOpenMPBuilder())
2686 ompBuilder->finalize();
2688 if (!disableVerification &&
2689 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2692 return std::move(translator.llvmModule);