34 #include "llvm/ADT/STLExtras.h"
35 #include "llvm/ADT/StringExtras.h"
36 #include "llvm/ADT/TypeSwitch.h"
37 #include "llvm/Analysis/TargetFolder.h"
38 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
39 #include "llvm/IR/BasicBlock.h"
40 #include "llvm/IR/CFG.h"
41 #include "llvm/IR/Constants.h"
42 #include "llvm/IR/DerivedTypes.h"
43 #include "llvm/IR/IRBuilder.h"
44 #include "llvm/IR/InlineAsm.h"
45 #include "llvm/IR/LLVMContext.h"
46 #include "llvm/IR/MDBuilder.h"
47 #include "llvm/IR/Module.h"
48 #include "llvm/IR/Verifier.h"
49 #include "llvm/Support/Debug.h"
50 #include "llvm/Support/ErrorHandling.h"
51 #include "llvm/Support/raw_ostream.h"
52 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
53 #include "llvm/Transforms/Utils/Cloning.h"
54 #include "llvm/Transforms/Utils/ModuleUtils.h"
58 #define DEBUG_TYPE "llvm-dialect-to-llvm-ir"
64 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
87 class InstructionCapturingInserter :
public llvm::IRBuilderCallbackInserter {
90 InstructionCapturingInserter()
91 : llvm::IRBuilderCallbackInserter([
this](llvm::Instruction *instruction) {
92 if (LLVM_LIKELY(enabled))
93 capturedInstructions.push_back(instruction);
98 return capturedInstructions;
102 void clearCapturedInstructions() { capturedInstructions.clear(); }
105 class CollectionScope {
108 CollectionScope(llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing);
116 return inserter->getCapturedInstructions();
121 InstructionCapturingInserter *inserter =
nullptr;
131 void setEnabled(
bool enabled =
true) { this->enabled = enabled; }
138 bool enabled =
false;
141 using CapturingIRBuilder =
142 llvm::IRBuilder<llvm::TargetFolder, InstructionCapturingInserter>;
145 InstructionCapturingInserter::CollectionScope::CollectionScope(
146 llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing) {
148 if (!isBuilderCapturing)
151 auto &capturingIRBuilder =
static_cast<CapturingIRBuilder &
>(irBuilder);
152 inserter = &capturingIRBuilder.getInserter();
153 wasEnabled = inserter->enabled;
155 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
156 inserter->setEnabled(
true);
159 InstructionCapturingInserter::CollectionScope::~CollectionScope() {
163 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
167 llvm::append_range(inserter->capturedInstructions,
168 previouslyCollectedInstructions);
170 inserter->setEnabled(wasEnabled);
175 static FailureOr<llvm::DataLayout>
178 std::optional<Location> loc = std::nullopt) {
183 std::string llvmDataLayout;
184 llvm::raw_string_ostream layoutStream(llvmDataLayout);
185 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
186 auto key = llvm::dyn_cast_if_present<StringAttr>(entry.getKey());
189 if (key.getValue() == DLTIDialect::kDataLayoutEndiannessKey) {
190 auto value = cast<StringAttr>(entry.getValue());
191 bool isLittleEndian =
192 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle;
193 layoutStream <<
"-" << (isLittleEndian ?
"e" :
"E");
196 if (key.getValue() == DLTIDialect::kDataLayoutManglingModeKey) {
197 auto value = cast<StringAttr>(entry.getValue());
198 layoutStream <<
"-m:" << value.getValue();
201 if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
202 auto value = cast<IntegerAttr>(entry.getValue());
203 uint64_t space = value.getValue().getZExtValue();
207 layoutStream <<
"-P" << space;
210 if (key.getValue() == DLTIDialect::kDataLayoutGlobalMemorySpaceKey) {
211 auto value = cast<IntegerAttr>(entry.getValue());
212 uint64_t space = value.getValue().getZExtValue();
216 layoutStream <<
"-G" << space;
219 if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
220 auto value = cast<IntegerAttr>(entry.getValue());
221 uint64_t space = value.getValue().getZExtValue();
225 layoutStream <<
"-A" << space;
228 if (key.getValue() == DLTIDialect::kDataLayoutStackAlignmentKey) {
229 auto value = cast<IntegerAttr>(entry.getValue());
230 uint64_t alignment = value.getValue().getZExtValue();
234 layoutStream <<
"-S" << alignment;
237 if (key.getValue() == DLTIDialect::kDataLayoutFunctionPointerAlignmentKey) {
238 auto value = cast<FunctionPointerAlignmentAttr>(entry.getValue());
239 uint64_t alignment = value.getAlignment();
243 layoutStream <<
"-F" << (value.getFunctionDependent() ?
"n" :
"i")
247 if (key.getValue() == DLTIDialect::kDataLayoutLegalIntWidthsKey) {
248 layoutStream <<
"-n";
250 cast<DenseI32ArrayAttr>(entry.getValue()).asArrayRef(), layoutStream,
251 [&](int32_t val) { layoutStream << val; },
":");
254 emitError(*loc) <<
"unsupported data layout key " << key;
261 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
262 auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
266 if (isa<IndexType>(type))
269 LogicalResult result =
271 .Case<IntegerType, Float16Type, Float32Type, Float64Type,
272 Float80Type, Float128Type>([&](
Type type) -> LogicalResult {
273 if (
auto intType = dyn_cast<IntegerType>(type)) {
274 if (intType.getSignedness() != IntegerType::Signless)
276 <<
"unsupported data layout for non-signless integer "
286 layoutStream << size <<
":" << abi;
287 if (abi != preferred)
288 layoutStream <<
":" << preferred;
291 .Case([&](LLVMPointerType type) {
292 layoutStream <<
"p" << type.getAddressSpace() <<
":";
298 layoutStream << size <<
":" << abi <<
":" << preferred <<
":"
302 .Default([loc](
Type type) {
304 <<
"unsupported type in data layout: " << type;
309 StringRef layoutSpec(llvmDataLayout);
310 layoutSpec.consume_front(
"-");
312 return llvm::DataLayout(layoutSpec);
319 static llvm::Constant *
324 llvm::Constant *result = constants.front();
325 constants = constants.drop_front();
329 llvm::Type *elementType;
330 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
331 elementType = arrayTy->getElementType();
332 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
333 elementType = vectorTy->getElementType();
335 emitError(loc) <<
"expected sequential LLVM types wrapping a scalar";
340 nested.reserve(shape.front());
341 for (int64_t i = 0; i < shape.front(); ++i) {
348 if (shape.size() == 1 && type->isVectorTy())
357 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
358 type = arrayTy->getElementType();
359 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
360 type = vectorTy->getElementType();
374 static llvm::Constant *
376 llvm::Type *llvmType,
378 if (!denseElementsAttr)
382 if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
385 ShapedType type = denseElementsAttr.
getType();
386 if (type.getNumElements() == 0)
394 int64_t elementByteSize = denseElementsAttr.
getRawData().size() /
396 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
401 bool hasVectorElementType = isa<VectorType>(type.getElementType());
402 int64_t numAggregates =
404 (hasVectorElementType ? 1
405 : denseElementsAttr.
getType().getShape().back());
407 if (!hasVectorElementType)
408 outerShape = outerShape.drop_back();
411 if (denseElementsAttr.
isSplat() &&
412 (isa<VectorType>(type) || hasVectorElementType)) {
416 llvm::Constant *splatVector =
417 llvm::ConstantDataVector::getSplat(0, splatValue);
422 if (denseElementsAttr.
isSplat())
427 std::function<llvm::Constant *(StringRef)> buildCstData;
428 if (isa<TensorType>(type)) {
429 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
430 if (vectorElementType && vectorElementType.getRank() == 1) {
431 buildCstData = [&](StringRef data) {
432 return llvm::ConstantDataVector::getRaw(
433 data, vectorElementType.getShape().back(), innermostLLVMType);
435 }
else if (!vectorElementType) {
436 buildCstData = [&](StringRef data) {
437 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
441 }
else if (isa<VectorType>(type)) {
442 buildCstData = [&](StringRef data) {
443 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
453 int64_t aggregateSize = denseElementsAttr.
getType().getShape().back() *
454 (innermostLLVMType->getScalarSizeInBits() / 8);
455 constants.reserve(numAggregates);
456 for (
unsigned i = 0; i < numAggregates; ++i) {
457 StringRef data(denseElementsAttr.
getRawData().data() + i * aggregateSize,
459 constants.push_back(buildCstData(data));
475 assert(denseResourceAttr &&
"expected non-null attribute");
478 if (!llvm::ConstantDataSequential::isElementTypeCompatible(
479 innermostLLVMType)) {
480 emitError(loc,
"no known conversion for innermost element type");
484 ShapedType type = denseResourceAttr.getType();
485 assert(type.getNumElements() > 0 &&
"Expected non-empty elements attribute");
489 emitError(loc,
"resource does not exist");
500 int64_t numElements = denseResourceAttr.getType().getNumElements();
501 int64_t elementByteSize = rawData.size() / numElements;
502 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
503 emitError(loc,
"raw data size does not match element type size");
509 bool hasVectorElementType = isa<VectorType>(type.getElementType());
510 int64_t numAggregates =
511 numElements / (hasVectorElementType
513 : denseResourceAttr.getType().getShape().back());
515 if (!hasVectorElementType)
516 outerShape = outerShape.drop_back();
519 std::function<llvm::Constant *(StringRef)> buildCstData;
520 if (isa<TensorType>(type)) {
521 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
522 if (vectorElementType && vectorElementType.getRank() == 1) {
523 buildCstData = [&](StringRef data) {
524 return llvm::ConstantDataVector::getRaw(
525 data, vectorElementType.getShape().back(), innermostLLVMType);
527 }
else if (!vectorElementType) {
528 buildCstData = [&](StringRef data) {
529 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
533 }
else if (isa<VectorType>(type)) {
534 buildCstData = [&](StringRef data) {
535 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
540 emitError(loc,
"unsupported dense_resource type");
547 int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
548 (innermostLLVMType->getScalarSizeInBits() / 8);
549 constants.reserve(numAggregates);
550 for (
unsigned i = 0; i < numAggregates; ++i) {
551 StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
552 constants.push_back(buildCstData(data));
567 if (!attr || isa<UndefAttr>(attr))
569 if (isa<ZeroAttr>(attr))
570 return llvm::Constant::getNullValue(llvmType);
571 if (
auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
572 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
574 emitError(loc,
"expected an array attribute for a struct constant");
578 structElements.reserve(structType->getNumElements());
579 for (
auto [elemType, elemAttr] :
580 zip_equal(structType->elements(), arrayAttr)) {
581 llvm::Constant *element =
585 structElements.push_back(element);
591 if (
auto intAttr = dyn_cast<IntegerAttr>(attr))
594 intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
595 if (
auto floatAttr = dyn_cast<FloatAttr>(attr)) {
596 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
601 unsigned floatWidth = APFloat::getSizeInBits(sem);
602 if (llvmType->isIntegerTy(floatWidth))
604 floatAttr.getValue().bitcastToAPInt());
606 llvm::Type::getFloatingPointTy(llvmType->getContext(),
607 floatAttr.getValue().getSemantics())) {
608 emitError(loc,
"FloatAttr does not match expected type of the constant");
613 if (
auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
614 return llvm::ConstantExpr::getBitCast(
616 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
617 llvm::Type *elementType;
618 uint64_t numElements;
619 bool isScalable =
false;
620 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
621 elementType = arrayTy->getElementType();
622 numElements = arrayTy->getNumElements();
623 }
else if (
auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
624 elementType = fVectorTy->getElementType();
625 numElements = fVectorTy->getNumElements();
626 }
else if (
auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
627 elementType = sVectorTy->getElementType();
628 numElements = sVectorTy->getMinNumElements();
631 llvm_unreachable(
"unrecognized constant vector type");
636 bool elementTypeSequential =
637 isa<llvm::ArrayType, llvm::VectorType>(elementType);
640 elementTypeSequential ? splatAttr
642 loc, moduleTranslation);
645 if (llvmType->isVectorTy())
646 return llvm::ConstantVector::getSplat(
648 if (llvmType->isArrayTy()) {
650 if (child->isZeroValue()) {
653 if (llvm::ConstantDataSequential::isElementTypeCompatible(
656 if (isa<llvm::IntegerType>(elementType)) {
657 if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
658 if (ci->getBitWidth() == 8) {
663 if (ci->getBitWidth() == 16) {
668 if (ci->getBitWidth() == 32) {
673 if (ci->getBitWidth() == 64) {
683 std::vector<llvm::Constant *> constants(numElements, child);
690 if (llvm::Constant *result =
692 llvmType, moduleTranslation)) {
696 if (
auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
702 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
703 assert(elementsAttr.getShapedType().hasStaticShape());
704 assert(!elementsAttr.getShapedType().getShape().empty() &&
705 "unexpected empty elements attribute shape");
708 constants.reserve(elementsAttr.getNumElements());
710 for (
auto n : elementsAttr.getValues<
Attribute>()) {
713 if (!constants.back())
718 constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
719 assert(constantsRef.empty() &&
"did not consume all elemental constants");
723 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
730 if (
auto arrayAttr = dyn_cast<ArrayAttr>(attr)) {
731 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
732 llvm::Type *elementType = arrayTy->getElementType();
734 llvm::Constant *elementCst =
nullptr;
736 constants.reserve(arrayTy->getNumElements());
737 for (
Attribute elementAttr : arrayAttr) {
741 if (!previousElementAttr || previousElementAttr != elementAttr) {
742 previousElementAttr = elementAttr;
748 constants.push_back(elementCst);
754 emitError(loc,
"unsupported constant value");
758 ModuleTranslation::ModuleTranslation(
Operation *module,
759 std::unique_ptr<llvm::Module> llvmModule)
760 : mlirModule(module), llvmModule(std::move(llvmModule)),
764 *this, *this->llvmModule)),
765 typeTranslator(this->llvmModule->
getContext()),
768 "mlirModule should honor LLVM's module semantics.");
771 ModuleTranslation::~ModuleTranslation() {
772 if (ompBuilder && !ompBuilder->isFinalized())
773 ompBuilder->finalize();
778 toProcess.push_back(®ion);
779 while (!toProcess.empty()) {
780 Region *current = toProcess.pop_back_val();
781 for (
Block &block : *current) {
782 blockMapping.erase(&block);
783 for (
Value arg : block.getArguments())
784 valueMapping.erase(arg);
786 for (
Value value : op.getResults())
787 valueMapping.erase(value);
788 if (op.hasSuccessors())
789 branchMapping.erase(&op);
790 if (isa<LLVM::GlobalOp>(op))
791 globalsMapping.erase(&op);
792 if (isa<LLVM::AliasOp>(op))
793 aliasesMapping.erase(&op);
794 if (isa<LLVM::IFuncOp>(op))
795 ifuncMapping.erase(&op);
796 if (isa<LLVM::CallOp>(op))
797 callMapping.erase(&op);
800 llvm::map_range(op.getRegions(), [](
Region &r) { return &r; }));
809 unsigned numArguments,
unsigned index) {
811 if (isa<LLVM::BrOp>(terminator))
818 auto branch = cast<BranchOpInterface>(terminator);
821 (!seenSuccessors.contains(successor) || successorOperands.
empty()) &&
822 "successors with arguments in LLVM branches must be different blocks");
823 seenSuccessors.insert(successor);
829 if (
auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
832 return condBranchOp.getSuccessor(0) == current
833 ? condBranchOp.getTrueDestOperands()[index]
834 : condBranchOp.getFalseDestOperands()[index];
837 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
840 if (switchOp.getDefaultDestination() == current)
841 return switchOp.getDefaultOperands()[index];
843 if (i.value() == current)
844 return switchOp.getCaseOperands(i.index())[index];
847 if (
auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(terminator)) {
850 if (indBrOp->getSuccessor(i.index()) == current)
851 return indBrOp.getSuccessorOperands(i.index())[index];
855 if (
auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
856 return invokeOp.getNormalDest() == current
857 ? invokeOp.getNormalDestOperands()[index]
858 : invokeOp.getUnwindDestOperands()[index];
862 "only branch, switch or invoke operations can be terminators "
863 "of a block that has successors");
871 for (
Block &bb : llvm::drop_begin(region)) {
872 llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
873 auto phis = llvmBB->phis();
874 auto numArguments = bb.getNumArguments();
875 assert(numArguments == std::distance(phis.begin(), phis.end()));
877 for (
auto *pred : bb.getPredecessors()) {
883 llvm::Instruction *terminator =
884 state.lookupBranch(pred->getTerminator());
885 assert(terminator &&
"missing the mapping for a terminator");
887 &bb, pred, numArguments, index)),
888 terminator->getParent());
897 llvm::Module *module = builder.GetInsertBlock()->getModule();
899 llvm::Intrinsic::getOrInsertDeclaration(module, intrinsic, tys);
900 return builder.CreateCall(fn, args);
909 assert(immArgPositions.size() == immArgAttrNames.size() &&
910 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
914 size_t numOpBundleOperands = 0;
915 auto opBundleSizesAttr = cast_if_present<DenseI32ArrayAttr>(
916 intrOp->
getAttr(LLVMDialect::getOpBundleSizesAttrName()));
917 auto opBundleTagsAttr = cast_if_present<ArrayAttr>(
918 intrOp->
getAttr(LLVMDialect::getOpBundleTagsAttrName()));
920 if (opBundleSizesAttr && opBundleTagsAttr) {
921 ArrayRef<int> opBundleSizes = opBundleSizesAttr.asArrayRef();
922 assert(opBundleSizes.size() == opBundleTagsAttr.size() &&
923 "operand bundles and tags do not match");
925 numOpBundleOperands =
926 std::accumulate(opBundleSizes.begin(), opBundleSizes.end(),
size_t(0));
927 assert(numOpBundleOperands <= intrOp->getNumOperands() &&
928 "operand bundle operands is more than the number of operands");
931 size_t nextOperandIdx = 0;
932 opBundles.reserve(opBundleSizesAttr.size());
934 for (
auto [opBundleTagAttr, bundleSize] :
935 llvm::zip(opBundleTagsAttr, opBundleSizes)) {
936 auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
938 operands.slice(nextOperandIdx, bundleSize));
939 opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
940 nextOperandIdx += bundleSize;
945 auto opOperands = intrOp->
getOperands().drop_back(numOpBundleOperands);
946 auto operands = moduleTranslation.
lookupValues(opOperands);
948 for (
auto [immArgPos, immArgName] :
949 llvm::zip(immArgPositions, immArgAttrNames)) {
950 auto attr = llvm::cast<TypedAttr>(intrOp->
getAttr(immArgName));
951 assert(attr.getType().isIntOrFloat() &&
"expected int or float immarg");
952 auto *type = moduleTranslation.
convertType(attr.getType());
954 type, attr, intrOp->
getLoc(), moduleTranslation);
957 for (
auto &arg : args) {
959 arg = operands[opArg++];
964 for (
unsigned overloadedResultIdx : overloadedResults) {
965 if (numResults > 1) {
967 overloadedTypes.push_back(moduleTranslation.
convertType(
969 .getBody()[overloadedResultIdx]));
971 overloadedTypes.push_back(
975 for (
unsigned overloadedOperandIdx : overloadedOperands)
976 overloadedTypes.push_back(args[overloadedOperandIdx]->
getType());
977 llvm::Module *module = builder.GetInsertBlock()->getModule();
978 llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
979 module, intrinsic, overloadedTypes);
981 return builder.CreateCall(llvmIntr, args, opBundles);
986 LogicalResult ModuleTranslation::convertOperation(
Operation &op,
987 llvm::IRBuilderBase &builder,
988 bool recordInsertions) {
991 return op.
emitError(
"cannot be converted to LLVM IR: missing "
992 "`LLVMTranslationDialectInterface` registration for "
996 InstructionCapturingInserter::CollectionScope scope(builder,
999 return op.
emitError(
"LLVM Translation failed for operation: ")
1002 return convertDialectAttributes(&op, scope.getCapturedInstructions());
1012 LogicalResult ModuleTranslation::convertBlockImpl(
Block &bb,
1013 bool ignoreArguments,
1014 llvm::IRBuilderBase &builder,
1015 bool recordInsertions) {
1017 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
1025 if (!ignoreArguments) {
1027 unsigned numPredecessors =
1028 std::distance(predecessors.begin(), predecessors.end());
1030 auto wrappedType = arg.getType();
1033 "block argument does not have an LLVM type");
1034 builder.SetCurrentDebugLocation(
1035 debugTranslation->translateLoc(arg.getLoc(), subprogram));
1037 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
1043 for (
auto &op : bb) {
1045 builder.SetCurrentDebugLocation(
1046 debugTranslation->translateLoc(op.
getLoc(), subprogram));
1048 if (
failed(convertOperation(op, builder, recordInsertions)))
1052 if (
auto iface = dyn_cast<WeightedBranchOpInterface>(op))
1071 llvm::Constant *cst) {
1072 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1073 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1079 llvm::GlobalValue *gv) {
1080 if (dsoLocalRequested)
1081 gv->setDSOLocal(
true);
1090 static FailureOr<llvm::Attribute>
1092 StringRef value = StringRef()) {
1093 auto kind = llvm::Attribute::getAttrKindFromName(key);
1097 if (llvm::Attribute::isIntAttrKind(
kind)) {
1099 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1102 if (!value.getAsInteger(0, result))
1108 return emitError(loc) <<
"LLVM attribute '" << key
1109 <<
"' does not expect a value, found '" << value
1123 static FailureOr<llvm::AttrBuilder>
1125 ArrayAttr arrayAttr, StringRef arrayAttrName) {
1126 llvm::AttrBuilder attrBuilder(ctx);
1131 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1132 FailureOr<llvm::Attribute> llvmAttr =
1136 attrBuilder.addAttribute(*llvmAttr);
1140 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1141 if (!arrayAttr || arrayAttr.size() != 2)
1142 return emitError(loc) <<
"expected '" << arrayAttrName
1143 <<
"' to contain string or array attributes";
1145 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1146 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1147 if (!keyAttr || !valueAttr)
1148 return emitError(loc) <<
"expected arrays within '" << arrayAttrName
1149 <<
"' to contain two strings";
1152 loc, ctx, keyAttr.getValue(), valueAttr.getValue());
1155 attrBuilder.addAttribute(*llvmAttr);
1161 LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
1170 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1172 llvm::Constant *cst =
nullptr;
1173 if (op.getValueOrNull()) {
1176 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1177 cst = llvm::ConstantDataArray::getString(
1178 llvmModule->getContext(), strAttr.getValue(),
false);
1179 type = cst->getType();
1186 auto linkage = convertLinkageToLLVM(op.getLinkage());
1192 if (!dropInitializer && !cst)
1194 else if (dropInitializer && cst)
1197 auto *var =
new llvm::GlobalVariable(
1198 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1200 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1201 : llvm::GlobalValue::NotThreadLocal,
1202 op.getAddrSpace(), op.getExternallyInitialized());
1204 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1205 auto selectorOp = cast<ComdatSelectorOp>(
1207 var->setComdat(comdatMapping.lookup(selectorOp));
1210 if (op.getUnnamedAddr().has_value())
1211 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1213 if (op.getSection().has_value())
1214 var->setSection(*op.getSection());
1218 std::optional<uint64_t> alignment = op.getAlignment();
1219 if (alignment.has_value())
1220 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1222 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1224 globalsMapping.try_emplace(op, var);
1227 if (op.getDbgExprs()) {
1228 for (
auto exprAttr :
1229 op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1230 llvm::DIGlobalVariableExpression *diGlobalExpr =
1231 debugTranslation->translateGlobalVariableExpression(exprAttr);
1232 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1233 var->addDebugInfo(diGlobalExpr);
1252 llvm::DIScope *scope = diGlobalVar->getScope();
1253 if (
auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1254 scope = mod->getScope();
1255 else if (
auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1257 dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1258 scope = sp->getUnit();
1259 }
else if (
auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1260 scope = sp->getUnit();
1263 if (llvm::DICompileUnit *compileUnit =
1264 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1267 allGVars[compileUnit].push_back(diGlobalExpr);
1273 FailureOr<llvm::AttrBuilder> convertedTargetSpecificAttrs =
1275 op.getTargetSpecificAttrsAttr(),
1276 op.getTargetSpecificAttrsAttrName());
1277 if (
failed(convertedTargetSpecificAttrs))
1279 var->addAttributes(*convertedTargetSpecificAttrs);
1283 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1285 llvm::Constant *cst =
nullptr;
1286 llvm::GlobalValue::LinkageTypes linkage =
1287 convertLinkageToLLVM(op.getLinkage());
1288 llvm::Module &llvmMod = *llvmModule;
1291 llvm::GlobalAlias *var = llvm::GlobalAlias::create(
1292 type, op.getAddrSpace(), linkage, op.getSymName(), cst,
1295 var->setThreadLocalMode(op.getThreadLocal_()
1296 ? llvm::GlobalAlias::GeneralDynamicTLSModel
1297 : llvm::GlobalAlias::NotThreadLocal);
1302 if (op.getUnnamedAddr().has_value())
1303 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1305 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1307 aliasesMapping.try_emplace(op, var);
1311 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1312 if (
Block *initializer = op.getInitializerBlock()) {
1313 llvm::IRBuilder<llvm::TargetFolder> builder(
1314 llvmModule->getContext(),
1315 llvm::TargetFolder(llvmModule->getDataLayout()));
1317 [[maybe_unused]]
int numConstantsHit = 0;
1318 [[maybe_unused]]
int numConstantsErased = 0;
1321 for (
auto &op : initializer->without_terminator()) {
1322 if (
failed(convertOperation(op, builder)))
1335 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1339 auto [iterator, inserted] =
1340 constantAggregateUseMap.try_emplace(agg, numUsers);
1343 iterator->second += numUsers;
1349 auto cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1352 auto iter = constantAggregateUseMap.find(cst);
1353 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1355 if (iter->second == 0) {
1358 if (cst->user_empty()) {
1359 cst->destroyConstant();
1360 numConstantsErased++;
1362 constantAggregateUseMap.erase(iter);
1367 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1368 llvm::Constant *cst =
1369 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1370 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1372 global->setInitializer(cst);
1376 for (
auto it : constantAggregateUseMap) {
1377 auto cst = it.first;
1378 cst->removeDeadConstantUsers();
1379 if (cst->user_empty()) {
1380 cst->destroyConstant();
1381 numConstantsErased++;
1385 LLVM_DEBUG(llvm::dbgs()
1386 <<
"Convert initializer for " << op.
getName() <<
"\n";
1387 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1389 << numConstantsErased <<
" dangling constants erased\n";);
1395 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1396 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1397 if (!ctorOp && !dtorOp)
1403 if ((ctorOp && ctorOp.getCtors().empty()) ||
1404 (dtorOp && dtorOp.getDtors().empty())) {
1405 llvm::IRBuilder<llvm::TargetFolder> builder(
1406 llvmModule->getContext(),
1407 llvm::TargetFolder(llvmModule->getDataLayout()));
1409 builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1411 llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1412 (void)
new llvm::GlobalVariable(
1413 *llvmModule, zeroInit->getType(),
false,
1414 llvm::GlobalValue::AppendingLinkage, zeroInit,
1415 ctorOp ?
"llvm.global_ctors" :
"llvm.global_dtors");
1418 ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1419 :
llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1420 auto appendGlobalFn =
1421 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1422 for (
const auto &[sym, prio] : range) {
1425 appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1431 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1432 if (
failed(convertDialectAttributes(op, {})))
1437 for (
const auto &[compileUnit, globals] : allGVars) {
1438 compileUnit->replaceGlobalVariables(
1443 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1444 Block &initializer = op.getInitializerBlock();
1445 llvm::IRBuilder<llvm::TargetFolder> builder(
1446 llvmModule->getContext(),
1447 llvm::TargetFolder(llvmModule->getDataLayout()));
1450 if (
failed(convertOperation(op, builder)))
1457 auto *cst = cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1458 assert(aliasesMapping.count(op));
1459 auto *alias = cast<llvm::GlobalAlias>(aliasesMapping[op]);
1460 alias->setAliasee(cst);
1463 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>())
1464 if (
failed(convertDialectAttributes(op, {})))
1472 const llvm::APInt &value) {
1479 const llvm::APInt &value) {
1487 llvm::Metadata *typeMD =
1489 llvm::Metadata *isSignedMD =
1499 values, std::back_inserter(mdValues), [&context](int32_t value) {
1505 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1508 blockMapping.clear();
1509 valueMapping.clear();
1510 branchMapping.clear();
1514 for (
auto [mlirArg, llvmArg] :
1515 llvm::zip(func.getArguments(), llvmFunc->args()))
1519 if (func.getPersonality()) {
1520 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1521 if (llvm::Constant *pfunc =
getLLVMConstant(ty, func.getPersonalityAttr(),
1522 func.getLoc(), *
this))
1523 llvmFunc->setPersonalityFn(pfunc);
1526 if (std::optional<StringRef> section = func.getSection())
1527 llvmFunc->setSection(*section);
1529 if (func.getArmStreaming())
1530 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1531 else if (func.getArmLocallyStreaming())
1532 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1533 else if (func.getArmStreamingCompatible())
1534 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1536 if (func.getArmNewZa())
1537 llvmFunc->addFnAttr(
"aarch64_new_za");
1538 else if (func.getArmInZa())
1539 llvmFunc->addFnAttr(
"aarch64_in_za");
1540 else if (func.getArmOutZa())
1541 llvmFunc->addFnAttr(
"aarch64_out_za");
1542 else if (func.getArmInoutZa())
1543 llvmFunc->addFnAttr(
"aarch64_inout_za");
1544 else if (func.getArmPreservesZa())
1545 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1547 if (
auto targetCpu = func.getTargetCpu())
1548 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1550 if (
auto tuneCpu = func.getTuneCpu())
1551 llvmFunc->addFnAttr(
"tune-cpu", *tuneCpu);
1553 if (
auto reciprocalEstimates = func.getReciprocalEstimates())
1554 llvmFunc->addFnAttr(
"reciprocal-estimates", *reciprocalEstimates);
1556 if (
auto preferVectorWidth = func.getPreferVectorWidth())
1557 llvmFunc->addFnAttr(
"prefer-vector-width", *preferVectorWidth);
1559 if (
auto attr = func.getVscaleRange())
1560 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1562 attr->getMaxRange().getInt()));
1564 if (
auto unsafeFpMath = func.getUnsafeFpMath())
1565 llvmFunc->addFnAttr(
"unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1567 if (
auto noInfsFpMath = func.getNoInfsFpMath())
1568 llvmFunc->addFnAttr(
"no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1570 if (
auto noNansFpMath = func.getNoNansFpMath())
1571 llvmFunc->addFnAttr(
"no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1573 if (
auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1574 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1575 llvm::toStringRef(*noSignedZerosFpMath));
1577 if (
auto denormalFpMath = func.getDenormalFpMath())
1578 llvmFunc->addFnAttr(
"denormal-fp-math", *denormalFpMath);
1580 if (
auto denormalFpMathF32 = func.getDenormalFpMathF32())
1581 llvmFunc->addFnAttr(
"denormal-fp-math-f32", *denormalFpMathF32);
1583 if (
auto fpContract = func.getFpContract())
1584 llvmFunc->addFnAttr(
"fp-contract", *fpContract);
1586 if (
auto instrumentFunctionEntry = func.getInstrumentFunctionEntry())
1587 llvmFunc->addFnAttr(
"instrument-function-entry", *instrumentFunctionEntry);
1589 if (
auto instrumentFunctionExit = func.getInstrumentFunctionExit())
1590 llvmFunc->addFnAttr(
"instrument-function-exit", *instrumentFunctionExit);
1593 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1594 for (
auto &bb : func) {
1595 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1596 llvmBB->insertInto(llvmFunc);
1603 for (
Block *bb : blocks) {
1604 CapturingIRBuilder builder(llvmContext,
1605 llvm::TargetFolder(llvmModule->getDataLayout()));
1606 if (
failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1616 return convertDialectAttributes(func, {});
1619 LogicalResult ModuleTranslation::convertDialectAttributes(
1630 llvm::Function *llvmFunc) {
1631 if (!func.getMemoryEffects())
1634 MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1637 llvm::MemoryEffects newMemEffects =
1638 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1639 convertModRefInfoToLLVM(memEffects.getArgMem()));
1640 newMemEffects |= llvm::MemoryEffects(
1641 llvm::MemoryEffects::Location::InaccessibleMem,
1642 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1644 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1645 convertModRefInfoToLLVM(memEffects.getOther()));
1646 llvmFunc->setMemoryEffects(newMemEffects);
1651 llvm::Function *llvmFunc) {
1652 if (func.getNoInlineAttr())
1653 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1654 if (func.getAlwaysInlineAttr())
1655 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1656 if (func.getOptimizeNoneAttr())
1657 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1658 if (func.getConvergentAttr())
1659 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1660 if (func.getNoUnwindAttr())
1661 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1662 if (func.getWillReturnAttr())
1663 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1664 if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
1665 llvmFunc->addFnAttr(
"target-features", targetFeatAttr.getFeaturesString());
1666 if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())
1667 llvmFunc->addFnAttr(
"frame-pointer", stringifyFramePointerKind(
1668 fpAttr.getFramePointerKind()));
1669 if (UWTableKindAttr uwTableKindAttr = func.getUwtableKindAttr())
1670 llvmFunc->setUWTableKind(
1671 convertUWTableKindToLLVM(uwTableKindAttr.getUwtableKind()));
1677 llvm::Function *llvmFunc,
1679 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1681 if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1682 Type type = vecTypeHint.getHint().getValue();
1683 llvm::Type *llvmType = translation.
convertType(type);
1684 bool isSigned = vecTypeHint.getIsSigned();
1685 llvmFunc->setMetadata(
1686 func.getVecTypeHintAttrName(),
1691 func.getWorkGroupSizeHint()) {
1692 llvmFunc->setMetadata(
1693 func.getWorkGroupSizeHintAttrName(),
1698 func.getReqdWorkGroupSize()) {
1699 llvmFunc->setMetadata(
1700 func.getReqdWorkGroupSizeAttrName(),
1704 if (std::optional<uint32_t> intelReqdSubGroupSize =
1705 func.getIntelReqdSubGroupSize()) {
1706 llvmFunc->setMetadata(
1707 func.getIntelReqdSubGroupSizeAttrName(),
1709 llvm::APInt(32, *intelReqdSubGroupSize)));
1714 llvm::Attribute::AttrKind llvmKind,
1719 .Case<TypeAttr>([&](
auto typeAttr) {
1720 attrBuilder.addTypeAttr(
1721 llvmKind, moduleTranslation.
convertType(typeAttr.getValue()));
1724 .Case<IntegerAttr>([&](
auto intAttr) {
1725 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1728 .Case<UnitAttr>([&](
auto) {
1729 attrBuilder.addAttribute(llvmKind);
1732 .Case<LLVM::ConstantRangeAttr>([&](
auto rangeAttr) {
1733 attrBuilder.addConstantRangeAttr(
1735 llvm::ConstantRange(rangeAttr.getLower(), rangeAttr.getUpper()));
1738 .Default([loc](
auto) {
1739 return emitError(loc,
"unsupported parameter attribute type");
1743 FailureOr<llvm::AttrBuilder>
1744 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func,
int argIdx,
1745 DictionaryAttr paramAttrs) {
1746 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1750 for (
auto namedAttr : paramAttrs) {
1751 auto it = attrNameToKindMapping.find(namedAttr.getName());
1752 if (it != attrNameToKindMapping.end()) {
1753 llvm::Attribute::AttrKind llvmKind = it->second;
1757 }
else if (namedAttr.getNameDialect()) {
1767 ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call,
1770 if (ArrayAttr argAttrsArray = attrsOp.getArgAttrsAttr()) {
1771 unsigned argAttrIdx = 0;
1772 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
1773 immArgPositions.end());
1774 for (
unsigned argIdx : llvm::seq<unsigned>(call->arg_size())) {
1775 if (argAttrIdx >= argAttrsArray.size())
1778 if (immArgPositionsSet.contains(argIdx))
1781 auto argAttrs = cast<DictionaryAttr>(argAttrsArray[argAttrIdx++]);
1782 if (argAttrs.empty())
1785 FailureOr<llvm::AttrBuilder> attrBuilder =
1786 convertParameterAttrs(attrsOp->getLoc(), argAttrs);
1789 call->addParamAttrs(argIdx, *attrBuilder);
1794 if (ArrayAttr resAttrsArray = attrsOp.getResAttrsAttr()) {
1795 if (!resAttrsArray.empty()) {
1796 auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
1797 FailureOr<llvm::AttrBuilder> attrBuilder =
1798 convertParameterAttrs(attrsOp->getLoc(), resAttrs);
1801 call->addRetAttrs(*attrBuilder);
1808 FailureOr<llvm::AttrBuilder>
1809 ModuleTranslation::convertParameterAttrs(
Location loc,
1810 DictionaryAttr paramAttrs) {
1811 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1814 for (
auto namedAttr : paramAttrs) {
1815 auto it = attrNameToKindMapping.find(namedAttr.getName());
1816 if (it != attrNameToKindMapping.end()) {
1817 llvm::Attribute::AttrKind llvmKind = it->second;
1827 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1830 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1831 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1833 cast<llvm::FunctionType>(
convertType(
function.getFunctionType())));
1834 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1835 llvmFunc->setLinkage(convertLinkageToLLVM(
function.getLinkage()));
1836 llvmFunc->setCallingConv(convertCConvToLLVM(
function.getCConv()));
1847 if (std::optional<uint64_t> entryCount =
function.getFunctionEntryCount())
1848 llvmFunc->setEntryCount(entryCount.value());
1851 if (ArrayAttr allResultAttrs =
function.getAllResultAttrs()) {
1852 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1853 FailureOr<llvm::AttrBuilder> attrBuilder =
1854 convertParameterAttrs(
function, -1, resultAttrs);
1857 llvmFunc->addRetAttrs(*attrBuilder);
1863 FailureOr<llvm::AttrBuilder> attrBuilder =
1864 convertParameterAttrs(
function, argIdx, argAttrs);
1867 llvmArg.addAttrs(*attrBuilder);
1872 FailureOr<llvm::AttrBuilder> convertedPassthroughAttrs =
1874 function.getPassthroughAttr(),
1875 function.getPassthroughAttrName());
1876 if (
failed(convertedPassthroughAttrs))
1878 llvmFunc->addFnAttrs(*convertedPassthroughAttrs);
1881 llvmFunc->setVisibility(convertVisibilityToLLVM(
function.getVisibility_()));
1884 if (std::optional<mlir::SymbolRefAttr> comdat =
function.getComdat()) {
1885 auto selectorOp = cast<ComdatSelectorOp>(
1887 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1890 if (
auto gc =
function.getGarbageCollector())
1891 llvmFunc->setGC(gc->str());
1893 if (
auto unnamedAddr =
function.getUnnamedAddr())
1894 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1896 if (
auto alignment =
function.getAlignment())
1897 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1900 debugTranslation->translate(
function, *llvmFunc);
1906 LogicalResult ModuleTranslation::convertFunctions() {
1908 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1911 if (
function.isExternal()) {
1912 if (
failed(convertDialectAttributes(
function, {})))
1917 if (
failed(convertOneFunction(
function)))
1924 LogicalResult ModuleTranslation::convertIFuncs() {
1925 for (
auto op :
getModuleBody(mlirModule).getOps<IFuncOp>()) {
1926 llvm::Type *type =
convertType(op.getIFuncType());
1927 llvm::GlobalValue::LinkageTypes linkage =
1928 convertLinkageToLLVM(op.getLinkage());
1929 llvm::Constant *resolver;
1931 resolver = cast<llvm::Constant>(resolverFn);
1934 op.getResolverAttr());
1935 resolver = cast<llvm::Constant>(
lookupAlias(aliasOp));
1939 llvm::GlobalIFunc::create(type, op.getAddressSpace(), linkage,
1940 op.getSymName(), resolver, llvmModule.get());
1942 ifunc->setUnnamedAddr(convertUnnamedAddrToLLVM(op.getUnnamedAddr()));
1943 ifunc->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1945 ifuncMapping.try_emplace(op, ifunc);
1951 LogicalResult ModuleTranslation::convertComdats() {
1952 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
1953 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1955 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1957 <<
"comdat selection symbols must be unique even in different "
1959 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1960 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1961 comdatMapping.try_emplace(selectorOp, comdat);
1967 LogicalResult ModuleTranslation::convertUnresolvedBlockAddress() {
1968 for (
auto &[blockAddressOp, llvmCst] : unresolvedBlockAddressMapping) {
1969 BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
1971 assert(llvmBlock &&
"expected LLVM blocks to be already translated");
1975 lookupFunction(blockAddressAttr.getFunction().getValue()), llvmBlock);
1976 llvmCst->replaceAllUsesWith(llvmBlockAddr);
1977 assert(llvmCst->use_empty() &&
"expected all uses to be replaced");
1978 cast<llvm::GlobalVariable>(llvmCst)->eraseFromParent();
1980 unresolvedBlockAddressMapping.clear();
1985 llvm::Instruction *inst) {
1986 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1987 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1992 auto [scopeIt, scopeInserted] =
1993 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
1995 return scopeIt->second;
1996 llvm::LLVMContext &ctx = llvmModule->getContext();
1997 auto dummy = llvm::MDNode::getTemporary(ctx, {});
1999 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
2000 aliasScopeAttr.getDomain(),
nullptr);
2001 if (insertedDomain) {
2004 operands.push_back(dummy.get());
2005 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
2009 llvm::Metadata *replacement;
2010 if (
auto stringAttr =
2011 dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId()))
2014 replacement = domainIt->second;
2015 domainIt->second->replaceOperandWith(0, replacement);
2018 assert(domainIt->second &&
"Scope's domain should already be valid");
2021 operands.push_back(dummy.get());
2022 operands.push_back(domainIt->second);
2023 if (StringAttr description = aliasScopeAttr.getDescription())
2027 llvm::Metadata *replacement;
2028 if (
auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId()))
2031 replacement = scopeIt->second;
2032 scopeIt->second->replaceOperandWith(0, replacement);
2033 return scopeIt->second;
2039 nodes.reserve(aliasScopeAttrs.size());
2040 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
2046 llvm::Instruction *inst) {
2047 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
2048 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
2051 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
2052 inst->setMetadata(
kind, node);
2055 populateScopeMetadata(op.getAliasScopesOrNull(),
2056 llvm::LLVMContext::MD_alias_scope);
2057 populateScopeMetadata(op.getNoAliasScopesOrNull(),
2058 llvm::LLVMContext::MD_noalias);
2061 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
2062 return tbaaMetadataMapping.lookup(tbaaAttr);
2066 llvm::Instruction *inst) {
2067 ArrayAttr tagRefs = op.getTBAATagsOrNull();
2068 if (!tagRefs || tagRefs.empty())
2075 if (tagRefs.size() > 1) {
2076 op.emitWarning() <<
"TBAA access tags were not translated, because LLVM "
2077 "IR only supports a single tag per instruction";
2081 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
2082 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
2086 DereferenceableOpInterface op, llvm::Instruction *inst) {
2087 DereferenceableAttr derefAttr = op.getDereferenceableOrNull();
2095 unsigned kindId = derefAttr.getMayBeNull()
2096 ? llvm::LLVMContext::MD_dereferenceable_or_null
2097 : llvm::LLVMContext::MD_dereferenceable;
2098 inst->setMetadata(kindId, derefSizeNode);
2103 llvm::transform(op.getWeights(), std::back_inserter(weights),
2104 [](int32_t value) { return static_cast<uint32_t>(value); });
2105 if (weights.empty())
2109 assert(inst &&
"expected the operation to have a mapping to an instruction");
2111 llvm::LLVMContext::MD_prof,
2115 LogicalResult ModuleTranslation::createTBAAMetadata() {
2116 llvm::LLVMContext &ctx = llvmModule->getContext();
2128 walker.
addWalk([&](TBAARootAttr root) {
2129 tbaaMetadataMapping.insert(
2133 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
2136 for (TBAAMemberAttr member : descriptor.getMembers()) {
2137 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
2145 walker.
addWalk([&](TBAATagAttr tag) {
2148 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
2149 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
2153 if (tag.getConstant())
2160 mlirModule->
walk([&](AliasAnalysisOpInterface analysisOpInterface) {
2161 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
2168 LogicalResult ModuleTranslation::createIdentMetadata() {
2170 LLVMDialect::getIdentAttrName())) {
2171 StringRef ident = attr;
2172 llvm::LLVMContext &ctx = llvmModule->getContext();
2173 llvm::NamedMDNode *namedMd =
2174 llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
2176 namedMd->addOperand(md);
2182 LogicalResult ModuleTranslation::createCommandlineMetadata() {
2184 LLVMDialect::getCommandlineAttrName())) {
2185 StringRef cmdLine = attr;
2186 llvm::LLVMContext &ctx = llvmModule->getContext();
2187 llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
2188 LLVMDialect::getCommandlineAttrName());
2191 nmd->addOperand(md);
2197 LogicalResult ModuleTranslation::createDependentLibrariesMetadata() {
2199 LLVM::LLVMDialect::getDependentLibrariesAttrName())) {
2201 llvmModule->getOrInsertNamedMetadata(
"llvm.dependent-libraries");
2202 llvm::LLVMContext &ctx = llvmModule->getContext();
2204 cast<ArrayAttr>(dependentLibrariesAttr).getAsRange<StringAttr>()) {
2207 nmd->addOperand(md);
2214 llvm::Instruction *inst) {
2215 LoopAnnotationAttr attr =
2217 .Case<LLVM::BrOp, LLVM::CondBrOp>(
2218 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
2221 llvm::MDNode *loopMD =
2222 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
2223 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
2227 auto iface = cast<DisjointFlagInterface>(op);
2229 if (
auto disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
2230 disjointInst->setIsDisjoint(iface.getIsDisjoint());
2240 remapped.reserve(values.size());
2241 for (
Value v : values)
2248 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
2249 ompBuilder->initialize();
2254 ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
2262 return ompBuilder.get();
2266 llvm::DILocalScope *scope) {
2267 return debugTranslation->translateLoc(loc, scope);
2270 llvm::DIExpression *
2272 return debugTranslation->translateExpression(attr);
2275 llvm::DIGlobalVariableExpression *
2277 LLVM::DIGlobalVariableExpressionAttr attr) {
2278 return debugTranslation->translateGlobalVariableExpression(attr);
2282 return debugTranslation->translate(attr);
2287 return convertRoundingModeToLLVM(rounding);
2291 LLVM::FPExceptionBehavior exceptionBehavior) {
2292 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
2297 return llvmModule->getOrInsertNamedMetadata(name);
2300 static std::unique_ptr<llvm::Module>
2304 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
2305 if (
auto dataLayoutAttr =
2307 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
2309 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(
""));
2310 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
2311 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2315 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
2316 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2321 if (
failed(llvmDataLayout))
2323 llvmModule->setDataLayout(*llvmDataLayout);
2325 if (
auto targetTripleAttr =
2327 llvmModule->setTargetTriple(
2328 llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
2331 LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
2332 auto asmArrayAttr = dyn_cast<ArrayAttr>(asmAttr);
2333 if (!asmArrayAttr) {
2334 m->
emitError(
"expected an array attribute for a module level asm");
2339 auto asmStrAttr = dyn_cast<StringAttr>(elt);
2342 "expected a string attribute for each entry of a module level asm");
2345 llvmModule->appendModuleInlineAsm(asmStrAttr.getValue());
2352 std::unique_ptr<llvm::Module>
2354 StringRef name,
bool disableVerification) {
2356 module->
emitOpError(
"can not be translated to an LLVMIR module");
2360 std::unique_ptr<llvm::Module> llvmModule =
2369 llvm::IRBuilder<llvm::TargetFolder> llvmBuilder(
2371 llvm::TargetFolder(translator.getLLVMModule()->getDataLayout()));
2377 if (
failed(translator.convertOperation(*module, llvmBuilder)))
2380 if (
failed(translator.convertComdats()))
2382 if (
failed(translator.convertFunctionSignatures()))
2384 if (
failed(translator.convertGlobalsAndAliases()))
2386 if (
failed(translator.convertIFuncs()))
2388 if (
failed(translator.createTBAAMetadata()))
2390 if (
failed(translator.createIdentMetadata()))
2392 if (
failed(translator.createCommandlineMetadata()))
2394 if (
failed(translator.createDependentLibrariesMetadata()))
2399 if (!isa<LLVM::LLVMFuncOp, LLVM::AliasOp, LLVM::GlobalOp,
2400 LLVM::GlobalCtorsOp, LLVM::GlobalDtorsOp, LLVM::ComdatOp,
2401 LLVM::IFuncOp>(&o) &&
2403 failed(translator.convertOperation(o, llvmBuilder))) {
2411 if (
failed(translator.convertFunctions()))
2416 if (
failed(translator.convertUnresolvedBlockAddress()))
2421 translator.debugTranslation->addModuleFlagsIfNotPresent();
2424 if (
auto *ompBuilder = translator.getOpenMPBuilder())
2425 ompBuilder->finalize();
2427 if (!disableVerification &&
2428 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2431 return std::move(translator.llvmModule);
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1242::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 FailureOr< llvm::Attribute > convertMLIRAttributeToLLVM(Location loc, llvm::LLVMContext &ctx, StringRef key, StringRef value=StringRef())
Attempts to translate an MLIR attribute identified by key, optionally with the given value,...
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 FailureOr< llvm::AttrBuilder > convertMLIRAttributesToLLVM(Location loc, llvm::LLVMContext &ctx, ArrayAttr arrayAttr, StringRef arrayAttrName)
Converts the MLIR attributes listed in the given array attribute into LLVM attributes.
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 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.
MLIRContext * getContext() const
Return the context this attribute belongs to.
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.
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.
SymbolTableCollection & symbolTable()
LogicalResult convertArgAndResultAttrs(ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call, ArrayRef< unsigned > immArgPositions={})
Converts argument and result attributes from attrsOp to LLVM IR attributes on the call instruction.
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::GlobalValue * lookupAlias(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global alias va...
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...
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
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),...
MLIRContext * getContext()
Return the context this operation is associated with.
Location getLoc()
The source location the operation was defined or derived from.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
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.
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
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.
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
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...