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/Analysis/TargetFolder.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"
62 #define DEBUG_TYPE "llvm-dialect-to-llvm-ir"
70 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
93 class InstructionCapturingInserter :
public llvm::IRBuilderCallbackInserter {
96 InstructionCapturingInserter()
97 : llvm::IRBuilderCallbackInserter([
this](llvm::Instruction *instruction) {
98 if (LLVM_LIKELY(enabled))
99 capturedInstructions.push_back(instruction);
104 return capturedInstructions;
108 void clearCapturedInstructions() { capturedInstructions.clear(); }
111 class CollectionScope {
114 CollectionScope(llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing);
122 return inserter->getCapturedInstructions();
127 InstructionCapturingInserter *inserter =
nullptr;
137 void setEnabled(
bool enabled =
true) { this->enabled = enabled; }
144 bool enabled =
false;
147 using CapturingIRBuilder =
148 llvm::IRBuilder<llvm::TargetFolder, InstructionCapturingInserter>;
151 InstructionCapturingInserter::CollectionScope::CollectionScope(
152 llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing) {
154 if (!isBuilderCapturing)
157 auto &capturingIRBuilder =
static_cast<CapturingIRBuilder &
>(irBuilder);
158 inserter = &capturingIRBuilder.getInserter();
159 wasEnabled = inserter->enabled;
161 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
162 inserter->setEnabled(
true);
165 InstructionCapturingInserter::CollectionScope::~CollectionScope() {
169 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
173 llvm::append_range(inserter->capturedInstructions,
174 previouslyCollectedInstructions);
176 inserter->setEnabled(wasEnabled);
181 static FailureOr<llvm::DataLayout>
184 std::optional<Location> loc = std::nullopt) {
189 std::string llvmDataLayout;
190 llvm::raw_string_ostream layoutStream(llvmDataLayout);
191 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
192 auto key = llvm::dyn_cast_if_present<StringAttr>(entry.getKey());
195 if (key.getValue() == DLTIDialect::kDataLayoutEndiannessKey) {
196 auto value = cast<StringAttr>(entry.getValue());
197 bool isLittleEndian =
198 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle;
199 layoutStream <<
"-" << (isLittleEndian ?
"e" :
"E");
202 if (key.getValue() == DLTIDialect::kDataLayoutManglingModeKey) {
203 auto value = cast<StringAttr>(entry.getValue());
204 layoutStream <<
"-m:" << value.getValue();
207 if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
208 auto value = cast<IntegerAttr>(entry.getValue());
209 uint64_t space = value.getValue().getZExtValue();
213 layoutStream <<
"-P" << space;
216 if (key.getValue() == DLTIDialect::kDataLayoutGlobalMemorySpaceKey) {
217 auto value = cast<IntegerAttr>(entry.getValue());
218 uint64_t space = value.getValue().getZExtValue();
222 layoutStream <<
"-G" << space;
225 if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
226 auto value = cast<IntegerAttr>(entry.getValue());
227 uint64_t space = value.getValue().getZExtValue();
231 layoutStream <<
"-A" << space;
234 if (key.getValue() == DLTIDialect::kDataLayoutStackAlignmentKey) {
235 auto value = cast<IntegerAttr>(entry.getValue());
236 uint64_t alignment = value.getValue().getZExtValue();
240 layoutStream <<
"-S" << alignment;
243 emitError(*loc) <<
"unsupported data layout key " << key;
250 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
251 auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
255 if (isa<IndexType>(type))
258 LogicalResult result =
260 .Case<IntegerType, Float16Type, Float32Type, Float64Type,
261 Float80Type, Float128Type>([&](
Type type) -> LogicalResult {
262 if (
auto intType = dyn_cast<IntegerType>(type)) {
263 if (intType.getSignedness() != IntegerType::Signless)
265 <<
"unsupported data layout for non-signless integer "
275 layoutStream << size <<
":" << abi;
276 if (abi != preferred)
277 layoutStream <<
":" << preferred;
280 .Case([&](LLVMPointerType type) {
281 layoutStream <<
"p" << type.getAddressSpace() <<
":";
287 layoutStream << size <<
":" << abi <<
":" << preferred <<
":"
291 .Default([loc](
Type type) {
293 <<
"unsupported type in data layout: " << type;
298 StringRef layoutSpec(llvmDataLayout);
299 if (layoutSpec.starts_with(
"-"))
300 layoutSpec = layoutSpec.drop_front();
302 return llvm::DataLayout(layoutSpec);
309 static llvm::Constant *
314 llvm::Constant *result = constants.front();
315 constants = constants.drop_front();
319 llvm::Type *elementType;
320 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
321 elementType = arrayTy->getElementType();
322 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
323 elementType = vectorTy->getElementType();
325 emitError(loc) <<
"expected sequential LLVM types wrapping a scalar";
330 nested.reserve(shape.front());
331 for (int64_t i = 0; i < shape.front(); ++i) {
338 if (shape.size() == 1 && type->isVectorTy())
347 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
348 type = arrayTy->getElementType();
349 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
350 type = vectorTy->getElementType();
364 static llvm::Constant *
366 llvm::Type *llvmType,
368 if (!denseElementsAttr)
372 if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
375 ShapedType type = denseElementsAttr.
getType();
376 if (type.getNumElements() == 0)
384 int64_t elementByteSize = denseElementsAttr.
getRawData().size() /
386 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
391 bool hasVectorElementType = isa<VectorType>(type.getElementType());
392 int64_t numAggregates =
394 (hasVectorElementType ? 1
395 : denseElementsAttr.
getType().getShape().back());
397 if (!hasVectorElementType)
398 outerShape = outerShape.drop_back();
401 if (denseElementsAttr.
isSplat() &&
402 (isa<VectorType>(type) || hasVectorElementType)) {
406 llvm::Constant *splatVector =
407 llvm::ConstantDataVector::getSplat(0, splatValue);
412 if (denseElementsAttr.
isSplat())
417 std::function<llvm::Constant *(StringRef)> buildCstData;
418 if (isa<TensorType>(type)) {
419 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
420 if (vectorElementType && vectorElementType.getRank() == 1) {
421 buildCstData = [&](StringRef data) {
422 return llvm::ConstantDataVector::getRaw(
423 data, vectorElementType.getShape().back(), innermostLLVMType);
425 }
else if (!vectorElementType) {
426 buildCstData = [&](StringRef data) {
427 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
431 }
else if (isa<VectorType>(type)) {
432 buildCstData = [&](StringRef data) {
433 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
443 int64_t aggregateSize = denseElementsAttr.
getType().getShape().back() *
444 (innermostLLVMType->getScalarSizeInBits() / 8);
445 constants.reserve(numAggregates);
446 for (
unsigned i = 0; i < numAggregates; ++i) {
447 StringRef data(denseElementsAttr.
getRawData().data() + i * aggregateSize,
449 constants.push_back(buildCstData(data));
465 assert(denseResourceAttr &&
"expected non-null attribute");
468 if (!llvm::ConstantDataSequential::isElementTypeCompatible(
469 innermostLLVMType)) {
470 emitError(loc,
"no known conversion for innermost element type");
474 ShapedType type = denseResourceAttr.getType();
475 assert(type.getNumElements() > 0 &&
"Expected non-empty elements attribute");
479 emitError(loc,
"resource does not exist");
490 int64_t numElements = denseResourceAttr.getType().getNumElements();
491 int64_t elementByteSize = rawData.size() / numElements;
492 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
493 emitError(loc,
"raw data size does not match element type size");
499 bool hasVectorElementType = isa<VectorType>(type.getElementType());
500 int64_t numAggregates =
501 numElements / (hasVectorElementType
503 : denseResourceAttr.getType().getShape().back());
505 if (!hasVectorElementType)
506 outerShape = outerShape.drop_back();
509 std::function<llvm::Constant *(StringRef)> buildCstData;
510 if (isa<TensorType>(type)) {
511 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
512 if (vectorElementType && vectorElementType.getRank() == 1) {
513 buildCstData = [&](StringRef data) {
514 return llvm::ConstantDataVector::getRaw(
515 data, vectorElementType.getShape().back(), innermostLLVMType);
517 }
else if (!vectorElementType) {
518 buildCstData = [&](StringRef data) {
519 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
523 }
else if (isa<VectorType>(type)) {
524 buildCstData = [&](StringRef data) {
525 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
530 emitError(loc,
"unsupported dense_resource type");
537 int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
538 (innermostLLVMType->getScalarSizeInBits() / 8);
539 constants.reserve(numAggregates);
540 for (
unsigned i = 0; i < numAggregates; ++i) {
541 StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
542 constants.push_back(buildCstData(data));
559 if (
auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
560 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
562 emitError(loc,
"expected an array attribute for a struct constant");
566 structElements.reserve(structType->getNumElements());
567 for (
auto [elemType, elemAttr] :
568 zip_equal(structType->elements(), arrayAttr)) {
569 llvm::Constant *element =
573 structElements.push_back(element);
579 if (
auto intAttr = dyn_cast<IntegerAttr>(attr))
582 intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
583 if (
auto floatAttr = dyn_cast<FloatAttr>(attr)) {
584 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
589 unsigned floatWidth = APFloat::getSizeInBits(sem);
590 if (llvmType->isIntegerTy(floatWidth))
592 floatAttr.getValue().bitcastToAPInt());
594 llvm::Type::getFloatingPointTy(llvmType->getContext(),
595 floatAttr.getValue().getSemantics())) {
596 emitError(loc,
"FloatAttr does not match expected type of the constant");
601 if (
auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
602 return llvm::ConstantExpr::getBitCast(
604 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
605 llvm::Type *elementType;
606 uint64_t numElements;
607 bool isScalable =
false;
608 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
609 elementType = arrayTy->getElementType();
610 numElements = arrayTy->getNumElements();
611 }
else if (
auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
612 elementType = fVectorTy->getElementType();
613 numElements = fVectorTy->getNumElements();
614 }
else if (
auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
615 elementType = sVectorTy->getElementType();
616 numElements = sVectorTy->getMinNumElements();
619 llvm_unreachable(
"unrecognized constant vector type");
624 bool elementTypeSequential =
625 isa<llvm::ArrayType, llvm::VectorType>(elementType);
628 elementTypeSequential ? splatAttr
630 loc, moduleTranslation);
633 if (llvmType->isVectorTy())
634 return llvm::ConstantVector::getSplat(
636 if (llvmType->isArrayTy()) {
638 if (child->isZeroValue()) {
641 if (llvm::ConstantDataSequential::isElementTypeCompatible(
644 if (isa<llvm::IntegerType>(elementType)) {
645 if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
646 if (ci->getBitWidth() == 8) {
651 if (ci->getBitWidth() == 16) {
656 if (ci->getBitWidth() == 32) {
661 if (ci->getBitWidth() == 64) {
671 std::vector<llvm::Constant *> constants(numElements, child);
678 if (llvm::Constant *result =
680 llvmType, moduleTranslation)) {
684 if (
auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
690 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
691 assert(elementsAttr.getShapedType().hasStaticShape());
692 assert(!elementsAttr.getShapedType().getShape().empty() &&
693 "unexpected empty elements attribute shape");
696 constants.reserve(elementsAttr.getNumElements());
698 for (
auto n : elementsAttr.getValues<
Attribute>()) {
701 if (!constants.back())
706 constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
707 assert(constantsRef.empty() &&
"did not consume all elemental constants");
711 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
715 stringAttr.getValue().size()});
717 emitError(loc,
"unsupported constant value");
721 ModuleTranslation::ModuleTranslation(
Operation *module,
722 std::unique_ptr<llvm::Module> llvmModule)
723 : mlirModule(module), llvmModule(std::move(llvmModule)),
727 *this, *this->llvmModule)),
728 typeTranslator(this->llvmModule->
getContext()),
731 "mlirModule should honor LLVM's module semantics.");
734 ModuleTranslation::~ModuleTranslation() {
736 ompBuilder->finalize();
741 toProcess.push_back(®ion);
742 while (!toProcess.empty()) {
743 Region *current = toProcess.pop_back_val();
744 for (
Block &block : *current) {
745 blockMapping.erase(&block);
746 for (
Value arg : block.getArguments())
747 valueMapping.erase(arg);
749 for (
Value value : op.getResults())
750 valueMapping.erase(value);
751 if (op.hasSuccessors())
752 branchMapping.erase(&op);
753 if (isa<LLVM::GlobalOp>(op))
754 globalsMapping.erase(&op);
755 if (isa<LLVM::AliasOp>(op))
756 aliasesMapping.erase(&op);
757 if (isa<LLVM::CallOp>(op))
758 callMapping.erase(&op);
761 llvm::map_range(op.getRegions(), [](
Region &r) { return &r; }));
770 unsigned numArguments,
unsigned index) {
772 if (isa<LLVM::BrOp>(terminator))
779 auto branch = cast<BranchOpInterface>(terminator);
782 (!seenSuccessors.contains(successor) || successorOperands.
empty()) &&
783 "successors with arguments in LLVM branches must be different blocks");
784 seenSuccessors.insert(successor);
790 if (
auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
793 return condBranchOp.getSuccessor(0) == current
794 ? condBranchOp.getTrueDestOperands()[index]
795 : condBranchOp.getFalseDestOperands()[index];
798 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
801 if (switchOp.getDefaultDestination() == current)
802 return switchOp.getDefaultOperands()[index];
804 if (i.value() == current)
805 return switchOp.getCaseOperands(i.index())[index];
808 if (
auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(terminator)) {
811 if (indBrOp->getSuccessor(i.index()) == current)
812 return indBrOp.getSuccessorOperands(i.index())[index];
816 if (
auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
817 return invokeOp.getNormalDest() == current
818 ? invokeOp.getNormalDestOperands()[index]
819 : invokeOp.getUnwindDestOperands()[index];
823 "only branch, switch or invoke operations can be terminators "
824 "of a block that has successors");
832 for (
Block &bb : llvm::drop_begin(region)) {
833 llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
834 auto phis = llvmBB->phis();
835 auto numArguments = bb.getNumArguments();
836 assert(numArguments == std::distance(phis.begin(), phis.end()));
838 for (
auto *pred : bb.getPredecessors()) {
844 llvm::Instruction *terminator =
845 state.lookupBranch(pred->getTerminator());
846 assert(terminator &&
"missing the mapping for a terminator");
848 &bb, pred, numArguments, index)),
849 terminator->getParent());
858 llvm::Module *module = builder.GetInsertBlock()->getModule();
860 llvm::Intrinsic::getOrInsertDeclaration(module, intrinsic, tys);
861 return builder.CreateCall(fn, args);
870 assert(immArgPositions.size() == immArgAttrNames.size() &&
871 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
875 size_t numOpBundleOperands = 0;
876 auto opBundleSizesAttr = cast_if_present<DenseI32ArrayAttr>(
877 intrOp->
getAttr(LLVMDialect::getOpBundleSizesAttrName()));
878 auto opBundleTagsAttr = cast_if_present<ArrayAttr>(
879 intrOp->
getAttr(LLVMDialect::getOpBundleTagsAttrName()));
881 if (opBundleSizesAttr && opBundleTagsAttr) {
882 ArrayRef<int> opBundleSizes = opBundleSizesAttr.asArrayRef();
883 assert(opBundleSizes.size() == opBundleTagsAttr.size() &&
884 "operand bundles and tags do not match");
886 numOpBundleOperands =
887 std::accumulate(opBundleSizes.begin(), opBundleSizes.end(),
size_t(0));
888 assert(numOpBundleOperands <= intrOp->getNumOperands() &&
889 "operand bundle operands is more than the number of operands");
892 size_t nextOperandIdx = 0;
893 opBundles.reserve(opBundleSizesAttr.size());
895 for (
auto [opBundleTagAttr, bundleSize] :
896 llvm::zip(opBundleTagsAttr, opBundleSizes)) {
897 auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
899 operands.slice(nextOperandIdx, bundleSize));
900 opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
901 nextOperandIdx += bundleSize;
906 auto opOperands = intrOp->
getOperands().drop_back(numOpBundleOperands);
907 auto operands = moduleTranslation.
lookupValues(opOperands);
909 for (
auto [immArgPos, immArgName] :
910 llvm::zip(immArgPositions, immArgAttrNames)) {
911 auto attr = llvm::cast<TypedAttr>(intrOp->
getAttr(immArgName));
912 assert(attr.getType().isIntOrFloat() &&
"expected int or float immarg");
913 auto *type = moduleTranslation.
convertType(attr.getType());
915 type, attr, intrOp->
getLoc(), moduleTranslation);
918 for (
auto &arg : args) {
920 arg = operands[opArg++];
925 for (
unsigned overloadedResultIdx : overloadedResults) {
926 if (numResults > 1) {
928 overloadedTypes.push_back(moduleTranslation.
convertType(
930 .getBody()[overloadedResultIdx]));
932 overloadedTypes.push_back(
936 for (
unsigned overloadedOperandIdx : overloadedOperands)
937 overloadedTypes.push_back(args[overloadedOperandIdx]->
getType());
938 llvm::Module *module = builder.GetInsertBlock()->getModule();
939 llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
940 module, intrinsic, overloadedTypes);
942 return builder.CreateCall(llvmIntr, args, opBundles);
947 LogicalResult ModuleTranslation::convertOperation(
Operation &op,
948 llvm::IRBuilderBase &builder,
949 bool recordInsertions) {
952 return op.
emitError(
"cannot be converted to LLVM IR: missing "
953 "`LLVMTranslationDialectInterface` registration for "
957 InstructionCapturingInserter::CollectionScope scope(builder,
960 return op.
emitError(
"LLVM Translation failed for operation: ")
963 return convertDialectAttributes(&op, scope.getCapturedInstructions());
973 LogicalResult ModuleTranslation::convertBlockImpl(
Block &bb,
974 bool ignoreArguments,
975 llvm::IRBuilderBase &builder,
976 bool recordInsertions) {
978 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
986 if (!ignoreArguments) {
988 unsigned numPredecessors =
989 std::distance(predecessors.begin(), predecessors.end());
991 auto wrappedType = arg.getType();
994 "block argument does not have an LLVM type");
995 builder.SetCurrentDebugLocation(
996 debugTranslation->translateLoc(arg.getLoc(), subprogram));
998 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
1004 for (
auto &op : bb) {
1006 builder.SetCurrentDebugLocation(
1007 debugTranslation->translateLoc(op.
getLoc(), subprogram));
1009 if (failed(convertOperation(op, builder, recordInsertions)))
1013 if (
auto iface = dyn_cast<BranchWeightOpInterface>(op))
1032 llvm::Constant *cst) {
1033 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1034 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1040 llvm::GlobalValue *gv) {
1041 if (dsoLocalRequested)
1042 gv->setDSOLocal(
true);
1045 LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
1054 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1056 llvm::Constant *cst =
nullptr;
1057 if (op.getValueOrNull()) {
1060 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1061 cst = llvm::ConstantDataArray::getString(
1062 llvmModule->getContext(), strAttr.getValue(),
false);
1063 type = cst->getType();
1070 auto linkage = convertLinkageToLLVM(op.getLinkage());
1076 if (!dropInitializer && !cst)
1078 else if (dropInitializer && cst)
1081 auto *var =
new llvm::GlobalVariable(
1082 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1084 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1085 : llvm::GlobalValue::NotThreadLocal,
1086 op.getAddrSpace(), op.getExternallyInitialized());
1088 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1089 auto selectorOp = cast<ComdatSelectorOp>(
1091 var->setComdat(comdatMapping.lookup(selectorOp));
1094 if (op.getUnnamedAddr().has_value())
1095 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1097 if (op.getSection().has_value())
1098 var->setSection(*op.getSection());
1102 std::optional<uint64_t> alignment = op.getAlignment();
1103 if (alignment.has_value())
1104 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1106 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1108 globalsMapping.try_emplace(op, var);
1111 if (op.getDbgExprs()) {
1112 for (
auto exprAttr :
1113 op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1114 llvm::DIGlobalVariableExpression *diGlobalExpr =
1115 debugTranslation->translateGlobalVariableExpression(exprAttr);
1116 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1117 var->addDebugInfo(diGlobalExpr);
1136 llvm::DIScope *scope = diGlobalVar->getScope();
1137 if (
auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1138 scope = mod->getScope();
1139 else if (
auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1141 dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1142 scope = sp->getUnit();
1143 }
else if (
auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1144 scope = sp->getUnit();
1147 if (llvm::DICompileUnit *compileUnit =
1148 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1151 allGVars[compileUnit].push_back(diGlobalExpr);
1158 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1160 llvm::Constant *cst =
nullptr;
1161 llvm::GlobalValue::LinkageTypes linkage =
1162 convertLinkageToLLVM(op.getLinkage());
1163 llvm::Module &llvmMod = *llvmModule;
1166 llvm::GlobalAlias *var = llvm::GlobalAlias::create(
1167 type, op.getAddrSpace(), linkage, op.getSymName(), cst,
1170 var->setThreadLocalMode(op.getThreadLocal_()
1171 ? llvm::GlobalAlias::GeneralDynamicTLSModel
1172 : llvm::GlobalAlias::NotThreadLocal);
1177 if (op.getUnnamedAddr().has_value())
1178 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1180 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1182 aliasesMapping.try_emplace(op, var);
1186 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1187 if (
Block *initializer = op.getInitializerBlock()) {
1188 llvm::IRBuilder<llvm::TargetFolder> builder(
1189 llvmModule->getContext(),
1190 llvm::TargetFolder(llvmModule->getDataLayout()));
1192 [[maybe_unused]]
int numConstantsHit = 0;
1193 [[maybe_unused]]
int numConstantsErased = 0;
1196 for (
auto &op : initializer->without_terminator()) {
1197 if (failed(convertOperation(op, builder)))
1210 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1214 auto [iterator, inserted] =
1215 constantAggregateUseMap.try_emplace(agg, numUsers);
1218 iterator->second += numUsers;
1224 auto cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1227 auto iter = constantAggregateUseMap.find(cst);
1228 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1230 if (iter->second == 0) {
1233 if (cst->user_empty()) {
1234 cst->destroyConstant();
1235 numConstantsErased++;
1237 constantAggregateUseMap.erase(iter);
1242 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1243 llvm::Constant *cst =
1244 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1245 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1247 global->setInitializer(cst);
1251 for (
auto it : constantAggregateUseMap) {
1252 auto cst = it.first;
1253 cst->removeDeadConstantUsers();
1254 if (cst->user_empty()) {
1255 cst->destroyConstant();
1256 numConstantsErased++;
1260 LLVM_DEBUG(llvm::dbgs()
1261 <<
"Convert initializer for " << op.
getName() <<
"\n";
1262 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1264 << numConstantsErased <<
" dangling constants erased\n";);
1270 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1271 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1272 if (!ctorOp && !dtorOp)
1278 if ((ctorOp && ctorOp.getCtors().empty()) ||
1279 (dtorOp && dtorOp.getDtors().empty())) {
1280 llvm::IRBuilder<llvm::TargetFolder> builder(
1281 llvmModule->getContext(),
1282 llvm::TargetFolder(llvmModule->getDataLayout()));
1284 builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1286 llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1287 (void)
new llvm::GlobalVariable(
1288 *llvmModule, zeroInit->getType(),
false,
1289 llvm::GlobalValue::AppendingLinkage, zeroInit,
1290 ctorOp ?
"llvm.global_ctors" :
"llvm.global_dtors");
1293 ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1294 :
llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1295 auto appendGlobalFn =
1296 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1297 for (
const auto &[sym, prio] : range) {
1300 appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1306 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1307 if (failed(convertDialectAttributes(op, {})))
1312 for (
const auto &[compileUnit, globals] : allGVars) {
1313 compileUnit->replaceGlobalVariables(
1318 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1319 Block &initializer = op.getInitializerBlock();
1320 llvm::IRBuilder<llvm::TargetFolder> builder(
1321 llvmModule->getContext(),
1322 llvm::TargetFolder(llvmModule->getDataLayout()));
1325 if (failed(convertOperation(op, builder)))
1332 auto *cst = cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1333 assert(aliasesMapping.count(op));
1334 auto *alias = cast<llvm::GlobalAlias>(aliasesMapping[op]);
1335 alias->setAliasee(cst);
1338 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>())
1339 if (failed(convertDialectAttributes(op, {})))
1352 llvm::Function *llvmFunc,
1354 StringRef value = StringRef()) {
1355 auto kind = llvm::Attribute::getAttrKindFromName(key);
1357 llvmFunc->addFnAttr(key, value);
1361 if (llvm::Attribute::isIntAttrKind(
kind)) {
1363 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1366 if (!value.getAsInteger(0, result))
1367 llvmFunc->addFnAttr(
1370 llvmFunc->addFnAttr(key, value);
1375 return emitError(loc) <<
"LLVM attribute '" << key
1376 <<
"' does not expect a value, found '" << value
1379 llvmFunc->addFnAttr(
kind);
1385 const llvm::APInt &value) {
1392 const llvm::APInt &value) {
1400 llvm::Metadata *typeMD =
1402 llvm::Metadata *isSignedMD =
1412 values, std::back_inserter(mdValues), [&context](int32_t value) {
1425 static LogicalResult
1427 llvm::Function *llvmFunc) {
1432 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1439 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1440 if (!arrayAttr || arrayAttr.size() != 2)
1442 <<
"expected 'passthrough' to contain string or array attributes";
1444 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1445 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1446 if (!keyAttr || !valueAttr)
1448 <<
"expected arrays within 'passthrough' to contain two strings";
1451 valueAttr.getValue())))
1457 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1460 blockMapping.clear();
1461 valueMapping.clear();
1462 branchMapping.clear();
1466 for (
auto [mlirArg, llvmArg] :
1467 llvm::zip(func.getArguments(), llvmFunc->args()))
1471 if (func.getPersonality()) {
1472 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1473 if (llvm::Constant *pfunc =
getLLVMConstant(ty, func.getPersonalityAttr(),
1474 func.getLoc(), *
this))
1475 llvmFunc->setPersonalityFn(pfunc);
1478 if (std::optional<StringRef> section = func.getSection())
1479 llvmFunc->setSection(*section);
1481 if (func.getArmStreaming())
1482 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1483 else if (func.getArmLocallyStreaming())
1484 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1485 else if (func.getArmStreamingCompatible())
1486 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1488 if (func.getArmNewZa())
1489 llvmFunc->addFnAttr(
"aarch64_new_za");
1490 else if (func.getArmInZa())
1491 llvmFunc->addFnAttr(
"aarch64_in_za");
1492 else if (func.getArmOutZa())
1493 llvmFunc->addFnAttr(
"aarch64_out_za");
1494 else if (func.getArmInoutZa())
1495 llvmFunc->addFnAttr(
"aarch64_inout_za");
1496 else if (func.getArmPreservesZa())
1497 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1499 if (
auto targetCpu = func.getTargetCpu())
1500 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1502 if (
auto tuneCpu = func.getTuneCpu())
1503 llvmFunc->addFnAttr(
"tune-cpu", *tuneCpu);
1505 if (
auto attr = func.getVscaleRange())
1506 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1508 attr->getMaxRange().getInt()));
1510 if (
auto unsafeFpMath = func.getUnsafeFpMath())
1511 llvmFunc->addFnAttr(
"unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1513 if (
auto noInfsFpMath = func.getNoInfsFpMath())
1514 llvmFunc->addFnAttr(
"no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1516 if (
auto noNansFpMath = func.getNoNansFpMath())
1517 llvmFunc->addFnAttr(
"no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1519 if (
auto approxFuncFpMath = func.getApproxFuncFpMath())
1520 llvmFunc->addFnAttr(
"approx-func-fp-math",
1521 llvm::toStringRef(*approxFuncFpMath));
1523 if (
auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1524 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1525 llvm::toStringRef(*noSignedZerosFpMath));
1527 if (
auto denormalFpMath = func.getDenormalFpMath())
1528 llvmFunc->addFnAttr(
"denormal-fp-math", *denormalFpMath);
1530 if (
auto denormalFpMathF32 = func.getDenormalFpMathF32())
1531 llvmFunc->addFnAttr(
"denormal-fp-math-f32", *denormalFpMathF32);
1533 if (
auto fpContract = func.getFpContract())
1534 llvmFunc->addFnAttr(
"fp-contract", *fpContract);
1537 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1538 for (
auto &bb : func) {
1539 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1540 llvmBB->insertInto(llvmFunc);
1547 for (
Block *bb : blocks) {
1548 CapturingIRBuilder builder(llvmContext,
1549 llvm::TargetFolder(llvmModule->getDataLayout()));
1550 if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1560 return convertDialectAttributes(func, {});
1563 LogicalResult ModuleTranslation::convertDialectAttributes(
1566 if (failed(iface.
amendOperation(op, instructions, attribute, *
this)))
1574 llvm::Function *llvmFunc) {
1575 if (!func.getMemoryEffects())
1578 MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1581 llvm::MemoryEffects newMemEffects =
1582 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1583 convertModRefInfoToLLVM(memEffects.getArgMem()));
1584 newMemEffects |= llvm::MemoryEffects(
1585 llvm::MemoryEffects::Location::InaccessibleMem,
1586 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1588 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1589 convertModRefInfoToLLVM(memEffects.getOther()));
1590 llvmFunc->setMemoryEffects(newMemEffects);
1595 llvm::Function *llvmFunc) {
1596 if (func.getNoInlineAttr())
1597 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1598 if (func.getAlwaysInlineAttr())
1599 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1600 if (func.getOptimizeNoneAttr())
1601 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1602 if (func.getConvergentAttr())
1603 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1604 if (func.getNoUnwindAttr())
1605 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1606 if (func.getWillReturnAttr())
1607 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1608 if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
1609 llvmFunc->addFnAttr(
"target-features", targetFeatAttr.getFeaturesString());
1610 if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())
1611 llvmFunc->addFnAttr(
"frame-pointer", stringifyFramePointerKind(
1612 fpAttr.getFramePointerKind()));
1613 if (UWTableKindAttr uwTableKindAttr = func.getUwtableKindAttr())
1614 llvmFunc->setUWTableKind(
1615 convertUWTableKindToLLVM(uwTableKindAttr.getUwtableKind()));
1621 llvm::Function *llvmFunc,
1623 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1625 if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1626 Type type = vecTypeHint.getHint().getValue();
1627 llvm::Type *llvmType = translation.
convertType(type);
1628 bool isSigned = vecTypeHint.getIsSigned();
1629 llvmFunc->setMetadata(
1630 func.getVecTypeHintAttrName(),
1635 func.getWorkGroupSizeHint()) {
1636 llvmFunc->setMetadata(
1637 func.getWorkGroupSizeHintAttrName(),
1642 func.getReqdWorkGroupSize()) {
1643 llvmFunc->setMetadata(
1644 func.getReqdWorkGroupSizeAttrName(),
1648 if (std::optional<uint32_t> intelReqdSubGroupSize =
1649 func.getIntelReqdSubGroupSize()) {
1650 llvmFunc->setMetadata(
1651 func.getIntelReqdSubGroupSizeAttrName(),
1653 llvm::APInt(32, *intelReqdSubGroupSize)));
1658 llvm::Attribute::AttrKind llvmKind,
1663 .Case<TypeAttr>([&](
auto typeAttr) {
1664 attrBuilder.addTypeAttr(
1665 llvmKind, moduleTranslation.
convertType(typeAttr.getValue()));
1668 .Case<IntegerAttr>([&](
auto intAttr) {
1669 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1672 .Case<UnitAttr>([&](
auto) {
1673 attrBuilder.addAttribute(llvmKind);
1676 .Case<LLVM::ConstantRangeAttr>([&](
auto rangeAttr) {
1677 attrBuilder.addConstantRangeAttr(
1679 llvm::ConstantRange(rangeAttr.getLower(), rangeAttr.getUpper()));
1682 .Default([loc](
auto) {
1683 return emitError(loc,
"unsupported parameter attribute type");
1687 FailureOr<llvm::AttrBuilder>
1689 DictionaryAttr paramAttrs) {
1690 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1694 for (
auto namedAttr : paramAttrs) {
1695 auto it = attrNameToKindMapping.find(namedAttr.getName());
1696 if (it != attrNameToKindMapping.end()) {
1697 llvm::Attribute::AttrKind llvmKind = it->second;
1701 }
else if (namedAttr.getNameDialect()) {
1710 FailureOr<llvm::AttrBuilder>
1712 DictionaryAttr paramAttrs) {
1713 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1716 for (
auto namedAttr : paramAttrs) {
1717 auto it = attrNameToKindMapping.find(namedAttr.getName());
1718 if (it != attrNameToKindMapping.end()) {
1719 llvm::Attribute::AttrKind llvmKind = it->second;
1729 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1732 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1733 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1735 cast<llvm::FunctionType>(
convertType(
function.getFunctionType())));
1736 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1737 llvmFunc->setLinkage(convertLinkageToLLVM(
function.getLinkage()));
1738 llvmFunc->setCallingConv(convertCConvToLLVM(
function.getCConv()));
1749 if (std::optional<uint64_t> entryCount =
function.getFunctionEntryCount())
1750 llvmFunc->setEntryCount(entryCount.value());
1753 if (ArrayAttr allResultAttrs =
function.getAllResultAttrs()) {
1754 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1755 FailureOr<llvm::AttrBuilder> attrBuilder =
1757 if (failed(attrBuilder))
1759 llvmFunc->addRetAttrs(*attrBuilder);
1765 FailureOr<llvm::AttrBuilder> attrBuilder =
1767 if (failed(attrBuilder))
1769 llvmArg.addAttrs(*attrBuilder);
1775 function.getLoc(),
function.getPassthrough(), llvmFunc)))
1779 llvmFunc->setVisibility(convertVisibilityToLLVM(
function.getVisibility_()));
1782 if (std::optional<mlir::SymbolRefAttr> comdat =
function.getComdat()) {
1783 auto selectorOp = cast<ComdatSelectorOp>(
1785 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1788 if (
auto gc =
function.getGarbageCollector())
1789 llvmFunc->setGC(gc->str());
1791 if (
auto unnamedAddr =
function.getUnnamedAddr())
1792 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1794 if (
auto alignment =
function.getAlignment())
1795 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1798 debugTranslation->translate(
function, *llvmFunc);
1804 LogicalResult ModuleTranslation::convertFunctions() {
1806 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1809 if (
function.isExternal()) {
1810 if (failed(convertDialectAttributes(
function, {})))
1815 if (failed(convertOneFunction(
function)))
1822 LogicalResult ModuleTranslation::convertComdats() {
1823 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
1824 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1826 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1828 <<
"comdat selection symbols must be unique even in different "
1830 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1831 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1832 comdatMapping.try_emplace(selectorOp, comdat);
1838 LogicalResult ModuleTranslation::convertUnresolvedBlockAddress() {
1839 for (
auto &[blockAddressOp, llvmCst] : unresolvedBlockAddressMapping) {
1840 BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
1842 assert(blockTagOp &&
"expected all block tags to be already seen");
1844 llvm::BasicBlock *llvmBlock =
lookupBlock(blockTagOp->getBlock());
1845 assert(llvmBlock &&
"expected LLVM blocks to be already translated");
1849 lookupFunction(blockAddressAttr.getFunction().getValue()), llvmBlock);
1850 llvmCst->replaceAllUsesWith(llvmBlockAddr);
1851 mapValue(blockAddressOp.getResult(), llvmBlockAddr);
1852 assert(llvmCst->use_empty() &&
"expected all uses to be replaced");
1853 cast<llvm::GlobalVariable>(llvmCst)->eraseFromParent();
1855 unresolvedBlockAddressMapping.clear();
1860 llvm::Instruction *inst) {
1861 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1862 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1867 auto [scopeIt, scopeInserted] =
1868 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
1870 return scopeIt->second;
1871 llvm::LLVMContext &ctx = llvmModule->getContext();
1872 auto dummy = llvm::MDNode::getTemporary(ctx, std::nullopt);
1874 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1875 aliasScopeAttr.getDomain(),
nullptr);
1876 if (insertedDomain) {
1879 operands.push_back(dummy.get());
1880 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
1884 llvm::Metadata *replacement;
1885 if (
auto stringAttr =
1886 dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId()))
1889 replacement = domainIt->second;
1890 domainIt->second->replaceOperandWith(0, replacement);
1893 assert(domainIt->second &&
"Scope's domain should already be valid");
1896 operands.push_back(dummy.get());
1897 operands.push_back(domainIt->second);
1898 if (StringAttr description = aliasScopeAttr.getDescription())
1902 llvm::Metadata *replacement;
1903 if (
auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId()))
1906 replacement = scopeIt->second;
1907 scopeIt->second->replaceOperandWith(0, replacement);
1908 return scopeIt->second;
1914 nodes.reserve(aliasScopeAttrs.size());
1915 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
1921 llvm::Instruction *inst) {
1922 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
1923 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
1926 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
1927 inst->setMetadata(
kind, node);
1930 populateScopeMetadata(op.getAliasScopesOrNull(),
1931 llvm::LLVMContext::MD_alias_scope);
1932 populateScopeMetadata(op.getNoAliasScopesOrNull(),
1933 llvm::LLVMContext::MD_noalias);
1936 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
1937 return tbaaMetadataMapping.lookup(tbaaAttr);
1941 llvm::Instruction *inst) {
1942 ArrayAttr tagRefs = op.getTBAATagsOrNull();
1943 if (!tagRefs || tagRefs.empty())
1950 if (tagRefs.size() > 1) {
1951 op.emitWarning() <<
"TBAA access tags were not translated, because LLVM "
1952 "IR only supports a single tag per instruction";
1956 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
1957 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
1961 DereferenceableOpInterface op, llvm::Instruction *inst) {
1962 DereferenceableAttr derefAttr = op.getDereferenceableOrNull();
1970 unsigned kindId = derefAttr.getMayBeNull()
1971 ? llvm::LLVMContext::MD_dereferenceable_or_null
1972 : llvm::LLVMContext::MD_dereferenceable;
1973 inst->setMetadata(kindId, derefSizeNode);
1982 assert(inst &&
"expected the operation to have a mapping to an instruction");
1985 llvm::LLVMContext::MD_prof,
1989 LogicalResult ModuleTranslation::createTBAAMetadata() {
1990 llvm::LLVMContext &ctx = llvmModule->getContext();
2002 walker.
addWalk([&](TBAARootAttr root) {
2003 tbaaMetadataMapping.insert(
2007 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
2010 for (TBAAMemberAttr member : descriptor.getMembers()) {
2011 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
2019 walker.
addWalk([&](TBAATagAttr tag) {
2022 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
2023 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
2027 if (tag.getConstant())
2034 mlirModule->
walk([&](AliasAnalysisOpInterface analysisOpInterface) {
2035 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
2042 LogicalResult ModuleTranslation::createIdentMetadata() {
2044 LLVMDialect::getIdentAttrName())) {
2045 StringRef ident = attr;
2046 llvm::LLVMContext &ctx = llvmModule->getContext();
2047 llvm::NamedMDNode *namedMd =
2048 llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
2050 namedMd->addOperand(md);
2056 LogicalResult ModuleTranslation::createCommandlineMetadata() {
2058 LLVMDialect::getCommandlineAttrName())) {
2059 StringRef cmdLine = attr;
2060 llvm::LLVMContext &ctx = llvmModule->getContext();
2061 llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
2062 LLVMDialect::getCommandlineAttrName());
2065 nmd->addOperand(md);
2071 LogicalResult ModuleTranslation::createDependentLibrariesMetadata() {
2073 LLVM::LLVMDialect::getDependentLibrariesAttrName())) {
2075 llvmModule->getOrInsertNamedMetadata(
"llvm.dependent-libraries");
2076 llvm::LLVMContext &ctx = llvmModule->getContext();
2078 cast<ArrayAttr>(dependentLibrariesAttr).getAsRange<StringAttr>()) {
2081 nmd->addOperand(md);
2088 llvm::Instruction *inst) {
2089 LoopAnnotationAttr attr =
2091 .Case<LLVM::BrOp, LLVM::CondBrOp>(
2092 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
2095 llvm::MDNode *loopMD =
2096 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
2097 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
2101 auto iface = cast<DisjointFlagInterface>(op);
2103 if (
auto disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
2104 disjointInst->setIsDisjoint(iface.getIsDisjoint());
2114 remapped.reserve(values.size());
2115 for (
Value v : values)
2122 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
2123 ompBuilder->initialize();
2128 ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
2136 return ompBuilder.get();
2140 llvm::DILocalScope *scope) {
2141 return debugTranslation->translateLoc(loc, scope);
2144 llvm::DIExpression *
2146 return debugTranslation->translateExpression(attr);
2149 llvm::DIGlobalVariableExpression *
2151 LLVM::DIGlobalVariableExpressionAttr attr) {
2152 return debugTranslation->translateGlobalVariableExpression(attr);
2156 return debugTranslation->translate(attr);
2161 return convertRoundingModeToLLVM(rounding);
2165 LLVM::FPExceptionBehavior exceptionBehavior) {
2166 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
2171 return llvmModule->getOrInsertNamedMetadata(name);
2174 void ModuleTranslation::StackFrame::anchor() {}
2176 static std::unique_ptr<llvm::Module>
2179 m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
2180 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
2183 llvmModule->setNewDbgInfoFormatFlag(
false);
2184 if (
auto dataLayoutAttr =
2185 m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
2186 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
2188 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(
""));
2189 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
2190 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2194 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
2195 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2200 if (failed(llvmDataLayout))
2202 llvmModule->setDataLayout(*llvmDataLayout);
2204 if (
auto targetTripleAttr =
2205 m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
2206 llvmModule->setTargetTriple(
2207 llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
2212 std::unique_ptr<llvm::Module>
2214 StringRef name,
bool disableVerification) {
2216 module->
emitOpError(
"can not be translated to an LLVMIR module");
2220 std::unique_ptr<llvm::Module> llvmModule =
2229 llvm::IRBuilder<llvm::TargetFolder> llvmBuilder(
2231 llvm::TargetFolder(translator.getLLVMModule()->getDataLayout()));
2237 if (failed(translator.convertOperation(*module, llvmBuilder)))
2240 if (failed(translator.convertComdats()))
2242 if (failed(translator.convertFunctionSignatures()))
2244 if (failed(translator.convertGlobalsAndAliases()))
2246 if (failed(translator.createTBAAMetadata()))
2248 if (failed(translator.createIdentMetadata()))
2250 if (failed(translator.createCommandlineMetadata()))
2252 if (failed(translator.createDependentLibrariesMetadata()))
2257 if (!isa<LLVM::LLVMFuncOp, LLVM::AliasOp, LLVM::GlobalOp,
2258 LLVM::GlobalCtorsOp, LLVM::GlobalDtorsOp, LLVM::ComdatOp>(&o) &&
2260 failed(translator.convertOperation(o, llvmBuilder))) {
2268 if (failed(translator.convertFunctions()))
2273 if (failed(translator.convertUnresolvedBlockAddress()))
2283 translator.debugTranslation->addModuleFlagsIfNotPresent();
2285 if (!disableVerification &&
2286 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2289 return std::move(translator.llvmModule);
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1191::ArityGroupAndKind::Kind kind
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 LogicalResult convertParameterAttr(llvm::AttrBuilder &attrBuilder, llvm::Attribute::AttrKind llvmKind, NamedAttribute namedAttr, ModuleTranslation &moduleTranslation, Location loc)
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()
iterator_range< iterator > without_terminator()
Return an iterator range over the operation within this block excluding the terminator operation at t...
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.
FailureOr< llvm::AttrBuilder > convertParameterAttrs(mlir::Location loc, DictionaryAttr paramAttrs)
Translates parameter attributes of a call and adds them to the returned AttrBuilder.
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 setDereferenceableMetadata(DereferenceableOpInterface op, llvm::Instruction *inst)
Sets LLVM dereferenceable metadata for operations that have dereferenceable attributes.
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.
BlockTagOp lookupBlockTag(BlockAddressAttr attr) const
Finds an MLIR block 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.
Attribute getValue() const
Return the value of the attribute.
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)
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...