30 #include "llvm/ADT/DepthFirstIterator.h"
31 #include "llvm/ADT/PostOrderIterator.h"
32 #include "llvm/ADT/ScopeExit.h"
33 #include "llvm/ADT/StringExtras.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"
154 for (llvm::BasicBlock *basicBlock : basicBlocks) {
155 if (!blocks.contains(basicBlock)) {
156 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
157 blocks.insert_range(traversal);
160 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
165 std::unique_ptr<llvm::Module> llvmModule,
166 bool emitExpensiveWarnings,
167 bool importEmptyDICompositeTypes,
168 bool preferUnregisteredIntrinsics,
169 bool importStructsAsLiterals)
171 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
173 typeTranslator(*mlirModule->
getContext(), importStructsAsLiterals),
175 mlirModule, importEmptyDICompositeTypes)),
176 loopAnnotationImporter(
178 emitExpensiveWarnings(emitExpensiveWarnings),
179 preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
183 ComdatOp ModuleImport::getGlobalComdatOp() {
185 return globalComdatOp;
191 globalInsertionOp = globalComdatOp;
192 return globalComdatOp;
195 LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
200 auto getIdentityIfRootNode =
201 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
205 if (node->getNumOperands() > 1)
208 if (node->getNumOperands() == 1)
209 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
210 return std::optional<StringRef>{op0->getString()};
211 return std::optional<StringRef>{};
221 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
222 StringRef *identity =
nullptr,
224 nullptr) -> std::optional<bool> {
225 unsigned numOperands = node->getNumOperands();
234 const auto *identityNode =
235 dyn_cast<const llvm::MDString>(node->getOperand(0));
241 *identity = identityNode->getString();
243 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
244 const auto *memberNode =
245 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
247 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
248 <<
diagMD(node, llvmModule.get());
252 if (2 * pairNum + 2 >= numOperands) {
254 if (numOperands != 2) {
255 emitError(loc) <<
"missing member offset: "
256 <<
diagMD(node, llvmModule.get());
260 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
261 node->getOperand(2 * pairNum + 2));
263 emitError(loc) <<
"operand '" << 2 * pairNum + 2
264 <<
"' must be ConstantInt: "
265 <<
diagMD(node, llvmModule.get());
268 offset = offsetCI->getZExtValue();
273 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
286 auto isTagNode = [&](
const llvm::MDNode *node,
287 TBAATypeDescriptorAttr *baseAttr =
nullptr,
288 TBAATypeDescriptorAttr *accessAttr =
nullptr,
289 int64_t *offset =
nullptr,
290 bool *isConstant =
nullptr) -> std::optional<bool> {
298 unsigned numOperands = node->getNumOperands();
299 if (numOperands != 3 && numOperands != 4)
301 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
302 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
304 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
305 if (!baseMD || !accessMD || !offsetCI)
312 if (accessMD->getNumOperands() < 1 ||
313 !isa<llvm::MDString>(accessMD->getOperand(0)))
315 bool isConst =
false;
316 if (numOperands == 4) {
318 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
320 emitError(loc) <<
"operand '3' must be ConstantInt: "
321 <<
diagMD(node, llvmModule.get());
324 isConst = isConstantCI->getValue()[0];
327 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
329 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
331 *offset = offsetCI->getZExtValue();
333 *isConstant = isConst;
342 workList.push_back(node);
343 while (!workList.empty()) {
344 const llvm::MDNode *current = workList.back();
345 if (tbaaMapping.contains(current)) {
354 bool anyChildNotConverted =
false;
355 for (
const llvm::MDOperand &operand : current->operands())
356 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
357 if (!tbaaMapping.contains(childNode)) {
358 workList.push_back(childNode);
359 anyChildNotConverted =
true;
362 if (anyChildNotConverted) {
367 if (!seen.insert(current).second)
368 return emitError(loc) <<
"has cycle in TBAA graph: "
369 <<
diagMD(current, llvmModule.get());
377 FailureOr<std::optional<StringRef>> rootNodeIdentity =
378 getIdentityIfRootNode(current);
379 if (succeeded(rootNodeIdentity)) {
380 StringAttr stringAttr = *rootNodeIdentity
385 tbaaMapping.insert({current, builder.
getAttr<TBAARootAttr>(stringAttr)});
391 if (std::optional<bool> isValid =
392 isTypeDescriptorNode(current, &identity, &members)) {
393 assert(isValid.value() &&
"type descriptor node must be valid");
395 tbaaMapping.insert({current, builder.
getAttr<TBAATypeDescriptorAttr>(
396 identity, members)});
400 TBAATypeDescriptorAttr baseAttr, accessAttr;
403 if (std::optional<bool> isValid =
404 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
405 assert(isValid.value() &&
"access tag node must be valid");
407 {current, builder.
getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
412 return emitError(loc) <<
"unsupported TBAA node format: "
413 <<
diagMD(current, llvmModule.get());
419 ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
421 if (
failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
422 return emitError(loc) <<
"unsupported access group node: "
423 <<
diagMD(node, llvmModule.get());
428 ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
431 auto verifySelfRef = [](
const llvm::MDNode *node) {
432 return node->getNumOperands() != 0 &&
433 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
435 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
436 return node->getNumOperands() != 0 &&
437 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
438 isa<llvm::MDString>(node->getOperand(0)));
441 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
442 return idx >= node->getNumOperands() ||
443 isa<llvm::MDString>(node->getOperand(idx));
446 auto getIdAttr = [&](
const llvm::MDNode *node) ->
Attribute {
447 if (verifySelfRef(node))
450 auto name = cast<llvm::MDString>(node->getOperand(0));
455 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
456 StringAttr description =
nullptr;
457 if (aliasDomain->getNumOperands() >= 2)
458 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
460 Attribute idAttr = getIdAttr(aliasDomain);
461 return builder.
getAttr<AliasScopeDomainAttr>(idAttr, description);
465 for (
const llvm::MDOperand &operand : node->operands()) {
466 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
467 llvm::AliasScopeNode aliasScope(scope);
468 const llvm::MDNode *domain = aliasScope.getDomain();
474 if (!verifySelfRefOrString(scope) || !domain ||
475 !verifyDescription(scope, 2))
476 return emitError(loc) <<
"unsupported alias scope node: "
477 <<
diagMD(scope, llvmModule.get());
478 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
479 return emitError(loc) <<
"unsupported alias domain node: "
480 <<
diagMD(domain, llvmModule.get());
482 if (aliasScopeMapping.contains(scope))
486 auto it = aliasScopeMapping.find(aliasScope.getDomain());
487 if (it == aliasScopeMapping.end()) {
488 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
489 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
493 StringAttr description =
nullptr;
494 if (!aliasScope.getName().empty())
497 auto aliasScopeOp = builder.
getAttr<AliasScopeAttr>(
498 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
500 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
506 FailureOr<SmallVector<AliasScopeAttr>>
509 aliasScopes.reserve(node->getNumOperands());
510 for (
const llvm::MDOperand &operand : node->operands()) {
511 auto *node = cast<llvm::MDNode>(operand.get());
512 aliasScopes.push_back(
513 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
516 if (llvm::is_contained(aliasScopes,
nullptr))
522 debugIntrinsics.insert(intrinsic);
526 llvm::MDTuple *mdTuple) {
527 auto getLLVMFunction =
528 [&](
const llvm::MDOperand &funcMDO) -> llvm::Function * {
529 auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);
533 auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());
539 for (
unsigned i = 0; i < mdTuple->getNumOperands(); i++) {
540 const llvm::MDOperand &mdo = mdTuple->getOperand(i);
541 auto *cgEntry = cast<llvm::MDNode>(mdo);
542 llvm::Constant *llvmConstant =
543 cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();
544 uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();
545 auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));
546 auto *toFn = getLLVMFunction(cgEntry->getOperand(1));
549 mlirModule->getContext(),
563 const llvm::Module *llvmModule,
564 const llvm::MDOperand &md) {
565 auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
566 if (!tupleEntry || tupleEntry->getNumOperands() != 2)
568 <<
"expected 2-element tuple metadata: " <<
diagMD(md, llvmModule);
576 ModuleOp mlirModule,
const llvm::Module *llvmModule,
577 const llvm::MDOperand &md, StringRef matchKey,
bool optional =
false) {
581 auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
582 if (!keyMD || keyMD->getString() != matchKey) {
585 <<
"expected '" << matchKey <<
"' key, but found: "
586 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
590 return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));
596 static FailureOr<uint64_t>
598 const llvm::Module *llvmModule,
599 const llvm::MDOperand &md, StringRef matchKey) {
600 llvm::ConstantAsMetadata *valMD =
605 if (
auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))
606 return cstInt->getZExtValue();
609 <<
"expected integer metadata value for key '" << matchKey
610 <<
"': " <<
diagMD(md, llvmModule);
614 static std::optional<ProfileSummaryFormatKind>
616 const llvm::MDOperand &formatMD) {
621 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
622 if (!keyMD || keyMD->getString() !=
"ProfileFormat") {
624 <<
"expected 'ProfileFormat' key: "
625 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
629 llvm::MDString *valMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(1));
630 std::optional<ProfileSummaryFormatKind> fmtKind =
631 symbolizeProfileSummaryFormatKind(valMD->getString());
634 <<
"expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
636 <<
diagMD(valMD, llvmModule);
643 static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
645 const llvm::Module *llvmModule,
646 const llvm::MDOperand &summaryMD) {
651 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
652 if (!keyMD || keyMD->getString() !=
"DetailedSummary") {
654 <<
"expected 'DetailedSummary' key: "
655 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
659 llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
662 <<
"expected tuple value for 'DetailedSummary' key: "
663 <<
diagMD(tupleEntry->getOperand(1), llvmModule);
668 for (
auto &&entry : entriesMD->operands()) {
669 llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
670 if (!entryMD || entryMD->getNumOperands() != 3) {
672 <<
"'DetailedSummary' entry expects 3 operands: "
673 <<
diagMD(entry, llvmModule);
677 auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
678 auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
679 auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
680 if (!op0 || !op1 || !op2) {
682 <<
"expected only integer entries in 'DetailedSummary': "
683 <<
diagMD(entry, llvmModule);
688 mlirModule->getContext(),
689 cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
690 cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
691 cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
692 detailedSummary.push_back(detaildSummaryEntry);
694 return detailedSummary;
699 const llvm::Module *llvmModule,
700 llvm::MDTuple *mdTuple) {
701 unsigned profileNumEntries = mdTuple->getNumOperands();
702 if (profileNumEntries < 8) {
704 <<
"expected at 8 entries in 'ProfileSummary': "
705 <<
diagMD(mdTuple, llvmModule);
709 unsigned summayIdx = 0;
710 auto checkOptionalPosition = [&](
const llvm::MDOperand &md,
711 StringRef matchKey) -> LogicalResult {
715 if (summayIdx + 1 >= profileNumEntries) {
717 <<
"the last summary entry is '" << matchKey
718 <<
"', expected 'DetailedSummary': " <<
diagMD(md, llvmModule);
725 auto getOptIntValue =
726 [&](
const llvm::MDOperand &md,
727 StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
730 return FailureOr<std::optional<uint64_t>>(std::nullopt);
731 if (checkOptionalPosition(md, matchKey).failed())
733 FailureOr<uint64_t> val =
740 auto getOptDoubleValue = [&](
const llvm::MDOperand &md,
741 StringRef matchKey) -> FailureOr<FloatAttr> {
746 if (
auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
747 if (checkOptionalPosition(md, matchKey).
failed())
750 cstFP->getValueAPF());
753 <<
"expected double metadata value for key '" << matchKey
754 <<
"': " <<
diagMD(md, llvmModule);
761 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
762 if (!format.has_value())
766 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"TotalCount");
771 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"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");
793 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"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));
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 LLVM::ModuleFlagsOp::create(builder, 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 LLVM::LinkerOptionsOp::create(builder, 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 = ComdatSelectorOp::create(
990 builder, 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 for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1038 if (
failed(convertIFunc(&ifunc))) {
1040 <<
"unhandled global ifunc: " <<
diag(ifunc);
1047 Location loc = mlirModule.getLoc();
1049 context, llvmModule->getDataLayout().getStringRepresentation());
1051 return emitError(loc,
"cannot translate data layout: ")
1055 emitWarning(loc,
"unhandled data layout token: ") << token;
1057 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
1063 mlirModule->setAttr(
1064 LLVM::LLVMDialect::getTargetTripleAttrName(),
1065 builder.
getStringAttr(llvmModule->getTargetTriple().str()));
1069 llvm::StringRef asmStr = llvmModule->getModuleInlineAsm();
1072 for (llvm::StringRef line : llvm::split(asmStr,
'\n'))
1076 mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1081 for (llvm::Function &func : llvmModule->functions())
1087 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1090 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1091 for (
auto &[
kind, node] : allMetadata) {
1095 if (emitExpensiveWarnings) {
1096 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1098 <<
diagMD(node, llvmModule.get()) <<
" on "
1107 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1109 IntegerOverflowFlags value = {};
1110 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1112 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1114 iface.setOverflowFlags(value);
1118 auto iface = cast<ExactFlagInterface>(op);
1120 iface.setIsExact(inst->isExact());
1125 auto iface = cast<DisjointFlagInterface>(op);
1126 auto instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1128 iface.setIsDisjoint(instDisjoint->isDisjoint());
1132 auto iface = cast<NonNegFlagInterface>(op);
1134 iface.setNonNeg(inst->hasNonNeg());
1139 auto iface = cast<FastmathFlagsInterface>(op);
1145 if (!isa<llvm::FPMathOperator>(inst))
1147 llvm::FastMathFlags flags = inst->getFastMathFlags();
1150 FastmathFlags value = {};
1151 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1152 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1153 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1154 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1156 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1157 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1159 iface->setAttr(iface.getFastmathAttrName(), attr);
1171 if (numElements.isScalable()) {
1173 <<
"scalable vectors not supported";
1178 Type elementType = cast<VectorType>(type).getElementType();
1183 shape.push_back(numElements.getKnownMinValue());
1187 Type ModuleImport::getBuiltinTypeForAttr(
Type type) {
1202 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1203 arrayShape.push_back(arrayType.getNumElements());
1204 type = arrayType.getElementType();
1214 llvm::Constant *constScalar) {
1218 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1221 constInt->getValue());
1225 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1226 llvm::Type *type = constFloat->getType();
1227 FloatType floatType =
1233 <<
"unexpected floating-point type";
1236 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1245 llvm::ConstantDataSequential *constSequence) {
1247 elementAttrs.reserve(constSequence->getNumElements());
1248 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1249 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1252 return elementAttrs;
1255 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1261 auto getConstantShape = [&](llvm::Type *type) {
1262 return llvm::dyn_cast_if_present<ShapedType>(
1268 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1269 if (constArray->isString())
1271 auto shape = getConstantShape(constArray->getType());
1275 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1276 if (constVector && constVector->isSplat()) {
1279 builder, constVector->getElementAsConstant(0));
1290 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1291 auto shape = getConstantShape(constAggregate->getType());
1297 while (!workList.empty()) {
1298 llvm::Constant *current = workList.pop_back_val();
1301 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1303 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1304 workList.push_back(constAggregate->getAggregateElement(idx));
1309 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1312 elementAttrs.append(attrs.begin(), attrs.end());
1318 elementAttrs.push_back(scalarAttr);
1329 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1330 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1331 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1336 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1343 ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1344 assert(globalVar->getName().empty() &&
1345 "expected to work with a nameless global");
1346 auto [it, success] = namelessGlobals.try_emplace(globalVar);
1353 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1356 it->getSecond() = symbolRef;
1362 if (globalInsertionOp)
1369 LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1374 AliasOp aliasOp = AliasOp::create(builder, mlirModule.getLoc(), type,
1375 convertLinkageFromLLVM(alias->getLinkage()),
1377 alias->isDSOLocal(),
1378 alias->isThreadLocal(),
1380 globalInsertionOp = aliasOp;
1384 setConstantInsertionPointToStart(block);
1385 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1388 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1390 if (alias->hasAtLeastLocalUnnamedAddr())
1391 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1392 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1397 LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1401 llvm::Constant *resolver = ifunc->getResolver();
1403 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1404 resolver->getName(), resolverType,
1405 convertLinkageFromLLVM(ifunc->getLinkage()),
1406 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1407 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1408 convertVisibilityFromLLVM(ifunc->getVisibility()));
1417 llvm::AttributeSet attributes,
1420 for (llvm::Attribute attr : attributes) {
1422 if (attr.isStringAttribute())
1423 attrName = attr.getKindAsString();
1425 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1426 if (llvm::is_contained(attributesToSkip, attrName))
1430 if (attr.isStringAttribute()) {
1431 StringRef val = attr.getValueAsString();
1434 mlirAttributes.push_back(keyAttr);
1438 mlirAttributes.push_back(
1442 if (attr.isIntAttribute()) {
1445 auto val = std::to_string(attr.getValueAsInt());
1446 mlirAttributes.push_back(
1450 if (attr.isEnumAttribute()) {
1452 mlirAttributes.push_back(keyAttr);
1458 <<
"' attribute is invalid on current operation, skipping it";
1466 GlobalOp globalOp) {
1468 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1469 if (!targetSpecificAttrs.empty())
1470 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1473 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1478 if (globalVar->hasInitializer())
1479 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1482 uint64_t alignment = 0;
1483 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1484 if (maybeAlign.has_value()) {
1485 llvm::Align align = *maybeAlign;
1486 alignment = align.value();
1493 globalVar->getDebugInfo(globalExpressions);
1495 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1496 DIGlobalVariableExpressionAttr globalExpressionAttr =
1497 debugImporter->translateGlobalVariableExpression(expr);
1498 globalExpressionAttrs.push_back(globalExpressionAttr);
1503 StringRef globalName = globalVar->getName();
1504 if (globalName.empty())
1505 globalName = getOrCreateNamelessSymbolName(globalVar).
getValue();
1507 GlobalOp globalOp = GlobalOp::create(
1508 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1509 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1510 valueAttr, alignment, globalVar->getAddressSpace(),
1511 globalVar->isDSOLocal(),
1512 globalVar->isThreadLocal(), SymbolRefAttr(),
1514 globalInsertionOp = globalOp;
1516 if (globalVar->hasInitializer() && !valueAttr) {
1519 setConstantInsertionPointToStart(block);
1520 FailureOr<Value> initializer =
1521 convertConstantExpr(globalVar->getInitializer());
1524 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1526 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1527 globalOp.setUnnamedAddr(
1528 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1530 if (globalVar->hasSection())
1531 globalOp.setSection(globalVar->getSection());
1532 globalOp.setVisibility_(
1533 convertVisibilityFromLLVM(globalVar->getVisibility()));
1535 if (globalVar->hasComdat())
1536 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1544 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1545 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1547 llvm::Constant *initializer = globalVar->getInitializer();
1549 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1550 isa<llvm::ConstantAggregateZero>(initializer);
1557 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1558 if (caz->getElementCount().getFixedValue() != 0)
1565 for (llvm::Value *operand : initializer->operands()) {
1566 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1567 if (!aggregate || aggregate->getNumOperands() != 3)
1570 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1571 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1572 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1573 if (!priority || !func || !data)
1576 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1580 else if (data->isNullValue())
1586 priorities.push_back(priority->getValue().getZExtValue());
1587 dataList.push_back(dataAttr);
1594 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1595 builder, mlirModule.getLoc(), builder.
getArrayAttr(funcs),
1599 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1600 builder, mlirModule.getLoc(), builder.
getArrayAttr(funcs),
1606 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1608 if (valueMapping.contains(constant))
1617 workList.insert(constant);
1618 while (!workList.empty()) {
1619 llvm::Constant *current = workList.back();
1622 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1623 orderedSet.insert(current);
1624 workList.pop_back();
1630 auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);
1634 for (llvm::Value *operand : current->operands())
1635 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1636 adjacencyIt->getSecond().push_back(constDependency);
1639 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1640 unsigned numElements = constAgg->getElementCount().getFixedValue();
1641 for (
unsigned i = 0, e = numElements; i != e; ++i)
1642 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1648 if (adjacencyIt->getSecond().empty()) {
1649 orderedSet.insert(current);
1650 workList.pop_back();
1658 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1659 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1660 orderedSet.contains(dependency))
1662 workList.insert(dependency);
1668 FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1672 if (
Attribute attr = getConstantAsAttr(constant)) {
1674 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1675 return AddressOfOp::create(builder, loc, type, symbolRef.getValue())
1678 return ConstantOp::create(builder, loc, type, attr).getResult();
1682 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1684 return ZeroOp::create(builder, loc, type).getResult();
1688 if (isa<llvm::ConstantTokenNone>(constant)) {
1689 return NoneTokenOp::create(builder, loc).getResult();
1693 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1695 return PoisonOp::create(builder, loc, type).getResult();
1699 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1701 return UndefOp::create(builder, loc, type).getResult();
1705 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1707 return DSOLocalEquivalentOp::create(
1711 dsoLocalEquivalent->getGlobalValue()->getName()))
1716 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1718 StringRef globalName = globalObj->getName();
1721 if (globalName.empty())
1723 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1726 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1730 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1732 StringRef aliaseeName = globalAliasObj->getName();
1734 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1738 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1744 llvm::Instruction *inst = constExpr->getAsInstruction();
1745 auto guard = llvm::make_scope_exit([&]() {
1746 assert(!noResultOpMapping.contains(inst) &&
1747 "expected constant expression to return a result");
1748 valueMapping.erase(inst);
1749 inst->deleteValue();
1753 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1754 return valueMapping.contains(value);
1756 if (
failed(processInstruction(inst)))
1762 if (isa<llvm::ConstantAggregate>(constant) ||
1763 isa<llvm::ConstantAggregateZero>(constant)) {
1766 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1767 elementValues.reserve(constAgg->getNumOperands());
1768 for (llvm::Value *operand : constAgg->operands())
1771 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1772 unsigned numElements = constAgg->getElementCount().getFixedValue();
1773 elementValues.reserve(numElements);
1774 for (
unsigned i = 0, e = numElements; i != e; ++i)
1775 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1777 assert(llvm::count(elementValues,
nullptr) == 0 &&
1778 "expected all elements have been converted before");
1782 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1784 "unrecognized aggregate type");
1785 Value root = UndefOp::create(builder, loc, rootType);
1787 if (isArrayOrStruct) {
1789 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1793 ConstantOp::create(builder, loc, builder.
getI32Type(), indexAttr);
1794 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1801 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1802 LLVMTargetExtType targetExtType =
1803 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1804 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1805 "target extension type does not support zero-initialization");
1808 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1811 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1816 return BlockAddressOp::create(
1822 StringRef error =
"";
1824 if (isa<llvm::ConstantPtrAuth>(constant))
1825 error =
" since ptrauth(...) is unsupported";
1827 if (isa<llvm::NoCFIValue>(constant))
1828 error =
" since no_cfi is unsupported";
1830 if (isa<llvm::GlobalValue>(constant))
1831 error =
" since global value is unsupported";
1833 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1836 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1840 assert(!valueMapping.contains(constant) &&
1841 "expected constant has not been converted before");
1842 assert(constantInsertionBlock &&
1843 "expected the constant insertion block to be non-null");
1847 if (!constantInsertionOp)
1854 getConstantsToConvert(constant);
1855 for (llvm::Constant *constantToConvert : constantsToConvert) {
1856 FailureOr<Value> converted = convertConstant(constantToConvert);
1859 mapValue(constantToConvert, *converted);
1869 assert(!isa<llvm::MetadataAsValue>(value) &&
1870 "expected value to not be metadata");
1873 auto it = valueMapping.find(value);
1874 if (it != valueMapping.end())
1875 return it->getSecond();
1878 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1879 return convertConstantExpr(constant);
1882 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1884 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1890 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1893 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1896 value = node->getValue();
1899 auto it = valueMapping.find(value);
1900 if (it != valueMapping.end())
1901 return it->getSecond();
1904 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1905 return convertConstantExpr(constant);
1909 FailureOr<SmallVector<Value>>
1912 remapped.reserve(values.size());
1913 for (llvm::Value *value : values) {
1917 remapped.push_back(*converted);
1927 assert(immArgPositions.size() == immArgAttrNames.size() &&
1928 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1932 for (
auto [immArgPos, immArgName] :
1933 llvm::zip(immArgPositions, immArgAttrNames)) {
1934 auto &value = operands[immArgPos];
1935 auto *constant = llvm::cast<llvm::Constant>(value);
1937 assert(attr && attr.getType().isIntOrFloat() &&
1938 "expected immarg to be float or integer constant");
1940 attrsOut.push_back({nameAttr, attr});
1945 for (llvm::Value *value : operands) {
1951 valuesOut.push_back(*mlirValue);
1956 if (requiresOpBundles) {
1957 opBundleSizes.reserve(opBundles.size());
1958 opBundleTagAttrs.reserve(opBundles.size());
1960 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1961 opBundleSizes.push_back(bundle.Inputs.size());
1962 opBundleTagAttrs.push_back(
StringAttr::get(context, bundle.getTagName()));
1964 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1965 auto operandMlirValue =
convertValue(opBundleOperand.get());
1966 if (
failed(operandMlirValue))
1968 valuesOut.push_back(*operandMlirValue);
1973 auto opBundleSizesAttrNameAttr =
1975 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1977 auto opBundleTagsAttr =
ArrayAttr::get(context, opBundleTagAttrs);
1978 auto opBundleTagsAttrNameAttr =
1980 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1987 IntegerAttr integerAttr;
1989 bool success = succeeded(converted) &&
1991 assert(success &&
"expected a constant integer value");
1997 FloatAttr floatAttr;
2001 assert(success &&
"expected a constant float value");
2007 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2008 auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2009 return debugImporter->translate(node);
2013 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2014 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2015 return debugImporter->translate(node);
2018 FPExceptionBehaviorAttr
2020 auto *metadata = cast<llvm::MetadataAsValue>(value);
2021 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2022 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2023 llvm::convertStrToExceptionBehavior(mdstr->getString());
2024 assert(optLLVM &&
"Expecting FP exception behavior");
2025 return builder.
getAttr<FPExceptionBehaviorAttr>(
2026 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2030 auto *metadata = cast<llvm::MetadataAsValue>(value);
2031 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2032 std::optional<llvm::RoundingMode> optLLVM =
2033 llvm::convertStrToRoundingMode(mdstr->getString());
2034 assert(optLLVM &&
"Expecting rounding mode");
2035 return builder.
getAttr<RoundingModeAttr>(
2036 convertRoundingModeFromLLVM(*optLLVM));
2039 FailureOr<SmallVector<AliasScopeAttr>>
2041 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2042 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2047 return debugImporter->translateLoc(loc);
2051 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2052 llvm::BasicBlock *target,
2054 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2055 auto *phiInst = cast<llvm::PHINode>(&*inst);
2056 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2060 blockArguments.push_back(*converted);
2065 FailureOr<SmallVector<Value>>
2066 ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2067 bool allowInlineAsm) {
2068 bool isInlineAsm = callInst->isInlineAsm();
2069 if (isInlineAsm && !allowInlineAsm)
2079 llvm::Value *calleeOperand = callInst->getCalledOperand();
2080 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2084 operands.push_back(*called);
2088 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2092 llvm::append_range(operands, *arguments);
2098 static LogicalResult
2100 LLVMFunctionType calleeType) {
2101 if (callType.getReturnType() != calleeType.getReturnType())
2104 if (calleeType.isVarArg()) {
2107 if (callType.getNumParams() < calleeType.getNumParams())
2112 if (callType.getNumParams() != calleeType.getNumParams())
2117 for (
auto [operandType, argumentType] :
2118 llvm::zip(callType.getParams(), calleeType.getParams()))
2119 if (operandType != argumentType)
2125 FailureOr<LLVMFunctionType>
2126 ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2127 bool &isIncompatibleCall) {
2128 isIncompatibleCall =
false;
2129 auto castOrFailure = [](
Type convertedType) -> FailureOr<LLVMFunctionType> {
2130 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2136 llvm::Value *calledOperand = callInst->getCalledOperand();
2137 FailureOr<LLVMFunctionType> callType =
2138 castOrFailure(
convertType(callInst->getFunctionType()));
2141 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2143 llvm::FunctionType *origCalleeType =
nullptr;
2145 origCalleeType = callee->getFunctionType();
2146 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2147 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2151 if (!origCalleeType)
2154 FailureOr<LLVMFunctionType> calleeType =
2162 isIncompatibleCall =
true;
2164 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2165 <<
" and " << *calleeType;
2173 llvm::Value *calledOperand = callInst->getCalledOperand();
2174 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2179 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2184 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2188 ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2189 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2190 unsigned argIdx = 0;
2192 bool hasIndirect =
false;
2194 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2196 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2201 if (ci.isIndirect) {
2202 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2205 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2217 return hasIndirect ?
ArrayAttr::get(mlirModule->getContext(), opAttrs)
2221 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2224 if (inst->getOpcode() == llvm::Instruction::Br) {
2225 auto *brInst = cast<llvm::BranchInst>(inst);
2229 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2230 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2232 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2235 succBlockArgs.push_back(blockArgs);
2238 if (!brInst->isConditional()) {
2239 auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),
2240 succBlocks.front());
2244 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2247 auto condBrOp = LLVM::CondBrOp::create(
2248 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2249 succBlocks.back(), succBlockArgs.back());
2253 if (inst->getOpcode() == llvm::Instruction::Switch) {
2254 auto *swInst = cast<llvm::SwitchInst>(inst);
2256 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2261 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2262 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2266 unsigned numCases = swInst->getNumCases();
2272 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2273 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2274 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2276 caseOperandRefs[it.index()] = caseOperands[it.index()];
2277 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2281 auto switchOp = SwitchOp::create(builder, loc, *condition,
2283 caseValues, caseBlocks, caseOperandRefs);
2287 if (inst->getOpcode() == llvm::Instruction::PHI) {
2293 if (inst->getOpcode() == llvm::Instruction::Call) {
2294 auto *callInst = cast<llvm::CallInst>(inst);
2295 llvm::Value *calledOperand = callInst->getCalledOperand();
2297 FailureOr<SmallVector<Value>> operands =
2298 convertCallOperands(callInst,
true);
2302 auto callOp = [&]() -> FailureOr<Operation *> {
2303 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2307 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2308 return InlineAsmOp::create(
2309 builder, loc, resultTy, *operands,
2312 asmI->hasSideEffects(), asmI->isAlignStack(),
2313 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2315 mlirModule.getContext(),
2316 convertAsmDialectFromLLVM(asmI->getDialect())),
2320 bool isIncompatibleCall;
2321 FailureOr<LLVMFunctionType> funcTy =
2322 convertFunctionType(callInst, isIncompatibleCall);
2327 if (isIncompatibleCall) {
2332 Value indirectCallVal = LLVM::AddressOfOp::create(
2334 operands->insert(operands->begin(), indirectCallVal);
2337 callee = convertCalleeName(callInst);
2339 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2341 if (
failed(convertCallAttributes(callInst, callOp)))
2346 if (!isIncompatibleCall)
2348 return callOp.getOperation();
2354 if (!callInst->getType()->isVoidTy())
2355 mapValue(inst, (*callOp)->getResult(0));
2360 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2361 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2364 operands.reserve(lpInst->getNumClauses());
2365 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2366 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2369 operands.push_back(*operand);
2374 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2378 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2379 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2381 if (invokeInst->isInlineAsm())
2382 return emitError(loc) <<
"invoke of inline assembly is not supported";
2384 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2390 bool invokeResultUsedInPhi = llvm::any_of(
2391 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2392 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2397 Block *directNormalDest = normalDest;
2398 if (invokeResultUsedInPhi) {
2404 directNormalDest = builder.
createBlock(normalDest);
2408 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2412 bool isIncompatibleInvoke;
2413 FailureOr<LLVMFunctionType> funcTy =
2414 convertFunctionType(invokeInst, isIncompatibleInvoke);
2419 if (isIncompatibleInvoke) {
2424 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2426 operands->insert(operands->begin(), indirectInvokeVal);
2429 calleeName = convertCalleeName(invokeInst);
2434 auto invokeOp = InvokeOp::create(
2435 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2438 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2443 if (!isIncompatibleInvoke)
2446 if (!invokeInst->getType()->isVoidTy())
2447 mapValue(inst, invokeOp.getResults().front());
2452 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2456 if (invokeResultUsedInPhi) {
2462 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2466 assert(llvm::none_of(
2469 "An llvm.invoke operation cannot pass its result as a block "
2471 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2476 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2477 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2478 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2479 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2488 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2492 indices.push_back(*index);
2496 auto gepOp = GEPOp::create(
2497 builder, loc, type, sourceElementType, *basePtr, indices,
2498 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2503 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2504 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2506 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2512 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2513 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2515 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2518 succBlockArgs.push_back(blockArgs);
2521 llvm::to_vector_of<ValueRange>(succBlockArgs);
2523 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2524 succBlockArgsRange, succBlocks);
2534 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2537 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2544 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2545 return convertIntrinsic(intrinsic);
2548 return convertInstruction(inst);
2552 if (!f->hasPersonalityFn())
2555 llvm::Constant *pf = f->getPersonalityFn();
2563 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2564 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2565 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2566 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2574 llvm::MemoryEffects memEffects = func->getMemoryEffects();
2576 auto othermem = convertModRefInfoFromLLVM(
2577 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2578 auto argMem = convertModRefInfoFromLLVM(
2579 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2580 auto inaccessibleMem = convertModRefInfoFromLLVM(
2581 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2585 if (memAttr.isReadWrite())
2587 funcOp.setMemoryEffectsAttr(memAttr);
2593 StringLiteral(
"aarch64_in_za"),
2594 StringLiteral(
"aarch64_inout_za"),
2595 StringLiteral(
"aarch64_new_za"),
2596 StringLiteral(
"aarch64_out_za"),
2597 StringLiteral(
"aarch64_preserves_za"),
2598 StringLiteral(
"aarch64_pstate_sm_body"),
2599 StringLiteral(
"aarch64_pstate_sm_compatible"),
2600 StringLiteral(
"aarch64_pstate_sm_enabled"),
2601 StringLiteral(
"alwaysinline"),
2602 StringLiteral(
"convergent"),
2603 StringLiteral(
"denormal-fp-math"),
2604 StringLiteral(
"denormal-fp-math-f32"),
2605 StringLiteral(
"fp-contract"),
2606 StringLiteral(
"frame-pointer"),
2607 StringLiteral(
"instrument-function-entry"),
2608 StringLiteral(
"instrument-function-exit"),
2609 StringLiteral(
"memory"),
2610 StringLiteral(
"no-infs-fp-math"),
2611 StringLiteral(
"no-nans-fp-math"),
2612 StringLiteral(
"no-signed-zeros-fp-math"),
2613 StringLiteral(
"noinline"),
2614 StringLiteral(
"nounwind"),
2615 StringLiteral(
"optnone"),
2616 StringLiteral(
"target-features"),
2617 StringLiteral(
"tune-cpu"),
2618 StringLiteral(
"unsafe-fp-math"),
2619 StringLiteral(
"uwtable"),
2620 StringLiteral(
"vscale_range"),
2621 StringLiteral(
"willreturn"),
2628 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
2629 llvm::AttributeList::AttrIndex::FunctionIndex);
2630 ArrayAttr passthroughAttr =
2633 if (!passthroughAttr.empty())
2634 funcOp.setPassthroughAttr(passthroughAttr);
2638 LLVMFuncOp funcOp) {
2642 if (func->hasFnAttribute(llvm::Attribute::NoInline))
2643 funcOp.setNoInline(
true);
2644 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2645 funcOp.setAlwaysInline(
true);
2646 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2647 funcOp.setOptimizeNone(
true);
2648 if (func->hasFnAttribute(llvm::Attribute::Convergent))
2649 funcOp.setConvergent(
true);
2650 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
2651 funcOp.setNoUnwind(
true);
2652 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
2653 funcOp.setWillReturn(
true);
2655 if (func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2656 funcOp.setArmStreaming(
true);
2657 else if (func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2658 funcOp.setArmLocallyStreaming(
true);
2659 else if (func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2660 funcOp.setArmStreamingCompatible(
true);
2662 if (func->hasFnAttribute(
"aarch64_new_za"))
2663 funcOp.setArmNewZa(
true);
2664 else if (func->hasFnAttribute(
"aarch64_in_za"))
2665 funcOp.setArmInZa(
true);
2666 else if (func->hasFnAttribute(
"aarch64_out_za"))
2667 funcOp.setArmOutZa(
true);
2668 else if (func->hasFnAttribute(
"aarch64_inout_za"))
2669 funcOp.setArmInoutZa(
true);
2670 else if (func->hasFnAttribute(
"aarch64_preserves_za"))
2671 funcOp.setArmPreservesZa(
true);
2673 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
2674 if (attr.isValid()) {
2683 if (func->hasFnAttribute(
"frame-pointer")) {
2684 StringRef stringRefFramePointerKind =
2685 func->getFnAttribute(
"frame-pointer").getValueAsString();
2687 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2688 stringRefFramePointerKind)
2692 if (llvm::Attribute attr = func->getFnAttribute(
"target-cpu");
2693 attr.isStringAttribute())
2694 funcOp.setTargetCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
2696 if (llvm::Attribute attr = func->getFnAttribute(
"tune-cpu");
2697 attr.isStringAttribute())
2698 funcOp.setTuneCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
2700 if (llvm::Attribute attr = func->getFnAttribute(
"target-features");
2701 attr.isStringAttribute())
2702 funcOp.setTargetFeaturesAttr(
2705 if (llvm::Attribute attr = func->getFnAttribute(
"reciprocal-estimates");
2706 attr.isStringAttribute())
2707 funcOp.setReciprocalEstimatesAttr(
2710 if (llvm::Attribute attr = func->getFnAttribute(
"prefer-vector-width");
2711 attr.isStringAttribute())
2712 funcOp.setPreferVectorWidth(attr.getValueAsString());
2714 if (llvm::Attribute attr = func->getFnAttribute(
"unsafe-fp-math");
2715 attr.isStringAttribute())
2716 funcOp.setUnsafeFpMath(attr.getValueAsBool());
2718 if (llvm::Attribute attr = func->getFnAttribute(
"no-infs-fp-math");
2719 attr.isStringAttribute())
2720 funcOp.setNoInfsFpMath(attr.getValueAsBool());
2722 if (llvm::Attribute attr = func->getFnAttribute(
"no-nans-fp-math");
2723 attr.isStringAttribute())
2724 funcOp.setNoNansFpMath(attr.getValueAsBool());
2726 if (llvm::Attribute attr = func->getFnAttribute(
"instrument-function-entry");
2727 attr.isStringAttribute())
2728 funcOp.setInstrumentFunctionEntry(
2731 if (llvm::Attribute attr = func->getFnAttribute(
"instrument-function-exit");
2732 attr.isStringAttribute())
2733 funcOp.setInstrumentFunctionExit(
2736 if (llvm::Attribute attr = func->getFnAttribute(
"no-signed-zeros-fp-math");
2737 attr.isStringAttribute())
2738 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2740 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math");
2741 attr.isStringAttribute())
2742 funcOp.setDenormalFpMathAttr(
2745 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math-f32");
2746 attr.isStringAttribute())
2747 funcOp.setDenormalFpMathF32Attr(
2750 if (llvm::Attribute attr = func->getFnAttribute(
"fp-contract");
2751 attr.isStringAttribute())
2752 funcOp.setFpContractAttr(
StringAttr::get(context, attr.getValueAsString()));
2754 if (func->hasUWTable()) {
2755 ::llvm::UWTableKind uwtableKind = func->getUWTableKind();
2757 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2762 ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2765 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2767 if (!llvmAttr.isValid())
2772 if (llvmAttr.hasKindAsEnum() &&
2773 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2774 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2775 paramAttrs.push_back(
2781 if (llvmAttr.isTypeAttribute())
2783 else if (llvmAttr.isIntAttribute())
2785 else if (llvmAttr.isEnumAttribute())
2787 else if (llvmAttr.isConstantRangeAttribute()) {
2788 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2789 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2792 llvm_unreachable(
"unexpected parameter attribute kind");
2794 paramAttrs.push_back(builder.
getNamedAttr(mlirName, mlirAttr));
2801 LLVMFuncOp funcOp) {
2802 auto llvmAttrs = func->getAttributes();
2803 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2804 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2805 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2809 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2810 if (!llvmResAttr.hasAttributes())
2812 funcOp.setResAttrsAttr(
2813 builder.
getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2817 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2820 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2821 immArgPositions.end());
2823 llvm::AttributeList llvmAttrs = call->getAttributes();
2825 bool anyArgAttrs =
false;
2826 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
2828 if (immArgPositionsSet.contains(i))
2830 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
2831 if (llvmArgAttrsSet.back().hasAttributes())
2836 for (
auto &dict : dictAttrs)
2842 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
2843 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
2844 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
2848 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2849 if (!llvmResAttr.hasAttributes())
2851 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
2852 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
2855 template <
typename Op>
2857 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
2861 LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
2866 LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
2872 llvm::AttributeList callAttrs = inst->getAttributes();
2874 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
2875 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
2876 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
2877 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
2878 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
2880 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
2881 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
2883 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
2884 ModRefInfo othermem = convertModRefInfoFromLLVM(
2885 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2886 ModRefInfo argMem = convertModRefInfoFromLLVM(
2887 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2888 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
2889 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2893 if (!memAttr.isReadWrite())
2894 op.setMemoryEffectsAttr(memAttr);
2903 dyn_cast<LLVMFunctionType>(
convertType(func->getFunctionType()));
2904 if (func->isIntrinsic() &&
2908 bool dsoLocal = func->isDSOLocal();
2909 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
2915 Location loc = debugImporter->translateFuncLocation(func);
2916 LLVMFuncOp funcOp = LLVMFuncOp::create(
2917 builder, loc, func->getName(), functionType,
2918 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
2923 funcOp.setPersonalityAttr(personality);
2924 else if (func->hasPersonalityFn())
2925 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
2928 funcOp.setGarbageCollector(StringRef(func->getGC()));
2930 if (func->hasAtLeastLocalUnnamedAddr())
2931 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
2933 if (func->hasSection())
2934 funcOp.setSection(StringRef(func->getSection()));
2936 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
2938 if (func->hasComdat())
2939 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
2941 if (llvm::MaybeAlign maybeAlign = func->getAlign())
2942 funcOp.setAlignment(maybeAlign->value());
2949 func->getAllMetadata(allMetadata);
2950 for (
auto &[
kind, node] : allMetadata) {
2955 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
2956 <<
" on " <<
diag(*func);
2960 if (func->isDeclaration())
2969 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
2970 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
2975 for (llvm::BasicBlock &basicBlock : *func) {
2977 if (!reachable.contains(&basicBlock)) {
2978 if (basicBlock.hasAddressTaken())
2980 <<
"unreachable block '" << basicBlock.getName()
2981 <<
"' with address taken";
2984 Region &body = funcOp.getBody();
2987 reachableBasicBlocks.push_back(&basicBlock);
2992 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
2993 functionType.getParamType(it.index()), funcOp.getLoc());
3002 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3003 for (llvm::BasicBlock *basicBlock : blocks)
3009 if (
failed(processDebugIntrinsics()))
3018 if (!dbgIntr->isKillLocation())
3020 llvm::Value *value = dbgIntr->getArgOperand(0);
3021 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3024 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3028 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3031 auto emitUnsupportedWarning = [&]() {
3032 if (emitExpensiveWarnings)
3038 if (dbgIntr->hasArgList())
3039 return emitUnsupportedWarning();
3044 return emitUnsupportedWarning();
3048 DILocalVariableAttr localVariableAttr =
3050 if (!localVariableAttr)
3051 return emitUnsupportedWarning();
3054 return emitError(loc) <<
"failed to convert a debug intrinsic operand: "
3062 if (
Operation *op = argOperand->getDefiningOp();
3065 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3068 if (dominatedBlocks.empty())
3069 return emitUnsupportedWarning();
3072 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3075 Value insertPt = *argOperand;
3076 if (
auto blockArg = dyn_cast<BlockArgument>(*argOperand)) {
3081 Block *insertionBlock = argOperand->getParentBlock();
3082 if (!insertionBlock->
empty() &&
3083 isa<LandingpadOp>(insertionBlock->
front()))
3084 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3089 auto locationExprAttr =
3090 debugImporter->translateExpression(dbgIntr->getExpression());
3093 .Case([&](llvm::DbgDeclareInst *) {
3094 return LLVM::DbgDeclareOp::create(
3095 builder, loc, *argOperand, localVariableAttr, locationExprAttr);
3097 .Case([&](llvm::DbgValueInst *) {
3098 return LLVM::DbgValueOp::create(
3099 builder, loc, *argOperand, localVariableAttr, locationExprAttr);
3102 setNonDebugMetadataAttrs(dbgIntr, op);
3106 LogicalResult ModuleImport::processDebugIntrinsics() {
3108 for (llvm::Instruction *inst : debugIntrinsics) {
3109 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3110 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3116 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3119 for (llvm::Instruction &inst : *bb) {
3120 if (
failed(processInstruction(&inst)))
3125 if (debugIntrinsics.contains(&inst))
3132 setNonDebugMetadataAttrs(&inst, op);
3133 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3134 if (emitExpensiveWarnings) {
3135 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3141 if (bb->hasAddressTaken()) {
3150 FailureOr<SmallVector<AccessGroupAttr>>
3152 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3158 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3161 FailureOr<DereferenceableAttr>
3164 Location loc = mlirModule.getLoc();
3168 if (node->getNumOperands() != 1)
3169 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3170 <<
diagMD(node, llvmModule.get());
3172 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3173 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3174 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3175 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3176 "non-negative constant integer: "
3177 <<
diagMD(node, llvmModule.get());
3179 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3180 auto derefAttr = builder.
getAttr<DereferenceableAttr>(
3181 numBytesCst->getZExtValue(), mayBeNull);
3187 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3188 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3189 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3190 bool importStructsAsLiterals) {
3197 LLVMDialect::getDialectNamespace()));
3199 DLTIDialect::getDialectNamespace()));
3200 if (loadAllDialects)
3207 emitExpensiveWarnings, dropDICompositeTypeElements,
3208 preferUnregisteredIntrinsics,
3209 importStructsAsLiterals);
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1241::ArityGroupAndKind::Kind kind
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
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)
Converts LLVM attributes from func into MLIR attributes and adds them to funcOp as passthrough attrib...
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 std::array kExplicitLLVMFuncOpAttributes
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 void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar, GlobalOp globalOp)
Converts LLVM attributes from globalVar into MLIR attributes and adds them to globalOp as target-spec...
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 ArrayAttr convertLLVMAttributesToMLIR(Location loc, MLIRContext *context, llvm::AttributeSet attributes, ArrayRef< StringLiteral > attributesToSkip={})
Converts LLVM string, integer, and enum attributes into MLIR attributes, skipping those in attributes...
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 convertIFuncs()
Converts all ifuncs of the LLVM module to MLIR variables.
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 ...
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 convertModuleLevelAsm()
Converts the module level asm of the LLVM module to an MLIR module level asm specification.
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.
void convertArgAndResultAttrs(llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp, ArrayRef< unsigned > immArgPositions={})
Converts the argument and result attributes attached to call and adds them to attrsOp.
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 string 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.
ArrayRef< StringRef > getUnhandledTokens() const
Returns the data layout tokens that have not been handled during the data layout translation.
DataLayoutSpecInterface getDataLayoutSpec() const
Returns the MLIR data layout specification translated from the LLVM data layout.
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.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes={}, ArrayRef< Location > locs={})
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
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.
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
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.