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"
49 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
54 static std::string
diag(
const llvm::Value &value) {
56 llvm::raw_string_ostream os(str);
64 static std::string
diagMD(
const llvm::Metadata *node,
65 const llvm::Module *module) {
67 llvm::raw_string_ostream os(str);
68 node->print(os, module,
true);
74 return "llvm.global_ctors";
79 return "mlir.llvm.nameless_global";
84 return "llvm.global_dtors";
90 return "__llvm_global_comdat";
99 std::optional<llvm::SyncScope::ID> syncScopeID =
100 llvm::getAtomicSyncScopeID(inst);
107 llvm::LLVMContext &llvmContext = inst->getContext();
108 llvmContext.getSyncScopeNames(syncScopeName);
109 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
110 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
112 if (it != syncScopeName.end())
114 llvm_unreachable(
"incorrect sync scope identifier");
120 llvm::append_range(position, indices);
131 llvm::Instruction *inst,
144 #include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
152 for (llvm::BasicBlock *basicBlock : basicBlocks) {
153 if (!blocks.contains(basicBlock)) {
154 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
155 blocks.insert(traversal.begin(), traversal.end());
158 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
163 std::unique_ptr<llvm::Module> llvmModule,
164 bool emitExpensiveWarnings,
165 bool importEmptyDICompositeTypes)
167 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
171 mlirModule, importEmptyDICompositeTypes)),
172 loopAnnotationImporter(
174 emitExpensiveWarnings(emitExpensiveWarnings) {
178 ComdatOp ModuleImport::getGlobalComdatOp() {
180 return globalComdatOp;
186 globalInsertionOp = globalComdatOp;
187 return globalComdatOp;
190 LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
195 auto getIdentityIfRootNode =
196 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
200 if (node->getNumOperands() > 1)
203 if (node->getNumOperands() == 1)
204 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
205 return std::optional<StringRef>{op0->getString()};
206 return std::optional<StringRef>{};
216 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
217 StringRef *identity =
nullptr,
219 nullptr) -> std::optional<bool> {
220 unsigned numOperands = node->getNumOperands();
229 const auto *identityNode =
230 dyn_cast<const llvm::MDString>(node->getOperand(0));
236 *identity = identityNode->getString();
238 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
239 const auto *memberNode =
240 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
242 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
243 <<
diagMD(node, llvmModule.get());
247 if (2 * pairNum + 2 >= numOperands) {
249 if (numOperands != 2) {
250 emitError(loc) <<
"missing member offset: "
251 <<
diagMD(node, llvmModule.get());
255 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
256 node->getOperand(2 * pairNum + 2));
258 emitError(loc) <<
"operand '" << 2 * pairNum + 2
259 <<
"' must be ConstantInt: "
260 <<
diagMD(node, llvmModule.get());
263 offset = offsetCI->getZExtValue();
268 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
281 auto isTagNode = [&](
const llvm::MDNode *node,
282 TBAATypeDescriptorAttr *baseAttr =
nullptr,
283 TBAATypeDescriptorAttr *accessAttr =
nullptr,
284 int64_t *offset =
nullptr,
285 bool *isConstant =
nullptr) -> std::optional<bool> {
293 unsigned numOperands = node->getNumOperands();
294 if (numOperands != 3 && numOperands != 4)
296 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
297 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
299 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
300 if (!baseMD || !accessMD || !offsetCI)
307 if (accessMD->getNumOperands() < 1 ||
308 !isa<llvm::MDString>(accessMD->getOperand(0)))
310 bool isConst =
false;
311 if (numOperands == 4) {
313 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
315 emitError(loc) <<
"operand '3' must be ConstantInt: "
316 <<
diagMD(node, llvmModule.get());
319 isConst = isConstantCI->getValue()[0];
322 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
324 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
326 *offset = offsetCI->getZExtValue();
328 *isConstant = isConst;
337 workList.push_back(node);
338 while (!workList.empty()) {
339 const llvm::MDNode *current = workList.back();
340 if (tbaaMapping.contains(current)) {
349 bool anyChildNotConverted =
false;
350 for (
const llvm::MDOperand &operand : current->operands())
351 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
352 if (!tbaaMapping.contains(childNode)) {
353 workList.push_back(childNode);
354 anyChildNotConverted =
true;
357 if (anyChildNotConverted) {
362 if (!seen.insert(current).second)
363 return emitError(loc) <<
"has cycle in TBAA graph: "
364 <<
diagMD(current, llvmModule.get());
372 FailureOr<std::optional<StringRef>> rootNodeIdentity =
373 getIdentityIfRootNode(current);
374 if (succeeded(rootNodeIdentity)) {
375 StringAttr stringAttr = *rootNodeIdentity
380 tbaaMapping.insert({current, builder.
getAttr<TBAARootAttr>(stringAttr)});
386 if (std::optional<bool> isValid =
387 isTypeDescriptorNode(current, &identity, &members)) {
388 assert(isValid.value() &&
"type descriptor node must be valid");
390 tbaaMapping.insert({current, builder.
getAttr<TBAATypeDescriptorAttr>(
391 identity, members)});
395 TBAATypeDescriptorAttr baseAttr, accessAttr;
398 if (std::optional<bool> isValid =
399 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
400 assert(isValid.value() &&
"access tag node must be valid");
402 {current, builder.
getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
407 return emitError(loc) <<
"unsupported TBAA node format: "
408 <<
diagMD(current, llvmModule.get());
414 ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
416 if (failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
417 return emitError(loc) <<
"unsupported access group node: "
418 <<
diagMD(node, llvmModule.get());
423 ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
426 auto verifySelfRef = [](
const llvm::MDNode *node) {
427 return node->getNumOperands() != 0 &&
428 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
430 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
431 return node->getNumOperands() != 0 &&
432 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
433 isa<llvm::MDString>(node->getOperand(0)));
436 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
437 return idx >= node->getNumOperands() ||
438 isa<llvm::MDString>(node->getOperand(idx));
441 auto getIdAttr = [&](
const llvm::MDNode *node) ->
Attribute {
442 if (verifySelfRef(node))
445 auto name = cast<llvm::MDString>(node->getOperand(0));
450 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
451 StringAttr description =
nullptr;
452 if (aliasDomain->getNumOperands() >= 2)
453 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
455 Attribute idAttr = getIdAttr(aliasDomain);
456 return builder.
getAttr<AliasScopeDomainAttr>(idAttr, description);
460 for (
const llvm::MDOperand &operand : node->operands()) {
461 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
462 llvm::AliasScopeNode aliasScope(scope);
463 const llvm::MDNode *domain = aliasScope.getDomain();
469 if (!verifySelfRefOrString(scope) || !domain ||
470 !verifyDescription(scope, 2))
471 return emitError(loc) <<
"unsupported alias scope node: "
472 <<
diagMD(scope, llvmModule.get());
473 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
474 return emitError(loc) <<
"unsupported alias domain node: "
475 <<
diagMD(domain, llvmModule.get());
477 if (aliasScopeMapping.contains(scope))
481 auto it = aliasScopeMapping.find(aliasScope.getDomain());
482 if (it == aliasScopeMapping.end()) {
483 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
484 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
488 StringAttr description =
nullptr;
489 if (!aliasScope.getName().empty())
492 auto aliasScopeOp = builder.
getAttr<AliasScopeAttr>(
493 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
495 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
501 FailureOr<SmallVector<AliasScopeAttr>>
504 aliasScopes.reserve(node->getNumOperands());
505 for (
const llvm::MDOperand &operand : node->operands()) {
506 auto *node = cast<llvm::MDNode>(operand.get());
507 aliasScopes.push_back(
508 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
511 if (llvm::is_contained(aliasScopes,
nullptr))
517 debugIntrinsics.insert(intrinsic);
521 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
522 if (named.getName() !=
"llvm.linker.options")
525 for (
const llvm::MDNode *node : named.operands()) {
527 options.reserve(node->getNumOperands());
528 for (
const llvm::MDOperand &option : node->operands())
529 options.push_back(cast<llvm::MDString>(option)->getString());
530 builder.
create<LLVM::LinkerOptionsOp>(mlirModule.getLoc(),
538 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
541 if (named.getName() != LLVMDialect::getIdentAttrName())
544 if (named.getNumOperands() == 1)
545 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
546 if (md->getNumOperands() == 1)
547 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
548 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
555 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
558 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
561 if (nmd.getNumOperands() == 1)
562 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
563 if (md->getNumOperands() == 1)
564 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
565 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
574 for (
const llvm::Function &func : llvmModule->functions()) {
575 for (
const llvm::Instruction &inst : llvm::instructions(func)) {
577 if (llvm::MDNode *node =
578 inst.getMetadata(llvm::LLVMContext::MD_access_group))
579 if (failed(processAccessGroupMetadata(node)))
583 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
584 if (!aliasAnalysisNodes)
586 if (aliasAnalysisNodes.TBAA)
587 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
589 if (aliasAnalysisNodes.Scope)
590 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
592 if (aliasAnalysisNodes.NoAlias)
593 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
606 void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
607 if (comdatMapping.contains(comdat))
610 ComdatOp comdatOp = getGlobalComdatOp();
613 auto selectorOp = builder.
create<ComdatSelectorOp>(
614 mlirModule.getLoc(), comdat->getName(),
615 convertComdatFromLLVM(comdat->getSelectionKind()));
619 comdatMapping.try_emplace(comdat, symbolRef);
623 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
624 if (globalVar.hasComdat())
625 processComdat(globalVar.getComdat());
626 for (llvm::Function &func : llvmModule->functions())
627 if (func.hasComdat())
628 processComdat(func.getComdat());
633 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
636 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
638 <<
"unhandled global variable: " <<
diag(globalVar);
642 if (failed(convertGlobal(&globalVar))) {
644 <<
"unhandled global variable: " <<
diag(globalVar);
654 return emitError(loc,
"cannot translate data layout: ")
658 emitWarning(loc,
"unhandled data layout token: ") << token;
660 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
666 for (llvm::Function &func : llvmModule->functions())
672 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
675 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
676 for (
auto &[kind, node] : allMetadata) {
680 if (emitExpensiveWarnings) {
681 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
683 <<
diagMD(node, llvmModule.get()) <<
" on "
692 auto iface = cast<IntegerOverflowFlagsInterface>(op);
694 IntegerOverflowFlags value = {};
695 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
697 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
699 iface.setOverflowFlags(value);
703 auto iface = cast<ExactFlagInterface>(op);
705 iface.setIsExact(inst->isExact());
710 auto iface = cast<DisjointFlagInterface>(op);
711 auto instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
713 iface.setIsDisjoint(instDisjoint->isDisjoint());
717 auto iface = cast<NonNegFlagInterface>(op);
719 iface.setNonNeg(inst->hasNonNeg());
724 auto iface = cast<FastmathFlagsInterface>(op);
730 if (!isa<llvm::FPMathOperator>(inst))
732 llvm::FastMathFlags flags = inst->getFastMathFlags();
735 FastmathFlags value = {};
736 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
737 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
738 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
739 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
741 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
742 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
744 iface->setAttr(iface.getFastmathAttrName(), attr);
749 return isa<IntegerType, FloatType>(type);
761 if (numElements.isScalable()) {
763 <<
"scalable vectors not supported";
773 shape.push_back(numElements.getKnownMinValue());
777 Type ModuleImport::getBuiltinTypeForAttr(
Type type) {
792 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
793 arrayShape.push_back(arrayType.getNumElements());
794 type = arrayType.getElementType();
804 llvm::Constant *constScalar) {
808 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
811 constInt->getValue());
815 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
816 llvm::Type *type = constFloat->getType();
817 FloatType floatType =
823 <<
"unexpected floating-point type";
826 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
835 llvm::ConstantDataSequential *constSequence) {
837 elementAttrs.reserve(constSequence->getNumElements());
838 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
839 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
845 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
851 auto getConstantShape = [&](llvm::Type *type) {
852 return llvm::dyn_cast_if_present<ShapedType>(
858 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
859 if (constArray->isString())
861 auto shape = getConstantShape(constArray->getType());
865 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
866 if (constVector && constVector->isSplat()) {
869 builder, constVector->getElementAsConstant(0));
880 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
881 auto shape = getConstantShape(constAggregate->getType());
887 while (!workList.empty()) {
888 llvm::Constant *current = workList.pop_back_val();
891 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
893 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
894 workList.push_back(constAggregate->getAggregateElement(idx));
899 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
902 elementAttrs.append(attrs.begin(), attrs.end());
908 elementAttrs.push_back(scalarAttr);
919 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
920 auto shape = llvm::dyn_cast_if_present<ShapedType>(
921 getBuiltinTypeForAttr(
convertType(constZero->getType())));
926 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
933 ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
934 assert(globalVar->getName().empty() &&
935 "expected to work with a nameless global");
936 auto [it, success] = namelessGlobals.try_emplace(globalVar);
943 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
946 it->getSecond() = symbolRef;
950 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
953 if (!globalInsertionOp)
959 if (globalVar->hasInitializer())
960 valueAttr = getConstantAsAttr(globalVar->getInitializer());
963 uint64_t alignment = 0;
964 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
965 if (maybeAlign.has_value()) {
966 llvm::Align align = *maybeAlign;
967 alignment = align.value();
974 globalVar->getDebugInfo(globalExpressions);
976 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
977 DIGlobalVariableExpressionAttr globalExpressionAttr =
978 debugImporter->translateGlobalVariableExpression(expr);
979 globalExpressionAttrs.push_back(globalExpressionAttr);
984 StringRef globalName = globalVar->getName();
985 if (globalName.empty())
986 globalName = getOrCreateNamelessSymbolName(globalVar).
getValue();
988 GlobalOp globalOp = builder.
create<GlobalOp>(
989 mlirModule.getLoc(), type, globalVar->isConstant(),
990 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
991 valueAttr, alignment, globalVar->getAddressSpace(),
992 globalVar->isDSOLocal(),
993 globalVar->isThreadLocal(), SymbolRefAttr(),
995 globalInsertionOp = globalOp;
997 if (globalVar->hasInitializer() && !valueAttr) {
1000 setConstantInsertionPointToStart(block);
1001 FailureOr<Value> initializer =
1002 convertConstantExpr(globalVar->getInitializer());
1003 if (failed(initializer))
1005 builder.
create<ReturnOp>(globalOp.getLoc(), *initializer);
1007 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1008 globalOp.setUnnamedAddr(
1009 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1011 if (globalVar->hasSection())
1012 globalOp.setSection(globalVar->getSection());
1013 globalOp.setVisibility_(
1014 convertVisibilityFromLLVM(globalVar->getVisibility()));
1016 if (globalVar->hasComdat())
1017 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1023 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1024 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1027 dyn_cast<llvm::ConstantArray>(globalVar->getInitializer());
1033 for (llvm::Value *operand : initializer->operands()) {
1034 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1035 if (!aggregate || aggregate->getNumOperands() != 3)
1038 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1039 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1040 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1041 if (!priority || !func || !data)
1045 if (!data->isNullValue())
1049 priorities.push_back(priority->getValue().getZExtValue());
1053 if (!globalInsertionOp)
1059 globalInsertionOp = builder.
create<LLVM::GlobalCtorsOp>(
1064 globalInsertionOp = builder.
create<LLVM::GlobalDtorsOp>(
1071 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1073 if (valueMapping.contains(constant))
1082 workList.insert(constant);
1083 while (!workList.empty()) {
1084 llvm::Constant *current = workList.back();
1087 if (isa<llvm::GlobalObject>(current)) {
1088 orderedSet.insert(current);
1089 workList.pop_back();
1095 auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);
1099 for (llvm::Value *operand : current->operands())
1100 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1101 adjacencyIt->getSecond().push_back(constDependency);
1104 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1105 unsigned numElements = constAgg->getElementCount().getFixedValue();
1106 for (
unsigned i = 0, e = numElements; i != e; ++i)
1107 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1113 if (adjacencyIt->getSecond().empty()) {
1114 orderedSet.insert(current);
1115 workList.pop_back();
1123 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1124 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1125 orderedSet.contains(dependency))
1127 workList.insert(dependency);
1133 FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1137 if (
Attribute attr = getConstantAsAttr(constant)) {
1139 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1140 return builder.
create<AddressOfOp>(loc, type, symbolRef.getValue())
1143 return builder.
create<ConstantOp>(loc, type, attr).getResult();
1147 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1149 return builder.
create<ZeroOp>(loc, type).getResult();
1153 if (isa<llvm::ConstantTokenNone>(constant)) {
1154 return builder.
create<NoneTokenOp>(loc).getResult();
1158 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1160 return builder.
create<PoisonOp>(loc, type).getResult();
1164 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1166 return builder.
create<UndefOp>(loc, type).getResult();
1170 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1172 StringRef globalName = globalObj->getName();
1175 if (globalName.empty())
1177 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1180 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1184 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1190 llvm::Instruction *inst = constExpr->getAsInstruction();
1191 auto guard = llvm::make_scope_exit([&]() {
1192 assert(!noResultOpMapping.contains(inst) &&
1193 "expected constant expression to return a result");
1194 valueMapping.erase(inst);
1195 inst->deleteValue();
1199 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1200 return valueMapping.contains(value);
1202 if (failed(processInstruction(inst)))
1208 if (isa<llvm::ConstantAggregate>(constant) ||
1209 isa<llvm::ConstantAggregateZero>(constant)) {
1212 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1213 elementValues.reserve(constAgg->getNumOperands());
1214 for (llvm::Value *operand : constAgg->operands())
1217 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1218 unsigned numElements = constAgg->getElementCount().getFixedValue();
1219 elementValues.reserve(numElements);
1220 for (
unsigned i = 0, e = numElements; i != e; ++i)
1221 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1223 assert(llvm::count(elementValues,
nullptr) == 0 &&
1224 "expected all elements have been converted before");
1228 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1230 "unrecognized aggregate type");
1231 Value root = builder.
create<UndefOp>(loc, rootType);
1233 if (isArrayOrStruct) {
1234 root = builder.
create<InsertValueOp>(loc, root, it.value(), it.index());
1239 root = builder.
create<InsertElementOp>(loc, rootType, root, it.value(),
1246 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1247 LLVMTargetExtType targetExtType =
1248 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1249 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1250 "target extension type does not support zero-initialization");
1253 return builder.
create<LLVM::ZeroOp>(loc, targetExtType).getRes();
1256 StringRef error =
"";
1257 if (isa<llvm::BlockAddress>(constant))
1258 error =
" since blockaddress(...) is unsupported";
1260 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1263 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1267 assert(!valueMapping.contains(constant) &&
1268 "expected constant has not been converted before");
1269 assert(constantInsertionBlock &&
1270 "expected the constant insertion block to be non-null");
1274 if (!constantInsertionOp)
1281 getConstantsToConvert(constant);
1282 for (llvm::Constant *constantToConvert : constantsToConvert) {
1283 FailureOr<Value> converted = convertConstant(constantToConvert);
1284 if (failed(converted))
1286 mapValue(constantToConvert, *converted);
1296 assert(!isa<llvm::MetadataAsValue>(value) &&
1297 "expected value to not be metadata");
1300 auto it = valueMapping.find(value);
1301 if (it != valueMapping.end())
1302 return it->getSecond();
1305 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1306 return convertConstantExpr(constant);
1309 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1311 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1317 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1320 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1323 value = node->getValue();
1326 auto it = valueMapping.find(value);
1327 if (it != valueMapping.end())
1328 return it->getSecond();
1331 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1332 return convertConstantExpr(constant);
1336 FailureOr<SmallVector<Value>>
1339 remapped.reserve(values.size());
1340 for (llvm::Value *value : values) {
1342 if (failed(converted))
1344 remapped.push_back(*converted);
1354 assert(immArgPositions.size() == immArgAttrNames.size() &&
1355 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1359 for (
auto [immArgPos, immArgName] :
1360 llvm::zip(immArgPositions, immArgAttrNames)) {
1361 auto &value = operands[immArgPos];
1362 auto *constant = llvm::cast<llvm::Constant>(value);
1364 assert(attr && attr.getType().isIntOrFloat() &&
1365 "expected immarg to be float or integer constant");
1367 attrsOut.push_back({nameAttr, attr});
1372 for (llvm::Value *value : operands) {
1376 if (failed(mlirValue))
1378 valuesOut.push_back(*mlirValue);
1383 if (requiresOpBundles) {
1384 opBundleSizes.reserve(opBundles.size());
1385 opBundleTagAttrs.reserve(opBundles.size());
1387 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1388 opBundleSizes.push_back(bundle.Inputs.size());
1389 opBundleTagAttrs.push_back(
StringAttr::get(context, bundle.getTagName()));
1391 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1392 auto operandMlirValue =
convertValue(opBundleOperand.get());
1393 if (failed(operandMlirValue))
1395 valuesOut.push_back(*operandMlirValue);
1400 auto opBundleSizesAttrNameAttr =
1402 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1404 auto opBundleTagsAttr =
ArrayAttr::get(context, opBundleTagAttrs);
1405 auto opBundleTagsAttrNameAttr =
1407 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1414 IntegerAttr integerAttr;
1416 bool success = succeeded(converted) &&
1418 assert(success &&
"expected a constant integer value");
1424 FloatAttr floatAttr;
1428 assert(success &&
"expected a constant float value");
1434 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1435 auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
1436 return debugImporter->translate(node);
1440 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1441 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
1442 return debugImporter->translate(node);
1445 FPExceptionBehaviorAttr
1447 auto *metadata = cast<llvm::MetadataAsValue>(value);
1448 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1449 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
1450 llvm::convertStrToExceptionBehavior(mdstr->getString());
1451 assert(optLLVM &&
"Expecting FP exception behavior");
1452 return builder.
getAttr<FPExceptionBehaviorAttr>(
1453 convertFPExceptionBehaviorFromLLVM(*optLLVM));
1457 auto *metadata = cast<llvm::MetadataAsValue>(value);
1458 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1459 std::optional<llvm::RoundingMode> optLLVM =
1460 llvm::convertStrToRoundingMode(mdstr->getString());
1461 assert(optLLVM &&
"Expecting rounding mode");
1462 return builder.
getAttr<RoundingModeAttr>(
1463 convertRoundingModeFromLLVM(*optLLVM));
1466 FailureOr<SmallVector<AliasScopeAttr>>
1468 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1469 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
1474 return debugImporter->translateLoc(loc);
1478 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
1479 llvm::BasicBlock *target,
1481 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
1482 auto *phiInst = cast<llvm::PHINode>(&*inst);
1483 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
1485 if (failed(converted))
1487 blockArguments.push_back(*converted);
1492 LogicalResult ModuleImport::convertCallTypeAndOperands(
1495 if (!callInst->getType()->isVoidTy())
1496 types.push_back(
convertType(callInst->getType()));
1498 if (!callInst->getCalledFunction()) {
1499 if (!allowInlineAsm ||
1500 !isa<llvm::InlineAsm>(callInst->getCalledOperand())) {
1501 FailureOr<Value> called =
convertValue(callInst->getCalledOperand());
1504 operands.push_back(*called);
1508 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
1509 if (failed(arguments))
1511 llvm::append_range(operands, *arguments);
1515 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
1520 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
1523 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1526 if (inst->getOpcode() == llvm::Instruction::Br) {
1527 auto *brInst = cast<llvm::BranchInst>(inst);
1531 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
1532 llvm::BasicBlock *succ = brInst->getSuccessor(i);
1534 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
1537 succBlockArgs.push_back(blockArgs);
1540 if (!brInst->isConditional()) {
1541 auto brOp = builder.
create<LLVM::BrOp>(loc, succBlockArgs.front(),
1542 succBlocks.front());
1546 FailureOr<Value> condition =
convertValue(brInst->getCondition());
1547 if (failed(condition))
1549 auto condBrOp = builder.
create<LLVM::CondBrOp>(
1550 loc, *condition, succBlocks.front(), succBlockArgs.front(),
1551 succBlocks.back(), succBlockArgs.back());
1555 if (inst->getOpcode() == llvm::Instruction::Switch) {
1556 auto *swInst = cast<llvm::SwitchInst>(inst);
1558 FailureOr<Value> condition =
convertValue(swInst->getCondition());
1559 if (failed(condition))
1563 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
1564 if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
1568 unsigned numCases = swInst->getNumCases();
1574 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
1575 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
1576 if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
1578 caseOperandRefs[it.index()] = caseOperands[it.index()];
1579 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
1583 auto switchOp = builder.
create<SwitchOp>(
1584 loc, *condition,
lookupBlock(defaultBB), defaultBlockArgs, caseValues,
1585 caseBlocks, caseOperandRefs);
1589 if (inst->getOpcode() == llvm::Instruction::PHI) {
1595 if (inst->getOpcode() == llvm::Instruction::Call) {
1596 auto *callInst = cast<llvm::CallInst>(inst);
1600 if (failed(convertCallTypeAndOperands(callInst, types, operands,
1605 dyn_cast<LLVMFunctionType>(
convertType(callInst->getFunctionType()));
1609 if (
auto asmI = dyn_cast<llvm::InlineAsm>(callInst->getCalledOperand())) {
1610 auto callOp = builder.
create<InlineAsmOp>(
1611 loc, funcTy.getReturnType(), operands,
1617 if (!callInst->getType()->isVoidTy())
1618 mapValue(inst, callOp.getResult(0));
1624 if (llvm::Function *callee = callInst->getCalledFunction()) {
1625 callOp = builder.
create<CallOp>(
1629 callOp = builder.
create<CallOp>(loc, funcTy, operands);
1631 callOp.setCConv(convertCConvFromLLVM(callInst->getCallingConv()));
1632 callOp.setTailCallKind(
1633 convertTailCallKindFromLLVM(callInst->getTailCallKind()));
1637 if (callInst->hasFnAttr(llvm::Attribute::Convergent))
1638 callOp.setConvergent(
true);
1639 if (callInst->hasFnAttr(llvm::Attribute::NoUnwind))
1640 callOp.setNoUnwind(
true);
1641 if (callInst->hasFnAttr(llvm::Attribute::WillReturn))
1642 callOp.setWillReturn(
true);
1644 llvm::MemoryEffects memEffects = callInst->getMemoryEffects();
1645 ModRefInfo othermem = convertModRefInfoFromLLVM(
1646 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1647 ModRefInfo argMem = convertModRefInfoFromLLVM(
1648 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1649 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
1650 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1652 argMem, inaccessibleMem);
1654 if (!memAttr.isReadWrite())
1655 callOp.setMemoryEffectsAttr(memAttr);
1657 if (!callInst->getType()->isVoidTy())
1658 mapValue(inst, callOp.getResult());
1664 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
1665 auto *lpInst = cast<llvm::LandingPadInst>(inst);
1668 operands.reserve(lpInst->getNumClauses());
1669 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
1670 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
1671 if (failed(operand))
1673 operands.push_back(*operand);
1678 builder.
create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
1682 if (inst->getOpcode() == llvm::Instruction::Invoke) {
1683 auto *invokeInst = cast<llvm::InvokeInst>(inst);
1687 if (failed(convertCallTypeAndOperands(invokeInst, types, operands)))
1692 bool invokeResultUsedInPhi = llvm::any_of(
1693 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
1694 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
1699 Block *directNormalDest = normalDest;
1700 if (invokeResultUsedInPhi) {
1706 directNormalDest = builder.
createBlock(normalDest);
1710 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
1715 dyn_cast<LLVMFunctionType>(
convertType(invokeInst->getFunctionType()));
1723 if (llvm::Function *callee = invokeInst->getCalledFunction()) {
1724 invokeOp = builder.
create<InvokeOp>(
1728 lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
1730 invokeOp = builder.
create<InvokeOp>(
1731 loc, funcTy,
nullptr, operands, directNormalDest,
1734 invokeOp.setCConv(convertCConvFromLLVM(invokeInst->getCallingConv()));
1735 if (!invokeInst->getType()->isVoidTy())
1736 mapValue(inst, invokeOp.getResults().front());
1741 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
1745 if (invokeResultUsedInPhi) {
1751 builder.
create<LLVM::BrOp>(loc, normalArgs, normalDest);
1755 assert(llvm::none_of(
1758 "An llvm.invoke operation cannot pass its result as a block "
1760 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
1765 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
1766 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
1767 Type sourceElementType =
convertType(gepInst->getSourceElementType());
1768 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
1769 if (failed(basePtr))
1777 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
1781 indices.push_back(*index);
1785 auto gepOp = builder.
create<GEPOp>(loc, type, sourceElementType, *basePtr,
1786 indices, gepInst->isInBounds());
1795 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
1798 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
1805 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
1806 return convertIntrinsic(intrinsic);
1809 return convertInstruction(inst);
1813 if (!f->hasPersonalityFn())
1816 llvm::Constant *pf = f->getPersonalityFn();
1824 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1825 if (ce->getOpcode() == llvm::Instruction::BitCast &&
1826 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
1827 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
1835 llvm::MemoryEffects memEffects = func->getMemoryEffects();
1837 auto othermem = convertModRefInfoFromLLVM(
1838 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1839 auto argMem = convertModRefInfoFromLLVM(
1840 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1841 auto inaccessibleMem = convertModRefInfoFromLLVM(
1842 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1846 if (memAttr.isReadWrite())
1848 funcOp.setMemoryEffectsAttr(memAttr);
1854 StringLiteral(
"aarch64_in_za"),
1855 StringLiteral(
"aarch64_inout_za"),
1856 StringLiteral(
"aarch64_new_za"),
1857 StringLiteral(
"aarch64_out_za"),
1858 StringLiteral(
"aarch64_preserves_za"),
1859 StringLiteral(
"aarch64_pstate_sm_body"),
1860 StringLiteral(
"aarch64_pstate_sm_compatible"),
1861 StringLiteral(
"aarch64_pstate_sm_enabled"),
1862 StringLiteral(
"alwaysinline"),
1863 StringLiteral(
"approx-func-fp-math"),
1864 StringLiteral(
"convergent"),
1865 StringLiteral(
"denormal-fp-math"),
1866 StringLiteral(
"denormal-fp-math-f32"),
1867 StringLiteral(
"fp-contract"),
1868 StringLiteral(
"frame-pointer"),
1869 StringLiteral(
"no-infs-fp-math"),
1870 StringLiteral(
"no-nans-fp-math"),
1871 StringLiteral(
"no-signed-zeros-fp-math"),
1872 StringLiteral(
"noinline"),
1873 StringLiteral(
"nounwind"),
1874 StringLiteral(
"optnone"),
1875 StringLiteral(
"target-features"),
1876 StringLiteral(
"tune-cpu"),
1877 StringLiteral(
"unsafe-fp-math"),
1878 StringLiteral(
"vscale_range"),
1879 StringLiteral(
"willreturn"),
1885 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
1886 llvm::AttributeList::AttrIndex::FunctionIndex);
1887 for (llvm::Attribute attr : funcAttrs) {
1890 if (attr.hasAttribute(llvm::Attribute::Memory))
1894 if (attr.isTypeAttribute()) {
1896 "type attributes on a function are invalid, skipping it");
1901 if (attr.isStringAttribute())
1902 attrName = attr.getKindAsString();
1904 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1911 if (attr.isStringAttribute()) {
1912 StringRef val = attr.getValueAsString();
1914 passthroughs.push_back(keyAttr);
1917 passthroughs.push_back(
1921 if (attr.isIntAttribute()) {
1922 auto val = std::to_string(attr.getValueAsInt());
1923 passthroughs.push_back(
1927 if (attr.isEnumAttribute()) {
1928 passthroughs.push_back(keyAttr);
1932 llvm_unreachable(
"unexpected attribute kind");
1935 if (!passthroughs.empty())
1936 funcOp.setPassthroughAttr(
ArrayAttr::get(context, passthroughs));
1940 LLVMFuncOp funcOp) {
1944 if (func->hasFnAttribute(llvm::Attribute::NoInline))
1945 funcOp.setNoInline(
true);
1946 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
1947 funcOp.setAlwaysInline(
true);
1948 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
1949 funcOp.setOptimizeNone(
true);
1950 if (func->hasFnAttribute(llvm::Attribute::Convergent))
1951 funcOp.setConvergent(
true);
1952 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
1953 funcOp.setNoUnwind(
true);
1954 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
1955 funcOp.setWillReturn(
true);
1957 if (func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
1958 funcOp.setArmStreaming(
true);
1959 else if (func->hasFnAttribute(
"aarch64_pstate_sm_body"))
1960 funcOp.setArmLocallyStreaming(
true);
1961 else if (func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
1962 funcOp.setArmStreamingCompatible(
true);
1964 if (func->hasFnAttribute(
"aarch64_new_za"))
1965 funcOp.setArmNewZa(
true);
1966 else if (func->hasFnAttribute(
"aarch64_in_za"))
1967 funcOp.setArmInZa(
true);
1968 else if (func->hasFnAttribute(
"aarch64_out_za"))
1969 funcOp.setArmOutZa(
true);
1970 else if (func->hasFnAttribute(
"aarch64_inout_za"))
1971 funcOp.setArmInoutZa(
true);
1972 else if (func->hasFnAttribute(
"aarch64_preserves_za"))
1973 funcOp.setArmPreservesZa(
true);
1975 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
1976 if (attr.isValid()) {
1985 if (func->hasFnAttribute(
"frame-pointer")) {
1986 StringRef stringRefFramePointerKind =
1987 func->getFnAttribute(
"frame-pointer").getValueAsString();
1989 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
1990 stringRefFramePointerKind)
1994 if (llvm::Attribute attr = func->getFnAttribute(
"target-cpu");
1995 attr.isStringAttribute())
1996 funcOp.setTargetCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
1998 if (llvm::Attribute attr = func->getFnAttribute(
"tune-cpu");
1999 attr.isStringAttribute())
2000 funcOp.setTuneCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
2002 if (llvm::Attribute attr = func->getFnAttribute(
"target-features");
2003 attr.isStringAttribute())
2004 funcOp.setTargetFeaturesAttr(
2007 if (llvm::Attribute attr = func->getFnAttribute(
"unsafe-fp-math");
2008 attr.isStringAttribute())
2009 funcOp.setUnsafeFpMath(attr.getValueAsBool());
2011 if (llvm::Attribute attr = func->getFnAttribute(
"no-infs-fp-math");
2012 attr.isStringAttribute())
2013 funcOp.setNoInfsFpMath(attr.getValueAsBool());
2015 if (llvm::Attribute attr = func->getFnAttribute(
"no-nans-fp-math");
2016 attr.isStringAttribute())
2017 funcOp.setNoNansFpMath(attr.getValueAsBool());
2019 if (llvm::Attribute attr = func->getFnAttribute(
"approx-func-fp-math");
2020 attr.isStringAttribute())
2021 funcOp.setApproxFuncFpMath(attr.getValueAsBool());
2023 if (llvm::Attribute attr = func->getFnAttribute(
"no-signed-zeros-fp-math");
2024 attr.isStringAttribute())
2025 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2027 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math");
2028 attr.isStringAttribute())
2029 funcOp.setDenormalFpMathAttr(
2032 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math-f32");
2033 attr.isStringAttribute())
2034 funcOp.setDenormalFpMathF32Attr(
2037 if (llvm::Attribute attr = func->getFnAttribute(
"fp-contract");
2038 attr.isStringAttribute())
2039 funcOp.setFpContractAttr(
StringAttr::get(context, attr.getValueAsString()));
2043 ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
2047 auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
2049 if (!llvmAttr.isValid())
2052 if (llvmAttr.isTypeAttribute())
2054 else if (llvmAttr.isIntAttribute())
2056 else if (llvmAttr.isEnumAttribute())
2058 else if (llvmAttr.isConstantRangeAttribute()) {
2059 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2060 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2063 llvm_unreachable(
"unexpected parameter attribute kind");
2064 paramAttrs.push_back(builder.
getNamedAttr(mlirName, mlirAttr));
2070 void ModuleImport::convertParameterAttributes(llvm::Function *func,
2073 auto llvmAttrs = func->getAttributes();
2074 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2075 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2076 funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder));
2080 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2081 if (!llvmResAttr.hasAttributes())
2083 funcOp.setResAttrsAttr(
2084 builder.
getArrayAttr(convertParameterAttribute(llvmResAttr, builder)));
2091 dyn_cast<LLVMFunctionType>(
convertType(func->getFunctionType()));
2092 if (func->isIntrinsic() &&
2096 bool dsoLocal = func->hasLocalLinkage();
2097 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
2103 Location loc = debugImporter->translateFuncLocation(func);
2104 LLVMFuncOp funcOp = builder.
create<LLVMFuncOp>(
2105 loc, func->getName(), functionType,
2106 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
2108 convertParameterAttributes(func, funcOp, builder);
2111 funcOp.setPersonalityAttr(personality);
2112 else if (func->hasPersonalityFn())
2113 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
2116 funcOp.setGarbageCollector(StringRef(func->getGC()));
2118 if (func->hasAtLeastLocalUnnamedAddr())
2119 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
2121 if (func->hasSection())
2122 funcOp.setSection(StringRef(func->getSection()));
2124 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
2126 if (func->hasComdat())
2127 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
2129 if (llvm::MaybeAlign maybeAlign = func->getAlign())
2130 funcOp.setAlignment(maybeAlign->value());
2137 func->getAllMetadata(allMetadata);
2138 for (
auto &[kind, node] : allMetadata) {
2143 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
2144 <<
" on " <<
diag(*func);
2148 if (func->isDeclaration())
2157 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
2158 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
2163 for (llvm::BasicBlock &basicBlock : *func) {
2165 if (!reachable.contains(&basicBlock))
2167 Region &body = funcOp.getBody();
2170 reachableBasicBlocks.push_back(&basicBlock);
2175 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
2176 functionType.getParamType(it.index()), funcOp.getLoc());
2185 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
2186 for (llvm::BasicBlock *basicBlock : blocks)
2187 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
2192 if (failed(processDebugIntrinsics()))
2201 if (!dbgIntr->isKillLocation())
2203 llvm::Value *value = dbgIntr->getArgOperand(0);
2204 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2207 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2211 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
2214 auto emitUnsupportedWarning = [&]() {
2215 if (emitExpensiveWarnings)
2221 if (dbgIntr->hasArgList())
2222 return emitUnsupportedWarning();
2227 return emitUnsupportedWarning();
2231 DILocalVariableAttr localVariableAttr =
2233 if (!localVariableAttr)
2234 return emitUnsupportedWarning();
2236 if (failed(argOperand))
2237 return emitError(loc) <<
"failed to convert a debug intrinsic operand: "
2245 if (
Operation *op = argOperand->getDefiningOp();
2251 if (dominatedBlocks.empty())
2252 return emitUnsupportedWarning();
2255 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
2260 auto locationExprAttr =
2261 debugImporter->translateExpression(dbgIntr->getExpression());
2264 .Case([&](llvm::DbgDeclareInst *) {
2265 return builder.
create<LLVM::DbgDeclareOp>(
2266 loc, *argOperand, localVariableAttr, locationExprAttr);
2268 .Case([&](llvm::DbgValueInst *) {
2269 return builder.
create<LLVM::DbgValueOp>(
2270 loc, *argOperand, localVariableAttr, locationExprAttr);
2273 setNonDebugMetadataAttrs(dbgIntr, op);
2277 LogicalResult ModuleImport::processDebugIntrinsics() {
2279 for (llvm::Instruction *inst : debugIntrinsics) {
2280 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
2281 if (failed(processDebugIntrinsic(intrCall, domInfo)))
2287 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
2290 for (llvm::Instruction &inst : *bb) {
2291 if (failed(processInstruction(&inst)))
2296 if (debugIntrinsics.contains(&inst))
2303 setNonDebugMetadataAttrs(&inst, op);
2304 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
2305 if (emitExpensiveWarnings) {
2306 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
2314 FailureOr<SmallVector<AccessGroupAttr>>
2316 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
2322 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
2328 bool dropDICompositeTypeElements,
2329 bool loadAllDialects) {
2336 LLVMDialect::getDialectNamespace()));
2338 DLTIDialect::getDialectNamespace()));
2339 if (loadAllDialects)
2346 emitExpensiveWarnings, dropDICompositeTypeElements);
static MLIRContext * getContext(OpFoldResult val)
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 void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static constexpr StringRef getGlobalDtorsVarName()
Returns the name of the global_dtors global variables.
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 constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
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 bool isScalarType(Type type)
Returns if type is a scalar integer or floating-point type.
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.
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 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 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.
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.
RoundingModeAttr matchRoundingModeAttr(llvm::Value *value)
Converts value to a rounding mode attribute.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes)
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.
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.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Block * getBlock()
Returns the operation block that contains this operation.
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.
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.
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
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.
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true, bool dropDICompositeTypeElements=false, bool loadAllDialects=true)
Translates the LLVM module into an MLIR module living in the given context.
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.