37 #include "llvm/ADT/PostOrderIterator.h"
38 #include "llvm/ADT/STLExtras.h"
39 #include "llvm/ADT/SetVector.h"
40 #include "llvm/ADT/StringExtras.h"
41 #include "llvm/ADT/TypeSwitch.h"
42 #include "llvm/Analysis/TargetFolder.h"
43 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
44 #include "llvm/IR/BasicBlock.h"
45 #include "llvm/IR/CFG.h"
46 #include "llvm/IR/Constants.h"
47 #include "llvm/IR/DerivedTypes.h"
48 #include "llvm/IR/IRBuilder.h"
49 #include "llvm/IR/InlineAsm.h"
50 #include "llvm/IR/IntrinsicsNVPTX.h"
51 #include "llvm/IR/LLVMContext.h"
52 #include "llvm/IR/MDBuilder.h"
53 #include "llvm/IR/Module.h"
54 #include "llvm/IR/Verifier.h"
55 #include "llvm/Support/Debug.h"
56 #include "llvm/Support/ErrorHandling.h"
57 #include "llvm/Support/raw_ostream.h"
58 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
59 #include "llvm/Transforms/Utils/Cloning.h"
60 #include "llvm/Transforms/Utils/ModuleUtils.h"
64 #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 if (key.getValue() == DLTIDialect::kDataLayoutFunctionPointerAlignmentKey) {
244 auto value = cast<FunctionPointerAlignmentAttr>(entry.getValue());
245 uint64_t alignment = value.getAlignment();
249 layoutStream <<
"-F" << (value.getFunctionDependent() ?
"n" :
"i")
253 if (key.getValue() == DLTIDialect::kDataLayoutLegalIntWidthsKey) {
254 layoutStream <<
"-n";
256 cast<DenseI32ArrayAttr>(entry.getValue()).asArrayRef(), layoutStream,
257 [&](int32_t val) { layoutStream << val; },
":");
260 emitError(*loc) <<
"unsupported data layout key " << key;
267 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
268 auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
272 if (isa<IndexType>(type))
275 LogicalResult result =
277 .Case<IntegerType, Float16Type, Float32Type, Float64Type,
278 Float80Type, Float128Type>([&](
Type type) -> LogicalResult {
279 if (
auto intType = dyn_cast<IntegerType>(type)) {
280 if (intType.getSignedness() != IntegerType::Signless)
282 <<
"unsupported data layout for non-signless integer "
292 layoutStream << size <<
":" << abi;
293 if (abi != preferred)
294 layoutStream <<
":" << preferred;
297 .Case([&](LLVMPointerType type) {
298 layoutStream <<
"p" << type.getAddressSpace() <<
":";
304 layoutStream << size <<
":" << abi <<
":" << preferred <<
":"
308 .Default([loc](
Type type) {
310 <<
"unsupported type in data layout: " << type;
315 StringRef layoutSpec(llvmDataLayout);
316 layoutSpec.consume_front(
"-");
318 return llvm::DataLayout(layoutSpec);
325 static llvm::Constant *
330 llvm::Constant *result = constants.front();
331 constants = constants.drop_front();
335 llvm::Type *elementType;
336 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
337 elementType = arrayTy->getElementType();
338 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
339 elementType = vectorTy->getElementType();
341 emitError(loc) <<
"expected sequential LLVM types wrapping a scalar";
346 nested.reserve(shape.front());
347 for (int64_t i = 0; i < shape.front(); ++i) {
354 if (shape.size() == 1 && type->isVectorTy())
363 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
364 type = arrayTy->getElementType();
365 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
366 type = vectorTy->getElementType();
380 static llvm::Constant *
382 llvm::Type *llvmType,
384 if (!denseElementsAttr)
388 if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
391 ShapedType type = denseElementsAttr.
getType();
392 if (type.getNumElements() == 0)
400 int64_t elementByteSize = denseElementsAttr.
getRawData().size() /
402 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
407 bool hasVectorElementType = isa<VectorType>(type.getElementType());
408 int64_t numAggregates =
410 (hasVectorElementType ? 1
411 : denseElementsAttr.
getType().getShape().back());
413 if (!hasVectorElementType)
414 outerShape = outerShape.drop_back();
417 if (denseElementsAttr.
isSplat() &&
418 (isa<VectorType>(type) || hasVectorElementType)) {
422 llvm::Constant *splatVector =
423 llvm::ConstantDataVector::getSplat(0, splatValue);
428 if (denseElementsAttr.
isSplat())
433 std::function<llvm::Constant *(StringRef)> buildCstData;
434 if (isa<TensorType>(type)) {
435 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
436 if (vectorElementType && vectorElementType.getRank() == 1) {
437 buildCstData = [&](StringRef data) {
438 return llvm::ConstantDataVector::getRaw(
439 data, vectorElementType.getShape().back(), innermostLLVMType);
441 }
else if (!vectorElementType) {
442 buildCstData = [&](StringRef data) {
443 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
447 }
else if (isa<VectorType>(type)) {
448 buildCstData = [&](StringRef data) {
449 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
459 int64_t aggregateSize = denseElementsAttr.
getType().getShape().back() *
460 (innermostLLVMType->getScalarSizeInBits() / 8);
461 constants.reserve(numAggregates);
462 for (
unsigned i = 0; i < numAggregates; ++i) {
463 StringRef data(denseElementsAttr.
getRawData().data() + i * aggregateSize,
465 constants.push_back(buildCstData(data));
481 assert(denseResourceAttr &&
"expected non-null attribute");
484 if (!llvm::ConstantDataSequential::isElementTypeCompatible(
485 innermostLLVMType)) {
486 emitError(loc,
"no known conversion for innermost element type");
490 ShapedType type = denseResourceAttr.getType();
491 assert(type.getNumElements() > 0 &&
"Expected non-empty elements attribute");
495 emitError(loc,
"resource does not exist");
506 int64_t numElements = denseResourceAttr.getType().getNumElements();
507 int64_t elementByteSize = rawData.size() / numElements;
508 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
509 emitError(loc,
"raw data size does not match element type size");
515 bool hasVectorElementType = isa<VectorType>(type.getElementType());
516 int64_t numAggregates =
517 numElements / (hasVectorElementType
519 : denseResourceAttr.getType().getShape().back());
521 if (!hasVectorElementType)
522 outerShape = outerShape.drop_back();
525 std::function<llvm::Constant *(StringRef)> buildCstData;
526 if (isa<TensorType>(type)) {
527 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
528 if (vectorElementType && vectorElementType.getRank() == 1) {
529 buildCstData = [&](StringRef data) {
530 return llvm::ConstantDataVector::getRaw(
531 data, vectorElementType.getShape().back(), innermostLLVMType);
533 }
else if (!vectorElementType) {
534 buildCstData = [&](StringRef data) {
535 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
539 }
else if (isa<VectorType>(type)) {
540 buildCstData = [&](StringRef data) {
541 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
546 emitError(loc,
"unsupported dense_resource type");
553 int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
554 (innermostLLVMType->getScalarSizeInBits() / 8);
555 constants.reserve(numAggregates);
556 for (
unsigned i = 0; i < numAggregates; ++i) {
557 StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
558 constants.push_back(buildCstData(data));
573 if (!attr || isa<UndefAttr>(attr))
575 if (isa<ZeroAttr>(attr))
576 return llvm::Constant::getNullValue(llvmType);
577 if (
auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
578 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
580 emitError(loc,
"expected an array attribute for a struct constant");
584 structElements.reserve(structType->getNumElements());
585 for (
auto [elemType, elemAttr] :
586 zip_equal(structType->elements(), arrayAttr)) {
587 llvm::Constant *element =
591 structElements.push_back(element);
597 if (
auto intAttr = dyn_cast<IntegerAttr>(attr))
600 intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
601 if (
auto floatAttr = dyn_cast<FloatAttr>(attr)) {
602 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
607 unsigned floatWidth = APFloat::getSizeInBits(sem);
608 if (llvmType->isIntegerTy(floatWidth))
610 floatAttr.getValue().bitcastToAPInt());
612 llvm::Type::getFloatingPointTy(llvmType->getContext(),
613 floatAttr.getValue().getSemantics())) {
614 emitError(loc,
"FloatAttr does not match expected type of the constant");
619 if (
auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
620 return llvm::ConstantExpr::getBitCast(
622 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
623 llvm::Type *elementType;
624 uint64_t numElements;
625 bool isScalable =
false;
626 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
627 elementType = arrayTy->getElementType();
628 numElements = arrayTy->getNumElements();
629 }
else if (
auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
630 elementType = fVectorTy->getElementType();
631 numElements = fVectorTy->getNumElements();
632 }
else if (
auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
633 elementType = sVectorTy->getElementType();
634 numElements = sVectorTy->getMinNumElements();
637 llvm_unreachable(
"unrecognized constant vector type");
642 bool elementTypeSequential =
643 isa<llvm::ArrayType, llvm::VectorType>(elementType);
646 elementTypeSequential ? splatAttr
648 loc, moduleTranslation);
651 if (llvmType->isVectorTy())
652 return llvm::ConstantVector::getSplat(
654 if (llvmType->isArrayTy()) {
656 if (child->isZeroValue()) {
659 if (llvm::ConstantDataSequential::isElementTypeCompatible(
662 if (isa<llvm::IntegerType>(elementType)) {
663 if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
664 if (ci->getBitWidth() == 8) {
669 if (ci->getBitWidth() == 16) {
674 if (ci->getBitWidth() == 32) {
679 if (ci->getBitWidth() == 64) {
689 std::vector<llvm::Constant *> constants(numElements, child);
696 if (llvm::Constant *result =
698 llvmType, moduleTranslation)) {
702 if (
auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
708 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
709 assert(elementsAttr.getShapedType().hasStaticShape());
710 assert(!elementsAttr.getShapedType().getShape().empty() &&
711 "unexpected empty elements attribute shape");
714 constants.reserve(elementsAttr.getNumElements());
716 for (
auto n : elementsAttr.getValues<
Attribute>()) {
719 if (!constants.back())
724 constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
725 assert(constantsRef.empty() &&
"did not consume all elemental constants");
729 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
733 stringAttr.getValue().size()});
738 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
739 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
740 llvm::Type *elementType = arrayTy->getElementType();
742 llvm::Constant *elementCst =
nullptr;
744 constants.reserve(arrayTy->getNumElements());
745 for (
Attribute elementAttr : arrayAttr) {
749 if (!previousElementAttr || previousElementAttr != elementAttr) {
750 previousElementAttr = elementAttr;
756 constants.push_back(elementCst);
762 emitError(loc,
"unsupported constant value");
766 ModuleTranslation::ModuleTranslation(
Operation *module,
767 std::unique_ptr<llvm::Module> llvmModule)
768 : mlirModule(module), llvmModule(std::move(llvmModule)),
772 *this, *this->llvmModule)),
773 typeTranslator(this->llvmModule->
getContext()),
776 "mlirModule should honor LLVM's module semantics.");
779 ModuleTranslation::~ModuleTranslation() {
781 ompBuilder->finalize();
786 toProcess.push_back(®ion);
787 while (!toProcess.empty()) {
788 Region *current = toProcess.pop_back_val();
789 for (
Block &block : *current) {
790 blockMapping.erase(&block);
791 for (
Value arg : block.getArguments())
792 valueMapping.erase(arg);
794 for (
Value value : op.getResults())
795 valueMapping.erase(value);
796 if (op.hasSuccessors())
797 branchMapping.erase(&op);
798 if (isa<LLVM::GlobalOp>(op))
799 globalsMapping.erase(&op);
800 if (isa<LLVM::AliasOp>(op))
801 aliasesMapping.erase(&op);
802 if (isa<LLVM::CallOp>(op))
803 callMapping.erase(&op);
806 llvm::map_range(op.getRegions(), [](
Region &r) { return &r; }));
815 unsigned numArguments,
unsigned index) {
817 if (isa<LLVM::BrOp>(terminator))
824 auto branch = cast<BranchOpInterface>(terminator);
827 (!seenSuccessors.contains(successor) || successorOperands.
empty()) &&
828 "successors with arguments in LLVM branches must be different blocks");
829 seenSuccessors.insert(successor);
835 if (
auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
838 return condBranchOp.getSuccessor(0) == current
839 ? condBranchOp.getTrueDestOperands()[index]
840 : condBranchOp.getFalseDestOperands()[index];
843 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
846 if (switchOp.getDefaultDestination() == current)
847 return switchOp.getDefaultOperands()[index];
849 if (i.value() == current)
850 return switchOp.getCaseOperands(i.index())[index];
853 if (
auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(terminator)) {
856 if (indBrOp->getSuccessor(i.index()) == current)
857 return indBrOp.getSuccessorOperands(i.index())[index];
861 if (
auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
862 return invokeOp.getNormalDest() == current
863 ? invokeOp.getNormalDestOperands()[index]
864 : invokeOp.getUnwindDestOperands()[index];
868 "only branch, switch or invoke operations can be terminators "
869 "of a block that has successors");
877 for (
Block &bb : llvm::drop_begin(region)) {
878 llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
879 auto phis = llvmBB->phis();
880 auto numArguments = bb.getNumArguments();
881 assert(numArguments == std::distance(phis.begin(), phis.end()));
883 for (
auto *pred : bb.getPredecessors()) {
889 llvm::Instruction *terminator =
890 state.lookupBranch(pred->getTerminator());
891 assert(terminator &&
"missing the mapping for a terminator");
893 &bb, pred, numArguments, index)),
894 terminator->getParent());
903 llvm::Module *module = builder.GetInsertBlock()->getModule();
905 llvm::Intrinsic::getOrInsertDeclaration(module, intrinsic, tys);
906 return builder.CreateCall(fn, args);
915 assert(immArgPositions.size() == immArgAttrNames.size() &&
916 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
920 size_t numOpBundleOperands = 0;
921 auto opBundleSizesAttr = cast_if_present<DenseI32ArrayAttr>(
922 intrOp->
getAttr(LLVMDialect::getOpBundleSizesAttrName()));
923 auto opBundleTagsAttr = cast_if_present<ArrayAttr>(
924 intrOp->
getAttr(LLVMDialect::getOpBundleTagsAttrName()));
926 if (opBundleSizesAttr && opBundleTagsAttr) {
927 ArrayRef<int> opBundleSizes = opBundleSizesAttr.asArrayRef();
928 assert(opBundleSizes.size() == opBundleTagsAttr.size() &&
929 "operand bundles and tags do not match");
931 numOpBundleOperands =
932 std::accumulate(opBundleSizes.begin(), opBundleSizes.end(),
size_t(0));
933 assert(numOpBundleOperands <= intrOp->getNumOperands() &&
934 "operand bundle operands is more than the number of operands");
937 size_t nextOperandIdx = 0;
938 opBundles.reserve(opBundleSizesAttr.size());
940 for (
auto [opBundleTagAttr, bundleSize] :
941 llvm::zip(opBundleTagsAttr, opBundleSizes)) {
942 auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
944 operands.slice(nextOperandIdx, bundleSize));
945 opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
946 nextOperandIdx += bundleSize;
951 auto opOperands = intrOp->
getOperands().drop_back(numOpBundleOperands);
952 auto operands = moduleTranslation.
lookupValues(opOperands);
954 for (
auto [immArgPos, immArgName] :
955 llvm::zip(immArgPositions, immArgAttrNames)) {
956 auto attr = llvm::cast<TypedAttr>(intrOp->
getAttr(immArgName));
957 assert(attr.getType().isIntOrFloat() &&
"expected int or float immarg");
958 auto *type = moduleTranslation.
convertType(attr.getType());
960 type, attr, intrOp->
getLoc(), moduleTranslation);
963 for (
auto &arg : args) {
965 arg = operands[opArg++];
970 for (
unsigned overloadedResultIdx : overloadedResults) {
971 if (numResults > 1) {
973 overloadedTypes.push_back(moduleTranslation.
convertType(
975 .getBody()[overloadedResultIdx]));
977 overloadedTypes.push_back(
981 for (
unsigned overloadedOperandIdx : overloadedOperands)
982 overloadedTypes.push_back(args[overloadedOperandIdx]->
getType());
983 llvm::Module *module = builder.GetInsertBlock()->getModule();
984 llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
985 module, intrinsic, overloadedTypes);
987 return builder.CreateCall(llvmIntr, args, opBundles);
992 LogicalResult ModuleTranslation::convertOperation(
Operation &op,
993 llvm::IRBuilderBase &builder,
994 bool recordInsertions) {
997 return op.
emitError(
"cannot be converted to LLVM IR: missing "
998 "`LLVMTranslationDialectInterface` registration for "
1002 InstructionCapturingInserter::CollectionScope scope(builder,
1005 return op.
emitError(
"LLVM Translation failed for operation: ")
1008 return convertDialectAttributes(&op, scope.getCapturedInstructions());
1018 LogicalResult ModuleTranslation::convertBlockImpl(
Block &bb,
1019 bool ignoreArguments,
1020 llvm::IRBuilderBase &builder,
1021 bool recordInsertions) {
1023 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
1031 if (!ignoreArguments) {
1033 unsigned numPredecessors =
1034 std::distance(predecessors.begin(), predecessors.end());
1036 auto wrappedType = arg.getType();
1039 "block argument does not have an LLVM type");
1040 builder.SetCurrentDebugLocation(
1041 debugTranslation->translateLoc(arg.getLoc(), subprogram));
1043 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
1049 for (
auto &op : bb) {
1051 builder.SetCurrentDebugLocation(
1052 debugTranslation->translateLoc(op.
getLoc(), subprogram));
1054 if (failed(convertOperation(op, builder, recordInsertions)))
1058 if (
auto iface = dyn_cast<WeightedBranchOpInterface>(op))
1077 llvm::Constant *cst) {
1078 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1079 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1085 llvm::GlobalValue *gv) {
1086 if (dsoLocalRequested)
1087 gv->setDSOLocal(
true);
1090 LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
1099 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1101 llvm::Constant *cst =
nullptr;
1102 if (op.getValueOrNull()) {
1105 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1106 cst = llvm::ConstantDataArray::getString(
1107 llvmModule->getContext(), strAttr.getValue(),
false);
1108 type = cst->getType();
1115 auto linkage = convertLinkageToLLVM(op.getLinkage());
1121 if (!dropInitializer && !cst)
1123 else if (dropInitializer && cst)
1126 auto *var =
new llvm::GlobalVariable(
1127 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1129 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1130 : llvm::GlobalValue::NotThreadLocal,
1131 op.getAddrSpace(), op.getExternallyInitialized());
1133 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1134 auto selectorOp = cast<ComdatSelectorOp>(
1136 var->setComdat(comdatMapping.lookup(selectorOp));
1139 if (op.getUnnamedAddr().has_value())
1140 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1142 if (op.getSection().has_value())
1143 var->setSection(*op.getSection());
1147 std::optional<uint64_t> alignment = op.getAlignment();
1148 if (alignment.has_value())
1149 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1151 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1153 globalsMapping.try_emplace(op, var);
1156 if (op.getDbgExprs()) {
1157 for (
auto exprAttr :
1158 op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1159 llvm::DIGlobalVariableExpression *diGlobalExpr =
1160 debugTranslation->translateGlobalVariableExpression(exprAttr);
1161 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1162 var->addDebugInfo(diGlobalExpr);
1181 llvm::DIScope *scope = diGlobalVar->getScope();
1182 if (
auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1183 scope = mod->getScope();
1184 else if (
auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1186 dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1187 scope = sp->getUnit();
1188 }
else if (
auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1189 scope = sp->getUnit();
1192 if (llvm::DICompileUnit *compileUnit =
1193 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1196 allGVars[compileUnit].push_back(diGlobalExpr);
1203 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1205 llvm::Constant *cst =
nullptr;
1206 llvm::GlobalValue::LinkageTypes linkage =
1207 convertLinkageToLLVM(op.getLinkage());
1208 llvm::Module &llvmMod = *llvmModule;
1211 llvm::GlobalAlias *var = llvm::GlobalAlias::create(
1212 type, op.getAddrSpace(), linkage, op.getSymName(), cst,
1215 var->setThreadLocalMode(op.getThreadLocal_()
1216 ? llvm::GlobalAlias::GeneralDynamicTLSModel
1217 : llvm::GlobalAlias::NotThreadLocal);
1222 if (op.getUnnamedAddr().has_value())
1223 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1225 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1227 aliasesMapping.try_emplace(op, var);
1231 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1232 if (
Block *initializer = op.getInitializerBlock()) {
1233 llvm::IRBuilder<llvm::TargetFolder> builder(
1234 llvmModule->getContext(),
1235 llvm::TargetFolder(llvmModule->getDataLayout()));
1237 [[maybe_unused]]
int numConstantsHit = 0;
1238 [[maybe_unused]]
int numConstantsErased = 0;
1241 for (
auto &op : initializer->without_terminator()) {
1242 if (failed(convertOperation(op, builder)))
1255 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1259 auto [iterator, inserted] =
1260 constantAggregateUseMap.try_emplace(agg, numUsers);
1263 iterator->second += numUsers;
1269 auto cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1272 auto iter = constantAggregateUseMap.find(cst);
1273 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1275 if (iter->second == 0) {
1278 if (cst->user_empty()) {
1279 cst->destroyConstant();
1280 numConstantsErased++;
1282 constantAggregateUseMap.erase(iter);
1287 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1288 llvm::Constant *cst =
1289 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1290 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1292 global->setInitializer(cst);
1296 for (
auto it : constantAggregateUseMap) {
1297 auto cst = it.first;
1298 cst->removeDeadConstantUsers();
1299 if (cst->user_empty()) {
1300 cst->destroyConstant();
1301 numConstantsErased++;
1305 LLVM_DEBUG(llvm::dbgs()
1306 <<
"Convert initializer for " << op.
getName() <<
"\n";
1307 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1309 << numConstantsErased <<
" dangling constants erased\n";);
1315 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1316 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1317 if (!ctorOp && !dtorOp)
1323 if ((ctorOp && ctorOp.getCtors().empty()) ||
1324 (dtorOp && dtorOp.getDtors().empty())) {
1325 llvm::IRBuilder<llvm::TargetFolder> builder(
1326 llvmModule->getContext(),
1327 llvm::TargetFolder(llvmModule->getDataLayout()));
1329 builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1331 llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1332 (void)
new llvm::GlobalVariable(
1333 *llvmModule, zeroInit->getType(),
false,
1334 llvm::GlobalValue::AppendingLinkage, zeroInit,
1335 ctorOp ?
"llvm.global_ctors" :
"llvm.global_dtors");
1338 ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1339 :
llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1340 auto appendGlobalFn =
1341 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1342 for (
const auto &[sym, prio] : range) {
1345 appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1351 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1352 if (failed(convertDialectAttributes(op, {})))
1357 for (
const auto &[compileUnit, globals] : allGVars) {
1358 compileUnit->replaceGlobalVariables(
1363 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1364 Block &initializer = op.getInitializerBlock();
1365 llvm::IRBuilder<llvm::TargetFolder> builder(
1366 llvmModule->getContext(),
1367 llvm::TargetFolder(llvmModule->getDataLayout()));
1370 if (failed(convertOperation(op, builder)))
1377 auto *cst = cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1378 assert(aliasesMapping.count(op));
1379 auto *alias = cast<llvm::GlobalAlias>(aliasesMapping[op]);
1380 alias->setAliasee(cst);
1383 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>())
1384 if (failed(convertDialectAttributes(op, {})))
1397 llvm::Function *llvmFunc,
1399 StringRef value = StringRef()) {
1400 auto kind = llvm::Attribute::getAttrKindFromName(key);
1402 llvmFunc->addFnAttr(key, value);
1406 if (llvm::Attribute::isIntAttrKind(
kind)) {
1408 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1411 if (!value.getAsInteger(0, result))
1412 llvmFunc->addFnAttr(
1415 llvmFunc->addFnAttr(key, value);
1420 return emitError(loc) <<
"LLVM attribute '" << key
1421 <<
"' does not expect a value, found '" << value
1424 llvmFunc->addFnAttr(
kind);
1430 const llvm::APInt &value) {
1437 const llvm::APInt &value) {
1445 llvm::Metadata *typeMD =
1447 llvm::Metadata *isSignedMD =
1457 values, std::back_inserter(mdValues), [&context](int32_t value) {
1470 static LogicalResult
1472 llvm::Function *llvmFunc) {
1477 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1484 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1485 if (!arrayAttr || arrayAttr.size() != 2)
1487 <<
"expected 'passthrough' to contain string or array attributes";
1489 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1490 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1491 if (!keyAttr || !valueAttr)
1493 <<
"expected arrays within 'passthrough' to contain two strings";
1496 valueAttr.getValue())))
1502 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1505 blockMapping.clear();
1506 valueMapping.clear();
1507 branchMapping.clear();
1511 for (
auto [mlirArg, llvmArg] :
1512 llvm::zip(func.getArguments(), llvmFunc->args()))
1516 if (func.getPersonality()) {
1517 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1518 if (llvm::Constant *pfunc =
getLLVMConstant(ty, func.getPersonalityAttr(),
1519 func.getLoc(), *
this))
1520 llvmFunc->setPersonalityFn(pfunc);
1523 if (std::optional<StringRef> section = func.getSection())
1524 llvmFunc->setSection(*section);
1526 if (func.getArmStreaming())
1527 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1528 else if (func.getArmLocallyStreaming())
1529 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1530 else if (func.getArmStreamingCompatible())
1531 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1533 if (func.getArmNewZa())
1534 llvmFunc->addFnAttr(
"aarch64_new_za");
1535 else if (func.getArmInZa())
1536 llvmFunc->addFnAttr(
"aarch64_in_za");
1537 else if (func.getArmOutZa())
1538 llvmFunc->addFnAttr(
"aarch64_out_za");
1539 else if (func.getArmInoutZa())
1540 llvmFunc->addFnAttr(
"aarch64_inout_za");
1541 else if (func.getArmPreservesZa())
1542 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1544 if (
auto targetCpu = func.getTargetCpu())
1545 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1547 if (
auto tuneCpu = func.getTuneCpu())
1548 llvmFunc->addFnAttr(
"tune-cpu", *tuneCpu);
1550 if (
auto reciprocalEstimates = func.getReciprocalEstimates())
1551 llvmFunc->addFnAttr(
"reciprocal-estimates", *reciprocalEstimates);
1553 if (
auto preferVectorWidth = func.getPreferVectorWidth())
1554 llvmFunc->addFnAttr(
"prefer-vector-width", *preferVectorWidth);
1556 if (
auto attr = func.getVscaleRange())
1557 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1559 attr->getMaxRange().getInt()));
1561 if (
auto unsafeFpMath = func.getUnsafeFpMath())
1562 llvmFunc->addFnAttr(
"unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1564 if (
auto noInfsFpMath = func.getNoInfsFpMath())
1565 llvmFunc->addFnAttr(
"no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1567 if (
auto noNansFpMath = func.getNoNansFpMath())
1568 llvmFunc->addFnAttr(
"no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1570 if (
auto approxFuncFpMath = func.getApproxFuncFpMath())
1571 llvmFunc->addFnAttr(
"approx-func-fp-math",
1572 llvm::toStringRef(*approxFuncFpMath));
1574 if (
auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1575 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1576 llvm::toStringRef(*noSignedZerosFpMath));
1578 if (
auto denormalFpMath = func.getDenormalFpMath())
1579 llvmFunc->addFnAttr(
"denormal-fp-math", *denormalFpMath);
1581 if (
auto denormalFpMathF32 = func.getDenormalFpMathF32())
1582 llvmFunc->addFnAttr(
"denormal-fp-math-f32", *denormalFpMathF32);
1584 if (
auto fpContract = func.getFpContract())
1585 llvmFunc->addFnAttr(
"fp-contract", *fpContract);
1587 if (
auto instrumentFunctionEntry = func.getInstrumentFunctionEntry())
1588 llvmFunc->addFnAttr(
"instrument-function-entry", *instrumentFunctionEntry);
1590 if (
auto instrumentFunctionExit = func.getInstrumentFunctionExit())
1591 llvmFunc->addFnAttr(
"instrument-function-exit", *instrumentFunctionExit);
1594 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1595 for (
auto &bb : func) {
1596 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1597 llvmBB->insertInto(llvmFunc);
1604 for (
Block *bb : blocks) {
1605 CapturingIRBuilder builder(llvmContext,
1606 llvm::TargetFolder(llvmModule->getDataLayout()));
1607 if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1617 return convertDialectAttributes(func, {});
1620 LogicalResult ModuleTranslation::convertDialectAttributes(
1623 if (failed(iface.
amendOperation(op, instructions, attribute, *
this)))
1631 llvm::Function *llvmFunc) {
1632 if (!func.getMemoryEffects())
1635 MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1638 llvm::MemoryEffects newMemEffects =
1639 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1640 convertModRefInfoToLLVM(memEffects.getArgMem()));
1641 newMemEffects |= llvm::MemoryEffects(
1642 llvm::MemoryEffects::Location::InaccessibleMem,
1643 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1645 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1646 convertModRefInfoToLLVM(memEffects.getOther()));
1647 llvmFunc->setMemoryEffects(newMemEffects);
1652 llvm::Function *llvmFunc) {
1653 if (func.getNoInlineAttr())
1654 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1655 if (func.getAlwaysInlineAttr())
1656 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1657 if (func.getOptimizeNoneAttr())
1658 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1659 if (func.getConvergentAttr())
1660 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1661 if (func.getNoUnwindAttr())
1662 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1663 if (func.getWillReturnAttr())
1664 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1665 if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
1666 llvmFunc->addFnAttr(
"target-features", targetFeatAttr.getFeaturesString());
1667 if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())
1668 llvmFunc->addFnAttr(
"frame-pointer", stringifyFramePointerKind(
1669 fpAttr.getFramePointerKind()));
1670 if (UWTableKindAttr uwTableKindAttr = func.getUwtableKindAttr())
1671 llvmFunc->setUWTableKind(
1672 convertUWTableKindToLLVM(uwTableKindAttr.getUwtableKind()));
1678 llvm::Function *llvmFunc,
1680 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1682 if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1683 Type type = vecTypeHint.getHint().getValue();
1684 llvm::Type *llvmType = translation.
convertType(type);
1685 bool isSigned = vecTypeHint.getIsSigned();
1686 llvmFunc->setMetadata(
1687 func.getVecTypeHintAttrName(),
1692 func.getWorkGroupSizeHint()) {
1693 llvmFunc->setMetadata(
1694 func.getWorkGroupSizeHintAttrName(),
1699 func.getReqdWorkGroupSize()) {
1700 llvmFunc->setMetadata(
1701 func.getReqdWorkGroupSizeAttrName(),
1705 if (std::optional<uint32_t> intelReqdSubGroupSize =
1706 func.getIntelReqdSubGroupSize()) {
1707 llvmFunc->setMetadata(
1708 func.getIntelReqdSubGroupSizeAttrName(),
1710 llvm::APInt(32, *intelReqdSubGroupSize)));
1715 llvm::Attribute::AttrKind llvmKind,
1720 .Case<TypeAttr>([&](
auto typeAttr) {
1721 attrBuilder.addTypeAttr(
1722 llvmKind, moduleTranslation.
convertType(typeAttr.getValue()));
1725 .Case<IntegerAttr>([&](
auto intAttr) {
1726 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1729 .Case<UnitAttr>([&](
auto) {
1730 attrBuilder.addAttribute(llvmKind);
1733 .Case<LLVM::ConstantRangeAttr>([&](
auto rangeAttr) {
1734 attrBuilder.addConstantRangeAttr(
1736 llvm::ConstantRange(rangeAttr.getLower(), rangeAttr.getUpper()));
1739 .Default([loc](
auto) {
1740 return emitError(loc,
"unsupported parameter attribute type");
1744 FailureOr<llvm::AttrBuilder>
1746 DictionaryAttr paramAttrs) {
1747 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1751 for (
auto namedAttr : paramAttrs) {
1752 auto it = attrNameToKindMapping.find(namedAttr.getName());
1753 if (it != attrNameToKindMapping.end()) {
1754 llvm::Attribute::AttrKind llvmKind = it->second;
1758 }
else if (namedAttr.getNameDialect()) {
1767 FailureOr<llvm::AttrBuilder>
1769 DictionaryAttr paramAttrs) {
1770 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1773 for (
auto namedAttr : paramAttrs) {
1774 auto it = attrNameToKindMapping.find(namedAttr.getName());
1775 if (it != attrNameToKindMapping.end()) {
1776 llvm::Attribute::AttrKind llvmKind = it->second;
1786 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1789 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1790 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1792 cast<llvm::FunctionType>(
convertType(
function.getFunctionType())));
1793 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1794 llvmFunc->setLinkage(convertLinkageToLLVM(
function.getLinkage()));
1795 llvmFunc->setCallingConv(convertCConvToLLVM(
function.getCConv()));
1806 if (std::optional<uint64_t> entryCount =
function.getFunctionEntryCount())
1807 llvmFunc->setEntryCount(entryCount.value());
1810 if (ArrayAttr allResultAttrs =
function.getAllResultAttrs()) {
1811 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1812 FailureOr<llvm::AttrBuilder> attrBuilder =
1814 if (failed(attrBuilder))
1816 llvmFunc->addRetAttrs(*attrBuilder);
1822 FailureOr<llvm::AttrBuilder> attrBuilder =
1824 if (failed(attrBuilder))
1826 llvmArg.addAttrs(*attrBuilder);
1832 function.getLoc(),
function.getPassthrough(), llvmFunc)))
1836 llvmFunc->setVisibility(convertVisibilityToLLVM(
function.getVisibility_()));
1839 if (std::optional<mlir::SymbolRefAttr> comdat =
function.getComdat()) {
1840 auto selectorOp = cast<ComdatSelectorOp>(
1842 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1845 if (
auto gc =
function.getGarbageCollector())
1846 llvmFunc->setGC(gc->str());
1848 if (
auto unnamedAddr =
function.getUnnamedAddr())
1849 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1851 if (
auto alignment =
function.getAlignment())
1852 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1855 debugTranslation->translate(
function, *llvmFunc);
1861 LogicalResult ModuleTranslation::convertFunctions() {
1863 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1866 if (
function.isExternal()) {
1867 if (failed(convertDialectAttributes(
function, {})))
1872 if (failed(convertOneFunction(
function)))
1879 LogicalResult ModuleTranslation::convertComdats() {
1880 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
1881 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1883 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1885 <<
"comdat selection symbols must be unique even in different "
1887 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1888 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1889 comdatMapping.try_emplace(selectorOp, comdat);
1895 LogicalResult ModuleTranslation::convertUnresolvedBlockAddress() {
1896 for (
auto &[blockAddressOp, llvmCst] : unresolvedBlockAddressMapping) {
1897 BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
1899 assert(llvmBlock &&
"expected LLVM blocks to be already translated");
1903 lookupFunction(blockAddressAttr.getFunction().getValue()), llvmBlock);
1904 llvmCst->replaceAllUsesWith(llvmBlockAddr);
1905 assert(llvmCst->use_empty() &&
"expected all uses to be replaced");
1906 cast<llvm::GlobalVariable>(llvmCst)->eraseFromParent();
1908 unresolvedBlockAddressMapping.clear();
1913 llvm::Instruction *inst) {
1914 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1915 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1920 auto [scopeIt, scopeInserted] =
1921 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
1923 return scopeIt->second;
1924 llvm::LLVMContext &ctx = llvmModule->getContext();
1925 auto dummy = llvm::MDNode::getTemporary(ctx, std::nullopt);
1927 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1928 aliasScopeAttr.getDomain(),
nullptr);
1929 if (insertedDomain) {
1932 operands.push_back(dummy.get());
1933 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
1937 llvm::Metadata *replacement;
1938 if (
auto stringAttr =
1939 dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId()))
1942 replacement = domainIt->second;
1943 domainIt->second->replaceOperandWith(0, replacement);
1946 assert(domainIt->second &&
"Scope's domain should already be valid");
1949 operands.push_back(dummy.get());
1950 operands.push_back(domainIt->second);
1951 if (StringAttr description = aliasScopeAttr.getDescription())
1955 llvm::Metadata *replacement;
1956 if (
auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId()))
1959 replacement = scopeIt->second;
1960 scopeIt->second->replaceOperandWith(0, replacement);
1961 return scopeIt->second;
1967 nodes.reserve(aliasScopeAttrs.size());
1968 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
1974 llvm::Instruction *inst) {
1975 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
1976 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
1979 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
1980 inst->setMetadata(
kind, node);
1983 populateScopeMetadata(op.getAliasScopesOrNull(),
1984 llvm::LLVMContext::MD_alias_scope);
1985 populateScopeMetadata(op.getNoAliasScopesOrNull(),
1986 llvm::LLVMContext::MD_noalias);
1989 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
1990 return tbaaMetadataMapping.lookup(tbaaAttr);
1994 llvm::Instruction *inst) {
1995 ArrayAttr tagRefs = op.getTBAATagsOrNull();
1996 if (!tagRefs || tagRefs.empty())
2003 if (tagRefs.size() > 1) {
2004 op.emitWarning() <<
"TBAA access tags were not translated, because LLVM "
2005 "IR only supports a single tag per instruction";
2009 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
2010 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
2014 DereferenceableOpInterface op, llvm::Instruction *inst) {
2015 DereferenceableAttr derefAttr = op.getDereferenceableOrNull();
2023 unsigned kindId = derefAttr.getMayBeNull()
2024 ? llvm::LLVMContext::MD_dereferenceable_or_null
2025 : llvm::LLVMContext::MD_dereferenceable;
2026 inst->setMetadata(kindId, derefSizeNode);
2031 llvm::transform(op.getWeights(), std::back_inserter(weights),
2032 [](int32_t value) { return static_cast<uint32_t>(value); });
2033 if (weights.empty())
2037 assert(inst &&
"expected the operation to have a mapping to an instruction");
2039 llvm::LLVMContext::MD_prof,
2043 LogicalResult ModuleTranslation::createTBAAMetadata() {
2044 llvm::LLVMContext &ctx = llvmModule->getContext();
2056 walker.
addWalk([&](TBAARootAttr root) {
2057 tbaaMetadataMapping.insert(
2061 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
2064 for (TBAAMemberAttr member : descriptor.getMembers()) {
2065 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
2073 walker.
addWalk([&](TBAATagAttr tag) {
2076 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
2077 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
2081 if (tag.getConstant())
2088 mlirModule->
walk([&](AliasAnalysisOpInterface analysisOpInterface) {
2089 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
2096 LogicalResult ModuleTranslation::createIdentMetadata() {
2098 LLVMDialect::getIdentAttrName())) {
2099 StringRef ident = attr;
2100 llvm::LLVMContext &ctx = llvmModule->getContext();
2101 llvm::NamedMDNode *namedMd =
2102 llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
2104 namedMd->addOperand(md);
2110 LogicalResult ModuleTranslation::createCommandlineMetadata() {
2112 LLVMDialect::getCommandlineAttrName())) {
2113 StringRef cmdLine = attr;
2114 llvm::LLVMContext &ctx = llvmModule->getContext();
2115 llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
2116 LLVMDialect::getCommandlineAttrName());
2119 nmd->addOperand(md);
2125 LogicalResult ModuleTranslation::createDependentLibrariesMetadata() {
2127 LLVM::LLVMDialect::getDependentLibrariesAttrName())) {
2129 llvmModule->getOrInsertNamedMetadata(
"llvm.dependent-libraries");
2130 llvm::LLVMContext &ctx = llvmModule->getContext();
2132 cast<ArrayAttr>(dependentLibrariesAttr).getAsRange<StringAttr>()) {
2135 nmd->addOperand(md);
2142 llvm::Instruction *inst) {
2143 LoopAnnotationAttr attr =
2145 .Case<LLVM::BrOp, LLVM::CondBrOp>(
2146 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
2149 llvm::MDNode *loopMD =
2150 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
2151 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
2155 auto iface = cast<DisjointFlagInterface>(op);
2157 if (
auto disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
2158 disjointInst->setIsDisjoint(iface.getIsDisjoint());
2168 remapped.reserve(values.size());
2169 for (
Value v : values)
2176 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
2177 ompBuilder->initialize();
2182 ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
2190 return ompBuilder.get();
2194 llvm::DILocalScope *scope) {
2195 return debugTranslation->translateLoc(loc, scope);
2198 llvm::DIExpression *
2200 return debugTranslation->translateExpression(attr);
2203 llvm::DIGlobalVariableExpression *
2205 LLVM::DIGlobalVariableExpressionAttr attr) {
2206 return debugTranslation->translateGlobalVariableExpression(attr);
2210 return debugTranslation->translate(attr);
2215 return convertRoundingModeToLLVM(rounding);
2219 LLVM::FPExceptionBehavior exceptionBehavior) {
2220 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
2225 return llvmModule->getOrInsertNamedMetadata(name);
2228 void ModuleTranslation::StackFrame::anchor() {}
2230 static std::unique_ptr<llvm::Module>
2233 m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
2234 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
2235 if (
auto dataLayoutAttr =
2236 m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
2237 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
2239 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(
""));
2240 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
2241 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2245 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
2246 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2251 if (failed(llvmDataLayout))
2253 llvmModule->setDataLayout(*llvmDataLayout);
2255 if (
auto targetTripleAttr =
2256 m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
2257 llvmModule->setTargetTriple(
2258 llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
2263 std::unique_ptr<llvm::Module>
2265 StringRef name,
bool disableVerification) {
2267 module->
emitOpError(
"can not be translated to an LLVMIR module");
2271 std::unique_ptr<llvm::Module> llvmModule =
2280 llvm::IRBuilder<llvm::TargetFolder> llvmBuilder(
2282 llvm::TargetFolder(translator.getLLVMModule()->getDataLayout()));
2288 if (failed(translator.convertOperation(*module, llvmBuilder)))
2291 if (failed(translator.convertComdats()))
2293 if (failed(translator.convertFunctionSignatures()))
2295 if (failed(translator.convertGlobalsAndAliases()))
2297 if (failed(translator.createTBAAMetadata()))
2299 if (failed(translator.createIdentMetadata()))
2301 if (failed(translator.createCommandlineMetadata()))
2303 if (failed(translator.createDependentLibrariesMetadata()))
2308 if (!isa<LLVM::LLVMFuncOp, LLVM::AliasOp, LLVM::GlobalOp,
2309 LLVM::GlobalCtorsOp, LLVM::GlobalDtorsOp, LLVM::ComdatOp>(&o) &&
2311 failed(translator.convertOperation(o, llvmBuilder))) {
2319 if (failed(translator.convertFunctions()))
2324 if (failed(translator.convertUnresolvedBlockAddress()))
2330 translator.llvmModule->convertToNewDbgValues();
2334 translator.debugTranslation->addModuleFlagsIfNotPresent();
2336 if (!disableVerification &&
2337 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2340 return std::move(translator.llvmModule);
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1209::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.
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(WeightedBranchOpInterface op)
Sets LLVM profiling metadata for operations that have branch weights.
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::RoundingMode translateRoundingMode(LLVM::RoundingMode rounding)
Translates the given LLVM rounding mode metadata.
void setTBAAMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
Sets LLVM TBAA metadata for memory operations that have TBAA attributes.
llvm::DIExpression * translateExpression(LLVM::DIExpressionAttr attr)
Translates the given LLVM DWARF expression metadata.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::CallInst * lookupCall(Operation *op) const
Finds an LLVM call instruction that corresponds to the given MLIR call operation.
llvm::Metadata * translateDebugInfo(LLVM::DINodeAttr attr)
Translates the given LLVM debug info metadata.
void setDisjointFlag(Operation *op, llvm::Value *value)
Sets the disjoint flag attribute for the exported instruction value given the original operation op.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
llvm::BasicBlock * lookupBlockAddress(BlockAddressAttr attr) const
Finds the LLVM basic block that corresponds to the given BlockAddressAttr.
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 a null Attribute if the discardable attribute does no...
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
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...