37 #include "llvm/ADT/PostOrderIterator.h"
38 #include "llvm/ADT/SetVector.h"
39 #include "llvm/ADT/StringExtras.h"
40 #include "llvm/ADT/TypeSwitch.h"
41 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
42 #include "llvm/IR/BasicBlock.h"
43 #include "llvm/IR/CFG.h"
44 #include "llvm/IR/Constants.h"
45 #include "llvm/IR/DerivedTypes.h"
46 #include "llvm/IR/IRBuilder.h"
47 #include "llvm/IR/InlineAsm.h"
48 #include "llvm/IR/IntrinsicsNVPTX.h"
49 #include "llvm/IR/LLVMContext.h"
50 #include "llvm/IR/MDBuilder.h"
51 #include "llvm/IR/Module.h"
52 #include "llvm/IR/Verifier.h"
53 #include "llvm/Support/Debug.h"
54 #include "llvm/Support/raw_ostream.h"
55 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
56 #include "llvm/Transforms/Utils/Cloning.h"
57 #include "llvm/Transforms/Utils/ModuleUtils.h"
61 #define DEBUG_TYPE "llvm-dialect-to-llvm-ir"
69 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
92 class InstructionCapturingInserter :
public llvm::IRBuilderCallbackInserter {
95 InstructionCapturingInserter()
96 : llvm::IRBuilderCallbackInserter([
this](llvm::Instruction *instruction) {
97 if (LLVM_LIKELY(enabled))
98 capturedInstructions.push_back(instruction);
103 return capturedInstructions;
107 void clearCapturedInstructions() { capturedInstructions.clear(); }
110 class CollectionScope {
113 CollectionScope(llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing);
121 return inserter->getCapturedInstructions();
126 InstructionCapturingInserter *inserter =
nullptr;
136 void setEnabled(
bool enabled =
true) { this->enabled = enabled; }
143 bool enabled =
false;
146 using CapturingIRBuilder =
147 llvm::IRBuilder<llvm::ConstantFolder, InstructionCapturingInserter>;
150 InstructionCapturingInserter::CollectionScope::CollectionScope(
151 llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing) {
153 if (!isBuilderCapturing)
156 auto &capturingIRBuilder =
static_cast<CapturingIRBuilder &
>(irBuilder);
157 inserter = &capturingIRBuilder.getInserter();
158 wasEnabled = inserter->enabled;
160 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
161 inserter->setEnabled(
true);
164 InstructionCapturingInserter::CollectionScope::~CollectionScope() {
168 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
172 llvm::append_range(inserter->capturedInstructions,
173 previouslyCollectedInstructions);
175 inserter->setEnabled(wasEnabled);
180 static FailureOr<llvm::DataLayout>
183 std::optional<Location> loc = std::nullopt) {
188 std::string llvmDataLayout;
189 llvm::raw_string_ostream layoutStream(llvmDataLayout);
190 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
191 auto key = llvm::dyn_cast_if_present<StringAttr>(entry.getKey());
194 if (key.getValue() == DLTIDialect::kDataLayoutEndiannessKey) {
195 auto value = cast<StringAttr>(entry.getValue());
196 bool isLittleEndian =
197 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle;
198 layoutStream <<
"-" << (isLittleEndian ?
"e" :
"E");
201 if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
202 auto value = cast<IntegerAttr>(entry.getValue());
203 uint64_t space = value.getValue().getZExtValue();
207 layoutStream <<
"-P" << space;
210 if (key.getValue() == DLTIDialect::kDataLayoutGlobalMemorySpaceKey) {
211 auto value = cast<IntegerAttr>(entry.getValue());
212 uint64_t space = value.getValue().getZExtValue();
216 layoutStream <<
"-G" << space;
219 if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
220 auto value = cast<IntegerAttr>(entry.getValue());
221 uint64_t space = value.getValue().getZExtValue();
225 layoutStream <<
"-A" << space;
228 if (key.getValue() == DLTIDialect::kDataLayoutStackAlignmentKey) {
229 auto value = cast<IntegerAttr>(entry.getValue());
230 uint64_t alignment = value.getValue().getZExtValue();
234 layoutStream <<
"-S" << alignment;
237 emitError(*loc) <<
"unsupported data layout key " << key;
244 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
245 auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
249 if (isa<IndexType>(type))
252 LogicalResult result =
254 .Case<IntegerType, Float16Type, Float32Type, Float64Type,
255 Float80Type, Float128Type>([&](
Type type) -> LogicalResult {
256 if (
auto intType = dyn_cast<IntegerType>(type)) {
257 if (intType.getSignedness() != IntegerType::Signless)
259 <<
"unsupported data layout for non-signless integer "
269 layoutStream << size <<
":" << abi;
270 if (abi != preferred)
271 layoutStream <<
":" << preferred;
274 .Case([&](LLVMPointerType type) {
275 layoutStream <<
"p" << type.getAddressSpace() <<
":";
281 layoutStream << size <<
":" << abi <<
":" << preferred <<
":"
285 .Default([loc](
Type type) {
287 <<
"unsupported type in data layout: " << type;
292 StringRef layoutSpec(llvmDataLayout);
293 if (layoutSpec.starts_with(
"-"))
294 layoutSpec = layoutSpec.drop_front();
296 return llvm::DataLayout(layoutSpec);
303 static llvm::Constant *
308 llvm::Constant *result = constants.front();
309 constants = constants.drop_front();
313 llvm::Type *elementType;
314 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
315 elementType = arrayTy->getElementType();
316 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
317 elementType = vectorTy->getElementType();
319 emitError(loc) <<
"expected sequential LLVM types wrapping a scalar";
324 nested.reserve(shape.front());
325 for (int64_t i = 0; i < shape.front(); ++i) {
332 if (shape.size() == 1 && type->isVectorTy())
341 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
342 type = arrayTy->getElementType();
343 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
344 type = vectorTy->getElementType();
358 static llvm::Constant *
360 llvm::Type *llvmType,
362 if (!denseElementsAttr)
366 if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
369 ShapedType type = denseElementsAttr.
getType();
370 if (type.getNumElements() == 0)
378 int64_t elementByteSize = denseElementsAttr.
getRawData().size() /
380 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
385 bool hasVectorElementType = isa<VectorType>(type.getElementType());
386 int64_t numAggregates =
388 (hasVectorElementType ? 1
389 : denseElementsAttr.
getType().getShape().back());
391 if (!hasVectorElementType)
392 outerShape = outerShape.drop_back();
395 if (denseElementsAttr.
isSplat() &&
396 (isa<VectorType>(type) || hasVectorElementType)) {
400 llvm::Constant *splatVector =
401 llvm::ConstantDataVector::getSplat(0, splatValue);
406 if (denseElementsAttr.
isSplat())
411 std::function<llvm::Constant *(StringRef)> buildCstData;
412 if (isa<TensorType>(type)) {
413 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
414 if (vectorElementType && vectorElementType.getRank() == 1) {
415 buildCstData = [&](StringRef data) {
416 return llvm::ConstantDataVector::getRaw(
417 data, vectorElementType.getShape().back(), innermostLLVMType);
419 }
else if (!vectorElementType) {
420 buildCstData = [&](StringRef data) {
421 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
425 }
else if (isa<VectorType>(type)) {
426 buildCstData = [&](StringRef data) {
427 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
437 int64_t aggregateSize = denseElementsAttr.
getType().getShape().back() *
438 (innermostLLVMType->getScalarSizeInBits() / 8);
439 constants.reserve(numAggregates);
440 for (
unsigned i = 0; i < numAggregates; ++i) {
441 StringRef data(denseElementsAttr.
getRawData().data() + i * aggregateSize,
443 constants.push_back(buildCstData(data));
459 assert(denseResourceAttr &&
"expected non-null attribute");
462 if (!llvm::ConstantDataSequential::isElementTypeCompatible(
463 innermostLLVMType)) {
464 emitError(loc,
"no known conversion for innermost element type");
468 ShapedType type = denseResourceAttr.getType();
469 assert(type.getNumElements() > 0 &&
"Expected non-empty elements attribute");
473 emitError(loc,
"resource does not exist");
484 int64_t numElements = denseResourceAttr.getType().getNumElements();
485 int64_t elementByteSize = rawData.size() / numElements;
486 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
487 emitError(loc,
"raw data size does not match element type size");
493 bool hasVectorElementType = isa<VectorType>(type.getElementType());
494 int64_t numAggregates =
495 numElements / (hasVectorElementType
497 : denseResourceAttr.getType().getShape().back());
499 if (!hasVectorElementType)
500 outerShape = outerShape.drop_back();
503 std::function<llvm::Constant *(StringRef)> buildCstData;
504 if (isa<TensorType>(type)) {
505 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
506 if (vectorElementType && vectorElementType.getRank() == 1) {
507 buildCstData = [&](StringRef data) {
508 return llvm::ConstantDataVector::getRaw(
509 data, vectorElementType.getShape().back(), innermostLLVMType);
511 }
else if (!vectorElementType) {
512 buildCstData = [&](StringRef data) {
513 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
517 }
else if (isa<VectorType>(type)) {
518 buildCstData = [&](StringRef data) {
519 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
524 emitError(loc,
"unsupported dense_resource type");
531 int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
532 (innermostLLVMType->getScalarSizeInBits() / 8);
533 constants.reserve(numAggregates);
534 for (
unsigned i = 0; i < numAggregates; ++i) {
535 StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
536 constants.push_back(buildCstData(data));
553 if (
auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
554 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
556 emitError(loc,
"expected an array attribute for a struct constant");
560 structElements.reserve(structType->getNumElements());
561 for (
auto [elemType, elemAttr] :
562 zip_equal(structType->elements(), arrayAttr)) {
563 llvm::Constant *element =
567 structElements.push_back(element);
573 if (
auto intAttr = dyn_cast<IntegerAttr>(attr))
576 intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
577 if (
auto floatAttr = dyn_cast<FloatAttr>(attr)) {
578 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
583 unsigned floatWidth = APFloat::getSizeInBits(sem);
584 if (llvmType->isIntegerTy(floatWidth))
586 floatAttr.getValue().bitcastToAPInt());
588 llvm::Type::getFloatingPointTy(llvmType->getContext(),
589 floatAttr.getValue().getSemantics())) {
590 emitError(loc,
"FloatAttr does not match expected type of the constant");
595 if (
auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
596 return llvm::ConstantExpr::getBitCast(
598 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
599 llvm::Type *elementType;
600 uint64_t numElements;
601 bool isScalable =
false;
602 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
603 elementType = arrayTy->getElementType();
604 numElements = arrayTy->getNumElements();
605 }
else if (
auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
606 elementType = fVectorTy->getElementType();
607 numElements = fVectorTy->getNumElements();
608 }
else if (
auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
609 elementType = sVectorTy->getElementType();
610 numElements = sVectorTy->getMinNumElements();
613 llvm_unreachable(
"unrecognized constant vector type");
618 bool elementTypeSequential =
619 isa<llvm::ArrayType, llvm::VectorType>(elementType);
622 elementTypeSequential ? splatAttr
624 loc, moduleTranslation);
627 if (llvmType->isVectorTy())
628 return llvm::ConstantVector::getSplat(
630 if (llvmType->isArrayTy()) {
632 if (child->isZeroValue()) {
635 if (llvm::ConstantDataSequential::isElementTypeCompatible(
638 if (isa<llvm::IntegerType>(elementType)) {
639 if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
640 if (ci->getBitWidth() == 8) {
645 if (ci->getBitWidth() == 16) {
650 if (ci->getBitWidth() == 32) {
655 if (ci->getBitWidth() == 64) {
665 std::vector<llvm::Constant *> constants(numElements, child);
672 if (llvm::Constant *result =
674 llvmType, moduleTranslation)) {
678 if (
auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
684 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
685 assert(elementsAttr.getShapedType().hasStaticShape());
686 assert(!elementsAttr.getShapedType().getShape().empty() &&
687 "unexpected empty elements attribute shape");
690 constants.reserve(elementsAttr.getNumElements());
692 for (
auto n : elementsAttr.getValues<
Attribute>()) {
695 if (!constants.back())
700 constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
701 assert(constantsRef.empty() &&
"did not consume all elemental constants");
705 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
709 stringAttr.getValue().size()});
711 emitError(loc,
"unsupported constant value");
715 ModuleTranslation::ModuleTranslation(
Operation *module,
716 std::unique_ptr<llvm::Module> llvmModule)
717 : mlirModule(module), llvmModule(std::move(llvmModule)),
721 *this, *this->llvmModule)),
722 typeTranslator(this->llvmModule->
getContext()),
725 "mlirModule should honor LLVM's module semantics.");
728 ModuleTranslation::~ModuleTranslation() {
730 ompBuilder->finalize();
735 toProcess.push_back(®ion);
736 while (!toProcess.empty()) {
737 Region *current = toProcess.pop_back_val();
738 for (
Block &block : *current) {
739 blockMapping.erase(&block);
740 for (
Value arg : block.getArguments())
741 valueMapping.erase(arg);
743 for (
Value value : op.getResults())
744 valueMapping.erase(value);
745 if (op.hasSuccessors())
746 branchMapping.erase(&op);
747 if (isa<LLVM::GlobalOp>(op))
748 globalsMapping.erase(&op);
749 if (isa<LLVM::CallOp>(op))
750 callMapping.erase(&op);
753 llvm::map_range(op.getRegions(), [](
Region &r) { return &r; }));
762 unsigned numArguments,
unsigned index) {
764 if (isa<LLVM::BrOp>(terminator))
771 auto branch = cast<BranchOpInterface>(terminator);
774 (!seenSuccessors.contains(successor) || successorOperands.
empty()) &&
775 "successors with arguments in LLVM branches must be different blocks");
776 seenSuccessors.insert(successor);
782 if (
auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
785 return condBranchOp.getSuccessor(0) == current
786 ? condBranchOp.getTrueDestOperands()[index]
787 : condBranchOp.getFalseDestOperands()[index];
790 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
793 if (switchOp.getDefaultDestination() == current)
794 return switchOp.getDefaultOperands()[index];
796 if (i.value() == current)
797 return switchOp.getCaseOperands(i.index())[index];
800 if (
auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
801 return invokeOp.getNormalDest() == current
802 ? invokeOp.getNormalDestOperands()[index]
803 : invokeOp.getUnwindDestOperands()[index];
807 "only branch, switch or invoke operations can be terminators "
808 "of a block that has successors");
816 for (
Block &bb : llvm::drop_begin(region)) {
817 llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
818 auto phis = llvmBB->phis();
819 auto numArguments = bb.getNumArguments();
820 assert(numArguments == std::distance(phis.begin(), phis.end()));
822 for (
auto *pred : bb.getPredecessors()) {
828 llvm::Instruction *terminator =
829 state.lookupBranch(pred->getTerminator());
830 assert(terminator &&
"missing the mapping for a terminator");
832 &bb, pred, numArguments, index)),
833 terminator->getParent());
842 llvm::Module *module = builder.GetInsertBlock()->getModule();
844 llvm::Intrinsic::getOrInsertDeclaration(module, intrinsic, tys);
845 return builder.CreateCall(fn, args);
854 assert(immArgPositions.size() == immArgAttrNames.size() &&
855 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
859 size_t numOpBundleOperands = 0;
860 auto opBundleSizesAttr = cast_if_present<DenseI32ArrayAttr>(
861 intrOp->
getAttr(LLVMDialect::getOpBundleSizesAttrName()));
862 auto opBundleTagsAttr = cast_if_present<ArrayAttr>(
863 intrOp->
getAttr(LLVMDialect::getOpBundleTagsAttrName()));
865 if (opBundleSizesAttr && opBundleTagsAttr) {
866 ArrayRef<int> opBundleSizes = opBundleSizesAttr.asArrayRef();
867 assert(opBundleSizes.size() == opBundleTagsAttr.size() &&
868 "operand bundles and tags do not match");
870 numOpBundleOperands =
871 std::accumulate(opBundleSizes.begin(), opBundleSizes.end(),
size_t(0));
872 assert(numOpBundleOperands <= intrOp->getNumOperands() &&
873 "operand bundle operands is more than the number of operands");
876 size_t nextOperandIdx = 0;
877 opBundles.reserve(opBundleSizesAttr.size());
879 for (
auto [opBundleTagAttr, bundleSize] :
880 llvm::zip(opBundleTagsAttr, opBundleSizes)) {
881 auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
883 operands.slice(nextOperandIdx, bundleSize));
884 opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
885 nextOperandIdx += bundleSize;
890 auto opOperands = intrOp->
getOperands().drop_back(numOpBundleOperands);
891 auto operands = moduleTranslation.
lookupValues(opOperands);
893 for (
auto [immArgPos, immArgName] :
894 llvm::zip(immArgPositions, immArgAttrNames)) {
895 auto attr = llvm::cast<TypedAttr>(intrOp->
getAttr(immArgName));
896 assert(attr.getType().isIntOrFloat() &&
"expected int or float immarg");
897 auto *type = moduleTranslation.
convertType(attr.getType());
899 type, attr, intrOp->
getLoc(), moduleTranslation);
902 for (
auto &arg : args) {
904 arg = operands[opArg++];
909 for (
unsigned overloadedResultIdx : overloadedResults) {
910 if (numResults > 1) {
912 overloadedTypes.push_back(moduleTranslation.
convertType(
914 .getBody()[overloadedResultIdx]));
916 overloadedTypes.push_back(
920 for (
unsigned overloadedOperandIdx : overloadedOperands)
921 overloadedTypes.push_back(args[overloadedOperandIdx]->
getType());
922 llvm::Module *module = builder.GetInsertBlock()->getModule();
923 llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
924 module, intrinsic, overloadedTypes);
926 return builder.CreateCall(llvmIntr, args, opBundles);
931 LogicalResult ModuleTranslation::convertOperation(
Operation &op,
932 llvm::IRBuilderBase &builder,
933 bool recordInsertions) {
936 return op.
emitError(
"cannot be converted to LLVM IR: missing "
937 "`LLVMTranslationDialectInterface` registration for "
941 InstructionCapturingInserter::CollectionScope scope(builder,
944 return op.
emitError(
"LLVM Translation failed for operation: ")
947 return convertDialectAttributes(&op, scope.getCapturedInstructions());
957 LogicalResult ModuleTranslation::convertBlockImpl(
Block &bb,
958 bool ignoreArguments,
959 llvm::IRBuilderBase &builder,
960 bool recordInsertions) {
962 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
970 if (!ignoreArguments) {
972 unsigned numPredecessors =
973 std::distance(predecessors.begin(), predecessors.end());
975 auto wrappedType = arg.getType();
978 "block argument does not have an LLVM type");
979 builder.SetCurrentDebugLocation(
980 debugTranslation->translateLoc(arg.getLoc(), subprogram));
982 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
988 for (
auto &op : bb) {
990 builder.SetCurrentDebugLocation(
991 debugTranslation->translateLoc(op.
getLoc(), subprogram));
993 if (failed(convertOperation(op, builder, recordInsertions)))
997 if (
auto iface = dyn_cast<BranchWeightOpInterface>(op))
1016 llvm::Constant *cst) {
1017 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1018 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1024 llvm::GlobalValue *gv) {
1025 if (dsoLocalRequested)
1026 gv->setDSOLocal(
true);
1031 LogicalResult ModuleTranslation::convertGlobals() {
1035 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1037 llvm::Constant *cst =
nullptr;
1038 if (op.getValueOrNull()) {
1041 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1042 cst = llvm::ConstantDataArray::getString(
1043 llvmModule->getContext(), strAttr.getValue(),
false);
1044 type = cst->getType();
1051 auto linkage = convertLinkageToLLVM(op.getLinkage());
1057 if (!dropInitializer && !cst)
1059 else if (dropInitializer && cst)
1062 auto *var =
new llvm::GlobalVariable(
1063 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1065 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1066 : llvm::GlobalValue::NotThreadLocal,
1067 op.getAddrSpace(), op.getExternallyInitialized());
1069 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1070 auto selectorOp = cast<ComdatSelectorOp>(
1072 var->setComdat(comdatMapping.lookup(selectorOp));
1075 if (op.getUnnamedAddr().has_value())
1076 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1078 if (op.getSection().has_value())
1079 var->setSection(*op.getSection());
1083 std::optional<uint64_t> alignment = op.getAlignment();
1084 if (alignment.has_value())
1085 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1087 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1089 globalsMapping.try_emplace(op, var);
1092 if (op.getDbgExprs()) {
1093 for (
auto exprAttr :
1094 op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1095 llvm::DIGlobalVariableExpression *diGlobalExpr =
1096 debugTranslation->translateGlobalVariableExpression(exprAttr);
1097 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1098 var->addDebugInfo(diGlobalExpr);
1117 llvm::DIScope *scope = diGlobalVar->getScope();
1118 if (
auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1119 scope = mod->getScope();
1120 else if (
auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1122 dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1123 scope = sp->getUnit();
1124 }
else if (
auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1125 scope = sp->getUnit();
1128 if (llvm::DICompileUnit *compileUnit =
1129 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1132 allGVars[compileUnit].push_back(diGlobalExpr);
1141 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1142 if (
Block *initializer = op.getInitializerBlock()) {
1143 llvm::IRBuilder<> builder(llvmModule->getContext());
1145 [[maybe_unused]]
int numConstantsHit = 0;
1146 [[maybe_unused]]
int numConstantsErased = 0;
1149 for (
auto &op : initializer->without_terminator()) {
1150 if (failed(convertOperation(op, builder)))
1163 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1167 auto [iterator, inserted] =
1168 constantAggregateUseMap.try_emplace(agg, numUsers);
1171 iterator->second += numUsers;
1177 auto cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1180 auto iter = constantAggregateUseMap.find(cst);
1181 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1183 if (iter->second == 0) {
1186 if (cst->user_empty()) {
1187 cst->destroyConstant();
1188 numConstantsErased++;
1190 constantAggregateUseMap.erase(iter);
1195 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1196 llvm::Constant *cst =
1197 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1198 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1200 global->setInitializer(cst);
1204 for (
auto it : constantAggregateUseMap) {
1205 auto cst = it.first;
1206 cst->removeDeadConstantUsers();
1207 if (cst->user_empty()) {
1208 cst->destroyConstant();
1209 numConstantsErased++;
1213 LLVM_DEBUG(llvm::dbgs()
1214 <<
"Convert initializer for " << op.
getName() <<
"\n";
1215 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1217 << numConstantsErased <<
" dangling constants erased\n";);
1223 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1224 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1225 if (!ctorOp && !dtorOp)
1227 auto range = ctorOp ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1228 :
llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1229 auto appendGlobalFn =
1230 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1231 for (
auto symbolAndPriority : range) {
1233 cast<FlatSymbolRefAttr>(std::get<0>(symbolAndPriority)).getValue());
1234 appendGlobalFn(*llvmModule, f,
1235 cast<IntegerAttr>(std::get<1>(symbolAndPriority)).getInt(),
1240 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1241 if (failed(convertDialectAttributes(op, {})))
1246 for (
const auto &[compileUnit, globals] : allGVars) {
1247 compileUnit->replaceGlobalVariables(
1261 llvm::Function *llvmFunc,
1263 StringRef value = StringRef()) {
1264 auto kind = llvm::Attribute::getAttrKindFromName(key);
1266 llvmFunc->addFnAttr(key, value);
1270 if (llvm::Attribute::isIntAttrKind(kind)) {
1272 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1275 if (!value.getAsInteger(0, result))
1276 llvmFunc->addFnAttr(
1279 llvmFunc->addFnAttr(key, value);
1284 return emitError(loc) <<
"LLVM attribute '" << key
1285 <<
"' does not expect a value, found '" << value
1288 llvmFunc->addFnAttr(kind);
1294 const llvm::APInt &value) {
1301 const llvm::APInt &value) {
1309 llvm::Metadata *typeMD =
1311 llvm::Metadata *isSignedMD =
1321 values, std::back_inserter(mdValues), [&context](int32_t value) {
1334 static LogicalResult
1336 llvm::Function *llvmFunc) {
1341 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1348 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1349 if (!arrayAttr || arrayAttr.size() != 2)
1351 <<
"expected 'passthrough' to contain string or array attributes";
1353 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1354 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1355 if (!keyAttr || !valueAttr)
1357 <<
"expected arrays within 'passthrough' to contain two strings";
1360 valueAttr.getValue())))
1366 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1369 blockMapping.clear();
1370 valueMapping.clear();
1371 branchMapping.clear();
1375 for (
auto [mlirArg, llvmArg] :
1376 llvm::zip(func.getArguments(), llvmFunc->args()))
1380 if (func.getPersonality()) {
1381 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1382 if (llvm::Constant *pfunc =
getLLVMConstant(ty, func.getPersonalityAttr(),
1383 func.getLoc(), *
this))
1384 llvmFunc->setPersonalityFn(pfunc);
1387 if (std::optional<StringRef> section = func.getSection())
1388 llvmFunc->setSection(*section);
1390 if (func.getArmStreaming())
1391 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1392 else if (func.getArmLocallyStreaming())
1393 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1394 else if (func.getArmStreamingCompatible())
1395 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1397 if (func.getArmNewZa())
1398 llvmFunc->addFnAttr(
"aarch64_new_za");
1399 else if (func.getArmInZa())
1400 llvmFunc->addFnAttr(
"aarch64_in_za");
1401 else if (func.getArmOutZa())
1402 llvmFunc->addFnAttr(
"aarch64_out_za");
1403 else if (func.getArmInoutZa())
1404 llvmFunc->addFnAttr(
"aarch64_inout_za");
1405 else if (func.getArmPreservesZa())
1406 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1408 if (
auto targetCpu = func.getTargetCpu())
1409 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1411 if (
auto tuneCpu = func.getTuneCpu())
1412 llvmFunc->addFnAttr(
"tune-cpu", *tuneCpu);
1414 if (
auto targetFeatures = func.getTargetFeatures())
1415 llvmFunc->addFnAttr(
"target-features", targetFeatures->getFeaturesString());
1417 if (
auto attr = func.getVscaleRange())
1418 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1420 attr->getMaxRange().getInt()));
1422 if (
auto unsafeFpMath = func.getUnsafeFpMath())
1423 llvmFunc->addFnAttr(
"unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1425 if (
auto noInfsFpMath = func.getNoInfsFpMath())
1426 llvmFunc->addFnAttr(
"no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1428 if (
auto noNansFpMath = func.getNoNansFpMath())
1429 llvmFunc->addFnAttr(
"no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1431 if (
auto approxFuncFpMath = func.getApproxFuncFpMath())
1432 llvmFunc->addFnAttr(
"approx-func-fp-math",
1433 llvm::toStringRef(*approxFuncFpMath));
1435 if (
auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1436 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1437 llvm::toStringRef(*noSignedZerosFpMath));
1439 if (
auto denormalFpMath = func.getDenormalFpMath())
1440 llvmFunc->addFnAttr(
"denormal-fp-math", *denormalFpMath);
1442 if (
auto denormalFpMathF32 = func.getDenormalFpMathF32())
1443 llvmFunc->addFnAttr(
"denormal-fp-math-f32", *denormalFpMathF32);
1445 if (
auto fpContract = func.getFpContract())
1446 llvmFunc->addFnAttr(
"fp-contract", *fpContract);
1449 if (FramePointerKindAttr attr = func.getFramePointerAttr())
1450 llvmFunc->addFnAttr(
"frame-pointer",
1451 LLVM::framePointerKind::stringifyFramePointerKind(
1452 (attr.getFramePointerKind())));
1455 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1456 for (
auto &bb : func) {
1457 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1458 llvmBB->insertInto(llvmFunc);
1465 for (
Block *bb : blocks) {
1466 CapturingIRBuilder builder(llvmContext);
1467 if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1477 return convertDialectAttributes(func, {});
1480 LogicalResult ModuleTranslation::convertDialectAttributes(
1483 if (failed(iface.
amendOperation(op, instructions, attribute, *
this)))
1491 llvm::Function *llvmFunc) {
1492 if (!func.getMemoryEffects())
1495 MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1498 llvm::MemoryEffects newMemEffects =
1499 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1500 convertModRefInfoToLLVM(memEffects.getArgMem()));
1501 newMemEffects |= llvm::MemoryEffects(
1502 llvm::MemoryEffects::Location::InaccessibleMem,
1503 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1505 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1506 convertModRefInfoToLLVM(memEffects.getOther()));
1507 llvmFunc->setMemoryEffects(newMemEffects);
1512 llvm::Function *llvmFunc) {
1513 if (func.getNoInlineAttr())
1514 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1515 if (func.getAlwaysInlineAttr())
1516 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1517 if (func.getOptimizeNoneAttr())
1518 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1519 if (func.getConvergentAttr())
1520 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1521 if (func.getNoUnwindAttr())
1522 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1523 if (func.getWillReturnAttr())
1524 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1530 llvm::Function *llvmFunc,
1532 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1534 if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1535 Type type = vecTypeHint.getHint().getValue();
1536 llvm::Type *llvmType = translation.
convertType(type);
1537 bool isSigned = vecTypeHint.getIsSigned();
1538 llvmFunc->setMetadata(
1539 func.getVecTypeHintAttrName(),
1544 func.getWorkGroupSizeHint()) {
1545 llvmFunc->setMetadata(
1546 func.getWorkGroupSizeHintAttrName(),
1551 func.getReqdWorkGroupSize()) {
1552 llvmFunc->setMetadata(
1553 func.getReqdWorkGroupSizeAttrName(),
1557 if (std::optional<uint32_t> intelReqdSubGroupSize =
1558 func.getIntelReqdSubGroupSize()) {
1559 llvmFunc->setMetadata(
1560 func.getIntelReqdSubGroupSizeAttrName(),
1562 llvm::APInt(32, *intelReqdSubGroupSize)));
1566 FailureOr<llvm::AttrBuilder>
1567 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func,
int argIdx,
1568 DictionaryAttr paramAttrs) {
1569 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1572 for (
auto namedAttr : paramAttrs) {
1573 auto it = attrNameToKindMapping.find(namedAttr.getName());
1574 if (it != attrNameToKindMapping.end()) {
1575 llvm::Attribute::AttrKind llvmKind = it->second;
1578 .Case<TypeAttr>([&](
auto typeAttr) {
1579 attrBuilder.addTypeAttr(llvmKind,
convertType(typeAttr.getValue()));
1581 .Case<IntegerAttr>([&](
auto intAttr) {
1582 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1584 .Case<UnitAttr>([&](
auto) { attrBuilder.addAttribute(llvmKind); })
1585 .Case<LLVM::ConstantRangeAttr>([&](
auto rangeAttr) {
1586 attrBuilder.addConstantRangeAttr(
1587 llvmKind, llvm::ConstantRange(rangeAttr.getLower(),
1588 rangeAttr.getUpper()));
1590 }
else if (namedAttr.getNameDialect()) {
1599 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1602 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1603 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1605 cast<llvm::FunctionType>(
convertType(
function.getFunctionType())));
1606 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1607 llvmFunc->setLinkage(convertLinkageToLLVM(
function.getLinkage()));
1608 llvmFunc->setCallingConv(convertCConvToLLVM(
function.getCConv()));
1619 if (std::optional<uint64_t> entryCount =
function.getFunctionEntryCount())
1620 llvmFunc->setEntryCount(entryCount.value());
1623 if (ArrayAttr allResultAttrs =
function.getAllResultAttrs()) {
1624 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1625 FailureOr<llvm::AttrBuilder> attrBuilder =
1626 convertParameterAttrs(
function, -1, resultAttrs);
1627 if (failed(attrBuilder))
1629 llvmFunc->addRetAttrs(*attrBuilder);
1635 FailureOr<llvm::AttrBuilder> attrBuilder =
1636 convertParameterAttrs(
function, argIdx, argAttrs);
1637 if (failed(attrBuilder))
1639 llvmArg.addAttrs(*attrBuilder);
1645 function.getLoc(),
function.getPassthrough(), llvmFunc)))
1649 llvmFunc->setVisibility(convertVisibilityToLLVM(
function.getVisibility_()));
1652 if (std::optional<mlir::SymbolRefAttr> comdat =
function.getComdat()) {
1653 auto selectorOp = cast<ComdatSelectorOp>(
1655 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1658 if (
auto gc =
function.getGarbageCollector())
1659 llvmFunc->setGC(gc->str());
1661 if (
auto unnamedAddr =
function.getUnnamedAddr())
1662 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1664 if (
auto alignment =
function.getAlignment())
1665 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1668 debugTranslation->translate(
function, *llvmFunc);
1674 LogicalResult ModuleTranslation::convertFunctions() {
1676 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1679 if (
function.isExternal()) {
1680 if (failed(convertDialectAttributes(
function, {})))
1685 if (failed(convertOneFunction(
function)))
1692 LogicalResult ModuleTranslation::convertComdats() {
1693 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
1694 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1696 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1698 <<
"comdat selection symbols must be unique even in different "
1700 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1701 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1702 comdatMapping.try_emplace(selectorOp, comdat);
1709 llvm::Instruction *inst) {
1710 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1711 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1716 auto [scopeIt, scopeInserted] =
1717 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
1719 return scopeIt->second;
1720 llvm::LLVMContext &ctx = llvmModule->getContext();
1721 auto dummy = llvm::MDNode::getTemporary(ctx, std::nullopt);
1723 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1724 aliasScopeAttr.getDomain(),
nullptr);
1725 if (insertedDomain) {
1728 operands.push_back(dummy.get());
1729 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
1733 domainIt->second->replaceOperandWith(0, domainIt->second);
1736 assert(domainIt->second &&
"Scope's domain should already be valid");
1739 operands.push_back(dummy.get());
1740 operands.push_back(domainIt->second);
1741 if (StringAttr description = aliasScopeAttr.getDescription())
1745 scopeIt->second->replaceOperandWith(0, scopeIt->second);
1746 return scopeIt->second;
1752 nodes.reserve(aliasScopeAttrs.size());
1753 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
1759 llvm::Instruction *inst) {
1760 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
1761 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
1764 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
1765 inst->setMetadata(kind, node);
1768 populateScopeMetadata(op.getAliasScopesOrNull(),
1769 llvm::LLVMContext::MD_alias_scope);
1770 populateScopeMetadata(op.getNoAliasScopesOrNull(),
1771 llvm::LLVMContext::MD_noalias);
1774 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
1775 return tbaaMetadataMapping.lookup(tbaaAttr);
1779 llvm::Instruction *inst) {
1780 ArrayAttr tagRefs = op.getTBAATagsOrNull();
1781 if (!tagRefs || tagRefs.empty())
1788 if (tagRefs.size() > 1) {
1789 op.emitWarning() <<
"TBAA access tags were not translated, because LLVM "
1790 "IR only supports a single tag per instruction";
1794 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
1795 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
1804 assert(inst &&
"expected the operation to have a mapping to an instruction");
1807 llvm::LLVMContext::MD_prof,
1811 LogicalResult ModuleTranslation::createTBAAMetadata() {
1812 llvm::LLVMContext &ctx = llvmModule->getContext();
1824 walker.
addWalk([&](TBAARootAttr root) {
1825 tbaaMetadataMapping.insert(
1829 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
1832 for (TBAAMemberAttr member : descriptor.getMembers()) {
1833 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
1841 walker.
addWalk([&](TBAATagAttr tag) {
1844 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
1845 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
1849 if (tag.getConstant())
1856 mlirModule->
walk([&](AliasAnalysisOpInterface analysisOpInterface) {
1857 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
1864 LogicalResult ModuleTranslation::createIdentMetadata() {
1866 LLVMDialect::getIdentAttrName())) {
1867 StringRef ident = attr;
1868 llvm::LLVMContext &ctx = llvmModule->getContext();
1869 llvm::NamedMDNode *namedMd =
1870 llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
1872 namedMd->addOperand(md);
1878 LogicalResult ModuleTranslation::createCommandlineMetadata() {
1880 LLVMDialect::getCommandlineAttrName())) {
1881 StringRef cmdLine = attr;
1882 llvm::LLVMContext &ctx = llvmModule->getContext();
1883 llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
1884 LLVMDialect::getCommandlineAttrName());
1887 nmd->addOperand(md);
1894 llvm::Instruction *inst) {
1895 LoopAnnotationAttr attr =
1897 .Case<LLVM::BrOp, LLVM::CondBrOp>(
1898 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
1901 llvm::MDNode *loopMD =
1902 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
1903 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
1907 auto iface = cast<DisjointFlagInterface>(op);
1909 if (
auto disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
1910 disjointInst->setIsDisjoint(iface.getIsDisjoint());
1920 remapped.reserve(values.size());
1921 for (
Value v : values)
1928 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
1929 ompBuilder->initialize();
1934 ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
1942 return ompBuilder.get();
1946 llvm::DILocalScope *scope) {
1947 return debugTranslation->translateLoc(loc, scope);
1950 llvm::DIExpression *
1952 return debugTranslation->translateExpression(attr);
1955 llvm::DIGlobalVariableExpression *
1957 LLVM::DIGlobalVariableExpressionAttr attr) {
1958 return debugTranslation->translateGlobalVariableExpression(attr);
1962 return debugTranslation->translate(attr);
1967 return convertRoundingModeToLLVM(rounding);
1971 LLVM::FPExceptionBehavior exceptionBehavior) {
1972 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
1977 return llvmModule->getOrInsertNamedMetadata(name);
1980 void ModuleTranslation::StackFrame::anchor() {}
1982 static std::unique_ptr<llvm::Module>
1985 m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
1986 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
1989 llvmModule->setNewDbgInfoFormatFlag(
false);
1990 if (
auto dataLayoutAttr =
1991 m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
1992 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
1994 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(
""));
1995 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
1996 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2000 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
2001 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2006 if (failed(llvmDataLayout))
2008 llvmModule->setDataLayout(*llvmDataLayout);
2010 if (
auto targetTripleAttr =
2011 m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
2012 llvmModule->setTargetTriple(cast<StringAttr>(targetTripleAttr).getValue());
2017 std::unique_ptr<llvm::Module>
2019 StringRef name,
bool disableVerification) {
2021 module->
emitOpError(
"can not be translated to an LLVMIR module");
2025 std::unique_ptr<llvm::Module> llvmModule =
2034 llvm::IRBuilder<> llvmBuilder(llvmContext);
2040 if (failed(translator.convertOperation(*module, llvmBuilder)))
2043 if (failed(translator.convertComdats()))
2045 if (failed(translator.convertFunctionSignatures()))
2047 if (failed(translator.convertGlobals()))
2049 if (failed(translator.createTBAAMetadata()))
2051 if (failed(translator.createIdentMetadata()))
2053 if (failed(translator.createCommandlineMetadata()))
2058 if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp, LLVM::GlobalCtorsOp,
2059 LLVM::GlobalDtorsOp, LLVM::ComdatOp>(&o) &&
2061 failed(translator.convertOperation(o, llvmBuilder))) {
2069 if (failed(translator.convertFunctions()))
2077 if (!disableVerification &&
2078 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2081 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::MDNode * convertIntegerToMDNode(llvm::LLVMContext &context, const llvm::APInt &value)
Return a representation of value as an MDNode.
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 llvm::MDNode * convertVecTypeHintToMDNode(llvm::LLVMContext &context, llvm::Type *type, bool isSigned)
Return an MDNode encoding vec_type_hint metadata.
static Block & getModuleBody(Operation *module)
A helper method to get the single Block in an operation honoring LLVM's module requirements.
static llvm::MDNode * convertIntegerArrayToMDNode(llvm::LLVMContext &context, ArrayRef< int32_t > values)
Return an MDNode with a tuple given by the values in values.
static llvm::Metadata * convertIntegerToMetadata(llvm::LLVMContext &context, const llvm::APInt &value)
Return a representation of value as metadata.
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 function attributes from func and attaches them to llvmFunc.
llvm::cl::opt< bool > UseNewDbgInfoFormat
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 void convertFunctionKernelAttributes(LLVMFuncOp func, llvm::Function *llvmFunc, ModuleTranslation &translation)
Converts function attributes from func and attaches them to llvmFunc.
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 void convertFunctionMemoryAttributes(LLVMFuncOp func, llvm::Function *llvmFunc)
Converts memory effect attributes from func and attaches them to llvmFunc.
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...
This class represents a processed binary blob of data.
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.
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.
void setDisjointFlag(Operation *op, llvm::Value *value)
Sets the disjoint flag attribute for the exported instruction value given the original operation op.
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...
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.
Value getOperand(unsigned idx)
AttrClass getAttrOfType(StringAttr name)
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Block * getSuccessor(unsigned index)
unsigned getNumSuccessors()
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),...
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'.
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.
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
The OpAsmOpInterface, see OpAsmInterface.td for more details.
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.
std::unique_ptr< llvm::Module > translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, llvm::StringRef name="LLVMDialectModule", bool disableVerification=false)
Translates a given LLVM dialect module into an LLVM IR module living in the given context.
SetVector< Block * > getBlocksSortedByDominance(Region ®ion)
Gets a list of blocks that is sorted according to dominance.
DataLayoutSpecInterface translateDataLayout(const llvm::DataLayout &dataLayout, MLIRContext *context)
Translate the given LLVM data layout into an MLIR equivalent using the DLTI dialect.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...