38 #include "llvm/ADT/PostOrderIterator.h"
39 #include "llvm/ADT/SetVector.h"
40 #include "llvm/ADT/StringExtras.h"
41 #include "llvm/ADT/TypeSwitch.h"
42 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
43 #include "llvm/IR/BasicBlock.h"
44 #include "llvm/IR/CFG.h"
45 #include "llvm/IR/Constants.h"
46 #include "llvm/IR/DerivedTypes.h"
47 #include "llvm/IR/IRBuilder.h"
48 #include "llvm/IR/InlineAsm.h"
49 #include "llvm/IR/IntrinsicsNVPTX.h"
50 #include "llvm/IR/LLVMContext.h"
51 #include "llvm/IR/MDBuilder.h"
52 #include "llvm/IR/Module.h"
53 #include "llvm/IR/Verifier.h"
54 #include "llvm/Support/Debug.h"
55 #include "llvm/Support/raw_ostream.h"
56 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
57 #include "llvm/Transforms/Utils/Cloning.h"
58 #include "llvm/Transforms/Utils/ModuleUtils.h"
61 #define DEBUG_TYPE "llvm-dialect-to-llvm-ir"
67 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
90 class InstructionCapturingInserter :
public llvm::IRBuilderCallbackInserter {
93 InstructionCapturingInserter()
94 : llvm::IRBuilderCallbackInserter([
this](llvm::Instruction *instruction) {
95 if (LLVM_LIKELY(enabled))
96 capturedInstructions.push_back(instruction);
101 return capturedInstructions;
105 void clearCapturedInstructions() { capturedInstructions.clear(); }
108 class CollectionScope {
111 CollectionScope(llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing);
119 return inserter->getCapturedInstructions();
124 InstructionCapturingInserter *inserter =
nullptr;
134 void setEnabled(
bool enabled =
true) { this->enabled = enabled; }
141 bool enabled =
false;
144 using CapturingIRBuilder =
145 llvm::IRBuilder<llvm::ConstantFolder, InstructionCapturingInserter>;
148 InstructionCapturingInserter::CollectionScope::CollectionScope(
149 llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing) {
151 if (!isBuilderCapturing)
154 auto &capturingIRBuilder =
static_cast<CapturingIRBuilder &
>(irBuilder);
155 inserter = &capturingIRBuilder.getInserter();
156 wasEnabled = inserter->enabled;
158 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
159 inserter->setEnabled(
true);
162 InstructionCapturingInserter::CollectionScope::~CollectionScope() {
166 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
170 llvm::append_range(inserter->capturedInstructions,
171 previouslyCollectedInstructions);
173 inserter->setEnabled(wasEnabled);
181 std::optional<Location> loc = std::nullopt) {
186 std::string llvmDataLayout;
187 llvm::raw_string_ostream layoutStream(llvmDataLayout);
188 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
189 auto key = llvm::dyn_cast_if_present<StringAttr>(entry.getKey());
192 if (key.getValue() == DLTIDialect::kDataLayoutEndiannessKey) {
193 auto value = cast<StringAttr>(entry.getValue());
194 bool isLittleEndian =
195 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle;
196 layoutStream <<
"-" << (isLittleEndian ?
"e" :
"E");
197 layoutStream.flush();
200 if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
201 auto value = cast<IntegerAttr>(entry.getValue());
202 uint64_t space = value.getValue().getZExtValue();
206 layoutStream <<
"-P" << space;
207 layoutStream.flush();
210 if (key.getValue() == DLTIDialect::kDataLayoutGlobalMemorySpaceKey) {
211 auto value = cast<IntegerAttr>(entry.getValue());
212 uint64_t space = value.getValue().getZExtValue();
216 layoutStream <<
"-G" << space;
217 layoutStream.flush();
220 if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
221 auto value = cast<IntegerAttr>(entry.getValue());
222 uint64_t space = value.getValue().getZExtValue();
226 layoutStream <<
"-A" << space;
227 layoutStream.flush();
230 if (key.getValue() == DLTIDialect::kDataLayoutStackAlignmentKey) {
231 auto value = cast<IntegerAttr>(entry.getValue());
232 uint64_t alignment = value.getValue().getZExtValue();
236 layoutStream <<
"-S" << alignment;
237 layoutStream.flush();
240 emitError(*loc) <<
"unsupported data layout key " << key;
247 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
248 auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
252 if (isa<IndexType>(type))
257 .Case<IntegerType, Float16Type, Float32Type, Float64Type,
259 if (
auto intType = dyn_cast<IntegerType>(type)) {
260 if (intType.getSignedness() != IntegerType::Signless)
262 <<
"unsupported data layout for non-signless integer "
272 layoutStream << size <<
":" << abi;
273 if (abi != preferred)
274 layoutStream <<
":" << preferred;
277 .Case([&](LLVMPointerType type) {
278 layoutStream <<
"p" << type.getAddressSpace() <<
":";
284 layoutStream << size <<
":" << abi <<
":" << preferred <<
":"
288 .Default([loc](
Type type) {
290 <<
"unsupported type in data layout: " << type;
295 layoutStream.flush();
296 StringRef layoutSpec(llvmDataLayout);
297 if (layoutSpec.starts_with(
"-"))
298 layoutSpec = layoutSpec.drop_front();
300 return llvm::DataLayout(layoutSpec);
307 static llvm::Constant *
312 llvm::Constant *result = constants.front();
313 constants = constants.drop_front();
317 llvm::Type *elementType;
318 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
319 elementType = arrayTy->getElementType();
320 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
321 elementType = vectorTy->getElementType();
323 emitError(loc) <<
"expected sequential LLVM types wrapping a scalar";
328 nested.reserve(shape.front());
329 for (int64_t i = 0; i < shape.front(); ++i) {
336 if (shape.size() == 1 && type->isVectorTy())
345 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
346 type = arrayTy->getElementType();
347 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
348 type = vectorTy->getElementType();
362 static llvm::Constant *
364 llvm::Type *llvmType,
366 if (!denseElementsAttr)
370 if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
373 ShapedType type = denseElementsAttr.
getType();
374 if (type.getNumElements() == 0)
382 int64_t elementByteSize = denseElementsAttr.
getRawData().size() /
384 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
389 bool hasVectorElementType = isa<VectorType>(type.getElementType());
390 int64_t numAggregates =
392 (hasVectorElementType ? 1
393 : denseElementsAttr.
getType().getShape().back());
395 if (!hasVectorElementType)
396 outerShape = outerShape.drop_back();
399 if (denseElementsAttr.
isSplat() &&
400 (isa<VectorType>(type) || hasVectorElementType)) {
404 llvm::Constant *splatVector =
405 llvm::ConstantDataVector::getSplat(0, splatValue);
410 if (denseElementsAttr.
isSplat())
415 std::function<llvm::Constant *(StringRef)> buildCstData;
416 if (isa<TensorType>(type)) {
417 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
418 if (vectorElementType && vectorElementType.getRank() == 1) {
419 buildCstData = [&](StringRef data) {
420 return llvm::ConstantDataVector::getRaw(
421 data, vectorElementType.getShape().back(), innermostLLVMType);
423 }
else if (!vectorElementType) {
424 buildCstData = [&](StringRef data) {
425 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
429 }
else if (isa<VectorType>(type)) {
430 buildCstData = [&](StringRef data) {
431 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
441 int64_t aggregateSize = denseElementsAttr.
getType().getShape().back() *
442 (innermostLLVMType->getScalarSizeInBits() / 8);
443 constants.reserve(numAggregates);
444 for (
unsigned i = 0; i < numAggregates; ++i) {
445 StringRef data(denseElementsAttr.
getRawData().data() + i * aggregateSize,
447 constants.push_back(buildCstData(data));
463 assert(denseResourceAttr &&
"expected non-null attribute");
466 if (!llvm::ConstantDataSequential::isElementTypeCompatible(
467 innermostLLVMType)) {
468 emitError(loc,
"no known conversion for innermost element type");
472 ShapedType type = denseResourceAttr.getType();
473 assert(type.getNumElements() > 0 &&
"Expected non-empty elements attribute");
477 emitError(loc,
"resource does not exist");
488 int64_t numElements = denseResourceAttr.getType().getNumElements();
489 int64_t elementByteSize = rawData.size() / numElements;
490 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
491 emitError(loc,
"raw data size does not match element type size");
497 bool hasVectorElementType = isa<VectorType>(type.getElementType());
498 int64_t numAggregates =
499 numElements / (hasVectorElementType
501 : denseResourceAttr.getType().getShape().back());
503 if (!hasVectorElementType)
504 outerShape = outerShape.drop_back();
507 std::function<llvm::Constant *(StringRef)> buildCstData;
508 if (isa<TensorType>(type)) {
509 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
510 if (vectorElementType && vectorElementType.getRank() == 1) {
511 buildCstData = [&](StringRef data) {
512 return llvm::ConstantDataVector::getRaw(
513 data, vectorElementType.getShape().back(), innermostLLVMType);
515 }
else if (!vectorElementType) {
516 buildCstData = [&](StringRef data) {
517 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
521 }
else if (isa<VectorType>(type)) {
522 buildCstData = [&](StringRef data) {
523 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
528 emitError(loc,
"unsupported dense_resource type");
535 int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
536 (innermostLLVMType->getScalarSizeInBits() / 8);
537 constants.reserve(numAggregates);
538 for (
unsigned i = 0; i < numAggregates; ++i) {
539 StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
540 constants.push_back(buildCstData(data));
557 if (
auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
558 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
559 if (!arrayAttr || arrayAttr.size() != 2) {
560 emitError(loc,
"expected struct type to be a complex number");
563 llvm::Type *elementType = structType->getElementType(0);
564 llvm::Constant *real =
568 llvm::Constant *imag =
576 if (
auto intAttr = dyn_cast<IntegerAttr>(attr))
579 intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
580 if (
auto floatAttr = dyn_cast<FloatAttr>(attr)) {
581 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
586 unsigned floatWidth = APFloat::getSizeInBits(sem);
587 if (llvmType->isIntegerTy(floatWidth))
589 floatAttr.getValue().bitcastToAPInt());
591 llvm::Type::getFloatingPointTy(llvmType->getContext(),
592 floatAttr.getValue().getSemantics())) {
593 emitError(loc,
"FloatAttr does not match expected type of the constant");
598 if (
auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
599 return llvm::ConstantExpr::getBitCast(
601 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
602 llvm::Type *elementType;
603 uint64_t numElements;
604 bool isScalable =
false;
605 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
606 elementType = arrayTy->getElementType();
607 numElements = arrayTy->getNumElements();
608 }
else if (
auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
609 elementType = fVectorTy->getElementType();
610 numElements = fVectorTy->getNumElements();
611 }
else if (
auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
612 elementType = sVectorTy->getElementType();
613 numElements = sVectorTy->getMinNumElements();
616 llvm_unreachable(
"unrecognized constant vector type");
621 bool elementTypeSequential =
622 isa<llvm::ArrayType, llvm::VectorType>(elementType);
625 elementTypeSequential ? splatAttr
627 loc, moduleTranslation);
630 if (llvmType->isVectorTy())
631 return llvm::ConstantVector::getSplat(
633 if (llvmType->isArrayTy()) {
641 if (llvm::Constant *result =
643 llvmType, moduleTranslation)) {
647 if (
auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
653 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
654 assert(elementsAttr.getShapedType().hasStaticShape());
655 assert(!elementsAttr.getShapedType().getShape().empty() &&
656 "unexpected empty elements attribute shape");
659 constants.reserve(elementsAttr.getNumElements());
661 for (
auto n : elementsAttr.getValues<
Attribute>()) {
664 if (!constants.back())
669 constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
670 assert(constantsRef.empty() &&
"did not consume all elemental constants");
674 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
678 stringAttr.getValue().size()});
680 emitError(loc,
"unsupported constant value");
684 ModuleTranslation::ModuleTranslation(
Operation *module,
685 std::unique_ptr<llvm::Module> llvmModule)
686 : mlirModule(module), llvmModule(std::move(llvmModule)),
690 *this, *this->llvmModule)),
691 typeTranslator(this->llvmModule->
getContext()),
694 "mlirModule should honor LLVM's module semantics.");
697 ModuleTranslation::~ModuleTranslation() {
699 ompBuilder->finalize();
704 toProcess.push_back(®ion);
705 while (!toProcess.empty()) {
706 Region *current = toProcess.pop_back_val();
707 for (
Block &block : *current) {
708 blockMapping.erase(&block);
709 for (
Value arg : block.getArguments())
710 valueMapping.erase(arg);
713 valueMapping.erase(value);
715 branchMapping.erase(&op);
716 if (isa<LLVM::GlobalOp>(op))
717 globalsMapping.erase(&op);
718 if (isa<LLVM::CallOp>(op))
719 callMapping.erase(&op);
731 unsigned numArguments,
unsigned index) {
733 if (isa<LLVM::BrOp>(terminator))
740 auto branch = cast<BranchOpInterface>(terminator);
743 (!seenSuccessors.contains(successor) || successorOperands.
empty()) &&
744 "successors with arguments in LLVM branches must be different blocks");
745 seenSuccessors.insert(successor);
751 if (
auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
754 return condBranchOp.getSuccessor(0) == current
755 ? condBranchOp.getTrueDestOperands()[index]
756 : condBranchOp.getFalseDestOperands()[index];
759 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
762 if (switchOp.getDefaultDestination() == current)
763 return switchOp.getDefaultOperands()[index];
765 if (i.value() == current)
766 return switchOp.getCaseOperands(i.index())[index];
769 if (
auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
770 return invokeOp.getNormalDest() == current
771 ? invokeOp.getNormalDestOperands()[index]
772 : invokeOp.getUnwindDestOperands()[index];
776 "only branch, switch or invoke operations can be terminators "
777 "of a block that has successors");
785 for (
Block &bb : llvm::drop_begin(region)) {
786 llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
787 auto phis = llvmBB->phis();
788 auto numArguments = bb.getNumArguments();
789 assert(numArguments == std::distance(phis.begin(), phis.end()));
791 for (
auto *pred : bb.getPredecessors()) {
797 llvm::Instruction *terminator =
798 state.lookupBranch(pred->getTerminator());
799 assert(terminator &&
"missing the mapping for a terminator");
801 &bb, pred, numArguments, index)),
802 terminator->getParent());
811 llvm::Module *module = builder.GetInsertBlock()->getModule();
812 llvm::Function *fn = llvm::Intrinsic::getDeclaration(module, intrinsic, tys);
813 return builder.CreateCall(fn, args);
822 assert(immArgPositions.size() == immArgAttrNames.size() &&
823 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
829 for (
auto [immArgPos, immArgName] :
830 llvm::zip(immArgPositions, immArgAttrNames)) {
831 auto attr = llvm::cast<TypedAttr>(intrOp->
getAttr(immArgName));
832 assert(attr.getType().isIntOrFloat() &&
"expected int or float immarg");
833 auto *type = moduleTranslation.
convertType(attr.getType());
835 type, attr, intrOp->
getLoc(), moduleTranslation);
838 for (
auto &arg : args) {
840 arg = operands[opArg++];
845 for (
unsigned overloadedResultIdx : overloadedResults) {
846 if (numResults > 1) {
848 overloadedTypes.push_back(moduleTranslation.
convertType(
850 .getBody()[overloadedResultIdx]));
852 overloadedTypes.push_back(
856 for (
unsigned overloadedOperandIdx : overloadedOperands)
857 overloadedTypes.push_back(args[overloadedOperandIdx]->getType());
858 llvm::Module *module = builder.GetInsertBlock()->getModule();
859 llvm::Function *llvmIntr =
860 llvm::Intrinsic::getDeclaration(module, intrinsic, overloadedTypes);
862 return builder.CreateCall(llvmIntr, args);
868 llvm::IRBuilderBase &builder,
869 bool recordInsertions) {
872 return op.
emitError(
"cannot be converted to LLVM IR: missing "
873 "`LLVMTranslationDialectInterface` registration for "
877 InstructionCapturingInserter::CollectionScope scope(builder,
880 return op.
emitError(
"LLVM Translation failed for operation: ")
883 return convertDialectAttributes(&op, scope.getCapturedInstructions());
894 bool ignoreArguments,
895 llvm::IRBuilderBase &builder,
896 bool recordInsertions) {
898 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
906 if (!ignoreArguments) {
908 unsigned numPredecessors =
909 std::distance(predecessors.begin(), predecessors.end());
911 auto wrappedType = arg.getType();
914 "block argument does not have an LLVM type");
916 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
922 for (
auto &op : bb) {
924 builder.SetCurrentDebugLocation(
925 debugTranslation->translateLoc(op.
getLoc(), subprogram));
927 if (
failed(convertOperation(op, builder, recordInsertions)))
931 if (
auto iface = dyn_cast<BranchWeightOpInterface>(op))
950 llvm::Constant *cst) {
951 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
952 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
958 llvm::GlobalValue *gv) {
959 if (dsoLocalRequested)
960 gv->setDSOLocal(
true);
969 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
971 llvm::Constant *cst =
nullptr;
972 if (op.getValueOrNull()) {
975 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
976 cst = llvm::ConstantDataArray::getString(
977 llvmModule->getContext(), strAttr.getValue(),
false);
978 type = cst->getType();
985 auto linkage = convertLinkageToLLVM(op.getLinkage());
986 auto addrSpace = op.getAddrSpace();
992 if (!dropInitializer && !cst)
994 else if (dropInitializer && cst)
997 auto *var =
new llvm::GlobalVariable(
998 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1000 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1001 : llvm::GlobalValue::NotThreadLocal,
1004 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1005 auto selectorOp = cast<ComdatSelectorOp>(
1007 var->setComdat(comdatMapping.lookup(selectorOp));
1010 if (op.getUnnamedAddr().has_value())
1011 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1013 if (op.getSection().has_value())
1014 var->setSection(*op.getSection());
1018 std::optional<uint64_t> alignment = op.getAlignment();
1019 if (alignment.has_value())
1020 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1022 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1024 globalsMapping.try_emplace(op, var);
1027 if (op.getDbgExpr()) {
1028 llvm::DIGlobalVariableExpression *diGlobalExpr =
1029 debugTranslation->translateGlobalVariableExpression(op.getDbgExpr());
1030 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1031 var->addDebugInfo(diGlobalExpr);
1034 if (llvm::DICompileUnit *compileUnit =
1035 dyn_cast_if_present<llvm::DICompileUnit>(
1036 diGlobalVar->getScope())) {
1039 allGVars[compileUnit].push_back(diGlobalExpr);
1047 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1048 if (
Block *initializer = op.getInitializerBlock()) {
1049 llvm::IRBuilder<> builder(llvmModule->getContext());
1051 [[maybe_unused]]
int numConstantsHit = 0;
1052 [[maybe_unused]]
int numConstantsErased = 0;
1055 for (
auto &op : initializer->without_terminator()) {
1056 if (
failed(convertOperation(op, builder)))
1069 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1073 auto [iterator, inserted] =
1074 constantAggregateUseMap.try_emplace(agg, numUsers);
1077 iterator->second += numUsers;
1083 auto cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1086 auto iter = constantAggregateUseMap.find(cst);
1087 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1089 if (iter->second == 0) {
1092 if (cst->user_empty()) {
1093 cst->destroyConstant();
1094 numConstantsErased++;
1096 constantAggregateUseMap.erase(iter);
1101 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1102 llvm::Constant *cst =
1103 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1104 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1106 global->setInitializer(cst);
1110 for (
auto it : constantAggregateUseMap) {
1111 auto cst = it.first;
1112 cst->removeDeadConstantUsers();
1113 if (cst->user_empty()) {
1114 cst->destroyConstant();
1115 numConstantsErased++;
1119 LLVM_DEBUG(llvm::dbgs()
1120 <<
"Convert initializer for " << op.
getName() <<
"\n";
1121 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1123 << numConstantsErased <<
" dangling constants erased\n";);
1129 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1130 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1131 if (!ctorOp && !dtorOp)
1133 auto range = ctorOp ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1134 :
llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1135 auto appendGlobalFn =
1136 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1137 for (
auto symbolAndPriority : range) {
1139 cast<FlatSymbolRefAttr>(std::get<0>(symbolAndPriority)).getValue());
1140 appendGlobalFn(*llvmModule, f,
1141 cast<IntegerAttr>(std::get<1>(symbolAndPriority)).getInt(),
1146 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1147 if (
failed(convertDialectAttributes(op, {})))
1152 for (
const auto &[compileUnit, globals] : allGVars) {
1153 compileUnit->replaceGlobalVariables(
1167 llvm::Function *llvmFunc,
1169 StringRef value = StringRef()) {
1170 auto kind = llvm::Attribute::getAttrKindFromName(key);
1172 llvmFunc->addFnAttr(key, value);
1176 if (llvm::Attribute::isIntAttrKind(kind)) {
1178 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1181 if (!value.getAsInteger(0, result))
1182 llvmFunc->addFnAttr(
1185 llvmFunc->addFnAttr(key, value);
1190 return emitError(loc) <<
"LLVM attribute '" << key
1191 <<
"' does not expect a value, found '" << value
1194 llvmFunc->addFnAttr(kind);
1207 llvm::Function *llvmFunc) {
1212 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1219 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1220 if (!arrayAttr || arrayAttr.size() != 2)
1222 <<
"expected 'passthrough' to contain string or array attributes";
1224 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1225 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1226 if (!keyAttr || !valueAttr)
1228 <<
"expected arrays within 'passthrough' to contain two strings";
1231 valueAttr.getValue())))
1237 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1240 blockMapping.clear();
1241 valueMapping.clear();
1242 branchMapping.clear();
1246 for (
auto [mlirArg, llvmArg] :
1247 llvm::zip(func.getArguments(), llvmFunc->args()))
1251 if (func.getPersonality()) {
1252 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1253 if (llvm::Constant *pfunc =
getLLVMConstant(ty, func.getPersonalityAttr(),
1254 func.getLoc(), *
this))
1255 llvmFunc->setPersonalityFn(pfunc);
1258 if (std::optional<StringRef> section = func.getSection())
1259 llvmFunc->setSection(*section);
1261 if (func.getArmStreaming())
1262 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1263 else if (func.getArmLocallyStreaming())
1264 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1265 else if (func.getArmStreamingCompatible())
1266 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1268 if (func.getArmNewZa())
1269 llvmFunc->addFnAttr(
"aarch64_new_za");
1270 else if (func.getArmInZa())
1271 llvmFunc->addFnAttr(
"aarch64_in_za");
1272 else if (func.getArmOutZa())
1273 llvmFunc->addFnAttr(
"aarch64_out_za");
1274 else if (func.getArmInoutZa())
1275 llvmFunc->addFnAttr(
"aarch64_inout_za");
1276 else if (func.getArmPreservesZa())
1277 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1279 if (
auto targetCpu = func.getTargetCpu())
1280 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1282 if (
auto targetFeatures = func.getTargetFeatures())
1283 llvmFunc->addFnAttr(
"target-features", targetFeatures->getFeaturesString());
1285 if (
auto attr = func.getVscaleRange())
1286 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1288 attr->getMaxRange().getInt()));
1290 if (
auto unsafeFpMath = func.getUnsafeFpMath())
1291 llvmFunc->addFnAttr(
"unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1293 if (
auto noInfsFpMath = func.getNoInfsFpMath())
1294 llvmFunc->addFnAttr(
"no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1296 if (
auto noNansFpMath = func.getNoNansFpMath())
1297 llvmFunc->addFnAttr(
"no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1299 if (
auto approxFuncFpMath = func.getApproxFuncFpMath())
1300 llvmFunc->addFnAttr(
"approx-func-fp-math",
1301 llvm::toStringRef(*approxFuncFpMath));
1303 if (
auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1304 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1305 llvm::toStringRef(*noSignedZerosFpMath));
1308 if (FramePointerKindAttr attr = func.getFramePointerAttr())
1309 llvmFunc->addFnAttr(
"frame-pointer",
1310 LLVM::framePointerKind::stringifyFramePointerKind(
1311 (attr.getFramePointerKind())));
1314 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1315 for (
auto &bb : func) {
1316 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1317 llvmBB->insertInto(llvmFunc);
1324 for (
Block *bb : blocks) {
1325 CapturingIRBuilder builder(llvmContext);
1326 if (
failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1336 return convertDialectAttributes(func, {});
1350 llvm::Function *llvmFunc) {
1351 if (!func.getMemory())
1354 MemoryEffectsAttr memEffects = func.getMemoryAttr();
1357 llvm::MemoryEffects newMemEffects =
1358 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1359 convertModRefInfoToLLVM(memEffects.getArgMem()));
1360 newMemEffects |= llvm::MemoryEffects(
1361 llvm::MemoryEffects::Location::InaccessibleMem,
1362 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1364 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1365 convertModRefInfoToLLVM(memEffects.getOther()));
1366 llvmFunc->setMemoryEffects(newMemEffects);
1370 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func,
int argIdx,
1371 DictionaryAttr paramAttrs) {
1372 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1375 for (
auto namedAttr : paramAttrs) {
1376 auto it = attrNameToKindMapping.find(namedAttr.getName());
1377 if (it != attrNameToKindMapping.end()) {
1378 llvm::Attribute::AttrKind llvmKind = it->second;
1381 .Case<TypeAttr>([&](
auto typeAttr) {
1382 attrBuilder.addTypeAttr(llvmKind,
convertType(typeAttr.getValue()));
1384 .Case<IntegerAttr>([&](
auto intAttr) {
1385 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1387 .Case<UnitAttr>([&](
auto) { attrBuilder.addAttribute(llvmKind); });
1388 }
else if (namedAttr.getNameDialect()) {
1397 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1400 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1401 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1403 cast<llvm::FunctionType>(
convertType(
function.getFunctionType())));
1404 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1405 llvmFunc->setLinkage(convertLinkageToLLVM(
function.getLinkage()));
1406 llvmFunc->setCallingConv(convertCConvToLLVM(
function.getCConv()));
1414 if (std::optional<uint64_t> entryCount =
function.getFunctionEntryCount())
1415 llvmFunc->setEntryCount(entryCount.value());
1418 if (ArrayAttr allResultAttrs =
function.getAllResultAttrs()) {
1419 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1421 convertParameterAttrs(
function, -1, resultAttrs);
1424 llvmFunc->addRetAttrs(*attrBuilder);
1431 convertParameterAttrs(
function, argIdx, argAttrs);
1434 llvmArg.addAttrs(*attrBuilder);
1440 function.getLoc(),
function.getPassthrough(), llvmFunc)))
1444 llvmFunc->setVisibility(convertVisibilityToLLVM(
function.getVisibility_()));
1447 if (std::optional<mlir::SymbolRefAttr> comdat =
function.getComdat()) {
1448 auto selectorOp = cast<ComdatSelectorOp>(
1450 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1453 if (
auto gc =
function.getGarbageCollector())
1454 llvmFunc->setGC(gc->str());
1456 if (
auto unnamedAddr =
function.getUnnamedAddr())
1457 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1459 if (
auto alignment =
function.getAlignment())
1460 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1463 debugTranslation->translate(
function, *llvmFunc);
1471 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1474 if (
function.isExternal()) {
1475 if (
failed(convertDialectAttributes(
function, {})))
1480 if (
failed(convertOneFunction(
function)))
1488 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
1489 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1491 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1493 <<
"comdat selection symbols must be unique even in different "
1495 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1496 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1497 comdatMapping.try_emplace(selectorOp, comdat);
1504 llvm::Instruction *inst) {
1505 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1506 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1511 auto [scopeIt, scopeInserted] =
1512 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
1514 return scopeIt->second;
1515 llvm::LLVMContext &ctx = llvmModule->getContext();
1516 auto dummy = llvm::MDNode::getTemporary(ctx, std::nullopt);
1518 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1519 aliasScopeAttr.getDomain(),
nullptr);
1520 if (insertedDomain) {
1523 operands.push_back(dummy.get());
1524 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
1528 domainIt->second->replaceOperandWith(0, domainIt->second);
1531 assert(domainIt->second &&
"Scope's domain should already be valid");
1534 operands.push_back(dummy.get());
1535 operands.push_back(domainIt->second);
1536 if (StringAttr description = aliasScopeAttr.getDescription())
1540 scopeIt->second->replaceOperandWith(0, scopeIt->second);
1541 return scopeIt->second;
1547 nodes.reserve(aliasScopeAttrs.size());
1548 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
1554 llvm::Instruction *inst) {
1555 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
1556 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
1559 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
1560 inst->setMetadata(kind, node);
1563 populateScopeMetadata(op.getAliasScopesOrNull(),
1564 llvm::LLVMContext::MD_alias_scope);
1565 populateScopeMetadata(op.getNoAliasScopesOrNull(),
1566 llvm::LLVMContext::MD_noalias);
1569 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
1570 return tbaaMetadataMapping.lookup(tbaaAttr);
1574 llvm::Instruction *inst) {
1575 ArrayAttr tagRefs = op.getTBAATagsOrNull();
1576 if (!tagRefs || tagRefs.empty())
1583 if (tagRefs.size() > 1) {
1584 op.
emitWarning() <<
"TBAA access tags were not translated, because LLVM "
1585 "IR only supports a single tag per instruction";
1589 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
1590 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
1599 assert(inst &&
"expected the operation to have a mapping to an instruction");
1602 llvm::LLVMContext::MD_prof,
1607 llvm::LLVMContext &ctx = llvmModule->getContext();
1619 walker.
addWalk([&](TBAARootAttr root) {
1620 tbaaMetadataMapping.insert(
1624 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
1627 for (TBAAMemberAttr member : descriptor.getMembers()) {
1628 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
1636 walker.
addWalk([&](TBAATagAttr tag) {
1639 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
1640 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
1644 if (tag.getConstant())
1651 mlirModule->
walk([&](AliasAnalysisOpInterface analysisOpInterface) {
1652 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
1660 llvm::Instruction *inst) {
1661 LoopAnnotationAttr attr =
1663 .Case<LLVM::BrOp, LLVM::CondBrOp>(
1664 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
1667 llvm::MDNode *loopMD =
1668 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
1669 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
1679 remapped.reserve(values.size());
1680 for (
Value v : values)
1687 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
1688 ompBuilder->initialize();
1693 ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
1701 return ompBuilder.get();
1705 llvm::DILocalScope *scope) {
1706 return debugTranslation->translateLoc(loc, scope);
1709 llvm::DIExpression *
1711 return debugTranslation->translateExpression(attr);
1714 llvm::DIGlobalVariableExpression *
1716 LLVM::DIGlobalVariableExpressionAttr attr) {
1717 return debugTranslation->translateGlobalVariableExpression(attr);
1721 return debugTranslation->translate(attr);
1726 return convertRoundingModeToLLVM(rounding);
1730 LLVM::FPExceptionBehavior exceptionBehavior) {
1731 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
1736 return llvmModule->getOrInsertNamedMetadata(name);
1739 void ModuleTranslation::StackFrame::anchor() {}
1741 static std::unique_ptr<llvm::Module>
1745 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
1746 if (
auto dataLayoutAttr =
1748 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
1751 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
1752 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
1756 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
1757 if (DataLayoutSpecInterface spec =
mod.getDataLayoutSpec()) {
1762 if (
failed(llvmDataLayout))
1764 llvmModule->setDataLayout(*llvmDataLayout);
1766 if (
auto targetTripleAttr =
1768 llvmModule->setTargetTriple(cast<StringAttr>(targetTripleAttr).getValue());
1773 std::unique_ptr<llvm::Module>
1777 module->
emitOpError(
"can not be translated to an LLVMIR module");
1781 std::unique_ptr<llvm::Module> llvmModule =
1790 llvm::IRBuilder<> llvmBuilder(llvmContext);
1796 if (
failed(translator.convertOperation(*module, llvmBuilder)))
1799 if (
failed(translator.convertComdats()))
1801 if (
failed(translator.convertFunctionSignatures()))
1803 if (
failed(translator.convertGlobals()))
1805 if (
failed(translator.createTBAAMetadata()))
1810 if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp, LLVM::GlobalCtorsOp,
1811 LLVM::GlobalDtorsOp, LLVM::ComdatOp>(&o) &&
1813 failed(translator.convertOperation(o, llvmBuilder))) {
1821 if (
failed(translator.convertFunctions()))
1824 if (llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
1827 return std::move(translator.llvmModule);
static MLIRContext * getContext(OpFoldResult val)
static Value getPHISourceValue(Block *current, Block *pred, unsigned numArguments, unsigned index)
Get the SSA value passed to the current block from the terminator operation of its predecessor.
static llvm::Constant * convertDenseElementsAttr(Location loc, DenseElementsAttr denseElementsAttr, llvm::Type *llvmType, const ModuleTranslation &moduleTranslation)
Convert a dense elements attribute to an LLVM IR constant using its raw data storage if possible.
static Block & getModuleBody(Operation *module)
A helper method to get the single Block in an operation honoring LLVM's module requirements.
static void addRuntimePreemptionSpecifier(bool dsoLocalRequested, llvm::GlobalValue *gv)
Sets the runtime preemption specifier of gv to dso_local if dsoLocalRequested is true,...
static LogicalResult checkedAddLLVMFnAttribute(Location loc, llvm::Function *llvmFunc, StringRef key, StringRef value=StringRef())
Attempts to add an attribute identified by key, optionally with the given value to LLVM function llvm...
static void convertFunctionAttributes(LLVMFuncOp func, llvm::Function *llvmFunc)
Converts the function attributes from LLVMFuncOp and attaches them to the llvm::Function.
static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage, llvm::Constant *cst)
A helper method to decide if a constant must not be set as a global variable initializer.
static llvm::Type * getInnermostElementType(llvm::Type *type)
Returns the first non-sequential type nested in sequential types.
static std::unique_ptr< llvm::Module > prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext, StringRef name)
static llvm::Constant * convertDenseResourceElementsAttr(Location loc, DenseResourceElementsAttr denseResourceAttr, llvm::Type *llvmType, const ModuleTranslation &moduleTranslation)
Convert a dense resource elements attribute to an LLVM IR constant using its raw data storage if poss...
static LogicalResult forwardPassthroughAttributes(Location loc, std::optional< ArrayAttr > attributes, llvm::Function *llvmFunc)
Attaches the attributes listed in the given array attribute to llvmFunc.
static llvm::Constant * buildSequentialConstant(ArrayRef< llvm::Constant * > &constants, ArrayRef< int64_t > shape, llvm::Type *type, Location loc)
Builds a constant of a sequential LLVM type type, potentially containing other sequential types recur...
The following classes enable support for parsing and printing resources within MLIR assembly formats.
ArrayRef< char > getData() const
Return the raw underlying data of this blob.
void addWalk(WalkFn< Attribute > &&fn)
Register a walk function for a given attribute or type.
WalkResult walk(T element)
Walk the given attribute/type, and recursively walk any sub elements.
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
Operation * getTerminator()
Get the terminator operation of this block.
iterator_range< pred_iterator > getPredecessors()
BlockArgListType getArguments()
The main mechanism for performing data layout queries.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
uint64_t getTypePreferredAlignment(Type t) const
Returns the preferred of the given type in the current scope.
uint64_t getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
An attribute that represents a reference to a dense vector or tensor object.
std::enable_if_t<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T > getSplatValue() const
Return the splat value for this attribute.
int64_t getNumElements() const
Returns the number of elements held by this attribute.
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
ArrayRef< char > getRawData() const
Return the raw storage data held by this attribute.
ShapedType getType() const
Return the type of this ElementsAttr, guaranteed to be a vector or tensor with static shape.
const InterfaceType * getInterfaceFor(Object *obj) const
Get the interface for a given object, or null if one is not registered.
This class provides support for representing a failure result, or a valid value of type T.
Base class for dialect interfaces providing translation to LLVM IR.
virtual LogicalResult convertOperation(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) const
Hook for derived dialect interface to provide translation of the operations to LLVM IR.
virtual LogicalResult convertParameterAttr(LLVM::LLVMFuncOp function, int argIdx, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const
Acts on the given function operation using the interface implemented by the dialect of one of the fun...
virtual LogicalResult amendOperation(Operation *op, ArrayRef< llvm::Instruction * > instructions, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const
Acts on the given operation using the interface implemented by the dialect of one of the operation's ...
This class represents the base attribute for all debug info attributes.
Implementation class for module translation.
llvm::fp::ExceptionBehavior translateFPExceptionBehavior(LLVM::FPExceptionBehavior exceptionBehavior)
Translates the given LLVM FP exception behavior metadata.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
llvm::DIGlobalVariableExpression * translateGlobalVariableExpression(LLVM::DIGlobalVariableExpressionAttr attr)
Translates the given LLVM global variable expression metadata.
llvm::NamedMDNode * getOrInsertNamedModuleMetadata(StringRef name)
Gets the named metadata in the LLVM IR module being constructed, creating it if it does not exist.
llvm::Instruction * lookupBranch(Operation *op) const
Finds an LLVM IR instruction that corresponds to the given MLIR operation with successors.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
void mapFunction(StringRef name, llvm::Function *func)
Stores the mapping between a function name and its LLVM IR representation.
llvm::DILocation * translateLoc(Location loc, llvm::DILocalScope *scope)
Translates the given location.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
void setBranchWeightsMetadata(BranchWeightOpInterface op)
Sets LLVM profiling metadata for operations that have branch weights.
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::RoundingMode translateRoundingMode(LLVM::RoundingMode rounding)
Translates the given LLVM rounding mode metadata.
void setTBAAMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
Sets LLVM TBAA metadata for memory operations that have TBAA attributes.
llvm::DIExpression * translateExpression(LLVM::DIExpressionAttr attr)
Translates the given LLVM DWARF expression metadata.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::CallInst * lookupCall(Operation *op) const
Finds an LLVM call instruction that corresponds to the given MLIR call operation.
llvm::Metadata * translateDebugInfo(LLVM::DINodeAttr attr)
Translates the given LLVM debug info metadata.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
llvm::MDNode * getOrCreateAliasScopes(ArrayRef< AliasScopeAttr > aliasScopeAttrs)
Returns the LLVM metadata corresponding to an array of mlir LLVM dialect alias scope attributes.
void mapBlock(Block *mlir, llvm::BasicBlock *llvm)
Stores the mapping between an MLIR block and LLVM IR basic block.
llvm::MDNode * getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr)
Returns the LLVM metadata corresponding to a mlir LLVM dialect alias scope attribute.
void forgetMapping(Region ®ion)
Removes the mapping for blocks contained in the region and values defined in these blocks.
void setAliasScopeMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
void setAccessGroupsMetadata(AccessGroupOpInterface op, llvm::Instruction *inst)
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
void setLoopMetadata(Operation *op, llvm::Instruction *inst)
Sets LLVM loop metadata for branch operations that have a loop annotation attribute.
llvm::Type * translateType(Type type)
Translates the given MLIR LLVM dialect type to LLVM IR.
A helper class that converts LoopAnnotationAttrs and AccessGroupAttrs into corresponding llvm::MDNode...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
NamedAttribute represents a combination of a name and an Attribute value.
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
Attribute getDiscardableAttr(StringRef name)
Access a discardable attribute by name, returns an null Attribute if the discardable attribute does n...
Value getOperand(unsigned idx)
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Block * getSuccessor(unsigned index)
unsigned getNumSuccessors()
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
MLIRContext * getContext()
Return the context this operation is associated with.
Location getLoc()
The source location the operation was defined or derived from.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
OperationName getName()
The name of an operation is the key identifier for it.
dialect_attr_range getDialectAttrs()
Return a range corresponding to the dialect attributes for this operation.
operand_range getOperands()
Returns an iterator on the underlying Value's.
result_range getResults()
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class models how operands are forwarded to block arguments in control flow.
bool empty() const
Returns true if there are no successor operands.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
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...
use_iterator use_end() const
Type getType() const
Return the type of this value.
use_iterator use_begin() const
ArrayRef< T > asArrayRef() const
Include the generated interface declarations.
void connectPHINodes(Region ®ion, const ModuleTranslation &state)
For all blocks in the region that were converted to LLVM IR using the given ModuleTranslation,...
llvm::CallInst * createIntrinsicCall(llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic, ArrayRef< llvm::Value * > args={}, ArrayRef< llvm::Type * > tys={})
Creates a call to an LLVM IR intrinsic function with the given arguments.
static llvm::DenseMap< llvm::StringRef, llvm::Attribute::AttrKind > getAttrNameToKindMapping()
Returns a dense map from LLVM attribute name to their kind in LLVM IR dialect.
llvm::Constant * getLLVMConstant(llvm::Type *llvmType, Attribute attr, Location loc, const ModuleTranslation &moduleTranslation)
Create an LLVM IR constant of llvmType from the MLIR attribute attr.
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
void legalizeDIExpressionsRecursively(Operation *op)
Register all known legalization patterns declared here and apply them to all ops in op.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
void ensureDistinctSuccessors(Operation *op)
Make argument-taking successors of each block distinct.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
DictionaryAttr getArgAttrDict(FunctionOpInterface op, unsigned index)
Returns the dictionary attribute corresponding to the argument at 'index'.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
SetVector< Block * > getTopologicallySortedBlocks(Region ®ion)
Get a topologically sorted list of blocks of the given region.
DataLayoutSpecInterface translateDataLayout(const llvm::DataLayout &dataLayout, MLIRContext *context)
Translate the given LLVM data layout into an MLIR equivalent using the DLTI dialect.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
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...
std::unique_ptr< llvm::Module > translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, llvm::StringRef name="LLVMDialectModule")
Translate operation that satisfies LLVM dialect module requirements into an LLVM IR module living in ...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
int64_t mod(int64_t lhs, int64_t rhs)
Returns MLIR's mod operation on constants.
This class represents an efficient way to signal success or failure.