30 #include "llvm/ADT/DepthFirstIterator.h"
31 #include "llvm/ADT/PostOrderIterator.h"
32 #include "llvm/ADT/ScopeExit.h"
33 #include "llvm/ADT/StringSet.h"
34 #include "llvm/ADT/TypeSwitch.h"
35 #include "llvm/IR/Comdat.h"
36 #include "llvm/IR/Constants.h"
37 #include "llvm/IR/InlineAsm.h"
38 #include "llvm/IR/InstIterator.h"
39 #include "llvm/IR/Instructions.h"
40 #include "llvm/IR/IntrinsicInst.h"
41 #include "llvm/IR/Metadata.h"
42 #include "llvm/IR/Operator.h"
43 #include "llvm/Support/ModRef.h"
50 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
55 static std::string
diag(
const llvm::Value &value) {
57 llvm::raw_string_ostream os(str);
65 static std::string
diagMD(
const llvm::Metadata *node,
66 const llvm::Module *module) {
68 llvm::raw_string_ostream os(str);
69 node->print(os, module,
true);
75 return "llvm.global_ctors";
80 return "mlir.llvm.nameless_global";
85 return "llvm.global_dtors";
91 return "__llvm_global_comdat";
100 std::optional<llvm::SyncScope::ID> syncScopeID =
101 llvm::getAtomicSyncScopeID(inst);
108 llvm::LLVMContext &llvmContext = inst->getContext();
109 llvmContext.getSyncScopeNames(syncScopeName);
110 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
111 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
113 if (it != syncScopeName.end())
115 llvm_unreachable(
"incorrect sync scope identifier");
121 llvm::append_range(position, indices);
132 llvm::Instruction *inst,
145 #include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
153 for (llvm::BasicBlock *basicBlock : basicBlocks) {
154 if (!blocks.contains(basicBlock)) {
155 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
156 blocks.insert_range(traversal);
159 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
164 std::unique_ptr<llvm::Module> llvmModule,
165 bool emitExpensiveWarnings,
166 bool importEmptyDICompositeTypes,
167 bool preferUnregisteredIntrinsics,
168 bool importStructsAsLiterals)
170 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
172 typeTranslator(*mlirModule->
getContext(), importStructsAsLiterals),
174 mlirModule, importEmptyDICompositeTypes)),
175 loopAnnotationImporter(
177 emitExpensiveWarnings(emitExpensiveWarnings),
178 preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
182 ComdatOp ModuleImport::getGlobalComdatOp() {
184 return globalComdatOp;
190 globalInsertionOp = globalComdatOp;
191 return globalComdatOp;
194 LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
199 auto getIdentityIfRootNode =
200 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
204 if (node->getNumOperands() > 1)
207 if (node->getNumOperands() == 1)
208 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
209 return std::optional<StringRef>{op0->getString()};
210 return std::optional<StringRef>{};
220 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
221 StringRef *identity =
nullptr,
223 nullptr) -> std::optional<bool> {
224 unsigned numOperands = node->getNumOperands();
233 const auto *identityNode =
234 dyn_cast<const llvm::MDString>(node->getOperand(0));
240 *identity = identityNode->getString();
242 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
243 const auto *memberNode =
244 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
246 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
247 <<
diagMD(node, llvmModule.get());
251 if (2 * pairNum + 2 >= numOperands) {
253 if (numOperands != 2) {
254 emitError(loc) <<
"missing member offset: "
255 <<
diagMD(node, llvmModule.get());
259 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
260 node->getOperand(2 * pairNum + 2));
262 emitError(loc) <<
"operand '" << 2 * pairNum + 2
263 <<
"' must be ConstantInt: "
264 <<
diagMD(node, llvmModule.get());
267 offset = offsetCI->getZExtValue();
272 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
285 auto isTagNode = [&](
const llvm::MDNode *node,
286 TBAATypeDescriptorAttr *baseAttr =
nullptr,
287 TBAATypeDescriptorAttr *accessAttr =
nullptr,
288 int64_t *offset =
nullptr,
289 bool *isConstant =
nullptr) -> std::optional<bool> {
297 unsigned numOperands = node->getNumOperands();
298 if (numOperands != 3 && numOperands != 4)
300 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
301 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
303 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
304 if (!baseMD || !accessMD || !offsetCI)
311 if (accessMD->getNumOperands() < 1 ||
312 !isa<llvm::MDString>(accessMD->getOperand(0)))
314 bool isConst =
false;
315 if (numOperands == 4) {
317 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
319 emitError(loc) <<
"operand '3' must be ConstantInt: "
320 <<
diagMD(node, llvmModule.get());
323 isConst = isConstantCI->getValue()[0];
326 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
328 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
330 *offset = offsetCI->getZExtValue();
332 *isConstant = isConst;
341 workList.push_back(node);
342 while (!workList.empty()) {
343 const llvm::MDNode *current = workList.back();
344 if (tbaaMapping.contains(current)) {
353 bool anyChildNotConverted =
false;
354 for (
const llvm::MDOperand &operand : current->operands())
355 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
356 if (!tbaaMapping.contains(childNode)) {
357 workList.push_back(childNode);
358 anyChildNotConverted =
true;
361 if (anyChildNotConverted) {
366 if (!seen.insert(current).second)
367 return emitError(loc) <<
"has cycle in TBAA graph: "
368 <<
diagMD(current, llvmModule.get());
376 FailureOr<std::optional<StringRef>> rootNodeIdentity =
377 getIdentityIfRootNode(current);
378 if (succeeded(rootNodeIdentity)) {
379 StringAttr stringAttr = *rootNodeIdentity
384 tbaaMapping.insert({current, builder.
getAttr<TBAARootAttr>(stringAttr)});
390 if (std::optional<bool> isValid =
391 isTypeDescriptorNode(current, &identity, &members)) {
392 assert(isValid.value() &&
"type descriptor node must be valid");
394 tbaaMapping.insert({current, builder.
getAttr<TBAATypeDescriptorAttr>(
395 identity, members)});
399 TBAATypeDescriptorAttr baseAttr, accessAttr;
402 if (std::optional<bool> isValid =
403 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
404 assert(isValid.value() &&
"access tag node must be valid");
406 {current, builder.
getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
411 return emitError(loc) <<
"unsupported TBAA node format: "
412 <<
diagMD(current, llvmModule.get());
418 ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
420 if (failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
421 return emitError(loc) <<
"unsupported access group node: "
422 <<
diagMD(node, llvmModule.get());
427 ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
430 auto verifySelfRef = [](
const llvm::MDNode *node) {
431 return node->getNumOperands() != 0 &&
432 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
434 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
435 return node->getNumOperands() != 0 &&
436 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
437 isa<llvm::MDString>(node->getOperand(0)));
440 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
441 return idx >= node->getNumOperands() ||
442 isa<llvm::MDString>(node->getOperand(idx));
445 auto getIdAttr = [&](
const llvm::MDNode *node) ->
Attribute {
446 if (verifySelfRef(node))
449 auto name = cast<llvm::MDString>(node->getOperand(0));
454 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
455 StringAttr description =
nullptr;
456 if (aliasDomain->getNumOperands() >= 2)
457 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
459 Attribute idAttr = getIdAttr(aliasDomain);
460 return builder.
getAttr<AliasScopeDomainAttr>(idAttr, description);
464 for (
const llvm::MDOperand &operand : node->operands()) {
465 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
466 llvm::AliasScopeNode aliasScope(scope);
467 const llvm::MDNode *domain = aliasScope.getDomain();
473 if (!verifySelfRefOrString(scope) || !domain ||
474 !verifyDescription(scope, 2))
475 return emitError(loc) <<
"unsupported alias scope node: "
476 <<
diagMD(scope, llvmModule.get());
477 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
478 return emitError(loc) <<
"unsupported alias domain node: "
479 <<
diagMD(domain, llvmModule.get());
481 if (aliasScopeMapping.contains(scope))
485 auto it = aliasScopeMapping.find(aliasScope.getDomain());
486 if (it == aliasScopeMapping.end()) {
487 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
488 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
492 StringAttr description =
nullptr;
493 if (!aliasScope.getName().empty())
496 auto aliasScopeOp = builder.
getAttr<AliasScopeAttr>(
497 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
499 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
505 FailureOr<SmallVector<AliasScopeAttr>>
508 aliasScopes.reserve(node->getNumOperands());
509 for (
const llvm::MDOperand &operand : node->operands()) {
510 auto *node = cast<llvm::MDNode>(operand.get());
511 aliasScopes.push_back(
512 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
515 if (llvm::is_contained(aliasScopes,
nullptr))
521 debugIntrinsics.insert(intrinsic);
525 llvm::MDTuple *mdTuple) {
526 auto getLLVMFunction =
527 [&](
const llvm::MDOperand &funcMDO) -> llvm::Function * {
528 auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);
532 auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());
538 for (
unsigned i = 0; i < mdTuple->getNumOperands(); i++) {
539 const llvm::MDOperand &mdo = mdTuple->getOperand(i);
540 auto *cgEntry = cast<llvm::MDNode>(mdo);
541 llvm::Constant *llvmConstant =
542 cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();
543 uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();
544 auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));
545 auto *toFn = getLLVMFunction(cgEntry->getOperand(1));
548 mlirModule->getContext(),
562 const llvm::Module *llvmModule,
563 const llvm::MDOperand &md) {
564 auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
565 if (!tupleEntry || tupleEntry->getNumOperands() != 2)
567 <<
"expected 2-element tuple metadata: " <<
diagMD(md, llvmModule);
575 ModuleOp mlirModule,
const llvm::Module *llvmModule,
576 const llvm::MDOperand &md, StringRef matchKey,
bool optional =
false) {
580 auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
581 if (!keyMD || keyMD->getString() != matchKey) {
584 <<
"expected '" << matchKey <<
"' key, but found: "
585 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
589 return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));
595 static FailureOr<uint64_t>
597 const llvm::Module *llvmModule,
598 const llvm::MDOperand &md, StringRef matchKey) {
599 llvm::ConstantAsMetadata *valMD =
604 if (
auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))
605 return cstInt->getZExtValue();
608 <<
"expected integer metadata value for key '" << matchKey
609 <<
"': " <<
diagMD(md, llvmModule);
613 static std::optional<ProfileSummaryFormatKind>
615 const llvm::MDOperand &formatMD) {
620 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
621 if (!keyMD || keyMD->getString() !=
"ProfileFormat") {
623 <<
"expected 'ProfileFormat' key: "
624 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
628 llvm::MDString *valMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(1));
629 std::optional<ProfileSummaryFormatKind> fmtKind =
630 symbolizeProfileSummaryFormatKind(valMD->getString());
633 <<
"expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
635 <<
diagMD(valMD, llvmModule);
642 static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
644 const llvm::Module *llvmModule,
645 const llvm::MDOperand &summaryMD) {
650 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
651 if (!keyMD || keyMD->getString() !=
"DetailedSummary") {
653 <<
"expected 'DetailedSummary' key: "
654 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
658 llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
661 <<
"expected tuple value for 'DetailedSummary' key: "
662 <<
diagMD(tupleEntry->getOperand(1), llvmModule);
667 for (
auto &&entry : entriesMD->operands()) {
668 llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
669 if (!entryMD || entryMD->getNumOperands() != 3) {
671 <<
"'DetailedSummary' entry expects 3 operands: "
672 <<
diagMD(entry, llvmModule);
676 auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
677 auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
678 auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
679 if (!op0 || !op1 || !op2) {
681 <<
"expected only integer entries in 'DetailedSummary': "
682 <<
diagMD(entry, llvmModule);
687 mlirModule->getContext(),
688 cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
689 cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
690 cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
691 detailedSummary.push_back(detaildSummaryEntry);
693 return detailedSummary;
698 const llvm::Module *llvmModule,
699 llvm::MDTuple *mdTuple) {
700 unsigned profileNumEntries = mdTuple->getNumOperands();
701 if (profileNumEntries < 8) {
703 <<
"expected at 8 entries in 'ProfileSummary': "
704 <<
diagMD(mdTuple, llvmModule);
708 unsigned summayIdx = 0;
709 auto checkOptionalPosition = [&](
const llvm::MDOperand &md,
710 StringRef matchKey) -> LogicalResult {
714 if (summayIdx + 1 >= profileNumEntries) {
716 <<
"the last summary entry is '" << matchKey
717 <<
"', expected 'DetailedSummary': " <<
diagMD(md, llvmModule);
724 auto getOptIntValue =
725 [&](
const llvm::MDOperand &md,
726 StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
729 return FailureOr<std::optional<uint64_t>>(std::nullopt);
730 if (checkOptionalPosition(md, matchKey).failed())
732 FailureOr<uint64_t> val =
739 auto getOptDoubleValue = [&](
const llvm::MDOperand &md,
740 StringRef matchKey) -> FailureOr<FloatAttr> {
745 if (
auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
746 if (checkOptionalPosition(md, matchKey).failed())
749 cstFP->getValueAPF());
752 <<
"expected double metadata value for key '" << matchKey
753 <<
"': " <<
diagMD(md, llvmModule);
761 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
762 if (!format.has_value())
766 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"TotalCount");
767 if (failed(totalCount))
771 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"MaxCount");
772 if (failed(maxCount))
776 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
778 if (failed(maxInternalCount))
782 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
784 if (failed(maxFunctionCount))
788 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumCounts");
789 if (failed(numCounts))
793 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumFunctions");
794 if (failed(numFunctions))
798 FailureOr<std::optional<uint64_t>> isPartialProfile =
799 getOptIntValue(mdTuple->getOperand(summayIdx),
"IsPartialProfile");
800 if (failed(isPartialProfile))
802 if (isPartialProfile->has_value())
805 FailureOr<FloatAttr> partialProfileRatio =
806 getOptDoubleValue(mdTuple->getOperand(summayIdx),
"PartialProfileRatio");
807 if (failed(partialProfileRatio))
809 if (*partialProfileRatio)
813 FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
815 mdTuple->getOperand(summayIdx));
816 if (failed(detailed))
821 mlirModule->getContext(), *format, *totalCount, *maxCount,
822 *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,
823 *isPartialProfile, *partialProfileRatio, *detailed);
830 const llvm::Module *llvmModule, StringRef key,
831 llvm::MDTuple *mdTuple) {
832 if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
834 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
842 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
845 for (
const auto [behavior, key, val] : llvmModuleFlags) {
847 if (
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
849 }
else if (
auto *mdString = dyn_cast<llvm::MDString>(val)) {
851 }
else if (
auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
853 key->getString(), mdTuple);
858 <<
"unsupported module flag value for key '" << key->getString()
859 <<
"' : " <<
diagMD(val, llvmModule.get());
863 moduleFlags.push_back(builder.
getAttr<ModuleFlagAttr>(
864 convertModFlagBehaviorFromLLVM(behavior),
868 if (!moduleFlags.empty())
869 builder.
create<LLVM::ModuleFlagsOp>(mlirModule.getLoc(),
876 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
877 if (named.getName() !=
"llvm.linker.options")
880 for (
const llvm::MDNode *node : named.operands()) {
882 options.reserve(node->getNumOperands());
883 for (
const llvm::MDOperand &option : node->operands())
884 options.push_back(cast<llvm::MDString>(option)->getString());
885 builder.
create<LLVM::LinkerOptionsOp>(mlirModule.getLoc(),
893 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
894 if (named.getName() !=
"llvm.dependent-libraries")
897 for (
const llvm::MDNode *node : named.operands()) {
898 if (node->getNumOperands() == 1)
899 if (
auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
900 libraries.push_back(mdString->getString());
902 if (!libraries.empty())
903 mlirModule->setAttr(LLVM::LLVMDialect::getDependentLibrariesAttrName(),
910 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
913 if (named.getName() != LLVMDialect::getIdentAttrName())
916 if (named.getNumOperands() == 1)
917 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
918 if (md->getNumOperands() == 1)
919 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
920 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
927 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
930 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
933 if (nmd.getNumOperands() == 1)
934 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
935 if (md->getNumOperands() == 1)
936 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
937 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
946 for (
const llvm::Function &func : llvmModule->functions()) {
947 for (
const llvm::Instruction &inst : llvm::instructions(func)) {
949 if (llvm::MDNode *node =
950 inst.getMetadata(llvm::LLVMContext::MD_access_group))
951 if (failed(processAccessGroupMetadata(node)))
955 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
956 if (!aliasAnalysisNodes)
958 if (aliasAnalysisNodes.TBAA)
959 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
961 if (aliasAnalysisNodes.Scope)
962 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
964 if (aliasAnalysisNodes.NoAlias)
965 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
982 void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
983 if (comdatMapping.contains(comdat))
986 ComdatOp comdatOp = getGlobalComdatOp();
989 auto selectorOp = builder.
create<ComdatSelectorOp>(
990 mlirModule.getLoc(), comdat->getName(),
991 convertComdatFromLLVM(comdat->getSelectionKind()));
995 comdatMapping.try_emplace(comdat, symbolRef);
999 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1000 if (globalVar.hasComdat())
1001 processComdat(globalVar.getComdat());
1002 for (llvm::Function &func : llvmModule->functions())
1003 if (func.hasComdat())
1004 processComdat(func.getComdat());
1009 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1012 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1014 <<
"unhandled global variable: " <<
diag(globalVar);
1018 if (failed(convertGlobal(&globalVar))) {
1020 <<
"unhandled global variable: " <<
diag(globalVar);
1027 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1028 if (failed(convertAlias(&alias))) {
1030 <<
"unhandled global alias: " <<
diag(alias);
1037 Location loc = mlirModule.getLoc();
1040 return emitError(loc,
"cannot translate data layout: ")
1044 emitWarning(loc,
"unhandled data layout token: ") << token;
1046 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
1052 mlirModule->setAttr(
1053 LLVM::LLVMDialect::getTargetTripleAttrName(),
1054 builder.
getStringAttr(llvmModule->getTargetTriple().str()));
1058 for (llvm::Function &func : llvmModule->functions())
1064 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1067 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1068 for (
auto &[
kind, node] : allMetadata) {
1072 if (emitExpensiveWarnings) {
1073 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1075 <<
diagMD(node, llvmModule.get()) <<
" on "
1084 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1086 IntegerOverflowFlags value = {};
1087 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1089 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1091 iface.setOverflowFlags(value);
1095 auto iface = cast<ExactFlagInterface>(op);
1097 iface.setIsExact(inst->isExact());
1102 auto iface = cast<DisjointFlagInterface>(op);
1103 auto instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1105 iface.setIsDisjoint(instDisjoint->isDisjoint());
1109 auto iface = cast<NonNegFlagInterface>(op);
1111 iface.setNonNeg(inst->hasNonNeg());
1116 auto iface = cast<FastmathFlagsInterface>(op);
1122 if (!isa<llvm::FPMathOperator>(inst))
1124 llvm::FastMathFlags flags = inst->getFastMathFlags();
1127 FastmathFlags value = {};
1128 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1129 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1130 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1131 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1133 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1134 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1136 iface->setAttr(iface.getFastmathAttrName(), attr);
1148 if (numElements.isScalable()) {
1150 <<
"scalable vectors not supported";
1155 Type elementType = cast<VectorType>(type).getElementType();
1160 shape.push_back(numElements.getKnownMinValue());
1164 Type ModuleImport::getBuiltinTypeForAttr(
Type type) {
1179 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1180 arrayShape.push_back(arrayType.getNumElements());
1181 type = arrayType.getElementType();
1191 llvm::Constant *constScalar) {
1195 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1198 constInt->getValue());
1202 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1203 llvm::Type *type = constFloat->getType();
1204 FloatType floatType =
1210 <<
"unexpected floating-point type";
1213 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1222 llvm::ConstantDataSequential *constSequence) {
1224 elementAttrs.reserve(constSequence->getNumElements());
1225 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1226 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1229 return elementAttrs;
1232 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1238 auto getConstantShape = [&](llvm::Type *type) {
1239 return llvm::dyn_cast_if_present<ShapedType>(
1245 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1246 if (constArray->isString())
1248 auto shape = getConstantShape(constArray->getType());
1252 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1253 if (constVector && constVector->isSplat()) {
1256 builder, constVector->getElementAsConstant(0));
1267 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1268 auto shape = getConstantShape(constAggregate->getType());
1274 while (!workList.empty()) {
1275 llvm::Constant *current = workList.pop_back_val();
1278 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1280 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1281 workList.push_back(constAggregate->getAggregateElement(idx));
1286 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1289 elementAttrs.append(attrs.begin(), attrs.end());
1295 elementAttrs.push_back(scalarAttr);
1306 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1307 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1308 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1313 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1320 ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1321 assert(globalVar->getName().empty() &&
1322 "expected to work with a nameless global");
1323 auto [it, success] = namelessGlobals.try_emplace(globalVar);
1330 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1333 it->getSecond() = symbolRef;
1339 if (globalInsertionOp)
1346 LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1351 AliasOp aliasOp = builder.
create<AliasOp>(
1352 mlirModule.getLoc(), type, convertLinkageFromLLVM(alias->getLinkage()),
1354 alias->isDSOLocal(),
1355 alias->isThreadLocal(),
1357 globalInsertionOp = aliasOp;
1361 setConstantInsertionPointToStart(block);
1362 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1363 if (failed(initializer))
1365 builder.
create<ReturnOp>(aliasOp.getLoc(), *initializer);
1367 if (alias->hasAtLeastLocalUnnamedAddr())
1368 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1369 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1374 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1379 if (globalVar->hasInitializer())
1380 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1383 uint64_t alignment = 0;
1384 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1385 if (maybeAlign.has_value()) {
1386 llvm::Align align = *maybeAlign;
1387 alignment = align.value();
1394 globalVar->getDebugInfo(globalExpressions);
1396 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1397 DIGlobalVariableExpressionAttr globalExpressionAttr =
1398 debugImporter->translateGlobalVariableExpression(expr);
1399 globalExpressionAttrs.push_back(globalExpressionAttr);
1404 StringRef globalName = globalVar->getName();
1405 if (globalName.empty())
1406 globalName = getOrCreateNamelessSymbolName(globalVar).
getValue();
1408 GlobalOp globalOp = builder.
create<GlobalOp>(
1409 mlirModule.getLoc(), type, globalVar->isConstant(),
1410 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1411 valueAttr, alignment, globalVar->getAddressSpace(),
1412 globalVar->isDSOLocal(),
1413 globalVar->isThreadLocal(), SymbolRefAttr(),
1415 globalInsertionOp = globalOp;
1417 if (globalVar->hasInitializer() && !valueAttr) {
1420 setConstantInsertionPointToStart(block);
1421 FailureOr<Value> initializer =
1422 convertConstantExpr(globalVar->getInitializer());
1423 if (failed(initializer))
1425 builder.
create<ReturnOp>(globalOp.getLoc(), *initializer);
1427 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1428 globalOp.setUnnamedAddr(
1429 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1431 if (globalVar->hasSection())
1432 globalOp.setSection(globalVar->getSection());
1433 globalOp.setVisibility_(
1434 convertVisibilityFromLLVM(globalVar->getVisibility()));
1436 if (globalVar->hasComdat())
1437 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1443 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1444 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1446 llvm::Constant *initializer = globalVar->getInitializer();
1448 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1449 isa<llvm::ConstantAggregateZero>(initializer);
1456 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1457 if (caz->getElementCount().getFixedValue() != 0)
1464 for (llvm::Value *operand : initializer->operands()) {
1465 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1466 if (!aggregate || aggregate->getNumOperands() != 3)
1469 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1470 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1471 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1472 if (!priority || !func || !data)
1475 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1479 else if (data->isNullValue())
1485 priorities.push_back(priority->getValue().getZExtValue());
1486 dataList.push_back(dataAttr);
1493 globalInsertionOp = builder.
create<LLVM::GlobalCtorsOp>(
1498 globalInsertionOp = builder.
create<LLVM::GlobalDtorsOp>(
1505 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1507 if (valueMapping.contains(constant))
1516 workList.insert(constant);
1517 while (!workList.empty()) {
1518 llvm::Constant *current = workList.back();
1521 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1522 orderedSet.insert(current);
1523 workList.pop_back();
1529 auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);
1533 for (llvm::Value *operand : current->operands())
1534 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1535 adjacencyIt->getSecond().push_back(constDependency);
1538 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1539 unsigned numElements = constAgg->getElementCount().getFixedValue();
1540 for (
unsigned i = 0, e = numElements; i != e; ++i)
1541 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1547 if (adjacencyIt->getSecond().empty()) {
1548 orderedSet.insert(current);
1549 workList.pop_back();
1557 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1558 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1559 orderedSet.contains(dependency))
1561 workList.insert(dependency);
1567 FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1571 if (
Attribute attr = getConstantAsAttr(constant)) {
1573 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1574 return builder.
create<AddressOfOp>(loc, type, symbolRef.getValue())
1577 return builder.
create<ConstantOp>(loc, type, attr).getResult();
1581 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1583 return builder.
create<ZeroOp>(loc, type).getResult();
1587 if (isa<llvm::ConstantTokenNone>(constant)) {
1588 return builder.
create<NoneTokenOp>(loc).getResult();
1592 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1594 return builder.
create<PoisonOp>(loc, type).getResult();
1598 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1600 return builder.
create<UndefOp>(loc, type).getResult();
1604 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1607 .
create<DSOLocalEquivalentOp>(
1611 dsoLocalEquivalent->getGlobalValue()->getName()))
1616 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1618 StringRef globalName = globalObj->getName();
1621 if (globalName.empty())
1623 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1626 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1630 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1632 StringRef aliaseeName = globalAliasObj->getName();
1634 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1638 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1644 llvm::Instruction *inst = constExpr->getAsInstruction();
1645 auto guard = llvm::make_scope_exit([&]() {
1646 assert(!noResultOpMapping.contains(inst) &&
1647 "expected constant expression to return a result");
1648 valueMapping.erase(inst);
1649 inst->deleteValue();
1653 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1654 return valueMapping.contains(value);
1656 if (failed(processInstruction(inst)))
1662 if (isa<llvm::ConstantAggregate>(constant) ||
1663 isa<llvm::ConstantAggregateZero>(constant)) {
1666 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1667 elementValues.reserve(constAgg->getNumOperands());
1668 for (llvm::Value *operand : constAgg->operands())
1671 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1672 unsigned numElements = constAgg->getElementCount().getFixedValue();
1673 elementValues.reserve(numElements);
1674 for (
unsigned i = 0, e = numElements; i != e; ++i)
1675 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1677 assert(llvm::count(elementValues,
nullptr) == 0 &&
1678 "expected all elements have been converted before");
1682 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1684 "unrecognized aggregate type");
1685 Value root = builder.
create<UndefOp>(loc, rootType);
1687 if (isArrayOrStruct) {
1688 root = builder.
create<InsertValueOp>(loc, root, it.value(), it.index());
1693 root = builder.
create<InsertElementOp>(loc, rootType, root, it.value(),
1700 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1701 LLVMTargetExtType targetExtType =
1702 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1703 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1704 "target extension type does not support zero-initialization");
1707 return builder.
create<LLVM::ZeroOp>(loc, targetExtType).getRes();
1710 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1721 StringRef error =
"";
1723 if (isa<llvm::ConstantPtrAuth>(constant))
1724 error =
" since ptrauth(...) is unsupported";
1726 if (isa<llvm::NoCFIValue>(constant))
1727 error =
" since no_cfi is unsupported";
1729 if (isa<llvm::GlobalValue>(constant))
1730 error =
" since global value is unsupported";
1732 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1735 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1739 assert(!valueMapping.contains(constant) &&
1740 "expected constant has not been converted before");
1741 assert(constantInsertionBlock &&
1742 "expected the constant insertion block to be non-null");
1746 if (!constantInsertionOp)
1753 getConstantsToConvert(constant);
1754 for (llvm::Constant *constantToConvert : constantsToConvert) {
1755 FailureOr<Value> converted = convertConstant(constantToConvert);
1756 if (failed(converted))
1758 mapValue(constantToConvert, *converted);
1768 assert(!isa<llvm::MetadataAsValue>(value) &&
1769 "expected value to not be metadata");
1772 auto it = valueMapping.find(value);
1773 if (it != valueMapping.end())
1774 return it->getSecond();
1777 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1778 return convertConstantExpr(constant);
1781 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1783 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1789 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1792 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1795 value = node->getValue();
1798 auto it = valueMapping.find(value);
1799 if (it != valueMapping.end())
1800 return it->getSecond();
1803 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1804 return convertConstantExpr(constant);
1808 FailureOr<SmallVector<Value>>
1811 remapped.reserve(values.size());
1812 for (llvm::Value *value : values) {
1814 if (failed(converted))
1816 remapped.push_back(*converted);
1826 assert(immArgPositions.size() == immArgAttrNames.size() &&
1827 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1831 for (
auto [immArgPos, immArgName] :
1832 llvm::zip(immArgPositions, immArgAttrNames)) {
1833 auto &value = operands[immArgPos];
1834 auto *constant = llvm::cast<llvm::Constant>(value);
1836 assert(attr && attr.getType().isIntOrFloat() &&
1837 "expected immarg to be float or integer constant");
1839 attrsOut.push_back({nameAttr, attr});
1844 for (llvm::Value *value : operands) {
1848 if (failed(mlirValue))
1850 valuesOut.push_back(*mlirValue);
1855 if (requiresOpBundles) {
1856 opBundleSizes.reserve(opBundles.size());
1857 opBundleTagAttrs.reserve(opBundles.size());
1859 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1860 opBundleSizes.push_back(bundle.Inputs.size());
1861 opBundleTagAttrs.push_back(
StringAttr::get(context, bundle.getTagName()));
1863 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1864 auto operandMlirValue =
convertValue(opBundleOperand.get());
1865 if (failed(operandMlirValue))
1867 valuesOut.push_back(*operandMlirValue);
1872 auto opBundleSizesAttrNameAttr =
1874 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1876 auto opBundleTagsAttr =
ArrayAttr::get(context, opBundleTagAttrs);
1877 auto opBundleTagsAttrNameAttr =
1879 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1886 IntegerAttr integerAttr;
1888 bool success = succeeded(converted) &&
1890 assert(success &&
"expected a constant integer value");
1896 FloatAttr floatAttr;
1900 assert(success &&
"expected a constant float value");
1906 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1907 auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
1908 return debugImporter->translate(node);
1912 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1913 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
1914 return debugImporter->translate(node);
1917 FPExceptionBehaviorAttr
1919 auto *metadata = cast<llvm::MetadataAsValue>(value);
1920 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1921 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
1922 llvm::convertStrToExceptionBehavior(mdstr->getString());
1923 assert(optLLVM &&
"Expecting FP exception behavior");
1924 return builder.
getAttr<FPExceptionBehaviorAttr>(
1925 convertFPExceptionBehaviorFromLLVM(*optLLVM));
1929 auto *metadata = cast<llvm::MetadataAsValue>(value);
1930 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1931 std::optional<llvm::RoundingMode> optLLVM =
1932 llvm::convertStrToRoundingMode(mdstr->getString());
1933 assert(optLLVM &&
"Expecting rounding mode");
1934 return builder.
getAttr<RoundingModeAttr>(
1935 convertRoundingModeFromLLVM(*optLLVM));
1938 FailureOr<SmallVector<AliasScopeAttr>>
1940 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1941 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
1946 return debugImporter->translateLoc(loc);
1950 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
1951 llvm::BasicBlock *target,
1953 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
1954 auto *phiInst = cast<llvm::PHINode>(&*inst);
1955 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
1957 if (failed(converted))
1959 blockArguments.push_back(*converted);
1964 FailureOr<SmallVector<Value>>
1965 ModuleImport::convertCallOperands(llvm::CallBase *callInst,
1966 bool allowInlineAsm) {
1967 bool isInlineAsm = callInst->isInlineAsm();
1968 if (isInlineAsm && !allowInlineAsm)
1978 if (!isa<llvm::Function>(callInst->getCalledOperand()) && !isInlineAsm) {
1979 FailureOr<Value> called =
convertValue(callInst->getCalledOperand());
1982 operands.push_back(*called);
1986 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
1987 if (failed(arguments))
1990 llvm::append_range(operands, *arguments);
1996 static LogicalResult
1998 LLVMFunctionType calleeType) {
1999 if (callType.getReturnType() != calleeType.getReturnType())
2002 if (calleeType.isVarArg()) {
2005 if (callType.getNumParams() < calleeType.getNumParams())
2010 if (callType.getNumParams() != calleeType.getNumParams())
2015 for (
auto [operandType, argumentType] :
2016 llvm::zip(callType.getParams(), calleeType.getParams()))
2017 if (operandType != argumentType)
2023 FailureOr<LLVMFunctionType>
2024 ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2025 bool &isIncompatibleCall) {
2026 isIncompatibleCall =
false;
2027 auto castOrFailure = [](
Type convertedType) -> FailureOr<LLVMFunctionType> {
2028 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2034 llvm::Value *calledOperand = callInst->getCalledOperand();
2035 FailureOr<LLVMFunctionType> callType =
2036 castOrFailure(
convertType(callInst->getFunctionType()));
2037 if (failed(callType))
2039 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2044 FailureOr<LLVMFunctionType> calleeType =
2045 castOrFailure(
convertType(callee->getFunctionType()));
2046 if (failed(calleeType))
2052 isIncompatibleCall =
true;
2054 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2055 <<
" and " << *calleeType;
2063 llvm::Value *calledOperand = callInst->getCalledOperand();
2064 if (
auto *callee = dyn_cast<llvm::Function>(calledOperand))
2069 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2074 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2078 ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2079 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2080 unsigned argIdx = 0;
2082 bool hasIndirect =
false;
2084 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2086 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2091 if (ci.isIndirect) {
2092 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2095 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2107 return hasIndirect ?
ArrayAttr::get(mlirModule->getContext(), opAttrs)
2111 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2114 if (inst->getOpcode() == llvm::Instruction::Br) {
2115 auto *brInst = cast<llvm::BranchInst>(inst);
2119 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2120 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2122 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
2125 succBlockArgs.push_back(blockArgs);
2128 if (!brInst->isConditional()) {
2129 auto brOp = builder.
create<LLVM::BrOp>(loc, succBlockArgs.front(),
2130 succBlocks.front());
2134 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2135 if (failed(condition))
2137 auto condBrOp = builder.
create<LLVM::CondBrOp>(
2138 loc, *condition, succBlocks.front(), succBlockArgs.front(),
2139 succBlocks.back(), succBlockArgs.back());
2143 if (inst->getOpcode() == llvm::Instruction::Switch) {
2144 auto *swInst = cast<llvm::SwitchInst>(inst);
2146 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2147 if (failed(condition))
2151 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2152 if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2156 unsigned numCases = swInst->getNumCases();
2162 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2163 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2164 if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2166 caseOperandRefs[it.index()] = caseOperands[it.index()];
2167 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2171 auto switchOp = builder.
create<SwitchOp>(
2172 loc, *condition,
lookupBlock(defaultBB), defaultBlockArgs, caseValues,
2173 caseBlocks, caseOperandRefs);
2177 if (inst->getOpcode() == llvm::Instruction::PHI) {
2183 if (inst->getOpcode() == llvm::Instruction::Call) {
2184 auto *callInst = cast<llvm::CallInst>(inst);
2185 llvm::Value *calledOperand = callInst->getCalledOperand();
2187 FailureOr<SmallVector<Value>> operands =
2188 convertCallOperands(callInst,
true);
2189 if (failed(operands))
2192 auto callOp = [&]() -> FailureOr<Operation *> {
2193 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2197 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2200 loc, resultTy, *operands,
2203 asmI->hasSideEffects(), asmI->isAlignStack(),
2205 mlirModule.getContext(),
2206 convertAsmDialectFromLLVM(asmI->getDialect())),
2210 bool isIncompatibleCall;
2211 FailureOr<LLVMFunctionType> funcTy =
2212 convertFunctionType(callInst, isIncompatibleCall);
2217 if (isIncompatibleCall) {
2222 Value indirectCallVal = builder.
create<LLVM::AddressOfOp>(
2224 operands->insert(operands->begin(), indirectCallVal);
2227 callee = convertCalleeName(callInst);
2229 CallOp callOp = builder.
create<CallOp>(loc, *funcTy, callee, *operands);
2231 if (failed(convertCallAttributes(callInst, callOp)))
2236 if (!isIncompatibleCall)
2238 return callOp.getOperation();
2244 if (!callInst->getType()->isVoidTy())
2245 mapValue(inst, (*callOp)->getResult(0));
2250 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2251 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2254 operands.reserve(lpInst->getNumClauses());
2255 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2256 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2257 if (failed(operand))
2259 operands.push_back(*operand);
2264 builder.
create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
2268 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2269 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2271 if (invokeInst->isInlineAsm())
2272 return emitError(loc) <<
"invoke of inline assembly is not supported";
2274 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2275 if (failed(operands))
2280 bool invokeResultUsedInPhi = llvm::any_of(
2281 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2282 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2287 Block *directNormalDest = normalDest;
2288 if (invokeResultUsedInPhi) {
2294 directNormalDest = builder.
createBlock(normalDest);
2298 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2302 bool isIncompatibleInvoke;
2303 FailureOr<LLVMFunctionType> funcTy =
2304 convertFunctionType(invokeInst, isIncompatibleInvoke);
2309 if (isIncompatibleInvoke) {
2314 Value indirectInvokeVal = builder.
create<LLVM::AddressOfOp>(
2316 operands->insert(operands->begin(), indirectInvokeVal);
2319 calleeName = convertCalleeName(invokeInst);
2324 auto invokeOp = builder.
create<InvokeOp>(
2325 loc, *funcTy, calleeName, *operands, directNormalDest,
ValueRange(),
2326 lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
2328 if (failed(convertInvokeAttributes(invokeInst, invokeOp)))
2333 if (!isIncompatibleInvoke)
2336 if (!invokeInst->getType()->isVoidTy())
2337 mapValue(inst, invokeOp.getResults().front());
2342 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2346 if (invokeResultUsedInPhi) {
2352 builder.
create<LLVM::BrOp>(loc, normalArgs, normalDest);
2356 assert(llvm::none_of(
2359 "An llvm.invoke operation cannot pass its result as a block "
2361 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2366 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2367 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2368 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2369 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2370 if (failed(basePtr))
2378 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2382 indices.push_back(*index);
2386 auto gepOp = builder.
create<GEPOp>(
2387 loc, type, sourceElementType, *basePtr, indices,
2388 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2393 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2394 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2396 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2397 if (failed(basePtr))
2402 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2403 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2405 if (failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2408 succBlockArgs.push_back(blockArgs);
2411 llvm::to_vector_of<ValueRange>(succBlockArgs);
2413 auto indBrOp = builder.
create<LLVM::IndirectBrOp>(
2414 loc, *basePtr, succBlockArgsRange, succBlocks);
2424 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2427 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2434 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2435 return convertIntrinsic(intrinsic);
2438 return convertInstruction(inst);
2442 if (!f->hasPersonalityFn())
2445 llvm::Constant *pf = f->getPersonalityFn();
2453 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2454 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2455 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2456 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2464 llvm::MemoryEffects memEffects = func->getMemoryEffects();
2466 auto othermem = convertModRefInfoFromLLVM(
2467 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2468 auto argMem = convertModRefInfoFromLLVM(
2469 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2470 auto inaccessibleMem = convertModRefInfoFromLLVM(
2471 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2475 if (memAttr.isReadWrite())
2477 funcOp.setMemoryEffectsAttr(memAttr);
2483 StringLiteral(
"aarch64_in_za"),
2484 StringLiteral(
"aarch64_inout_za"),
2485 StringLiteral(
"aarch64_new_za"),
2486 StringLiteral(
"aarch64_out_za"),
2487 StringLiteral(
"aarch64_preserves_za"),
2488 StringLiteral(
"aarch64_pstate_sm_body"),
2489 StringLiteral(
"aarch64_pstate_sm_compatible"),
2490 StringLiteral(
"aarch64_pstate_sm_enabled"),
2491 StringLiteral(
"alwaysinline"),
2492 StringLiteral(
"approx-func-fp-math"),
2493 StringLiteral(
"convergent"),
2494 StringLiteral(
"denormal-fp-math"),
2495 StringLiteral(
"denormal-fp-math-f32"),
2496 StringLiteral(
"fp-contract"),
2497 StringLiteral(
"frame-pointer"),
2498 StringLiteral(
"instrument-function-entry"),
2499 StringLiteral(
"instrument-function-exit"),
2500 StringLiteral(
"no-infs-fp-math"),
2501 StringLiteral(
"no-nans-fp-math"),
2502 StringLiteral(
"no-signed-zeros-fp-math"),
2503 StringLiteral(
"noinline"),
2504 StringLiteral(
"nounwind"),
2505 StringLiteral(
"optnone"),
2506 StringLiteral(
"target-features"),
2507 StringLiteral(
"tune-cpu"),
2508 StringLiteral(
"unsafe-fp-math"),
2509 StringLiteral(
"uwtable"),
2510 StringLiteral(
"vscale_range"),
2511 StringLiteral(
"willreturn"),
2517 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
2518 llvm::AttributeList::AttrIndex::FunctionIndex);
2519 for (llvm::Attribute attr : funcAttrs) {
2522 if (attr.hasAttribute(llvm::Attribute::Memory))
2526 if (attr.isTypeAttribute()) {
2528 "type attributes on a function are invalid, skipping it");
2533 if (attr.isStringAttribute())
2534 attrName = attr.getKindAsString();
2536 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
2543 if (attr.isStringAttribute()) {
2544 StringRef val = attr.getValueAsString();
2546 passthroughs.push_back(keyAttr);
2549 passthroughs.push_back(
2553 if (attr.isIntAttribute()) {
2554 auto val = std::to_string(attr.getValueAsInt());
2555 passthroughs.push_back(
2559 if (attr.isEnumAttribute()) {
2560 passthroughs.push_back(keyAttr);
2564 llvm_unreachable(
"unexpected attribute kind");
2567 if (!passthroughs.empty())
2568 funcOp.setPassthroughAttr(
ArrayAttr::get(context, passthroughs));
2572 LLVMFuncOp funcOp) {
2576 if (func->hasFnAttribute(llvm::Attribute::NoInline))
2577 funcOp.setNoInline(
true);
2578 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2579 funcOp.setAlwaysInline(
true);
2580 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2581 funcOp.setOptimizeNone(
true);
2582 if (func->hasFnAttribute(llvm::Attribute::Convergent))
2583 funcOp.setConvergent(
true);
2584 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
2585 funcOp.setNoUnwind(
true);
2586 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
2587 funcOp.setWillReturn(
true);
2589 if (func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2590 funcOp.setArmStreaming(
true);
2591 else if (func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2592 funcOp.setArmLocallyStreaming(
true);
2593 else if (func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2594 funcOp.setArmStreamingCompatible(
true);
2596 if (func->hasFnAttribute(
"aarch64_new_za"))
2597 funcOp.setArmNewZa(
true);
2598 else if (func->hasFnAttribute(
"aarch64_in_za"))
2599 funcOp.setArmInZa(
true);
2600 else if (func->hasFnAttribute(
"aarch64_out_za"))
2601 funcOp.setArmOutZa(
true);
2602 else if (func->hasFnAttribute(
"aarch64_inout_za"))
2603 funcOp.setArmInoutZa(
true);
2604 else if (func->hasFnAttribute(
"aarch64_preserves_za"))
2605 funcOp.setArmPreservesZa(
true);
2607 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
2608 if (attr.isValid()) {
2617 if (func->hasFnAttribute(
"frame-pointer")) {
2618 StringRef stringRefFramePointerKind =
2619 func->getFnAttribute(
"frame-pointer").getValueAsString();
2621 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2622 stringRefFramePointerKind)
2626 if (llvm::Attribute attr = func->getFnAttribute(
"target-cpu");
2627 attr.isStringAttribute())
2628 funcOp.setTargetCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
2630 if (llvm::Attribute attr = func->getFnAttribute(
"tune-cpu");
2631 attr.isStringAttribute())
2632 funcOp.setTuneCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
2634 if (llvm::Attribute attr = func->getFnAttribute(
"target-features");
2635 attr.isStringAttribute())
2636 funcOp.setTargetFeaturesAttr(
2639 if (llvm::Attribute attr = func->getFnAttribute(
"unsafe-fp-math");
2640 attr.isStringAttribute())
2641 funcOp.setUnsafeFpMath(attr.getValueAsBool());
2643 if (llvm::Attribute attr = func->getFnAttribute(
"no-infs-fp-math");
2644 attr.isStringAttribute())
2645 funcOp.setNoInfsFpMath(attr.getValueAsBool());
2647 if (llvm::Attribute attr = func->getFnAttribute(
"no-nans-fp-math");
2648 attr.isStringAttribute())
2649 funcOp.setNoNansFpMath(attr.getValueAsBool());
2651 if (llvm::Attribute attr = func->getFnAttribute(
"approx-func-fp-math");
2652 attr.isStringAttribute())
2653 funcOp.setApproxFuncFpMath(attr.getValueAsBool());
2655 if (llvm::Attribute attr = func->getFnAttribute(
"instrument-function-entry");
2656 attr.isStringAttribute())
2657 funcOp.setInstrumentFunctionEntry(
2660 if (llvm::Attribute attr = func->getFnAttribute(
"instrument-function-exit");
2661 attr.isStringAttribute())
2662 funcOp.setInstrumentFunctionExit(
2665 if (llvm::Attribute attr = func->getFnAttribute(
"no-signed-zeros-fp-math");
2666 attr.isStringAttribute())
2667 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2669 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math");
2670 attr.isStringAttribute())
2671 funcOp.setDenormalFpMathAttr(
2674 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math-f32");
2675 attr.isStringAttribute())
2676 funcOp.setDenormalFpMathF32Attr(
2679 if (llvm::Attribute attr = func->getFnAttribute(
"fp-contract");
2680 attr.isStringAttribute())
2681 funcOp.setFpContractAttr(
StringAttr::get(context, attr.getValueAsString()));
2683 if (func->hasUWTable()) {
2684 ::llvm::UWTableKind uwtableKind = func->getUWTableKind();
2686 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2691 ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
2695 auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
2697 if (!llvmAttr.isValid())
2702 if (llvmAttr.hasKindAsEnum() &&
2703 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2704 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2705 paramAttrs.push_back(
2711 if (llvmAttr.isTypeAttribute())
2713 else if (llvmAttr.isIntAttribute())
2715 else if (llvmAttr.isEnumAttribute())
2717 else if (llvmAttr.isConstantRangeAttribute()) {
2718 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2719 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2722 llvm_unreachable(
"unexpected parameter attribute kind");
2724 paramAttrs.push_back(builder.
getNamedAttr(mlirName, mlirAttr));
2733 auto llvmAttrs = func->getAttributes();
2734 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2735 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2736 funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder));
2740 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2741 if (!llvmResAttr.hasAttributes())
2743 funcOp.setResAttrsAttr(
2744 builder.
getArrayAttr(convertParameterAttribute(llvmResAttr, builder)));
2748 ArrayAttr &argsAttr,
2751 llvm::AttributeList llvmAttrs = call->getAttributes();
2753 bool anyArgAttrs =
false;
2754 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
2755 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
2756 if (llvmArgAttrsSet.back().hasAttributes())
2761 for (
auto &dict : dictAttrs)
2767 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
2768 argAttrs.emplace_back(convertParameterAttribute(llvmArgAttrs, builder));
2769 argsAttr = getArrayAttr(argAttrs);
2772 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2773 if (!llvmResAttr.hasAttributes())
2775 DictionaryAttr resAttrs = convertParameterAttribute(llvmResAttr, builder);
2776 resAttr = getArrayAttr({resAttrs});
2780 CallOpInterface callOp,
2782 ArrayAttr argsAttr, resAttr;
2784 callOp.setArgAttrsAttr(argsAttr);
2785 callOp.setResAttrsAttr(resAttr);
2788 template <
typename Op>
2790 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
2794 LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
2799 LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
2805 llvm::AttributeList callAttrs = inst->getAttributes();
2807 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
2808 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
2809 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
2810 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
2811 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
2813 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
2814 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
2816 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
2817 ModRefInfo othermem = convertModRefInfoFromLLVM(
2818 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2819 ModRefInfo argMem = convertModRefInfoFromLLVM(
2820 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2821 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
2822 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2826 if (!memAttr.isReadWrite())
2827 op.setMemoryEffectsAttr(memAttr);
2836 dyn_cast<LLVMFunctionType>(
convertType(func->getFunctionType()));
2837 if (func->isIntrinsic() &&
2841 bool dsoLocal = func->isDSOLocal();
2842 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
2848 Location loc = debugImporter->translateFuncLocation(func);
2849 LLVMFuncOp funcOp = builder.
create<LLVMFuncOp>(
2850 loc, func->getName(), functionType,
2851 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
2856 funcOp.setPersonalityAttr(personality);
2857 else if (func->hasPersonalityFn())
2858 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
2861 funcOp.setGarbageCollector(StringRef(func->getGC()));
2863 if (func->hasAtLeastLocalUnnamedAddr())
2864 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
2866 if (func->hasSection())
2867 funcOp.setSection(StringRef(func->getSection()));
2869 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
2871 if (func->hasComdat())
2872 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
2874 if (llvm::MaybeAlign maybeAlign = func->getAlign())
2875 funcOp.setAlignment(maybeAlign->value());
2882 func->getAllMetadata(allMetadata);
2883 for (
auto &[
kind, node] : allMetadata) {
2888 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
2889 <<
" on " <<
diag(*func);
2893 if (func->isDeclaration())
2902 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
2903 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
2908 for (llvm::BasicBlock &basicBlock : *func) {
2910 if (!reachable.contains(&basicBlock)) {
2911 if (basicBlock.hasAddressTaken())
2913 <<
"unreachable block '" << basicBlock.getName()
2914 <<
"' with address taken";
2917 Region &body = funcOp.getBody();
2920 reachableBasicBlocks.push_back(&basicBlock);
2925 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
2926 functionType.getParamType(it.index()), funcOp.getLoc());
2935 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
2936 for (llvm::BasicBlock *basicBlock : blocks)
2937 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
2942 if (failed(processDebugIntrinsics()))
2951 if (!dbgIntr->isKillLocation())
2953 llvm::Value *value = dbgIntr->getArgOperand(0);
2954 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2957 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2961 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
2964 auto emitUnsupportedWarning = [&]() {
2965 if (emitExpensiveWarnings)
2971 if (dbgIntr->hasArgList())
2972 return emitUnsupportedWarning();
2977 return emitUnsupportedWarning();
2981 DILocalVariableAttr localVariableAttr =
2983 if (!localVariableAttr)
2984 return emitUnsupportedWarning();
2986 if (failed(argOperand))
2987 return emitError(loc) <<
"failed to convert a debug intrinsic operand: "
2995 if (
Operation *op = argOperand->getDefiningOp();
2998 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3001 if (dominatedBlocks.empty())
3002 return emitUnsupportedWarning();
3005 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3008 Value insertPt = *argOperand;
3009 if (
auto blockArg = dyn_cast<BlockArgument>(*argOperand)) {
3014 Block *insertionBlock = argOperand->getParentBlock();
3015 if (!insertionBlock->
empty() &&
3016 isa<LandingpadOp>(insertionBlock->
front()))
3017 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3022 auto locationExprAttr =
3023 debugImporter->translateExpression(dbgIntr->getExpression());
3026 .Case([&](llvm::DbgDeclareInst *) {
3027 return builder.
create<LLVM::DbgDeclareOp>(
3028 loc, *argOperand, localVariableAttr, locationExprAttr);
3030 .Case([&](llvm::DbgValueInst *) {
3031 return builder.
create<LLVM::DbgValueOp>(
3032 loc, *argOperand, localVariableAttr, locationExprAttr);
3035 setNonDebugMetadataAttrs(dbgIntr, op);
3039 LogicalResult ModuleImport::processDebugIntrinsics() {
3041 for (llvm::Instruction *inst : debugIntrinsics) {
3042 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3043 if (failed(processDebugIntrinsic(intrCall, domInfo)))
3049 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3052 for (llvm::Instruction &inst : *bb) {
3053 if (failed(processInstruction(&inst)))
3058 if (debugIntrinsics.contains(&inst))
3065 setNonDebugMetadataAttrs(&inst, op);
3066 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3067 if (emitExpensiveWarnings) {
3068 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3074 if (bb->hasAddressTaken()) {
3083 FailureOr<SmallVector<AccessGroupAttr>>
3085 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3091 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3094 FailureOr<DereferenceableAttr>
3097 Location loc = mlirModule.getLoc();
3101 if (node->getNumOperands() != 1)
3102 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3103 <<
diagMD(node, llvmModule.get());
3105 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3106 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3107 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3108 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3109 "non-negative constant integer: "
3110 <<
diagMD(node, llvmModule.get());
3112 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3113 auto derefAttr = builder.
getAttr<DereferenceableAttr>(
3114 numBytesCst->getZExtValue(), mayBeNull);
3120 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3121 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3122 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3123 bool importStructsAsLiterals) {
3130 LLVMDialect::getDialectNamespace()));
3132 DLTIDialect::getDialectNamespace()));
3133 if (loadAllDialects)
3140 emitExpensiveWarnings, dropDICompositeTypeElements,
3141 preferUnregisteredIntrinsics,
3142 importStructsAsLiterals);
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1194::ArityGroupAndKind::Kind kind
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static constexpr std::array kExplicitAttributes
static StringRef getLLVMSyncScope(llvm::Instruction *inst)
Converts the sync scope identifier of inst to the string representation necessary to build an atomic ...
static std::string diag(const llvm::Value &value)
static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp)
static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op)
static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, llvm::MDTuple *mdTuple)
static constexpr StringRef getGlobalDtorsVarName()
Returns the name of the global_dtors global variables.
static llvm::ConstantAsMetadata * getConstantMDFromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey, bool optional=false)
Extract a constant metadata value from a two element tuple (<key, value>).
static Type getVectorTypeForAttr(Type type, ArrayRef< int64_t > arrayShape={})
Returns type if it is a builtin integer or floating-point vector type that can be used to create an a...
static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder, llvm::Instruction *inst, ModuleImport &moduleImport, LLVMImportInterface &iface)
Converts the LLVM instructions that have a generated MLIR builder.
static constexpr StringRef getNamelessGlobalPrefix()
Prefix used for symbols of nameless llvm globals.
static Attribute convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, StringRef key, llvm::MDTuple *mdTuple)
Invoke specific handlers for each known module flag value, returns nullptr if the key is unknown or u...
static constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static LogicalResult checkFunctionTypeCompatibility(LLVMFunctionType callType, LLVMFunctionType calleeType)
Checks if callType and calleeType are compatible and can be represented in MLIR.
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static Attribute convertProfileSummaryModuleFlagValue(ModuleOp mlirModule, const llvm::Module *llvmModule, llvm::MDTuple *mdTuple)
static std::optional< ProfileSummaryFormatKind > convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &formatMD)
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
static llvm::MDTuple * getTwoElementMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md)
Extract a two element MDTuple from a MDOperand.
static TypedAttr getScalarConstantAsAttr(OpBuilder &builder, llvm::Constant *constScalar)
Returns an integer or float attribute for the provided scalar constant constScalar or nullptr if the ...
static SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(ArrayRef< llvm::BasicBlock * > basicBlocks)
Get a topologically sorted list of blocks for the given basic blocks.
static std::string diagMD(const llvm::Metadata *node, const llvm::Module *module)
static FailureOr< SmallVector< ModuleFlagProfileSummaryDetailedAttr > > convertProfileSummaryDetailed(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &summaryMD)
static FailureOr< uint64_t > convertInt64FromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey)
Extract an integer value from a two element tuple (<key, value>).
static SmallVector< Attribute > getSequenceConstantAsAttrs(OpBuilder &builder, llvm::ConstantDataSequential *constSequence)
Returns an integer or float attribute array for the provided constant sequence constSequence or nullp...
static llvm::ManagedStatic< PassManagerOptions > options
static void contract(RootOrderingGraph &graph, ArrayRef< Value > cycle, const DenseMap< Value, unsigned > &parentDepths, DenseMap< Value, Value > &actualSource, DenseMap< Value, Value > &actualTarget)
Contracts the specified cycle in the given graph in-place.
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
IntegerAttr getI32IntegerAttr(int32_t value)
IntegerAttr getIntegerAttr(Type type, int64_t value)
ArrayAttr getI32ArrayAttr(ArrayRef< int32_t > values)
FloatAttr getFloatAttr(Type type, double value)
IntegerAttr getI64IntegerAttr(int64_t value)
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
MLIRContext * getContext() const
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
A class for computing basic dominance information.
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
StringRef getValue() const
Returns the name of the held symbol reference.
Interface collection for the import of LLVM IR that dispatches to a concrete dialect interface implem...
LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst, ArrayRef< llvm::Value * > llvmOperands, LLVM::ModuleImport &moduleImport) const
Converts the LLVM instruction to an MLIR operation if a conversion exists.
LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst, LLVM::ModuleImport &moduleImport) const
Converts the LLVM intrinsic to an MLIR operation if a conversion exists.
LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) const
Attaches the given LLVM metadata to the imported operation if a conversion to one or more MLIR dialec...
bool isConvertibleMetadata(unsigned kind)
Returns true if the given LLVM IR metadata is convertible to an MLIR attribute.
bool isConvertibleInstruction(unsigned id)
Returns true if the given LLVM IR instruction is convertible to an MLIR operation.
bool isConvertibleIntrinsic(llvm::Intrinsic::ID id)
Returns true if the given LLVM IR intrinsic is convertible to an MLIR operation.
Module import implementation class that provides methods to import globals and functions from an LLVM...
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, ArrayRef< llvm::OperandBundleUse > opBundles, bool requiresOpBundles, ArrayRef< unsigned > immArgPositions, ArrayRef< StringLiteral > immArgAttrNames, SmallVectorImpl< Value > &valuesOut, SmallVectorImpl< NamedAttribute > &attrsOut)
Converts the LLVM values for an intrinsic to mixed MLIR values and attributes for LLVM_IntrOpBase.
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LogicalResult convertComdats()
Converts all comdat selectors of the LLVM module to MLIR comdat operations.
LogicalResult convertAliases()
Converts all aliases of the LLVM module to MLIR variables.
LogicalResult convertFunctions()
Converts all functions of the LLVM module to MLIR functions.
FailureOr< SmallVector< Value > > convertValues(ArrayRef< llvm::Value * > values)
Converts a range of LLVM values to a range of MLIR values using the convertValue method,...
DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value)
Converts value to a local variable attribute.
LogicalResult convertLinkerOptionsMetadata()
Converts !llvm.linker.options metadata to the llvm.linker.options LLVM dialect operation.
void mapBlock(llvm::BasicBlock *llvm, Block *mlir)
Stores the mapping between an LLVM block and its MLIR counterpart.
void processFunctionAttributes(llvm::Function *func, LLVMFuncOp funcOp)
Converts function attributes of LLVM Function func into LLVM dialect attributes of LLVMFuncOp funcOp.
LogicalResult convertMetadata()
Converts all LLVM metadata nodes that translate to attributes such as alias analysis or access group ...
void convertParameterAttributes(llvm::CallBase *call, ArrayAttr &argsAttr, ArrayAttr &resAttr, OpBuilder &builder)
Converts the parameter and result attributes in argsAttr and resAttr and add them to the callOp.
FailureOr< Value > convertValue(llvm::Value *value)
Converts an LLVM value to an MLIR value, or returns failure if the conversion fails.
LogicalResult initializeImportInterface()
Calls the LLVMImportInterface initialization that queries the registered dialect interfaces for the s...
void addDebugIntrinsic(llvm::CallInst *intrinsic)
Adds a debug intrinsics to the list of intrinsics that should be converted after the function convers...
LogicalResult convertIdentMetadata()
Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute.
Block * lookupBlock(llvm::BasicBlock *block) const
Returns the MLIR block mapped to the given LLVM block.
FailureOr< Value > convertMetadataValue(llvm::Value *value)
Converts an LLVM metadata value to an MLIR value, or returns failure if the conversion fails.
FailureOr< SmallVector< AliasScopeAttr > > lookupAliasScopeAttrs(const llvm::MDNode *node) const
Returns the alias scope attributes that map to the alias scope nodes starting from the metadata node.
void setDisjointFlag(llvm::Instruction *inst, Operation *op) const
Sets the disjoint flag attribute for the imported operation op given the original instruction inst.
void mapNoResultOp(llvm::Instruction *llvm, Operation *mlir)
Stores a mapping between an LLVM instruction and the imported MLIR operation if the operation returns...
void setExactFlag(llvm::Instruction *inst, Operation *op) const
Sets the exact flag attribute for the imported operation op given the original instruction inst.
Type convertType(llvm::Type *type)
Converts the type from LLVM to MLIR LLVM dialect.
Operation * lookupOperation(llvm::Instruction *inst)
Returns the MLIR operation mapped to the given LLVM instruction.
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes, bool preferUnregisteredIntrinsics, bool importStructsAsLiterals)
DILabelAttr matchLabelAttr(llvm::Value *value)
Converts value to a label attribute. Asserts if the matching fails.
FloatAttr matchFloatAttr(llvm::Value *value)
Converts value to a float attribute. Asserts if the matching fails.
LoopAnnotationAttr translateLoopAnnotationAttr(const llvm::MDNode *node, Location loc) const
Returns the loop annotation attribute that corresponds to the given LLVM loop metadata node.
void setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const
Sets the fastmath flags attribute for the imported operation op given the original instruction inst.
FailureOr< SmallVector< AliasScopeAttr > > matchAliasScopeAttrs(llvm::Value *value)
Converts value to an array of alias scopes or returns failure if the conversion fails.
Value lookupValue(llvm::Value *value)
Returns the MLIR value mapped to the given LLVM value.
LogicalResult processFunction(llvm::Function *func)
Imports func into the current module.
LogicalResult convertDependentLibrariesMetadata()
Converts !llvm.dependent-libraries metadata to llvm.dependent_libraries LLVM ModuleOp attribute.
RoundingModeAttr matchRoundingModeAttr(llvm::Value *value)
Converts value to a rounding mode attribute.
void convertTargetTriple()
Converts target triple of the LLVM module to an MLIR target triple specification.
LogicalResult convertModuleFlagsMetadata()
Converts !llvm.module.flags metadata.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
FailureOr< SmallVector< AccessGroupAttr > > lookupAccessGroupAttrs(const llvm::MDNode *node) const
Returns the access group attributes that map to the access group nodes starting from the access group...
LogicalResult convertGlobals()
Converts all global variables of the LLVM module to MLIR global variables.
void setIntegerOverflowFlags(llvm::Instruction *inst, Operation *op) const
Sets the integer overflow flags (nsw/nuw) attribute for the imported operation op given the original ...
LogicalResult convertCommandlineMetadata()
Converts !llvm.commandline metadata to the llvm.commandline LLVM ModuleOp attribute.
FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value)
Converts value to a FP exception behavior attribute.
void setNonNegFlag(llvm::Instruction *inst, Operation *op) const
Sets the nneg flag attribute for the imported operation op given the original instruction inst.
FailureOr< DereferenceableAttr > translateDereferenceableAttr(const llvm::MDNode *node, unsigned kindID)
Returns the dereferenceable attribute that corresponds to the given LLVM dereferenceable or dereferen...
LogicalResult convertDataLayout()
Converts the data layout of the LLVM module to an MLIR data layout specification.
IntegerAttr matchIntegerAttr(llvm::Value *value)
Converts value to an integer attribute. Asserts if the matching fails.
Helper class that translates an LLVM data layout to an MLIR data layout specification.
StringRef getLastToken() const
Returns the last data layout token that has been processed before the data layout translation failed.
DataLayoutSpecInterface getDataLayout() const
Returns the MLIR data layout specification translated from the LLVM data layout.
ArrayRef< StringRef > getUnhandledTokens() const
Returns the data layout tokens that have not been handled during the data layout translation.
A helper class that converts llvm.loop metadata nodes into corresponding LoopAnnotationAttrs and llvm...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
std::vector< StringRef > getAvailableDialects()
Return information about all available dialects in the registry in this context.
void loadAllAvailableDialects()
Load all dialects available in the registry in this context.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class provides the API for ops that are known to be terminators.
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Location getLoc()
The source location the operation was defined or derived from.
OpTy get() const
Allow accessing the internal op.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
DominanceInfoNode * getNode(Block *a)
Return the dominance node from the Region containing block A.
static llvm::ArrayRef< std::pair< llvm::Attribute::AttrKind, llvm::StringRef > > getAttrKindToNameMapping()
Returns a list of pairs that each hold a mapping from LLVM attribute kinds to their corresponding str...
FloatType getFloatType(MLIRContext *context, unsigned width)
Returns a supported MLIR floating point type of the given bit width or null if the bit width is not s...
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true, bool dropDICompositeTypeElements=false, bool loadAllDialects=true, bool preferUnregisteredIntrinsics=false, bool importStructsAsLiterals=false)
Translates the LLVM module into an MLIR module living in the given context.