29 #include "llvm/ADT/PostOrderIterator.h"
30 #include "llvm/ADT/ScopeExit.h"
31 #include "llvm/ADT/StringSet.h"
32 #include "llvm/ADT/TypeSwitch.h"
33 #include "llvm/IR/Comdat.h"
34 #include "llvm/IR/Constants.h"
35 #include "llvm/IR/InlineAsm.h"
36 #include "llvm/IR/InstIterator.h"
37 #include "llvm/IR/Instructions.h"
38 #include "llvm/IR/IntrinsicInst.h"
39 #include "llvm/IR/Metadata.h"
40 #include "llvm/IR/Operator.h"
41 #include "llvm/Support/ModRef.h"
47 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
52 static std::string
diag(
const llvm::Value &value) {
54 llvm::raw_string_ostream os(str);
62 static std::string
diagMD(
const llvm::Metadata *node,
63 const llvm::Module *module) {
65 llvm::raw_string_ostream os(str);
66 node->print(os, module,
true);
72 return "llvm.global_ctors";
77 return "llvm.global_dtors";
83 return "__llvm_global_comdat";
92 std::optional<llvm::SyncScope::ID> syncScopeID =
93 llvm::getAtomicSyncScopeID(inst);
100 llvm::LLVMContext &llvmContext = inst->getContext();
101 llvmContext.getSyncScopeNames(syncScopeName);
102 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
103 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
105 if (it != syncScopeName.end())
107 llvm_unreachable(
"incorrect sync scope identifier");
113 llvm::append_range(position, indices);
124 llvm::Instruction *inst,
131 #include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
139 for (llvm::BasicBlock &bb : *func) {
140 if (!blocks.contains(&bb)) {
141 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(&bb);
142 blocks.insert(traversal.begin(), traversal.end());
145 assert(blocks.size() == func->size() &&
"some blocks are not sorted");
151 std::unique_ptr<llvm::Module> llvmModule,
152 bool emitExpensiveWarnings)
154 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
158 loopAnnotationImporter(
160 emitExpensiveWarnings(emitExpensiveWarnings) {
164 ComdatOp ModuleImport::getGlobalComdatOp() {
166 return globalComdatOp;
172 globalInsertionOp = globalComdatOp;
173 return globalComdatOp;
176 LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
181 auto getIdentityIfRootNode =
182 [&](
const llvm::MDNode *node) ->
FailureOr<std::optional<StringRef>> {
186 if (node->getNumOperands() > 1)
189 if (node->getNumOperands() == 1)
190 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
191 return std::optional<StringRef>{op0->getString()};
192 return std::optional<StringRef>{};
202 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
203 StringRef *identity =
nullptr,
205 nullptr) -> std::optional<bool> {
206 unsigned numOperands = node->getNumOperands();
215 const auto *identityNode =
216 dyn_cast<const llvm::MDString>(node->getOperand(0));
222 *identity = identityNode->getString();
224 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
225 const auto *memberNode =
226 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
228 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
229 <<
diagMD(node, llvmModule.get());
233 if (2 * pairNum + 2 >= numOperands) {
235 if (numOperands != 2) {
236 emitError(loc) <<
"missing member offset: "
237 <<
diagMD(node, llvmModule.get());
241 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
242 node->getOperand(2 * pairNum + 2));
244 emitError(loc) <<
"operand '" << 2 * pairNum + 2
245 <<
"' must be ConstantInt: "
246 <<
diagMD(node, llvmModule.get());
249 offset = offsetCI->getZExtValue();
254 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
267 auto isTagNode = [&](
const llvm::MDNode *node,
268 TBAATypeDescriptorAttr *baseAttr =
nullptr,
269 TBAATypeDescriptorAttr *accessAttr =
nullptr,
270 int64_t *offset =
nullptr,
271 bool *isConstant =
nullptr) -> std::optional<bool> {
279 unsigned numOperands = node->getNumOperands();
280 if (numOperands != 3 && numOperands != 4)
282 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
283 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
285 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
286 if (!baseMD || !accessMD || !offsetCI)
293 if (accessMD->getNumOperands() < 1 ||
294 !isa<llvm::MDString>(accessMD->getOperand(0)))
296 bool isConst =
false;
297 if (numOperands == 4) {
299 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
301 emitError(loc) <<
"operand '3' must be ConstantInt: "
302 <<
diagMD(node, llvmModule.get());
305 isConst = isConstantCI->getValue()[0];
308 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
310 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
312 *offset = offsetCI->getZExtValue();
314 *isConstant = isConst;
323 workList.push_back(node);
324 while (!workList.empty()) {
325 const llvm::MDNode *current = workList.back();
326 if (tbaaMapping.contains(current)) {
335 bool anyChildNotConverted =
false;
336 for (
const llvm::MDOperand &operand : current->operands())
337 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
338 if (!tbaaMapping.contains(childNode)) {
339 workList.push_back(childNode);
340 anyChildNotConverted =
true;
343 if (anyChildNotConverted) {
348 if (!seen.insert(current).second)
349 return emitError(loc) <<
"has cycle in TBAA graph: "
350 <<
diagMD(current, llvmModule.get());
359 getIdentityIfRootNode(current);
361 StringAttr stringAttr = *rootNodeIdentity
366 tbaaMapping.insert({current, builder.
getAttr<TBAARootAttr>(stringAttr)});
372 if (std::optional<bool> isValid =
373 isTypeDescriptorNode(current, &identity, &members)) {
374 assert(isValid.value() &&
"type descriptor node must be valid");
376 tbaaMapping.insert({current, builder.
getAttr<TBAATypeDescriptorAttr>(
377 identity, members)});
381 TBAATypeDescriptorAttr baseAttr, accessAttr;
384 if (std::optional<bool> isValid =
385 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
386 assert(isValid.value() &&
"access tag node must be valid");
388 {current, builder.
getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
393 return emitError(loc) <<
"unsupported TBAA node format: "
394 <<
diagMD(current, llvmModule.get());
400 ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
402 if (
failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
403 return emitError(loc) <<
"unsupported access group node: "
404 <<
diagMD(node, llvmModule.get());
409 ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
412 auto verifySelfRef = [](
const llvm::MDNode *node) {
413 return node->getNumOperands() != 0 &&
414 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
417 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
418 return idx >= node->getNumOperands() ||
419 isa<llvm::MDString>(node->getOperand(idx));
422 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
423 StringAttr description =
nullptr;
424 if (aliasDomain->getNumOperands() >= 2)
425 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
427 return builder.
getAttr<AliasScopeDomainAttr>(
432 for (
const llvm::MDOperand &operand : node->operands()) {
433 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
434 llvm::AliasScopeNode aliasScope(scope);
435 const llvm::MDNode *domain = aliasScope.getDomain();
441 if (!verifySelfRef(scope) || !domain || !verifyDescription(scope, 2))
442 return emitError(loc) <<
"unsupported alias scope node: "
443 <<
diagMD(scope, llvmModule.get());
444 if (!verifySelfRef(domain) || !verifyDescription(domain, 1))
445 return emitError(loc) <<
"unsupported alias domain node: "
446 <<
diagMD(domain, llvmModule.get());
448 if (aliasScopeMapping.contains(scope))
452 auto it = aliasScopeMapping.find(aliasScope.getDomain());
453 if (it == aliasScopeMapping.end()) {
454 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
455 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
459 StringAttr description =
nullptr;
460 if (!aliasScope.getName().empty())
462 auto aliasScopeOp = builder.
getAttr<AliasScopeAttr>(
464 cast<AliasScopeDomainAttr>(it->second), description);
465 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
474 aliasScopes.reserve(node->getNumOperands());
475 for (
const llvm::MDOperand &operand : node->operands()) {
476 auto *node = cast<llvm::MDNode>(operand.get());
477 aliasScopes.push_back(
478 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
481 if (llvm::is_contained(aliasScopes,
nullptr))
487 debugIntrinsics.insert(intrinsic);
493 for (
const llvm::Function &func : llvmModule->functions()) {
494 for (
const llvm::Instruction &inst : llvm::instructions(func)) {
496 if (llvm::MDNode *node =
497 inst.getMetadata(llvm::LLVMContext::MD_access_group))
498 if (
failed(processAccessGroupMetadata(node)))
502 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
503 if (!aliasAnalysisNodes)
505 if (aliasAnalysisNodes.TBAA)
506 if (
failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
508 if (aliasAnalysisNodes.Scope)
509 if (
failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
511 if (aliasAnalysisNodes.NoAlias)
512 if (
failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
519 void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
520 if (comdatMapping.contains(comdat))
523 ComdatOp comdatOp = getGlobalComdatOp();
526 auto selectorOp = builder.
create<ComdatSelectorOp>(
527 mlirModule.getLoc(), comdat->getName(),
528 convertComdatFromLLVM(comdat->getSelectionKind()));
532 comdatMapping.try_emplace(comdat, symbolRef);
536 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
537 if (globalVar.hasComdat())
538 processComdat(globalVar.getComdat());
539 for (llvm::Function &func : llvmModule->functions())
540 if (func.hasComdat())
541 processComdat(func.getComdat());
546 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
549 if (
failed(convertGlobalCtorsAndDtors(&globalVar))) {
551 <<
"unhandled global variable: " <<
diag(globalVar);
555 if (
failed(convertGlobal(&globalVar))) {
557 <<
"unhandled global variable: " <<
diag(globalVar);
567 return emitError(loc,
"cannot translate data layout: ")
571 emitWarning(loc,
"unhandled data layout token: ") << token;
573 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
579 for (llvm::Function &func : llvmModule->functions())
585 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
588 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
589 for (
auto &[kind, node] : allMetadata) {
593 if (emitExpensiveWarnings) {
594 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
596 <<
diagMD(node, llvmModule.get()) <<
" on "
605 auto iface = cast<FastmathFlagsInterface>(op);
611 if (!isa<llvm::FPMathOperator>(inst))
613 llvm::FastMathFlags flags = inst->getFastMathFlags();
616 FastmathFlags value = {};
617 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
618 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
619 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
620 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
622 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
623 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
625 iface->setAttr(iface.getFastmathAttrName(), attr);
630 return isa<IntegerType, FloatType>(type);
642 if (numElements.isScalable()) {
644 <<
"scalable vectors not supported";
654 shape.push_back(numElements.getKnownMinValue());
658 Type ModuleImport::getBuiltinTypeForAttr(
Type type) {
673 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
674 arrayShape.push_back(arrayType.getNumElements());
675 type = arrayType.getElementType();
685 llvm::Constant *constScalar) {
689 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
692 constInt->getValue());
696 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
697 llvm::Type *type = constFloat->getType();
704 <<
"unexpected floating-point type";
707 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
716 llvm::ConstantDataSequential *constSequence) {
718 elementAttrs.reserve(constSequence->getNumElements());
719 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
720 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
726 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
732 if (
auto *func = dyn_cast<llvm::Function>(constant))
736 auto getConstantShape = [&](llvm::Type *type) {
737 return llvm::dyn_cast_if_present<ShapedType>(
743 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
744 if (constArray->isString())
746 auto shape = getConstantShape(constArray->getType());
750 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
751 if (constVector && constVector->isSplat()) {
754 builder, constVector->getElementAsConstant(0));
765 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
766 auto shape = getConstantShape(constAggregate->getType());
772 while (!workList.empty()) {
773 llvm::Constant *current = workList.pop_back_val();
776 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
778 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
779 workList.push_back(constAggregate->getAggregateElement(idx));
784 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
787 elementAttrs.append(attrs.begin(), attrs.end());
793 elementAttrs.push_back(scalarAttr);
804 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
805 auto shape = llvm::dyn_cast_if_present<ShapedType>(
806 getBuiltinTypeForAttr(
convertType(constZero->getType())));
811 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
817 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
820 if (!globalInsertionOp)
826 if (globalVar->hasInitializer())
827 valueAttr = getConstantAsAttr(globalVar->getInitializer());
830 uint64_t alignment = 0;
831 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
832 if (maybeAlign.has_value()) {
833 llvm::Align align = *maybeAlign;
834 alignment = align.value();
837 GlobalOp globalOp = builder.
create<GlobalOp>(
838 mlirModule.getLoc(), type, globalVar->isConstant(),
839 convertLinkageFromLLVM(globalVar->getLinkage()), globalVar->getName(),
840 valueAttr, alignment, globalVar->getAddressSpace(),
841 globalVar->isDSOLocal(),
842 globalVar->isThreadLocal());
843 globalInsertionOp = globalOp;
845 if (globalVar->hasInitializer() && !valueAttr) {
848 setConstantInsertionPointToStart(block);
850 convertConstantExpr(globalVar->getInitializer());
853 builder.
create<ReturnOp>(globalOp.getLoc(), *initializer);
855 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
856 globalOp.setUnnamedAddr(
857 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
859 if (globalVar->hasSection())
860 globalOp.setSection(globalVar->getSection());
861 globalOp.setVisibility_(
862 convertVisibilityFromLLVM(globalVar->getVisibility()));
864 if (globalVar->hasComdat())
865 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
871 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
872 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
875 dyn_cast<llvm::ConstantArray>(globalVar->getInitializer());
881 for (llvm::Value *operand : initializer->operands()) {
882 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
883 if (!aggregate || aggregate->getNumOperands() != 3)
886 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
887 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
888 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
889 if (!priority || !func || !data)
893 if (!data->isNullValue())
897 priorities.push_back(priority->getValue().getZExtValue());
901 if (!globalInsertionOp)
907 globalInsertionOp = builder.
create<LLVM::GlobalCtorsOp>(
912 globalInsertionOp = builder.
create<LLVM::GlobalDtorsOp>(
919 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
921 if (valueMapping.contains(constant))
930 workList.insert(constant);
931 while (!workList.empty()) {
932 llvm::Constant *current = workList.back();
935 auto adjacencyIt = adjacencyLists.find(current);
936 if (adjacencyIt == adjacencyLists.end()) {
937 adjacencyIt = adjacencyLists.try_emplace(current).first;
940 for (llvm::Value *operand : current->operands())
941 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
942 adjacencyIt->getSecond().push_back(constDependency);
945 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
946 unsigned numElements = constAgg->getElementCount().getFixedValue();
947 for (
unsigned i = 0, e = numElements; i != e; ++i)
948 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
954 if (adjacencyIt->getSecond().empty()) {
955 orderedSet.insert(current);
964 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
965 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
966 orderedSet.contains(dependency))
968 workList.insert(dependency);
978 if (
Attribute attr = getConstantAsAttr(constant)) {
980 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
981 return builder.
create<AddressOfOp>(loc, type, symbolRef.getValue())
984 return builder.
create<ConstantOp>(loc, type, attr).getResult();
988 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
990 return builder.
create<ZeroOp>(loc, type).getResult();
994 if (
auto *noneToken = dyn_cast<llvm::ConstantTokenNone>(constant)) {
995 return builder.
create<NoneTokenOp>(loc).getResult();
999 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1001 return builder.
create<PoisonOp>(loc, type).getResult();
1005 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1007 return builder.
create<UndefOp>(loc, type).getResult();
1011 if (
auto *globalVar = dyn_cast<llvm::GlobalVariable>(constant)) {
1014 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1018 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1024 llvm::Instruction *inst = constExpr->getAsInstruction();
1025 auto guard = llvm::make_scope_exit([&]() {
1026 assert(!noResultOpMapping.contains(inst) &&
1027 "expected constant expression to return a result");
1028 valueMapping.erase(inst);
1029 inst->deleteValue();
1033 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1034 return valueMapping.contains(value);
1036 if (
failed(processInstruction(inst)))
1042 if (isa<llvm::ConstantAggregate>(constant) ||
1043 isa<llvm::ConstantAggregateZero>(constant)) {
1046 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1047 elementValues.reserve(constAgg->getNumOperands());
1048 for (llvm::Value *operand : constAgg->operands())
1051 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1052 unsigned numElements = constAgg->getElementCount().getFixedValue();
1053 elementValues.reserve(numElements);
1054 for (
unsigned i = 0, e = numElements; i != e; ++i)
1055 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1057 assert(llvm::count(elementValues,
nullptr) == 0 &&
1058 "expected all elements have been converted before");
1062 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1064 "unrecognized aggregate type");
1065 Value root = builder.
create<UndefOp>(loc, rootType);
1067 if (isArrayOrStruct) {
1068 root = builder.
create<InsertValueOp>(loc, root, it.value(), it.index());
1073 root = builder.
create<InsertElementOp>(loc, rootType, root, it.value(),
1080 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1081 LLVMTargetExtType targetExtType =
1082 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1083 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1084 "target extension type does not support zero-initialization");
1087 return builder.
create<LLVM::ZeroOp>(loc, targetExtType).getRes();
1090 StringRef error =
"";
1091 if (isa<llvm::BlockAddress>(constant))
1092 error =
" since blockaddress(...) is unsupported";
1094 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1097 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1101 assert(!valueMapping.contains(constant) &&
1102 "expected constant has not been converted before");
1103 assert(constantInsertionBlock &&
1104 "expected the constant insertion block to be non-null");
1108 if (!constantInsertionOp)
1115 getConstantsToConvert(constant);
1116 for (llvm::Constant *constantToConvert : constantsToConvert) {
1120 mapValue(constantToConvert, *converted);
1130 assert(!isa<llvm::MetadataAsValue>(value) &&
1131 "expected value to not be metadata");
1134 auto it = valueMapping.find(value);
1135 if (it != valueMapping.end())
1136 return it->getSecond();
1139 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1140 return convertConstantExpr(constant);
1143 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1145 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1151 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1154 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1157 value = node->getValue();
1160 auto it = valueMapping.find(value);
1161 if (it != valueMapping.end())
1162 return it->getSecond();
1165 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1166 return convertConstantExpr(constant);
1173 remapped.reserve(values.size());
1174 for (llvm::Value *value : values) {
1178 remapped.push_back(*converted);
1184 IntegerAttr integerAttr;
1188 assert(
success &&
"expected a constant integer value");
1194 FloatAttr floatAttr;
1198 assert(
success &&
"expected a constant float value");
1204 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1205 auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
1206 return debugImporter->translate(node);
1210 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1211 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
1212 return debugImporter->translate(node);
1217 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1218 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
1223 return debugImporter->translateLoc(loc);
1227 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
1228 llvm::BasicBlock *target,
1230 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
1231 auto *phiInst = cast<llvm::PHINode>(&*inst);
1232 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
1236 blockArguments.push_back(*converted);
1242 ModuleImport::convertCallTypeAndOperands(llvm::CallBase *callInst,
1245 if (!callInst->getType()->isVoidTy())
1246 types.push_back(
convertType(callInst->getType()));
1248 if (!callInst->getCalledFunction()) {
1252 operands.push_back(*called);
1258 llvm::append_range(operands, *arguments);
1262 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
1267 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
1270 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1273 if (inst->getOpcode() == llvm::Instruction::Br) {
1274 auto *brInst = cast<llvm::BranchInst>(inst);
1278 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
1279 llvm::BasicBlock *succ = brInst->getSuccessor(i);
1281 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
1284 succBlockArgs.push_back(blockArgs);
1287 if (!brInst->isConditional()) {
1288 auto brOp = builder.
create<LLVM::BrOp>(loc, succBlockArgs.front(),
1289 succBlocks.front());
1296 auto condBrOp = builder.
create<LLVM::CondBrOp>(
1297 loc, *condition, succBlocks.front(), succBlockArgs.front(),
1298 succBlocks.back(), succBlockArgs.back());
1302 if (inst->getOpcode() == llvm::Instruction::Switch) {
1303 auto *swInst = cast<llvm::SwitchInst>(inst);
1310 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
1311 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
1315 unsigned numCases = swInst->getNumCases();
1321 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
1322 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
1323 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
1325 caseOperandRefs[it.index()] = caseOperands[it.index()];
1326 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
1330 auto switchOp = builder.
create<SwitchOp>(
1331 loc, *condition,
lookupBlock(defaultBB), defaultBlockArgs, caseValues,
1332 caseBlocks, caseOperandRefs);
1336 if (inst->getOpcode() == llvm::Instruction::PHI) {
1342 if (inst->getOpcode() == llvm::Instruction::Call) {
1343 auto *callInst = cast<llvm::CallInst>(inst);
1347 if (
failed(convertCallTypeAndOperands(callInst, types, operands)))
1351 dyn_cast<LLVMFunctionType>(
convertType(callInst->getFunctionType()));
1357 if (llvm::Function *callee = callInst->getCalledFunction()) {
1358 callOp = builder.
create<CallOp>(
1362 callOp = builder.
create<CallOp>(loc, funcTy, operands);
1365 if (!callInst->getType()->isVoidTy())
1366 mapValue(inst, callOp.getResult());
1371 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
1372 auto *lpInst = cast<llvm::LandingPadInst>(inst);
1375 operands.reserve(lpInst->getNumClauses());
1376 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
1380 operands.push_back(*operand);
1385 builder.
create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
1389 if (inst->getOpcode() == llvm::Instruction::Invoke) {
1390 auto *invokeInst = cast<llvm::InvokeInst>(inst);
1394 if (
failed(convertCallTypeAndOperands(invokeInst, types, operands)))
1399 bool invokeResultUsedInPhi = llvm::any_of(
1400 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
1401 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
1406 Block *directNormalDest = normalDest;
1407 if (invokeResultUsedInPhi) {
1413 directNormalDest = builder.
createBlock(normalDest);
1417 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
1422 dyn_cast<LLVMFunctionType>(
convertType(invokeInst->getFunctionType()));
1430 if (llvm::Function *callee = invokeInst->getCalledFunction()) {
1431 invokeOp = builder.
create<InvokeOp>(
1435 lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
1437 invokeOp = builder.
create<InvokeOp>(
1438 loc, funcTy,
nullptr, operands, directNormalDest,
1441 if (!invokeInst->getType()->isVoidTy())
1442 mapValue(inst, invokeOp.getResults().front());
1447 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
1451 if (invokeResultUsedInPhi) {
1457 builder.
create<LLVM::BrOp>(loc, normalArgs, normalDest);
1461 assert(llvm::none_of(
1464 "An llvm.invoke operation cannot pass its result as a block "
1466 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
1471 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
1472 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
1473 Type sourceElementType =
convertType(gepInst->getSourceElementType());
1483 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
1487 indices.push_back(*index);
1491 auto gepOp = builder.
create<GEPOp>(loc, type, sourceElementType, *basePtr,
1492 indices, gepInst->isInBounds());
1501 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
1504 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
1511 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
1512 return convertIntrinsic(intrinsic);
1515 return convertInstruction(inst);
1519 if (!f->hasPersonalityFn())
1522 llvm::Constant *pf = f->getPersonalityFn();
1530 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1531 if (ce->getOpcode() == llvm::Instruction::BitCast &&
1532 ce->getType() == llvm::Type::getInt8PtrTy(f->getContext())) {
1533 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
1541 llvm::MemoryEffects memEffects = func->getMemoryEffects();
1543 auto othermem = convertModRefInfoFromLLVM(
1544 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1545 auto argMem = convertModRefInfoFromLLVM(
1546 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1547 auto inaccessibleMem = convertModRefInfoFromLLVM(
1548 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1552 if (memAttr.isReadWrite())
1554 funcOp.setMemoryAttr(memAttr);
1560 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
1561 llvm::AttributeList::AttrIndex::FunctionIndex);
1562 for (llvm::Attribute attr : funcAttrs) {
1565 if (attr.hasAttribute(llvm::Attribute::Memory))
1569 if (attr.isTypeAttribute()) {
1571 "type attributes on a function are invalid, skipping it");
1576 if (attr.isStringAttribute())
1577 attrName = attr.getKindAsString();
1579 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1585 if (attrName ==
"aarch64_pstate_sm_enabled" ||
1586 attrName ==
"aarch64_pstate_sm_body" || attrName ==
"vscale_range")
1589 if (attr.isStringAttribute()) {
1590 StringRef val = attr.getValueAsString();
1592 passthroughs.push_back(keyAttr);
1595 passthroughs.push_back(
1599 if (attr.isIntAttribute()) {
1600 auto val = std::to_string(attr.getValueAsInt());
1601 passthroughs.push_back(
1605 if (attr.isEnumAttribute()) {
1606 passthroughs.push_back(keyAttr);
1610 llvm_unreachable(
"unexpected attribute kind");
1613 if (!passthroughs.empty())
1614 funcOp.setPassthroughAttr(
ArrayAttr::get(context, passthroughs));
1618 LLVMFuncOp funcOp) {
1622 if (func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
1623 funcOp.setArmStreaming(
true);
1624 else if (func->hasFnAttribute(
"aarch64_pstate_sm_body"))
1625 funcOp.setArmLocallyStreaming(
true);
1626 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
1627 if (attr.isValid()) {
1637 ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
1641 auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
1643 if (!llvmAttr.isValid())
1646 if (llvmAttr.isTypeAttribute())
1648 else if (llvmAttr.isIntAttribute())
1650 else if (llvmAttr.isEnumAttribute())
1653 llvm_unreachable(
"unexpected parameter attribute kind");
1654 paramAttrs.push_back(builder.
getNamedAttr(mlirName, mlirAttr));
1660 void ModuleImport::convertParameterAttributes(llvm::Function *func,
1663 auto llvmAttrs = func->getAttributes();
1664 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
1665 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
1666 funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder));
1670 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
1671 if (!llvmResAttr.hasAttributes())
1673 funcOp.setResAttrsAttr(
1674 builder.
getArrayAttr(convertParameterAttribute(llvmResAttr, builder)));
1681 dyn_cast<LLVMFunctionType>(
convertType(func->getFunctionType()));
1682 if (func->isIntrinsic() &&
1686 bool dsoLocal = func->hasLocalLinkage();
1687 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
1693 Location loc = debugImporter->translateFuncLocation(func);
1694 LLVMFuncOp funcOp = builder.
create<LLVMFuncOp>(
1695 loc, func->getName(), functionType,
1696 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
1698 convertParameterAttributes(func, funcOp, builder);
1701 funcOp.setPersonalityAttr(personality);
1702 else if (func->hasPersonalityFn())
1703 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
1706 funcOp.setGarbageCollector(StringRef(func->getGC()));
1708 if (func->hasAtLeastLocalUnnamedAddr())
1709 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
1711 if (func->hasSection())
1712 funcOp.setSection(StringRef(func->getSection()));
1714 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
1716 if (func->hasComdat())
1717 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
1719 if (llvm::MaybeAlign maybeAlign = func->getAlign())
1720 funcOp.setAlignment(maybeAlign->value());
1727 func->getAllMetadata(allMetadata);
1728 for (
auto &[kind, node] : allMetadata) {
1733 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
1734 <<
" on " <<
diag(*func);
1738 if (func->isDeclaration())
1742 for (llvm::BasicBlock &bb : *func) {
1744 builder.
createBlock(&funcOp.getBody(), funcOp.getBody().end());
1750 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
1751 functionType.getParamType(it.index()), funcOp.getLoc());
1759 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
1760 for (llvm::BasicBlock *bb : blocks)
1766 if (
failed(processDebugIntrinsics()))
1775 if (!dbgIntr->isKillLocation())
1777 llvm::Value *value = dbgIntr->getArgOperand(0);
1778 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1781 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1785 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
1788 auto emitUnsupportedWarning = [&]() {
1789 if (emitExpensiveWarnings)
1795 if (dbgIntr->hasArgList() || dbgIntr->getExpression()->getNumElements() != 0)
1796 return emitUnsupportedWarning();
1801 return emitUnsupportedWarning();
1804 return emitError(loc) <<
"failed to convert a debug intrinsic operand: "
1812 if (
Operation *op = argOperand->getDefiningOp();
1818 if (dominatedBlocks.empty())
1819 return emitUnsupportedWarning();
1822 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
1827 DILocalVariableAttr localVariableAttr =
1831 .Case([&](llvm::DbgDeclareInst *) {
1832 return builder.
create<LLVM::DbgDeclareOp>(loc, *argOperand,
1835 .Case([&](llvm::DbgValueInst *) {
1836 return builder.
create<LLVM::DbgValueOp>(loc, *argOperand,
1840 setNonDebugMetadataAttrs(dbgIntr, op);
1846 for (llvm::Instruction *inst : debugIntrinsics) {
1847 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
1848 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
1854 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
1857 for (llvm::Instruction &inst : *bb) {
1858 if (
failed(processInstruction(&inst)))
1863 if (debugIntrinsics.contains(&inst))
1870 setNonDebugMetadataAttrs(&inst, op);
1871 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
1872 if (emitExpensiveWarnings) {
1873 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
1883 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
1889 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
1895 bool emitExpensiveWarnings) {
1902 LLVMDialect::getDialectNamespace()));
1904 DLTIDialect::getDialectNamespace()));
1911 emitExpensiveWarnings);
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 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 Attribute getScalarConstantAsAttr(OpBuilder &builder, llvm::Constant *constScalar)
Returns an integer or float attribute for the provided scalar constant constScalar or nullptr if the ...
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 constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder, llvm::Instruction *inst, ModuleImport &moduleImport)
Converts the LLVM instructions that have a generated MLIR builder.
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 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 SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(llvm::Function *func)
Get a topologically sorted list of blocks for the given function.
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 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)
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.
This class provides support for representing a failure result, or a valid value of type T.
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.
static FloatType getBF16(MLIRContext *ctx)
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 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...
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,...
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings)
DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value)
Converts value to a local variable attribute.
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...
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 mapNoResultOp(llvm::Instruction *llvm, Operation *mlir)
Stores a mapping between an LLVM instruction and the imported MLIR operation if the operation returns...
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.
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.
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.
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.
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...
SetVector< Block * > getTopologicallySortedBlocks(Region ®ion)
Get a topologically sorted list of blocks of the given region.
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)
This header declares functions that assist transformations in the MemRef dialect.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true)
Translates the LLVM module into an MLIR module living in the given context.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
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.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.