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() && !elementType->isFPOrFPVectorTy()) {
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 = llvm::sum_of(opBundleSizes);
926 assert(numOpBundleOperands <= intrOp->getNumOperands() &&
927 "operand bundle operands is more than the number of operands");
930 size_t nextOperandIdx = 0;
931 opBundles.reserve(opBundleSizesAttr.size());
933 for (
auto [opBundleTagAttr, bundleSize] :
934 llvm::zip(opBundleTagsAttr, opBundleSizes)) {
935 auto bundleTag = cast<StringAttr>(opBundleTagAttr).str();
937 operands.slice(nextOperandIdx, bundleSize));
938 opBundles.emplace_back(std::move(bundleTag), std::move(bundleOperands));
939 nextOperandIdx += bundleSize;
944 auto opOperands = intrOp->
getOperands().drop_back(numOpBundleOperands);
945 auto operands = moduleTranslation.
lookupValues(opOperands);
947 for (
auto [immArgPos, immArgName] :
948 llvm::zip(immArgPositions, immArgAttrNames)) {
949 auto attr = llvm::cast<TypedAttr>(intrOp->
getAttr(immArgName));
950 assert(attr.getType().isIntOrFloat() &&
"expected int or float immarg");
951 auto *type = moduleTranslation.
convertType(attr.getType());
953 type, attr, intrOp->
getLoc(), moduleTranslation);
956 for (
auto &arg : args) {
958 arg = operands[opArg++];
963 for (
unsigned overloadedResultIdx : overloadedResults) {
964 if (numResults > 1) {
966 overloadedTypes.push_back(moduleTranslation.
convertType(
968 .getBody()[overloadedResultIdx]));
970 overloadedTypes.push_back(
974 for (
unsigned overloadedOperandIdx : overloadedOperands)
975 overloadedTypes.push_back(args[overloadedOperandIdx]->
getType());
976 llvm::Module *module = builder.GetInsertBlock()->getModule();
977 llvm::Function *llvmIntr = llvm::Intrinsic::getOrInsertDeclaration(
978 module, intrinsic, overloadedTypes);
980 return builder.CreateCall(llvmIntr, args, opBundles);
985 LogicalResult ModuleTranslation::convertOperation(
Operation &op,
986 llvm::IRBuilderBase &builder,
987 bool recordInsertions) {
990 return op.
emitError(
"cannot be converted to LLVM IR: missing "
991 "`LLVMTranslationDialectInterface` registration for "
995 InstructionCapturingInserter::CollectionScope scope(builder,
998 return op.
emitError(
"LLVM Translation failed for operation: ")
1001 return convertDialectAttributes(&op, scope.getCapturedInstructions());
1011 LogicalResult ModuleTranslation::convertBlockImpl(
Block &bb,
1012 bool ignoreArguments,
1013 llvm::IRBuilderBase &builder,
1014 bool recordInsertions) {
1016 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
1024 if (!ignoreArguments) {
1026 unsigned numPredecessors =
1027 std::distance(predecessors.begin(), predecessors.end());
1029 auto wrappedType = arg.getType();
1032 "block argument does not have an LLVM type");
1033 builder.SetCurrentDebugLocation(
1034 debugTranslation->translateLoc(arg.getLoc(), subprogram));
1036 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
1042 for (
auto &op : bb) {
1044 builder.SetCurrentDebugLocation(
1045 debugTranslation->translateLoc(op.
getLoc(), subprogram));
1047 if (
failed(convertOperation(op, builder, recordInsertions)))
1051 if (
auto iface = dyn_cast<WeightedBranchOpInterface>(op))
1070 llvm::Constant *cst) {
1071 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
1072 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
1078 llvm::GlobalValue *gv) {
1079 if (dsoLocalRequested)
1080 gv->setDSOLocal(
true);
1089 static FailureOr<llvm::Attribute>
1091 StringRef value = StringRef()) {
1092 auto kind = llvm::Attribute::getAttrKindFromName(key);
1096 if (llvm::Attribute::isIntAttrKind(
kind)) {
1098 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1101 if (!value.getAsInteger(0, result))
1107 return emitError(loc) <<
"LLVM attribute '" << key
1108 <<
"' does not expect a value, found '" << value
1122 static FailureOr<llvm::AttrBuilder>
1124 ArrayAttr arrayAttr, StringRef arrayAttrName) {
1125 llvm::AttrBuilder attrBuilder(ctx);
1130 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1131 FailureOr<llvm::Attribute> llvmAttr =
1135 attrBuilder.addAttribute(*llvmAttr);
1139 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1140 if (!arrayAttr || arrayAttr.size() != 2)
1141 return emitError(loc) <<
"expected '" << arrayAttrName
1142 <<
"' to contain string or array attributes";
1144 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1145 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1146 if (!keyAttr || !valueAttr)
1147 return emitError(loc) <<
"expected arrays within '" << arrayAttrName
1148 <<
"' to contain two strings";
1151 loc, ctx, keyAttr.getValue(), valueAttr.getValue());
1154 attrBuilder.addAttribute(*llvmAttr);
1160 LogicalResult ModuleTranslation::convertGlobalsAndAliases() {
1169 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1171 llvm::Constant *cst =
nullptr;
1172 if (op.getValueOrNull()) {
1175 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1176 cst = llvm::ConstantDataArray::getString(
1177 llvmModule->getContext(), strAttr.getValue(),
false);
1178 type = cst->getType();
1185 auto linkage = convertLinkageToLLVM(op.getLinkage());
1191 if (!dropInitializer && !cst)
1193 else if (dropInitializer && cst)
1196 auto *var =
new llvm::GlobalVariable(
1197 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1199 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1200 : llvm::GlobalValue::NotThreadLocal,
1201 op.getAddrSpace(), op.getExternallyInitialized());
1203 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1204 auto selectorOp = cast<ComdatSelectorOp>(
1206 var->setComdat(comdatMapping.lookup(selectorOp));
1209 if (op.getUnnamedAddr().has_value())
1210 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1212 if (op.getSection().has_value())
1213 var->setSection(*op.getSection());
1217 std::optional<uint64_t> alignment = op.getAlignment();
1218 if (alignment.has_value())
1219 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1221 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1223 globalsMapping.try_emplace(op, var);
1226 if (op.getDbgExprs()) {
1227 for (
auto exprAttr :
1228 op.getDbgExprs()->getAsRange<DIGlobalVariableExpressionAttr>()) {
1229 llvm::DIGlobalVariableExpression *diGlobalExpr =
1230 debugTranslation->translateGlobalVariableExpression(exprAttr);
1231 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1232 var->addDebugInfo(diGlobalExpr);
1251 llvm::DIScope *scope = diGlobalVar->getScope();
1252 if (
auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1253 scope = mod->getScope();
1254 else if (
auto *cb = dyn_cast_if_present<llvm::DICommonBlock>(scope)) {
1256 dyn_cast_if_present<llvm::DISubprogram>(cb->getScope()))
1257 scope = sp->getUnit();
1258 }
else if (
auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1259 scope = sp->getUnit();
1262 if (llvm::DICompileUnit *compileUnit =
1263 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1266 allGVars[compileUnit].push_back(diGlobalExpr);
1272 FailureOr<llvm::AttrBuilder> convertedTargetSpecificAttrs =
1274 op.getTargetSpecificAttrsAttr(),
1275 op.getTargetSpecificAttrsAttrName());
1276 if (
failed(convertedTargetSpecificAttrs))
1278 var->addAttributes(*convertedTargetSpecificAttrs);
1282 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1284 llvm::Constant *cst =
nullptr;
1285 llvm::GlobalValue::LinkageTypes linkage =
1286 convertLinkageToLLVM(op.getLinkage());
1287 llvm::Module &llvmMod = *llvmModule;
1290 llvm::GlobalAlias *var = llvm::GlobalAlias::create(
1291 type, op.getAddrSpace(), linkage, op.getSymName(), cst,
1294 var->setThreadLocalMode(op.getThreadLocal_()
1295 ? llvm::GlobalAlias::GeneralDynamicTLSModel
1296 : llvm::GlobalAlias::NotThreadLocal);
1301 if (op.getUnnamedAddr().has_value())
1302 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1304 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1306 aliasesMapping.try_emplace(op, var);
1310 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1311 if (
Block *initializer = op.getInitializerBlock()) {
1312 llvm::IRBuilder<llvm::TargetFolder> builder(
1313 llvmModule->getContext(),
1314 llvm::TargetFolder(llvmModule->getDataLayout()));
1316 [[maybe_unused]]
int numConstantsHit = 0;
1317 [[maybe_unused]]
int numConstantsErased = 0;
1320 for (
auto &op : initializer->without_terminator()) {
1321 if (
failed(convertOperation(op, builder)))
1334 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1338 auto [iterator, inserted] =
1339 constantAggregateUseMap.try_emplace(agg, numUsers);
1342 iterator->second += numUsers;
1348 auto cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1351 auto iter = constantAggregateUseMap.find(cst);
1352 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1354 if (iter->second == 0) {
1357 if (cst->user_empty()) {
1358 cst->destroyConstant();
1359 numConstantsErased++;
1361 constantAggregateUseMap.erase(iter);
1366 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1367 llvm::Constant *cst =
1368 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1369 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1371 global->setInitializer(cst);
1375 for (
auto it : constantAggregateUseMap) {
1376 auto cst = it.first;
1377 cst->removeDeadConstantUsers();
1378 if (cst->user_empty()) {
1379 cst->destroyConstant();
1380 numConstantsErased++;
1384 LLVM_DEBUG(llvm::dbgs()
1385 <<
"Convert initializer for " << op.
getName() <<
"\n";
1386 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1388 << numConstantsErased <<
" dangling constants erased\n";);
1394 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1395 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1396 if (!ctorOp && !dtorOp)
1402 if ((ctorOp && ctorOp.getCtors().empty()) ||
1403 (dtorOp && dtorOp.getDtors().empty())) {
1404 llvm::IRBuilder<llvm::TargetFolder> builder(
1405 llvmModule->getContext(),
1406 llvm::TargetFolder(llvmModule->getDataLayout()));
1408 builder.getInt32Ty(), builder.getPtrTy(), builder.getPtrTy());
1410 llvm::Constant *zeroInit = llvm::Constant::getNullValue(at);
1411 (void)
new llvm::GlobalVariable(
1412 *llvmModule, zeroInit->getType(),
false,
1413 llvm::GlobalValue::AppendingLinkage, zeroInit,
1414 ctorOp ?
"llvm.global_ctors" :
"llvm.global_dtors");
1417 ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1418 :
llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1419 auto appendGlobalFn =
1420 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1421 for (
const auto &[sym, prio] : range) {
1424 appendGlobalFn(*llvmModule, f, cast<IntegerAttr>(prio).getInt(),
1430 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1431 if (
failed(convertDialectAttributes(op, {})))
1436 for (
const auto &[compileUnit, globals] : allGVars) {
1437 compileUnit->replaceGlobalVariables(
1442 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>()) {
1443 Block &initializer = op.getInitializerBlock();
1444 llvm::IRBuilder<llvm::TargetFolder> builder(
1445 llvmModule->getContext(),
1446 llvm::TargetFolder(llvmModule->getDataLayout()));
1449 if (
failed(convertOperation(op, builder)))
1456 auto *cst = cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1457 assert(aliasesMapping.count(op));
1458 auto *alias = cast<llvm::GlobalAlias>(aliasesMapping[op]);
1459 alias->setAliasee(cst);
1462 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::AliasOp>())
1463 if (
failed(convertDialectAttributes(op, {})))
1471 const llvm::APInt &value) {
1478 const llvm::APInt &value) {
1486 llvm::Metadata *typeMD =
1488 llvm::Metadata *isSignedMD =
1498 values, std::back_inserter(mdValues), [&context](int32_t value) {
1504 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1507 blockMapping.clear();
1508 valueMapping.clear();
1509 branchMapping.clear();
1513 for (
auto [mlirArg, llvmArg] :
1514 llvm::zip(func.getArguments(), llvmFunc->args()))
1518 if (func.getPersonality()) {
1519 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1520 if (llvm::Constant *pfunc =
getLLVMConstant(ty, func.getPersonalityAttr(),
1521 func.getLoc(), *
this))
1522 llvmFunc->setPersonalityFn(pfunc);
1525 if (std::optional<StringRef> section = func.getSection())
1526 llvmFunc->setSection(*section);
1528 if (func.getArmStreaming())
1529 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1530 else if (func.getArmLocallyStreaming())
1531 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1532 else if (func.getArmStreamingCompatible())
1533 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1535 if (func.getArmNewZa())
1536 llvmFunc->addFnAttr(
"aarch64_new_za");
1537 else if (func.getArmInZa())
1538 llvmFunc->addFnAttr(
"aarch64_in_za");
1539 else if (func.getArmOutZa())
1540 llvmFunc->addFnAttr(
"aarch64_out_za");
1541 else if (func.getArmInoutZa())
1542 llvmFunc->addFnAttr(
"aarch64_inout_za");
1543 else if (func.getArmPreservesZa())
1544 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1546 if (
auto targetCpu = func.getTargetCpu())
1547 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1549 if (
auto tuneCpu = func.getTuneCpu())
1550 llvmFunc->addFnAttr(
"tune-cpu", *tuneCpu);
1552 if (
auto reciprocalEstimates = func.getReciprocalEstimates())
1553 llvmFunc->addFnAttr(
"reciprocal-estimates", *reciprocalEstimates);
1555 if (
auto preferVectorWidth = func.getPreferVectorWidth())
1556 llvmFunc->addFnAttr(
"prefer-vector-width", *preferVectorWidth);
1558 if (
auto attr = func.getVscaleRange())
1559 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1561 attr->getMaxRange().getInt()));
1563 if (
auto unsafeFpMath = func.getUnsafeFpMath())
1564 llvmFunc->addFnAttr(
"unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1566 if (
auto noInfsFpMath = func.getNoInfsFpMath())
1567 llvmFunc->addFnAttr(
"no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1569 if (
auto noNansFpMath = func.getNoNansFpMath())
1570 llvmFunc->addFnAttr(
"no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1572 if (
auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1573 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1574 llvm::toStringRef(*noSignedZerosFpMath));
1576 if (
auto denormalFpMath = func.getDenormalFpMath())
1577 llvmFunc->addFnAttr(
"denormal-fp-math", *denormalFpMath);
1579 if (
auto denormalFpMathF32 = func.getDenormalFpMathF32())
1580 llvmFunc->addFnAttr(
"denormal-fp-math-f32", *denormalFpMathF32);
1582 if (
auto fpContract = func.getFpContract())
1583 llvmFunc->addFnAttr(
"fp-contract", *fpContract);
1585 if (
auto instrumentFunctionEntry = func.getInstrumentFunctionEntry())
1586 llvmFunc->addFnAttr(
"instrument-function-entry", *instrumentFunctionEntry);
1588 if (
auto instrumentFunctionExit = func.getInstrumentFunctionExit())
1589 llvmFunc->addFnAttr(
"instrument-function-exit", *instrumentFunctionExit);
1592 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1593 for (
auto &bb : func) {
1594 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1595 llvmBB->insertInto(llvmFunc);
1602 for (
Block *bb : blocks) {
1603 CapturingIRBuilder builder(llvmContext,
1604 llvm::TargetFolder(llvmModule->getDataLayout()));
1605 if (
failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1615 return convertDialectAttributes(func, {});
1618 LogicalResult ModuleTranslation::convertDialectAttributes(
1629 llvm::Function *llvmFunc) {
1630 if (!func.getMemoryEffects())
1633 MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1636 llvm::MemoryEffects newMemEffects =
1637 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1638 convertModRefInfoToLLVM(memEffects.getArgMem()));
1639 newMemEffects |= llvm::MemoryEffects(
1640 llvm::MemoryEffects::Location::InaccessibleMem,
1641 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1643 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1644 convertModRefInfoToLLVM(memEffects.getOther()));
1645 llvmFunc->setMemoryEffects(newMemEffects);
1650 llvm::Function *llvmFunc) {
1651 if (func.getNoInlineAttr())
1652 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1653 if (func.getAlwaysInlineAttr())
1654 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1655 if (func.getOptimizeNoneAttr())
1656 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1657 if (func.getConvergentAttr())
1658 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1659 if (func.getNoUnwindAttr())
1660 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1661 if (func.getWillReturnAttr())
1662 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1663 if (TargetFeaturesAttr targetFeatAttr = func.getTargetFeaturesAttr())
1664 llvmFunc->addFnAttr(
"target-features", targetFeatAttr.getFeaturesString());
1665 if (FramePointerKindAttr fpAttr = func.getFramePointerAttr())
1666 llvmFunc->addFnAttr(
"frame-pointer", stringifyFramePointerKind(
1667 fpAttr.getFramePointerKind()));
1668 if (UWTableKindAttr uwTableKindAttr = func.getUwtableKindAttr())
1669 llvmFunc->setUWTableKind(
1670 convertUWTableKindToLLVM(uwTableKindAttr.getUwtableKind()));
1676 llvm::Function *llvmFunc,
1678 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1680 if (VecTypeHintAttr vecTypeHint = func.getVecTypeHintAttr()) {
1681 Type type = vecTypeHint.getHint().getValue();
1682 llvm::Type *llvmType = translation.
convertType(type);
1683 bool isSigned = vecTypeHint.getIsSigned();
1684 llvmFunc->setMetadata(
1685 func.getVecTypeHintAttrName(),
1690 func.getWorkGroupSizeHint()) {
1691 llvmFunc->setMetadata(
1692 func.getWorkGroupSizeHintAttrName(),
1697 func.getReqdWorkGroupSize()) {
1698 llvmFunc->setMetadata(
1699 func.getReqdWorkGroupSizeAttrName(),
1703 if (std::optional<uint32_t> intelReqdSubGroupSize =
1704 func.getIntelReqdSubGroupSize()) {
1705 llvmFunc->setMetadata(
1706 func.getIntelReqdSubGroupSizeAttrName(),
1708 llvm::APInt(32, *intelReqdSubGroupSize)));
1713 llvm::Attribute::AttrKind llvmKind,
1718 .Case<TypeAttr>([&](
auto typeAttr) {
1719 attrBuilder.addTypeAttr(
1720 llvmKind, moduleTranslation.
convertType(typeAttr.getValue()));
1723 .Case<IntegerAttr>([&](
auto intAttr) {
1724 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1727 .Case<UnitAttr>([&](
auto) {
1728 attrBuilder.addAttribute(llvmKind);
1731 .Case<LLVM::ConstantRangeAttr>([&](
auto rangeAttr) {
1732 attrBuilder.addConstantRangeAttr(
1734 llvm::ConstantRange(rangeAttr.getLower(), rangeAttr.getUpper()));
1737 .Default([loc](
auto) {
1738 return emitError(loc,
"unsupported parameter attribute type");
1742 FailureOr<llvm::AttrBuilder>
1743 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func,
int argIdx,
1744 DictionaryAttr paramAttrs) {
1745 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1749 for (
auto namedAttr : paramAttrs) {
1750 auto it = attrNameToKindMapping.find(namedAttr.getName());
1751 if (it != attrNameToKindMapping.end()) {
1752 llvm::Attribute::AttrKind llvmKind = it->second;
1756 }
else if (namedAttr.getNameDialect()) {
1766 ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call,
1769 if (ArrayAttr argAttrsArray = attrsOp.getArgAttrsAttr()) {
1770 unsigned argAttrIdx = 0;
1771 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
1772 immArgPositions.end());
1773 for (
unsigned argIdx : llvm::seq<unsigned>(call->arg_size())) {
1774 if (argAttrIdx >= argAttrsArray.size())
1777 if (immArgPositionsSet.contains(argIdx))
1780 auto argAttrs = cast<DictionaryAttr>(argAttrsArray[argAttrIdx++]);
1781 if (argAttrs.empty())
1784 FailureOr<llvm::AttrBuilder> attrBuilder =
1785 convertParameterAttrs(attrsOp->getLoc(), argAttrs);
1788 call->addParamAttrs(argIdx, *attrBuilder);
1793 if (ArrayAttr resAttrsArray = attrsOp.getResAttrsAttr()) {
1794 if (!resAttrsArray.empty()) {
1795 auto resAttrs = cast<DictionaryAttr>(resAttrsArray[0]);
1796 FailureOr<llvm::AttrBuilder> attrBuilder =
1797 convertParameterAttrs(attrsOp->getLoc(), resAttrs);
1800 call->addRetAttrs(*attrBuilder);
1807 FailureOr<llvm::AttrBuilder>
1808 ModuleTranslation::convertParameterAttrs(
Location loc,
1809 DictionaryAttr paramAttrs) {
1810 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1813 for (
auto namedAttr : paramAttrs) {
1814 auto it = attrNameToKindMapping.find(namedAttr.getName());
1815 if (it != attrNameToKindMapping.end()) {
1816 llvm::Attribute::AttrKind llvmKind = it->second;
1826 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1829 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1830 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1832 cast<llvm::FunctionType>(
convertType(
function.getFunctionType())));
1833 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1834 llvmFunc->setLinkage(convertLinkageToLLVM(
function.getLinkage()));
1835 llvmFunc->setCallingConv(convertCConvToLLVM(
function.getCConv()));
1846 if (std::optional<uint64_t> entryCount =
function.getFunctionEntryCount())
1847 llvmFunc->setEntryCount(entryCount.value());
1850 if (ArrayAttr allResultAttrs =
function.getAllResultAttrs()) {
1851 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1852 FailureOr<llvm::AttrBuilder> attrBuilder =
1853 convertParameterAttrs(
function, -1, resultAttrs);
1856 llvmFunc->addRetAttrs(*attrBuilder);
1862 FailureOr<llvm::AttrBuilder> attrBuilder =
1863 convertParameterAttrs(
function, argIdx, argAttrs);
1866 llvmArg.addAttrs(*attrBuilder);
1871 FailureOr<llvm::AttrBuilder> convertedPassthroughAttrs =
1873 function.getPassthroughAttr(),
1874 function.getPassthroughAttrName());
1875 if (
failed(convertedPassthroughAttrs))
1877 llvmFunc->addFnAttrs(*convertedPassthroughAttrs);
1880 llvmFunc->setVisibility(convertVisibilityToLLVM(
function.getVisibility_()));
1883 if (std::optional<mlir::SymbolRefAttr> comdat =
function.getComdat()) {
1884 auto selectorOp = cast<ComdatSelectorOp>(
1886 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1889 if (
auto gc =
function.getGarbageCollector())
1890 llvmFunc->setGC(gc->str());
1892 if (
auto unnamedAddr =
function.getUnnamedAddr())
1893 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1895 if (
auto alignment =
function.getAlignment())
1896 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1899 debugTranslation->translate(
function, *llvmFunc);
1905 LogicalResult ModuleTranslation::convertFunctions() {
1907 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1910 if (
function.isExternal()) {
1911 if (
failed(convertDialectAttributes(
function, {})))
1916 if (
failed(convertOneFunction(
function)))
1923 LogicalResult ModuleTranslation::convertIFuncs() {
1924 for (
auto op :
getModuleBody(mlirModule).getOps<IFuncOp>()) {
1925 llvm::Type *type =
convertType(op.getIFuncType());
1926 llvm::GlobalValue::LinkageTypes linkage =
1927 convertLinkageToLLVM(op.getLinkage());
1928 llvm::Constant *resolver;
1930 resolver = cast<llvm::Constant>(resolverFn);
1933 op.getResolverAttr());
1934 resolver = cast<llvm::Constant>(
lookupAlias(aliasOp));
1938 llvm::GlobalIFunc::create(type, op.getAddressSpace(), linkage,
1939 op.getSymName(), resolver, llvmModule.get());
1941 ifunc->setUnnamedAddr(convertUnnamedAddrToLLVM(op.getUnnamedAddr()));
1942 ifunc->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1944 ifuncMapping.try_emplace(op, ifunc);
1950 LogicalResult ModuleTranslation::convertComdats() {
1951 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
1952 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1954 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1956 <<
"comdat selection symbols must be unique even in different "
1958 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1959 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1960 comdatMapping.try_emplace(selectorOp, comdat);
1966 LogicalResult ModuleTranslation::convertUnresolvedBlockAddress() {
1967 for (
auto &[blockAddressOp, llvmCst] : unresolvedBlockAddressMapping) {
1968 BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
1970 assert(llvmBlock &&
"expected LLVM blocks to be already translated");
1974 lookupFunction(blockAddressAttr.getFunction().getValue()), llvmBlock);
1975 llvmCst->replaceAllUsesWith(llvmBlockAddr);
1976 assert(llvmCst->use_empty() &&
"expected all uses to be replaced");
1977 cast<llvm::GlobalVariable>(llvmCst)->eraseFromParent();
1979 unresolvedBlockAddressMapping.clear();
1984 llvm::Instruction *inst) {
1985 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1986 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1991 auto [scopeIt, scopeInserted] =
1992 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
1994 return scopeIt->second;
1995 llvm::LLVMContext &ctx = llvmModule->getContext();
1996 auto dummy = llvm::MDNode::getTemporary(ctx, {});
1998 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1999 aliasScopeAttr.getDomain(),
nullptr);
2000 if (insertedDomain) {
2003 operands.push_back(dummy.get());
2004 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
2008 llvm::Metadata *replacement;
2009 if (
auto stringAttr =
2010 dyn_cast<StringAttr>(aliasScopeAttr.getDomain().getId()))
2013 replacement = domainIt->second;
2014 domainIt->second->replaceOperandWith(0, replacement);
2017 assert(domainIt->second &&
"Scope's domain should already be valid");
2020 operands.push_back(dummy.get());
2021 operands.push_back(domainIt->second);
2022 if (StringAttr description = aliasScopeAttr.getDescription())
2026 llvm::Metadata *replacement;
2027 if (
auto stringAttr = dyn_cast<StringAttr>(aliasScopeAttr.getId()))
2030 replacement = scopeIt->second;
2031 scopeIt->second->replaceOperandWith(0, replacement);
2032 return scopeIt->second;
2038 nodes.reserve(aliasScopeAttrs.size());
2039 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
2045 llvm::Instruction *inst) {
2046 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
2047 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
2050 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
2051 inst->setMetadata(
kind, node);
2054 populateScopeMetadata(op.getAliasScopesOrNull(),
2055 llvm::LLVMContext::MD_alias_scope);
2056 populateScopeMetadata(op.getNoAliasScopesOrNull(),
2057 llvm::LLVMContext::MD_noalias);
2060 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
2061 return tbaaMetadataMapping.lookup(tbaaAttr);
2065 llvm::Instruction *inst) {
2066 ArrayAttr tagRefs = op.getTBAATagsOrNull();
2067 if (!tagRefs || tagRefs.empty())
2074 if (tagRefs.size() > 1) {
2075 op.emitWarning() <<
"TBAA access tags were not translated, because LLVM "
2076 "IR only supports a single tag per instruction";
2080 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
2081 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
2085 DereferenceableOpInterface op, llvm::Instruction *inst) {
2086 DereferenceableAttr derefAttr = op.getDereferenceableOrNull();
2094 unsigned kindId = derefAttr.getMayBeNull()
2095 ? llvm::LLVMContext::MD_dereferenceable_or_null
2096 : llvm::LLVMContext::MD_dereferenceable;
2097 inst->setMetadata(kindId, derefSizeNode);
2102 llvm::transform(op.getWeights(), std::back_inserter(weights),
2103 [](int32_t value) { return static_cast<uint32_t>(value); });
2104 if (weights.empty())
2108 assert(inst &&
"expected the operation to have a mapping to an instruction");
2110 llvm::LLVMContext::MD_prof,
2114 LogicalResult ModuleTranslation::createTBAAMetadata() {
2115 llvm::LLVMContext &ctx = llvmModule->getContext();
2127 walker.
addWalk([&](TBAARootAttr root) {
2128 tbaaMetadataMapping.insert(
2132 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
2135 for (TBAAMemberAttr member : descriptor.getMembers()) {
2136 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
2144 walker.
addWalk([&](TBAATagAttr tag) {
2147 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
2148 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
2152 if (tag.getConstant())
2159 mlirModule->
walk([&](AliasAnalysisOpInterface analysisOpInterface) {
2160 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
2167 LogicalResult ModuleTranslation::createIdentMetadata() {
2169 LLVMDialect::getIdentAttrName())) {
2170 StringRef ident = attr;
2171 llvm::LLVMContext &ctx = llvmModule->getContext();
2172 llvm::NamedMDNode *namedMd =
2173 llvmModule->getOrInsertNamedMetadata(LLVMDialect::getIdentAttrName());
2175 namedMd->addOperand(md);
2181 LogicalResult ModuleTranslation::createCommandlineMetadata() {
2183 LLVMDialect::getCommandlineAttrName())) {
2184 StringRef cmdLine = attr;
2185 llvm::LLVMContext &ctx = llvmModule->getContext();
2186 llvm::NamedMDNode *nmd = llvmModule->getOrInsertNamedMetadata(
2187 LLVMDialect::getCommandlineAttrName());
2190 nmd->addOperand(md);
2196 LogicalResult ModuleTranslation::createDependentLibrariesMetadata() {
2198 LLVM::LLVMDialect::getDependentLibrariesAttrName())) {
2200 llvmModule->getOrInsertNamedMetadata(
"llvm.dependent-libraries");
2201 llvm::LLVMContext &ctx = llvmModule->getContext();
2203 cast<ArrayAttr>(dependentLibrariesAttr).getAsRange<StringAttr>()) {
2206 nmd->addOperand(md);
2213 llvm::Instruction *inst) {
2214 LoopAnnotationAttr attr =
2216 .Case<LLVM::BrOp, LLVM::CondBrOp>(
2217 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
2220 llvm::MDNode *loopMD =
2221 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
2222 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
2226 auto iface = cast<DisjointFlagInterface>(op);
2228 if (
auto disjointInst = dyn_cast<llvm::PossiblyDisjointInst>(value))
2229 disjointInst->setIsDisjoint(iface.getIsDisjoint());
2239 remapped.reserve(values.size());
2240 for (
Value v : values)
2247 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
2252 llvm::OpenMPIRBuilderConfig
config(
2259 unsigned int defaultAS =
2261 config.setDefaultTargetAS(defaultAS);
2262 ompBuilder->setConfig(std::move(
config));
2263 ompBuilder->initialize();
2265 return ompBuilder.get();
2269 llvm::DILocalScope *scope) {
2270 return debugTranslation->translateLoc(loc, scope);
2273 llvm::DIExpression *
2275 return debugTranslation->translateExpression(attr);
2278 llvm::DIGlobalVariableExpression *
2280 LLVM::DIGlobalVariableExpressionAttr attr) {
2281 return debugTranslation->translateGlobalVariableExpression(attr);
2285 return debugTranslation->translate(attr);
2290 return convertRoundingModeToLLVM(rounding);
2294 LLVM::FPExceptionBehavior exceptionBehavior) {
2295 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
2300 return llvmModule->getOrInsertNamedMetadata(name);
2303 static std::unique_ptr<llvm::Module>
2307 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
2308 if (
auto dataLayoutAttr =
2310 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
2312 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(
""));
2313 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
2314 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
2318 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
2319 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
2324 if (
failed(llvmDataLayout))
2326 llvmModule->setDataLayout(*llvmDataLayout);
2328 if (
auto targetTripleAttr =
2330 llvmModule->setTargetTriple(
2331 llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
2334 LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
2335 auto asmArrayAttr = dyn_cast<ArrayAttr>(asmAttr);
2336 if (!asmArrayAttr) {
2337 m->
emitError(
"expected an array attribute for a module level asm");
2342 auto asmStrAttr = dyn_cast<StringAttr>(elt);
2345 "expected a string attribute for each entry of a module level asm");
2348 llvmModule->appendModuleInlineAsm(asmStrAttr.getValue());
2355 std::unique_ptr<llvm::Module>
2357 StringRef name,
bool disableVerification) {
2359 module->
emitOpError(
"can not be translated to an LLVMIR module");
2363 std::unique_ptr<llvm::Module> llvmModule =
2372 llvm::IRBuilder<llvm::TargetFolder> llvmBuilder(
2374 llvm::TargetFolder(translator.getLLVMModule()->getDataLayout()));
2380 if (
failed(translator.convertOperation(*module, llvmBuilder)))
2383 if (
failed(translator.convertComdats()))
2385 if (
failed(translator.convertFunctionSignatures()))
2387 if (
failed(translator.convertGlobalsAndAliases()))
2389 if (
failed(translator.convertIFuncs()))
2391 if (
failed(translator.createTBAAMetadata()))
2393 if (
failed(translator.createIdentMetadata()))
2395 if (
failed(translator.createCommandlineMetadata()))
2397 if (
failed(translator.createDependentLibrariesMetadata()))
2402 if (!isa<LLVM::LLVMFuncOp, LLVM::AliasOp, LLVM::GlobalOp,
2403 LLVM::GlobalCtorsOp, LLVM::GlobalDtorsOp, LLVM::ComdatOp,
2404 LLVM::IFuncOp>(&o) &&
2406 failed(translator.convertOperation(o, llvmBuilder))) {
2414 if (
failed(translator.convertFunctions()))
2419 if (
failed(translator.convertUnresolvedBlockAddress()))
2424 translator.debugTranslation->addModuleFlagsIfNotPresent();
2427 if (
auto *ompBuilder = translator.getOpenMPBuilder())
2428 ompBuilder->finalize();
2430 if (!disableVerification &&
2431 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
2434 return std::move(translator.llvmModule);
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1252::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.
const FrozenRewritePatternSet GreedyRewriteConfig config
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...