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"
60 #define DEBUG_TYPE "llvm-dialect-to-llvm-ir"
68 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
91 class InstructionCapturingInserter :
public llvm::IRBuilderCallbackInserter {
94 InstructionCapturingInserter()
95 : llvm::IRBuilderCallbackInserter([
this](llvm::Instruction *instruction) {
96 if (LLVM_LIKELY(enabled))
97 capturedInstructions.push_back(instruction);
102 return capturedInstructions;
106 void clearCapturedInstructions() { capturedInstructions.clear(); }
109 class CollectionScope {
112 CollectionScope(llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing);
120 return inserter->getCapturedInstructions();
125 InstructionCapturingInserter *inserter =
nullptr;
135 void setEnabled(
bool enabled =
true) { this->enabled = enabled; }
142 bool enabled =
false;
145 using CapturingIRBuilder =
146 llvm::IRBuilder<llvm::ConstantFolder, InstructionCapturingInserter>;
149 InstructionCapturingInserter::CollectionScope::CollectionScope(
150 llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing) {
152 if (!isBuilderCapturing)
155 auto &capturingIRBuilder =
static_cast<CapturingIRBuilder &
>(irBuilder);
156 inserter = &capturingIRBuilder.getInserter();
157 wasEnabled = inserter->enabled;
159 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
160 inserter->setEnabled(
true);
163 InstructionCapturingInserter::CollectionScope::~CollectionScope() {
167 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
171 llvm::append_range(inserter->capturedInstructions,
172 previouslyCollectedInstructions);
174 inserter->setEnabled(wasEnabled);
179 static FailureOr<llvm::DataLayout>
182 std::optional<Location> loc = std::nullopt) {
187 std::string llvmDataLayout;
188 llvm::raw_string_ostream layoutStream(llvmDataLayout);
189 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
190 auto key = llvm::dyn_cast_if_present<StringAttr>(entry.getKey());
193 if (key.getValue() == DLTIDialect::kDataLayoutEndiannessKey) {
194 auto value = cast<StringAttr>(entry.getValue());
195 bool isLittleEndian =
196 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle;
197 layoutStream <<
"-" << (isLittleEndian ?
"e" :
"E");
200 if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
201 auto value = cast<IntegerAttr>(entry.getValue());
202 uint64_t space = value.getValue().getZExtValue();
206 layoutStream <<
"-P" << space;
209 if (key.getValue() == DLTIDialect::kDataLayoutGlobalMemorySpaceKey) {
210 auto value = cast<IntegerAttr>(entry.getValue());
211 uint64_t space = value.getValue().getZExtValue();
215 layoutStream <<
"-G" << space;
218 if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
219 auto value = cast<IntegerAttr>(entry.getValue());
220 uint64_t space = value.getValue().getZExtValue();
224 layoutStream <<
"-A" << space;
227 if (key.getValue() == DLTIDialect::kDataLayoutStackAlignmentKey) {
228 auto value = cast<IntegerAttr>(entry.getValue());
229 uint64_t alignment = value.getValue().getZExtValue();
233 layoutStream <<
"-S" << alignment;
236 emitError(*loc) <<
"unsupported data layout key " << key;
243 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
244 auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
248 if (isa<IndexType>(type))
251 LogicalResult result =
253 .Case<IntegerType, Float16Type, Float32Type, Float64Type,
254 Float80Type, Float128Type>([&](
Type type) -> LogicalResult {
255 if (
auto intType = dyn_cast<IntegerType>(type)) {
256 if (intType.getSignedness() != IntegerType::Signless)
258 <<
"unsupported data layout for non-signless integer "
268 layoutStream << size <<
":" << abi;
269 if (abi != preferred)
270 layoutStream <<
":" << preferred;
273 .Case([&](LLVMPointerType type) {
274 layoutStream <<
"p" << type.getAddressSpace() <<
":";
280 layoutStream << size <<
":" << abi <<
":" << preferred <<
":"
284 .Default([loc](
Type type) {
286 <<
"unsupported type in data layout: " << type;
291 StringRef layoutSpec(llvmDataLayout);
292 if (layoutSpec.starts_with(
"-"))
293 layoutSpec = layoutSpec.drop_front();
295 return llvm::DataLayout(layoutSpec);
302 static llvm::Constant *
307 llvm::Constant *result = constants.front();
308 constants = constants.drop_front();
312 llvm::Type *elementType;
313 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
314 elementType = arrayTy->getElementType();
315 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
316 elementType = vectorTy->getElementType();
318 emitError(loc) <<
"expected sequential LLVM types wrapping a scalar";
323 nested.reserve(shape.front());
324 for (int64_t i = 0; i < shape.front(); ++i) {
331 if (shape.size() == 1 && type->isVectorTy())
340 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
341 type = arrayTy->getElementType();
342 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
343 type = vectorTy->getElementType();
357 static llvm::Constant *
359 llvm::Type *llvmType,
361 if (!denseElementsAttr)
365 if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
368 ShapedType type = denseElementsAttr.
getType();
369 if (type.getNumElements() == 0)
377 int64_t elementByteSize = denseElementsAttr.
getRawData().size() /
379 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
384 bool hasVectorElementType = isa<VectorType>(type.getElementType());
385 int64_t numAggregates =
387 (hasVectorElementType ? 1
388 : denseElementsAttr.
getType().getShape().back());
390 if (!hasVectorElementType)
391 outerShape = outerShape.drop_back();
394 if (denseElementsAttr.
isSplat() &&
395 (isa<VectorType>(type) || hasVectorElementType)) {
399 llvm::Constant *splatVector =
400 llvm::ConstantDataVector::getSplat(0, splatValue);
405 if (denseElementsAttr.
isSplat())
410 std::function<llvm::Constant *(StringRef)> buildCstData;
411 if (isa<TensorType>(type)) {
412 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
413 if (vectorElementType && vectorElementType.getRank() == 1) {
414 buildCstData = [&](StringRef data) {
415 return llvm::ConstantDataVector::getRaw(
416 data, vectorElementType.getShape().back(), innermostLLVMType);
418 }
else if (!vectorElementType) {
419 buildCstData = [&](StringRef data) {
420 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
424 }
else if (isa<VectorType>(type)) {
425 buildCstData = [&](StringRef data) {
426 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
436 int64_t aggregateSize = denseElementsAttr.
getType().getShape().back() *
437 (innermostLLVMType->getScalarSizeInBits() / 8);
438 constants.reserve(numAggregates);
439 for (
unsigned i = 0; i < numAggregates; ++i) {
440 StringRef data(denseElementsAttr.
getRawData().data() + i * aggregateSize,
442 constants.push_back(buildCstData(data));
458 assert(denseResourceAttr &&
"expected non-null attribute");
461 if (!llvm::ConstantDataSequential::isElementTypeCompatible(
462 innermostLLVMType)) {
463 emitError(loc,
"no known conversion for innermost element type");
467 ShapedType type = denseResourceAttr.getType();
468 assert(type.getNumElements() > 0 &&
"Expected non-empty elements attribute");
472 emitError(loc,
"resource does not exist");
483 int64_t numElements = denseResourceAttr.getType().getNumElements();
484 int64_t elementByteSize = rawData.size() / numElements;
485 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
486 emitError(loc,
"raw data size does not match element type size");
492 bool hasVectorElementType = isa<VectorType>(type.getElementType());
493 int64_t numAggregates =
494 numElements / (hasVectorElementType
496 : denseResourceAttr.getType().getShape().back());
498 if (!hasVectorElementType)
499 outerShape = outerShape.drop_back();
502 std::function<llvm::Constant *(StringRef)> buildCstData;
503 if (isa<TensorType>(type)) {
504 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
505 if (vectorElementType && vectorElementType.getRank() == 1) {
506 buildCstData = [&](StringRef data) {
507 return llvm::ConstantDataVector::getRaw(
508 data, vectorElementType.getShape().back(), innermostLLVMType);
510 }
else if (!vectorElementType) {
511 buildCstData = [&](StringRef data) {
512 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
516 }
else if (isa<VectorType>(type)) {
517 buildCstData = [&](StringRef data) {
518 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
523 emitError(loc,
"unsupported dense_resource type");
530 int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
531 (innermostLLVMType->getScalarSizeInBits() / 8);
532 constants.reserve(numAggregates);
533 for (
unsigned i = 0; i < numAggregates; ++i) {
534 StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
535 constants.push_back(buildCstData(data));
552 if (
auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
553 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
555 emitError(loc,
"expected an array attribute for a struct constant");
559 structElements.reserve(structType->getNumElements());
560 for (
auto [elemType, elemAttr] :
561 zip_equal(structType->elements(), arrayAttr)) {
562 llvm::Constant *element =
566 structElements.push_back(element);
572 if (
auto intAttr = dyn_cast<IntegerAttr>(attr))
575 intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
576 if (
auto floatAttr = dyn_cast<FloatAttr>(attr)) {
577 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
582 unsigned floatWidth = APFloat::getSizeInBits(sem);
583 if (llvmType->isIntegerTy(floatWidth))
585 floatAttr.getValue().bitcastToAPInt());
587 llvm::Type::getFloatingPointTy(llvmType->getContext(),
588 floatAttr.getValue().getSemantics())) {
589 emitError(loc,
"FloatAttr does not match expected type of the constant");
594 if (
auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
595 return llvm::ConstantExpr::getBitCast(
597 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
598 llvm::Type *elementType;
599 uint64_t numElements;
600 bool isScalable =
false;
601 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
602 elementType = arrayTy->getElementType();
603 numElements = arrayTy->getNumElements();
604 }
else if (
auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
605 elementType = fVectorTy->getElementType();
606 numElements = fVectorTy->getNumElements();
607 }
else if (
auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
608 elementType = sVectorTy->getElementType();
609 numElements = sVectorTy->getMinNumElements();
612 llvm_unreachable(
"unrecognized constant vector type");
617 bool elementTypeSequential =
618 isa<llvm::ArrayType, llvm::VectorType>(elementType);
621 elementTypeSequential ? splatAttr
623 loc, moduleTranslation);
626 if (llvmType->isVectorTy())
627 return llvm::ConstantVector::getSplat(
629 if (llvmType->isArrayTy()) {
631 if (child->isZeroValue()) {
634 if (llvm::ConstantDataSequential::isElementTypeCompatible(
637 if (isa<llvm::IntegerType>(elementType)) {
638 if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
639 if (ci->getBitWidth() == 8) {
644 if (ci->getBitWidth() == 16) {
649 if (ci->getBitWidth() == 32) {
654 if (ci->getBitWidth() == 64) {
664 std::vector<llvm::Constant *> constants(numElements, child);
671 if (llvm::Constant *result =
673 llvmType, moduleTranslation)) {
677 if (
auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
683 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
684 assert(elementsAttr.getShapedType().hasStaticShape());
685 assert(!elementsAttr.getShapedType().getShape().empty() &&
686 "unexpected empty elements attribute shape");
689 constants.reserve(elementsAttr.getNumElements());
691 for (
auto n : elementsAttr.getValues<
Attribute>()) {
694 if (!constants.back())
699 constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
700 assert(constantsRef.empty() &&
"did not consume all elemental constants");
704 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
708 stringAttr.getValue().size()});
710 emitError(loc,
"unsupported constant value");
714 ModuleTranslation::ModuleTranslation(
Operation *module,
715 std::unique_ptr<llvm::Module> llvmModule)
716 : mlirModule(module), llvmModule(std::move(llvmModule)),
720 *this, *this->llvmModule)),
721 typeTranslator(this->llvmModule->
getContext()),
724 "mlirModule should honor LLVM's module semantics.");
727 ModuleTranslation::~ModuleTranslation() {
729 ompBuilder->finalize();
734 toProcess.push_back(®ion);
735 while (!toProcess.empty()) {
736 Region *current = toProcess.pop_back_val();
737 for (
Block &block : *current) {
738 blockMapping.erase(&block);
739 for (
Value arg : block.getArguments())
740 valueMapping.erase(arg);
743 valueMapping.erase(value);
745 branchMapping.erase(&op);
746 if (isa<LLVM::GlobalOp>(op))
747 globalsMapping.erase(&op);
748 if (isa<LLVM::CallOp>(op))
749 callMapping.erase(&op);
761 unsigned numArguments,
unsigned index) {
763 if (isa<LLVM::BrOp>(terminator))
770 auto branch = cast<BranchOpInterface>(terminator);
773 (!seenSuccessors.contains(successor) || successorOperands.
empty()) &&
774 "successors with arguments in LLVM branches must be different blocks");
775 seenSuccessors.insert(successor);
781 if (
auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
784 return condBranchOp.getSuccessor(0) == current
785 ? condBranchOp.getTrueDestOperands()[index]
786 : condBranchOp.getFalseDestOperands()[index];
789 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
792 if (switchOp.getDefaultDestination() == current)
793 return switchOp.getDefaultOperands()[index];
795 if (i.value() == current)
796 return switchOp.getCaseOperands(i.index())[index];
799 if (
auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
800 return invokeOp.getNormalDest() == current
801 ? invokeOp.getNormalDestOperands()[index]
802 : invokeOp.getUnwindDestOperands()[index];
806 "only branch, switch or invoke operations can be terminators "
807 "of a block that has successors");
815 for (
Block &bb : llvm::drop_begin(region)) {
816 llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
817 auto phis = llvmBB->phis();
818 auto numArguments = bb.getNumArguments();
819 assert(numArguments == std::distance(phis.begin(), phis.end()));
821 for (
auto *pred : bb.getPredecessors()) {
827 llvm::Instruction *terminator =
828 state.lookupBranch(pred->getTerminator());
829 assert(terminator &&
"missing the mapping for a terminator");
831 &bb, pred, numArguments, index)),
832 terminator->getParent());
841 llvm::Module *module = builder.GetInsertBlock()->getModule();
843 llvm::Intrinsic::getOrInsertDeclaration(module, intrinsic, tys);
844 return builder.CreateCall(fn, args);
853 assert(immArgPositions.size() == immArgAttrNames.size() &&
854 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
860 for (
auto [immArgPos, immArgName] :
861 llvm::zip(immArgPositions, immArgAttrNames)) {
862 auto attr = llvm::cast<TypedAttr>(intrOp->
getAttr(immArgName));
863 assert(attr.getType().isIntOrFloat() &&
"expected int or float immarg");
864 auto *type = moduleTranslation.
convertType(attr.getType());
866 type, attr, intrOp->
getLoc(), moduleTranslation);
869 for (
auto &arg : args) {
871 arg = operands[opArg++];
876 for (
unsigned overloadedResultIdx : overloadedResults) {
877 if (numResults > 1) {
879 overloadedTypes.push_back(moduleTranslation.
convertType(
881 .getBody()[overloadedResultIdx]));
883 overloadedTypes.push_back(
887 for (
unsigned overloadedOperandIdx : overloadedOperands)
888 overloadedTypes.push_back(args[overloadedOperandIdx]->
getType());
889 llvm::Module *module = builder.GetInsertBlock()->getModule();
890 llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
891 module, intrinsic, overloadedTypes);
893 return builder.CreateCall(llvmIntr, args);
898 LogicalResult ModuleTranslation::convertOperation(
Operation &op,
899 llvm::IRBuilderBase &builder,
900 bool recordInsertions) {
903 return op.
emitError(
"cannot be converted to LLVM IR: missing "
904 "`LLVMTranslationDialectInterface` registration for "
908 InstructionCapturingInserter::CollectionScope scope(builder,
911 return op.
emitError(
"LLVM Translation failed for operation: ")
914 return convertDialectAttributes(&op, scope.getCapturedInstructions());
924 LogicalResult ModuleTranslation::convertBlockImpl(
Block &bb,
925 bool ignoreArguments,
926 llvm::IRBuilderBase &builder,
927 bool recordInsertions) {
929 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
937 if (!ignoreArguments) {
939 unsigned numPredecessors =
940 std::distance(predecessors.begin(), predecessors.end());
942 auto wrappedType = arg.getType();
945 "block argument does not have an LLVM type");
946 builder.SetCurrentDebugLocation(
947 debugTranslation->translateLoc(arg.getLoc(), subprogram));
949 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
955 for (
auto &op : bb) {
957 builder.SetCurrentDebugLocation(
958 debugTranslation->translateLoc(op.
getLoc(), subprogram));
960 if (failed(convertOperation(op, builder, recordInsertions)))
964 if (
auto iface = dyn_cast<BranchWeightOpInterface>(op))
983 llvm::Constant *cst) {
984 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
985 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
991 llvm::GlobalValue *gv) {
992 if (dsoLocalRequested)
993 gv->setDSOLocal(
true);
998 LogicalResult ModuleTranslation::convertGlobals() {
1002 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1004 llvm::Constant *cst =
nullptr;
1005 if (op.getValueOrNull()) {
1008 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1009 cst = llvm::ConstantDataArray::getString(
1010 llvmModule->getContext(), strAttr.getValue(),
false);
1011 type = cst->getType();
1018 auto linkage = convertLinkageToLLVM(op.getLinkage());
1024 if (!dropInitializer && !cst)
1026 else if (dropInitializer && cst)
1029 auto *var =
new llvm::GlobalVariable(
1030 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1032 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1033 : llvm::GlobalValue::NotThreadLocal,
1034 op.getAddrSpace(), op.getExternallyInitialized());
1036 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1037 auto selectorOp = cast<ComdatSelectorOp>(
1039 var->setComdat(comdatMapping.lookup(selectorOp));
1042 if (op.getUnnamedAddr().has_value())
1043 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1045 if (op.getSection().has_value())
1046 var->setSection(*op.getSection());
1050 std::optional<uint64_t> alignment = op.getAlignment();
1051 if (alignment.has_value())
1052 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1054 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1056 globalsMapping.try_emplace(op, var);
1059 if (op.getDbgExpr()) {
1060 llvm::DIGlobalVariableExpression *diGlobalExpr =
1061 debugTranslation->translateGlobalVariableExpression(op.getDbgExpr());
1062 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1063 var->addDebugInfo(diGlobalExpr);
1082 llvm::DIScope *scope = diGlobalVar->getScope();
1083 if (
auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1084 scope = mod->getScope();
1085 else if (
auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1086 if (
auto *sp = dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1087 scope = sp->getUnit();
1088 }
else if (
auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1089 scope = sp->getUnit();
1092 if (llvm::DICompileUnit *compileUnit =
1093 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1096 allGVars[compileUnit].push_back(diGlobalExpr);
1104 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1105 if (
Block *initializer = op.getInitializerBlock()) {
1106 llvm::IRBuilder<> builder(llvmModule->getContext());
1108 [[maybe_unused]]
int numConstantsHit = 0;
1109 [[maybe_unused]]
int numConstantsErased = 0;
1112 for (
auto &op : initializer->without_terminator()) {
1113 if (failed(convertOperation(op, builder)))
1126 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1130 auto [iterator, inserted] =
1131 constantAggregateUseMap.try_emplace(agg, numUsers);
1134 iterator->second += numUsers;
1140 auto cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1143 auto iter = constantAggregateUseMap.find(cst);
1144 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1146 if (iter->second == 0) {
1149 if (cst->user_empty()) {
1150 cst->destroyConstant();
1151 numConstantsErased++;
1153 constantAggregateUseMap.erase(iter);
1158 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1159 llvm::Constant *cst =
1160 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1161 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1163 global->setInitializer(cst);
1167 for (
auto it : constantAggregateUseMap) {
1168 auto cst = it.first;
1169 cst->removeDeadConstantUsers();
1170 if (cst->user_empty()) {
1171 cst->destroyConstant();
1172 numConstantsErased++;
1176 LLVM_DEBUG(llvm::dbgs()
1177 <<
"Convert initializer for " << op.
getName() <<
"\n";
1178 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1180 << numConstantsErased <<
" dangling constants erased\n";);
1186 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1187 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1188 if (!ctorOp && !dtorOp)
1190 auto range = ctorOp ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1191 :
llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1192 auto appendGlobalFn =
1193 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1194 for (
auto symbolAndPriority : range) {
1196 cast<FlatSymbolRefAttr>(std::get<0>(symbolAndPriority)).getValue());
1197 appendGlobalFn(*llvmModule, f,
1198 cast<IntegerAttr>(std::get<1>(symbolAndPriority)).getInt(),
1203 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1204 if (failed(convertDialectAttributes(op, {})))
1209 for (
const auto &[compileUnit, globals] : allGVars) {
1210 compileUnit->replaceGlobalVariables(
1224 llvm::Function *llvmFunc,
1226 StringRef value = StringRef()) {
1227 auto kind = llvm::Attribute::getAttrKindFromName(key);
1229 llvmFunc->addFnAttr(key, value);
1233 if (llvm::Attribute::isIntAttrKind(kind)) {
1235 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1238 if (!value.getAsInteger(0, result))
1239 llvmFunc->addFnAttr(
1242 llvmFunc->addFnAttr(key, value);
1247 return emitError(loc) <<
"LLVM attribute '" << key
1248 <<
"' does not expect a value, found '" << value
1251 llvmFunc->addFnAttr(kind);
1257 const llvm::APInt &value) {
1264 const llvm::APInt &value) {
1272 llvm::Metadata *typeMD =
1274 llvm::Metadata *isSignedMD =
1284 values, std::back_inserter(mdValues), [&context](int32_t value) {
1297 static LogicalResult
1299 llvm::Function *llvmFunc) {
1304 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1311 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1312 if (!arrayAttr || arrayAttr.size() != 2)
1314 <<
"expected 'passthrough' to contain string or array attributes";
1316 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1317 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1318 if (!keyAttr || !valueAttr)
1320 <<
"expected arrays within 'passthrough' to contain two strings";
1323 valueAttr.getValue())))
1329 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1332 blockMapping.clear();
1333 valueMapping.clear();
1334 branchMapping.clear();
1338 for (
auto [mlirArg, llvmArg] :
1339 llvm::zip(func.getArguments(), llvmFunc->args()))
1343 if (func.getPersonality()) {
1344 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1345 if (llvm::Constant *pfunc =
getLLVMConstant(ty, func.getPersonalityAttr(),
1346 func.getLoc(), *
this))
1347 llvmFunc->setPersonalityFn(pfunc);
1350 if (std::optional<StringRef> section = func.getSection())
1351 llvmFunc->setSection(*section);
1353 if (func.getArmStreaming())
1354 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1355 else if (func.getArmLocallyStreaming())
1356 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1357 else if (func.getArmStreamingCompatible())
1358 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1360 if (func.getArmNewZa())
1361 llvmFunc->addFnAttr(
"aarch64_new_za");
1362 else if (func.getArmInZa())
1363 llvmFunc->addFnAttr(
"aarch64_in_za");
1364 else if (func.getArmOutZa())
1365 llvmFunc->addFnAttr(
"aarch64_out_za");
1366 else if (func.getArmInoutZa())
1367 llvmFunc->addFnAttr(
"aarch64_inout_za");
1368 else if (func.getArmPreservesZa())
1369 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1371 if (
auto targetCpu = func.getTargetCpu())
1372 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1374 if (
auto tuneCpu = func.getTuneCpu())
1375 llvmFunc->addFnAttr(
"tune-cpu", *tuneCpu);
1377 if (
auto targetFeatures = func.getTargetFeatures())
1378 llvmFunc->addFnAttr(
"target-features", targetFeatures->getFeaturesString());
1380 if (
auto attr = func.getVscaleRange())
1381 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1383 attr->getMaxRange().getInt()));
1385 if (
auto unsafeFpMath = func.getUnsafeFpMath())
1386 llvmFunc->addFnAttr(
"unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1388 if (
auto noInfsFpMath = func.getNoInfsFpMath())
1389 llvmFunc->addFnAttr(
"no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1391 if (
auto noNansFpMath = func.getNoNansFpMath())
1392 llvmFunc->addFnAttr(
"no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1394 if (
auto approxFuncFpMath = func.getApproxFuncFpMath())
1395 llvmFunc->addFnAttr(
"approx-func-fp-math",
1396 llvm::toStringRef(*approxFuncFpMath));
1398 if (
auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1399 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1400 llvm::toStringRef(*noSignedZerosFpMath));
1402 if (
auto denormalFpMath = func.getDenormalFpMath())
1403 llvmFunc->addFnAttr(
"denormal-fp-math", *denormalFpMath);
1405 if (
auto denormalFpMathF32 = func.getDenormalFpMathF32())
1406 llvmFunc->addFnAttr(
"denormal-fp-math-f32", *denormalFpMathF32);
1408 if (
auto fpContract = func.getFpContract())
1409 llvmFunc->addFnAttr(
"fp-contract", *fpContract);
1412 if (FramePointerKindAttr attr = func.getFramePointerAttr())
1413 llvmFunc->addFnAttr(
"frame-pointer",
1414 LLVM::framePointerKind::stringifyFramePointerKind(
1415 (attr.getFramePointerKind())));
1418 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1419 for (
auto &bb : func) {
1420 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1421 llvmBB->insertInto(llvmFunc);
1428 for (
Block *bb : blocks) {
1429 CapturingIRBuilder builder(llvmContext);
1430 if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1440 return convertDialectAttributes(func, {});
1443 LogicalResult ModuleTranslation::convertDialectAttributes(
1446 if (failed(iface.
amendOperation(op, instructions, attribute, *
this)))
1454 llvm::Function *llvmFunc) {
1455 if (!func.getMemoryEffects())
1458 MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1461 llvm::MemoryEffects newMemEffects =
1462 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1463 convertModRefInfoToLLVM(memEffects.getArgMem()));
1464 newMemEffects |= llvm::MemoryEffects(
1465 llvm::MemoryEffects::Location::InaccessibleMem,
1466 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1468 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1469 convertModRefInfoToLLVM(memEffects.getOther()));
1470 llvmFunc->setMemoryEffects(newMemEffects);
1475 llvm::Function *llvmFunc) {
1476 if (func.getNoInlineAttr())
1477 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1478 if (func.getAlwaysInlineAttr())
1479 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1480 if (func.getOptimizeNoneAttr())
1481 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1482 if (func.getConvergentAttr())
1483 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1484 if (func.getNoUnwindAttr())
1485 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1486 if (func.getWillReturnAttr())
1487 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1493 llvm::Function *llvmFunc,
1495 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1497 if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1498 Type type = vecTypeHint.getHint().getValue();
1499 llvm::Type *llvmType = translation.
convertType(type);
1500 bool isSigned = vecTypeHint.getIsSigned();
1501 llvmFunc->setMetadata(
1502 func.getVecTypeHintAttrName(),
1507 func.getWorkGroupSizeHint()) {
1508 llvmFunc->setMetadata(
1509 func.getWorkGroupSizeHintAttrName(),
1514 func.getReqdWorkGroupSize()) {
1515 llvmFunc->setMetadata(
1516 func.getReqdWorkGroupSizeAttrName(),
1520 if (std::optional<uint32_t> intelReqdSubGroupSize =
1521 func.getIntelReqdSubGroupSize()) {
1522 llvmFunc->setMetadata(
1523 func.getIntelReqdSubGroupSizeAttrName(),
1525 llvm::APInt(32, *intelReqdSubGroupSize)));
1529 FailureOr<llvm::AttrBuilder>
1530 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func,
int argIdx,
1531 DictionaryAttr paramAttrs) {
1532 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1535 for (
auto namedAttr : paramAttrs) {
1536 auto it = attrNameToKindMapping.find(namedAttr.getName());
1537 if (it != attrNameToKindMapping.end()) {
1538 llvm::Attribute::AttrKind llvmKind = it->second;
1541 .Case<TypeAttr>([&](
auto typeAttr) {
1542 attrBuilder.addTypeAttr(llvmKind,
convertType(typeAttr.getValue()));
1544 .Case<IntegerAttr>([&](
auto intAttr) {
1545 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1547 .Case<UnitAttr>([&](
auto) { attrBuilder.addAttribute(llvmKind); });
1548 }
else if (namedAttr.getNameDialect()) {
1557 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1560 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1561 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1563 cast<llvm::FunctionType>(
convertType(
function.getFunctionType())));
1564 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1565 llvmFunc->setLinkage(convertLinkageToLLVM(
function.getLinkage()));
1566 llvmFunc->setCallingConv(convertCConvToLLVM(
function.getCConv()));
1577 if (std::optional<uint64_t> entryCount =
function.getFunctionEntryCount())
1578 llvmFunc->setEntryCount(entryCount.value());
1581 if (ArrayAttr allResultAttrs =
function.getAllResultAttrs()) {
1582 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1583 FailureOr<llvm::AttrBuilder> attrBuilder =
1584 convertParameterAttrs(
function, -1, resultAttrs);
1585 if (failed(attrBuilder))
1587 llvmFunc->addRetAttrs(*attrBuilder);
1593 FailureOr<llvm::AttrBuilder> attrBuilder =
1594 convertParameterAttrs(
function, argIdx, argAttrs);
1595 if (failed(attrBuilder))
1597 llvmArg.addAttrs(*attrBuilder);
1603 function.getLoc(),
function.getPassthrough(), llvmFunc)))
1607 llvmFunc->setVisibility(convertVisibilityToLLVM(
function.getVisibility_()));
1610 if (std::optional<mlir::SymbolRefAttr> comdat =
function.getComdat()) {
1611 auto selectorOp = cast<ComdatSelectorOp>(
1613 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1616 if (
auto gc =
function.getGarbageCollector())
1617 llvmFunc->setGC(gc->str());
1619 if (
auto unnamedAddr =
function.getUnnamedAddr())
1620 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1622 if (
auto alignment =
function.getAlignment())
1623 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1626 debugTranslation->translate(
function, *llvmFunc);
1632 LogicalResult ModuleTranslation::convertFunctions() {
1634 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1637 if (
function.isExternal()) {
1638 if (failed(convertDialectAttributes(
function, {})))
1643 if (failed(convertOneFunction(
function)))
1650 LogicalResult ModuleTranslation::convertComdats() {
1651 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
1652 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1654 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1656 <<
"comdat selection symbols must be unique even in different "
1658 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1659 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1660 comdatMapping.try_emplace(selectorOp, comdat);
1667 llvm::Instruction *inst) {
1668 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1669 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1674 auto [scopeIt, scopeInserted] =
1675 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
1677 return scopeIt->second;
1678 llvm::LLVMContext &ctx = llvmModule->getContext();
1679 auto dummy = llvm::MDNode::getTemporary(ctx, std::nullopt);
1681 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1682 aliasScopeAttr.getDomain(),
nullptr);
1683 if (insertedDomain) {
1686 operands.push_back(dummy.get());
1687 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
1691 domainIt->second->replaceOperandWith(0, domainIt->second);
1694 assert(domainIt->second &&
"Scope's domain should already be valid");
1697 operands.push_back(dummy.get());
1698 operands.push_back(domainIt->second);
1699 if (StringAttr description = aliasScopeAttr.getDescription())
1703 scopeIt->second->replaceOperandWith(0, scopeIt->second);
1704 return scopeIt->second;
1710 nodes.reserve(aliasScopeAttrs.size());
1711 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
1717 llvm::Instruction *inst) {
1718 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
1719 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
1722 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
1723 inst->setMetadata(kind, node);
1726 populateScopeMetadata(op.getAliasScopesOrNull(),
1727 llvm::LLVMContext::MD_alias_scope);
1728 populateScopeMetadata(op.getNoAliasScopesOrNull(),
1729 llvm::LLVMContext::MD_noalias);
1732 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
1733 return tbaaMetadataMapping.lookup(tbaaAttr);
1737 llvm::Instruction *inst) {
1738 ArrayAttr tagRefs = op.getTBAATagsOrNull();
1739 if (!tagRefs || tagRefs.empty())
1746 if (tagRefs.size() > 1) {
1747 op.
emitWarning() <<
"TBAA access tags were not translated, because LLVM "
1748 "IR only supports a single tag per instruction";
1752 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
1753 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
1762 assert(inst &&
"expected the operation to have a mapping to an instruction");
1765 llvm::LLVMContext::MD_prof,
1769 LogicalResult ModuleTranslation::createTBAAMetadata() {
1770 llvm::LLVMContext &ctx = llvmModule->getContext();
1782 walker.
addWalk([&](TBAARootAttr root) {
1783 tbaaMetadataMapping.insert(
1787 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
1790 for (TBAAMemberAttr member : descriptor.getMembers()) {
1791 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
1799 walker.
addWalk([&](TBAATagAttr tag) {
1802 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
1803 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
1807 if (tag.getConstant())
1814 mlirModule->
walk([&](AliasAnalysisOpInterface analysisOpInterface) {
1815 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
1822 LogicalResult ModuleTranslation::createIdentMetadata() {
1824 LLVMDialect::getIdentAttrName())) {
1825 StringRef ident = attr;
1826 llvm::LLVMContext &ctx = llvmModule->getContext();
1827 llvm::NamedMDNode *namedMd =
1828 llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
1830 namedMd->addOperand(md);
1837 llvm::Instruction *inst) {
1838 LoopAnnotationAttr attr =
1840 .Case<LLVM::BrOp, LLVM::CondBrOp>(
1841 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
1844 llvm::MDNode *loopMD =
1845 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
1846 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
1856 remapped.reserve(values.size());
1857 for (
Value v : values)
1864 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
1865 ompBuilder->initialize();
1870 ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
1878 return ompBuilder.get();
1882 llvm::DILocalScope *scope) {
1883 return debugTranslation->translateLoc(loc, scope);
1886 llvm::DIExpression *
1888 return debugTranslation->translateExpression(attr);
1891 llvm::DIGlobalVariableExpression *
1893 LLVM::DIGlobalVariableExpressionAttr attr) {
1894 return debugTranslation->translateGlobalVariableExpression(attr);
1898 return debugTranslation->translate(attr);
1903 return convertRoundingModeToLLVM(rounding);
1907 LLVM::FPExceptionBehavior exceptionBehavior) {
1908 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
1913 return llvmModule->getOrInsertNamedMetadata(name);
1916 void ModuleTranslation::StackFrame::anchor() {}
1918 static std::unique_ptr<llvm::Module>
1921 m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
1922 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
1925 llvmModule->setNewDbgInfoFormatFlag(
false);
1926 if (
auto dataLayoutAttr =
1927 m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
1928 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
1930 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(
""));
1931 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
1932 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
1936 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
1937 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
1942 if (failed(llvmDataLayout))
1944 llvmModule->setDataLayout(*llvmDataLayout);
1946 if (
auto targetTripleAttr =
1947 m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
1948 llvmModule->setTargetTriple(cast<StringAttr>(targetTripleAttr).getValue());
1953 std::unique_ptr<llvm::Module>
1955 StringRef name,
bool disableVerification) {
1957 module->
emitOpError(
"can not be translated to an LLVMIR module");
1961 std::unique_ptr<llvm::Module> llvmModule =
1970 llvm::IRBuilder<> llvmBuilder(llvmContext);
1976 if (failed(translator.convertOperation(*module, llvmBuilder)))
1979 if (failed(translator.convertComdats()))
1981 if (failed(translator.convertFunctionSignatures()))
1983 if (failed(translator.convertGlobals()))
1985 if (failed(translator.createTBAAMetadata()))
1987 if (failed(translator.createIdentMetadata()))
1992 if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp, LLVM::GlobalCtorsOp,
1993 LLVM::GlobalDtorsOp, LLVM::ComdatOp>(&o) &&
1995 failed(translator.convertOperation(o, llvmBuilder))) {
2003 if (failed(translator.convertFunctions()))
2011 if (!disableVerification &&
2012 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2015 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.
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()
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Location getLoc()
The source location the operation was defined or derived from.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
OperationName getName()
The name of an operation is the key identifier for it.
dialect_attr_range getDialectAttrs()
Return a range corresponding to the dialect attributes for this operation.
operand_range getOperands()
Returns an iterator on the underlying Value's.
result_range getResults()
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class models how operands are forwarded to block arguments in control flow.
bool empty() const
Returns true if there are no successor operands.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
use_iterator use_end() const
Type getType() const
Return the type of this value.
use_iterator use_begin() const
ArrayRef< T > asArrayRef() const
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...