37 #include "llvm/ADT/PostOrderIterator.h"
38 #include "llvm/ADT/SetVector.h"
39 #include "llvm/ADT/StringExtras.h"
40 #include "llvm/ADT/TypeSwitch.h"
41 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
42 #include "llvm/IR/BasicBlock.h"
43 #include "llvm/IR/CFG.h"
44 #include "llvm/IR/Constants.h"
45 #include "llvm/IR/DerivedTypes.h"
46 #include "llvm/IR/IRBuilder.h"
47 #include "llvm/IR/InlineAsm.h"
48 #include "llvm/IR/IntrinsicsNVPTX.h"
49 #include "llvm/IR/LLVMContext.h"
50 #include "llvm/IR/MDBuilder.h"
51 #include "llvm/IR/Module.h"
52 #include "llvm/IR/Verifier.h"
53 #include "llvm/Support/Debug.h"
54 #include "llvm/Support/raw_ostream.h"
55 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
56 #include "llvm/Transforms/Utils/Cloning.h"
57 #include "llvm/Transforms/Utils/ModuleUtils.h"
60 #define DEBUG_TYPE "llvm-dialect-to-llvm-ir"
68 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
91 class InstructionCapturingInserter :
public llvm::IRBuilderCallbackInserter {
94 InstructionCapturingInserter()
95 : llvm::IRBuilderCallbackInserter([
this](llvm::Instruction *instruction) {
96 if (LLVM_LIKELY(enabled))
97 capturedInstructions.push_back(instruction);
102 return capturedInstructions;
106 void clearCapturedInstructions() { capturedInstructions.clear(); }
109 class CollectionScope {
112 CollectionScope(llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing);
120 return inserter->getCapturedInstructions();
125 InstructionCapturingInserter *inserter =
nullptr;
135 void setEnabled(
bool enabled =
true) { this->enabled = enabled; }
142 bool enabled =
false;
145 using CapturingIRBuilder =
146 llvm::IRBuilder<llvm::ConstantFolder, InstructionCapturingInserter>;
149 InstructionCapturingInserter::CollectionScope::CollectionScope(
150 llvm::IRBuilderBase &irBuilder,
bool isBuilderCapturing) {
152 if (!isBuilderCapturing)
155 auto &capturingIRBuilder =
static_cast<CapturingIRBuilder &
>(irBuilder);
156 inserter = &capturingIRBuilder.getInserter();
157 wasEnabled = inserter->enabled;
159 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
160 inserter->setEnabled(
true);
163 InstructionCapturingInserter::CollectionScope::~CollectionScope() {
167 previouslyCollectedInstructions.swap(inserter->capturedInstructions);
171 llvm::append_range(inserter->capturedInstructions,
172 previouslyCollectedInstructions);
174 inserter->setEnabled(wasEnabled);
179 static FailureOr<llvm::DataLayout>
182 std::optional<Location> loc = std::nullopt) {
187 std::string llvmDataLayout;
188 llvm::raw_string_ostream layoutStream(llvmDataLayout);
189 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
190 auto key = llvm::dyn_cast_if_present<StringAttr>(entry.getKey());
193 if (key.getValue() == DLTIDialect::kDataLayoutEndiannessKey) {
194 auto value = cast<StringAttr>(entry.getValue());
195 bool isLittleEndian =
196 value.getValue() == DLTIDialect::kDataLayoutEndiannessLittle;
197 layoutStream <<
"-" << (isLittleEndian ?
"e" :
"E");
198 layoutStream.flush();
201 if (key.getValue() == DLTIDialect::kDataLayoutProgramMemorySpaceKey) {
202 auto value = cast<IntegerAttr>(entry.getValue());
203 uint64_t space = value.getValue().getZExtValue();
207 layoutStream <<
"-P" << space;
208 layoutStream.flush();
211 if (key.getValue() == DLTIDialect::kDataLayoutGlobalMemorySpaceKey) {
212 auto value = cast<IntegerAttr>(entry.getValue());
213 uint64_t space = value.getValue().getZExtValue();
217 layoutStream <<
"-G" << space;
218 layoutStream.flush();
221 if (key.getValue() == DLTIDialect::kDataLayoutAllocaMemorySpaceKey) {
222 auto value = cast<IntegerAttr>(entry.getValue());
223 uint64_t space = value.getValue().getZExtValue();
227 layoutStream <<
"-A" << space;
228 layoutStream.flush();
231 if (key.getValue() == DLTIDialect::kDataLayoutStackAlignmentKey) {
232 auto value = cast<IntegerAttr>(entry.getValue());
233 uint64_t alignment = value.getValue().getZExtValue();
237 layoutStream <<
"-S" << alignment;
238 layoutStream.flush();
241 emitError(*loc) <<
"unsupported data layout key " << key;
248 for (DataLayoutEntryInterface entry : attribute.getEntries()) {
249 auto type = llvm::dyn_cast_if_present<Type>(entry.getKey());
253 if (isa<IndexType>(type))
256 LogicalResult result =
258 .Case<IntegerType, Float16Type, Float32Type, Float64Type,
259 Float80Type, Float128Type>([&](
Type type) -> LogicalResult {
260 if (
auto intType = dyn_cast<IntegerType>(type)) {
261 if (intType.getSignedness() != IntegerType::Signless)
263 <<
"unsupported data layout for non-signless integer "
273 layoutStream << size <<
":" << abi;
274 if (abi != preferred)
275 layoutStream <<
":" << preferred;
278 .Case([&](LLVMPointerType type) {
279 layoutStream <<
"p" << type.getAddressSpace() <<
":";
285 layoutStream << size <<
":" << abi <<
":" << preferred <<
":"
289 .Default([loc](
Type type) {
291 <<
"unsupported type in data layout: " << type;
296 layoutStream.flush();
297 StringRef layoutSpec(llvmDataLayout);
298 if (layoutSpec.starts_with(
"-"))
299 layoutSpec = layoutSpec.drop_front();
301 return llvm::DataLayout(layoutSpec);
308 static llvm::Constant *
313 llvm::Constant *result = constants.front();
314 constants = constants.drop_front();
318 llvm::Type *elementType;
319 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
320 elementType = arrayTy->getElementType();
321 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
322 elementType = vectorTy->getElementType();
324 emitError(loc) <<
"expected sequential LLVM types wrapping a scalar";
329 nested.reserve(shape.front());
330 for (int64_t i = 0; i < shape.front(); ++i) {
337 if (shape.size() == 1 && type->isVectorTy())
346 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(type)) {
347 type = arrayTy->getElementType();
348 }
else if (
auto *vectorTy = dyn_cast<llvm::VectorType>(type)) {
349 type = vectorTy->getElementType();
363 static llvm::Constant *
365 llvm::Type *llvmType,
367 if (!denseElementsAttr)
371 if (!llvm::ConstantDataSequential::isElementTypeCompatible(innermostLLVMType))
374 ShapedType type = denseElementsAttr.
getType();
375 if (type.getNumElements() == 0)
383 int64_t elementByteSize = denseElementsAttr.
getRawData().size() /
385 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits())
390 bool hasVectorElementType = isa<VectorType>(type.getElementType());
391 int64_t numAggregates =
393 (hasVectorElementType ? 1
394 : denseElementsAttr.
getType().getShape().back());
396 if (!hasVectorElementType)
397 outerShape = outerShape.drop_back();
400 if (denseElementsAttr.
isSplat() &&
401 (isa<VectorType>(type) || hasVectorElementType)) {
405 llvm::Constant *splatVector =
406 llvm::ConstantDataVector::getSplat(0, splatValue);
411 if (denseElementsAttr.
isSplat())
416 std::function<llvm::Constant *(StringRef)> buildCstData;
417 if (isa<TensorType>(type)) {
418 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
419 if (vectorElementType && vectorElementType.getRank() == 1) {
420 buildCstData = [&](StringRef data) {
421 return llvm::ConstantDataVector::getRaw(
422 data, vectorElementType.getShape().back(), innermostLLVMType);
424 }
else if (!vectorElementType) {
425 buildCstData = [&](StringRef data) {
426 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
430 }
else if (isa<VectorType>(type)) {
431 buildCstData = [&](StringRef data) {
432 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
442 int64_t aggregateSize = denseElementsAttr.
getType().getShape().back() *
443 (innermostLLVMType->getScalarSizeInBits() / 8);
444 constants.reserve(numAggregates);
445 for (
unsigned i = 0; i < numAggregates; ++i) {
446 StringRef data(denseElementsAttr.
getRawData().data() + i * aggregateSize,
448 constants.push_back(buildCstData(data));
464 assert(denseResourceAttr &&
"expected non-null attribute");
467 if (!llvm::ConstantDataSequential::isElementTypeCompatible(
468 innermostLLVMType)) {
469 emitError(loc,
"no known conversion for innermost element type");
473 ShapedType type = denseResourceAttr.getType();
474 assert(type.getNumElements() > 0 &&
"Expected non-empty elements attribute");
478 emitError(loc,
"resource does not exist");
489 int64_t numElements = denseResourceAttr.getType().getNumElements();
490 int64_t elementByteSize = rawData.size() / numElements;
491 if (8 * elementByteSize != innermostLLVMType->getScalarSizeInBits()) {
492 emitError(loc,
"raw data size does not match element type size");
498 bool hasVectorElementType = isa<VectorType>(type.getElementType());
499 int64_t numAggregates =
500 numElements / (hasVectorElementType
502 : denseResourceAttr.getType().getShape().back());
504 if (!hasVectorElementType)
505 outerShape = outerShape.drop_back();
508 std::function<llvm::Constant *(StringRef)> buildCstData;
509 if (isa<TensorType>(type)) {
510 auto vectorElementType = dyn_cast<VectorType>(type.getElementType());
511 if (vectorElementType && vectorElementType.getRank() == 1) {
512 buildCstData = [&](StringRef data) {
513 return llvm::ConstantDataVector::getRaw(
514 data, vectorElementType.getShape().back(), innermostLLVMType);
516 }
else if (!vectorElementType) {
517 buildCstData = [&](StringRef data) {
518 return llvm::ConstantDataArray::getRaw(data, type.getShape().back(),
522 }
else if (isa<VectorType>(type)) {
523 buildCstData = [&](StringRef data) {
524 return llvm::ConstantDataVector::getRaw(data, type.getShape().back(),
529 emitError(loc,
"unsupported dense_resource type");
536 int64_t aggregateSize = denseResourceAttr.getType().getShape().back() *
537 (innermostLLVMType->getScalarSizeInBits() / 8);
538 constants.reserve(numAggregates);
539 for (
unsigned i = 0; i < numAggregates; ++i) {
540 StringRef data(rawData.data() + i * aggregateSize, aggregateSize);
541 constants.push_back(buildCstData(data));
558 if (
auto *structType = dyn_cast<::llvm::StructType>(llvmType)) {
559 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
560 if (!arrayAttr || arrayAttr.size() != 2) {
561 emitError(loc,
"expected struct type to be a complex number");
564 llvm::Type *elementType = structType->getElementType(0);
565 llvm::Constant *real =
569 llvm::Constant *imag =
577 if (
auto intAttr = dyn_cast<IntegerAttr>(attr))
580 intAttr.getValue().sextOrTrunc(llvmType->getIntegerBitWidth()));
581 if (
auto floatAttr = dyn_cast<FloatAttr>(attr)) {
582 const llvm::fltSemantics &sem = floatAttr.getValue().getSemantics();
587 unsigned floatWidth = APFloat::getSizeInBits(sem);
588 if (llvmType->isIntegerTy(floatWidth))
590 floatAttr.getValue().bitcastToAPInt());
592 llvm::Type::getFloatingPointTy(llvmType->getContext(),
593 floatAttr.getValue().getSemantics())) {
594 emitError(loc,
"FloatAttr does not match expected type of the constant");
599 if (
auto funcAttr = dyn_cast<FlatSymbolRefAttr>(attr))
600 return llvm::ConstantExpr::getBitCast(
602 if (
auto splatAttr = dyn_cast<SplatElementsAttr>(attr)) {
603 llvm::Type *elementType;
604 uint64_t numElements;
605 bool isScalable =
false;
606 if (
auto *arrayTy = dyn_cast<llvm::ArrayType>(llvmType)) {
607 elementType = arrayTy->getElementType();
608 numElements = arrayTy->getNumElements();
609 }
else if (
auto *fVectorTy = dyn_cast<llvm::FixedVectorType>(llvmType)) {
610 elementType = fVectorTy->getElementType();
611 numElements = fVectorTy->getNumElements();
612 }
else if (
auto *sVectorTy = dyn_cast<llvm::ScalableVectorType>(llvmType)) {
613 elementType = sVectorTy->getElementType();
614 numElements = sVectorTy->getMinNumElements();
617 llvm_unreachable(
"unrecognized constant vector type");
622 bool elementTypeSequential =
623 isa<llvm::ArrayType, llvm::VectorType>(elementType);
626 elementTypeSequential ? splatAttr
628 loc, moduleTranslation);
631 if (llvmType->isVectorTy())
632 return llvm::ConstantVector::getSplat(
634 if (llvmType->isArrayTy()) {
636 if (child->isZeroValue()) {
639 if (llvm::ConstantDataSequential::isElementTypeCompatible(
642 if (isa<llvm::IntegerType>(elementType)) {
643 if (llvm::ConstantInt *ci = dyn_cast<llvm::ConstantInt>(child)) {
644 if (ci->getBitWidth() == 8) {
649 if (ci->getBitWidth() == 16) {
654 if (ci->getBitWidth() == 32) {
659 if (ci->getBitWidth() == 64) {
669 std::vector<llvm::Constant *> constants(numElements, child);
676 if (llvm::Constant *result =
678 llvmType, moduleTranslation)) {
682 if (
auto denseResourceAttr = dyn_cast<DenseResourceElementsAttr>(attr)) {
688 if (
auto elementsAttr = dyn_cast<ElementsAttr>(attr)) {
689 assert(elementsAttr.getShapedType().hasStaticShape());
690 assert(!elementsAttr.getShapedType().getShape().empty() &&
691 "unexpected empty elements attribute shape");
694 constants.reserve(elementsAttr.getNumElements());
696 for (
auto n : elementsAttr.getValues<
Attribute>()) {
699 if (!constants.back())
704 constantsRef, elementsAttr.getShapedType().getShape(), llvmType, loc);
705 assert(constantsRef.empty() &&
"did not consume all elemental constants");
709 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
713 stringAttr.getValue().size()});
715 emitError(loc,
"unsupported constant value");
719 ModuleTranslation::ModuleTranslation(
Operation *module,
720 std::unique_ptr<llvm::Module> llvmModule)
721 : mlirModule(module), llvmModule(std::move(llvmModule)),
725 *this, *this->llvmModule)),
726 typeTranslator(this->llvmModule->
getContext()),
729 "mlirModule should honor LLVM's module semantics.");
732 ModuleTranslation::~ModuleTranslation() {
734 ompBuilder->finalize();
739 toProcess.push_back(®ion);
740 while (!toProcess.empty()) {
741 Region *current = toProcess.pop_back_val();
742 for (
Block &block : *current) {
743 blockMapping.erase(&block);
744 for (
Value arg : block.getArguments())
745 valueMapping.erase(arg);
748 valueMapping.erase(value);
750 branchMapping.erase(&op);
751 if (isa<LLVM::GlobalOp>(op))
752 globalsMapping.erase(&op);
753 if (isa<LLVM::CallOp>(op))
754 callMapping.erase(&op);
766 unsigned numArguments,
unsigned index) {
768 if (isa<LLVM::BrOp>(terminator))
775 auto branch = cast<BranchOpInterface>(terminator);
778 (!seenSuccessors.contains(successor) || successorOperands.
empty()) &&
779 "successors with arguments in LLVM branches must be different blocks");
780 seenSuccessors.insert(successor);
786 if (
auto condBranchOp = dyn_cast<LLVM::CondBrOp>(terminator)) {
789 return condBranchOp.getSuccessor(0) == current
790 ? condBranchOp.getTrueDestOperands()[index]
791 : condBranchOp.getFalseDestOperands()[index];
794 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(terminator)) {
797 if (switchOp.getDefaultDestination() == current)
798 return switchOp.getDefaultOperands()[index];
800 if (i.value() == current)
801 return switchOp.getCaseOperands(i.index())[index];
804 if (
auto invokeOp = dyn_cast<LLVM::InvokeOp>(terminator)) {
805 return invokeOp.getNormalDest() == current
806 ? invokeOp.getNormalDestOperands()[index]
807 : invokeOp.getUnwindDestOperands()[index];
811 "only branch, switch or invoke operations can be terminators "
812 "of a block that has successors");
820 for (
Block &bb : llvm::drop_begin(region)) {
821 llvm::BasicBlock *llvmBB = state.lookupBlock(&bb);
822 auto phis = llvmBB->phis();
823 auto numArguments = bb.getNumArguments();
824 assert(numArguments == std::distance(phis.begin(), phis.end()));
826 for (
auto *pred : bb.getPredecessors()) {
832 llvm::Instruction *terminator =
833 state.lookupBranch(pred->getTerminator());
834 assert(terminator &&
"missing the mapping for a terminator");
836 &bb, pred, numArguments, index)),
837 terminator->getParent());
846 llvm::Module *module = builder.GetInsertBlock()->getModule();
847 llvm::Function *fn = llvm::Intrinsic::getDeclaration(module, intrinsic, tys);
848 return builder.CreateCall(fn, args);
857 assert(immArgPositions.size() == immArgAttrNames.size() &&
858 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
864 for (
auto [immArgPos, immArgName] :
865 llvm::zip(immArgPositions, immArgAttrNames)) {
866 auto attr = llvm::cast<TypedAttr>(intrOp->
getAttr(immArgName));
867 assert(attr.getType().isIntOrFloat() &&
"expected int or float immarg");
868 auto *type = moduleTranslation.
convertType(attr.getType());
870 type, attr, intrOp->
getLoc(), moduleTranslation);
873 for (
auto &arg : args) {
875 arg = operands[opArg++];
880 for (
unsigned overloadedResultIdx : overloadedResults) {
881 if (numResults > 1) {
883 overloadedTypes.push_back(moduleTranslation.
convertType(
885 .getBody()[overloadedResultIdx]));
887 overloadedTypes.push_back(
891 for (
unsigned overloadedOperandIdx : overloadedOperands)
892 overloadedTypes.push_back(args[overloadedOperandIdx]->
getType());
893 llvm::Module *module = builder.GetInsertBlock()->getModule();
894 llvm::Function *llvmIntr =
895 llvm::Intrinsic::getDeclaration(module, intrinsic, overloadedTypes);
897 return builder.CreateCall(llvmIntr, args);
902 LogicalResult ModuleTranslation::convertOperation(
Operation &op,
903 llvm::IRBuilderBase &builder,
904 bool recordInsertions) {
907 return op.
emitError(
"cannot be converted to LLVM IR: missing "
908 "`LLVMTranslationDialectInterface` registration for "
912 InstructionCapturingInserter::CollectionScope scope(builder,
915 return op.
emitError(
"LLVM Translation failed for operation: ")
918 return convertDialectAttributes(&op, scope.getCapturedInstructions());
928 LogicalResult ModuleTranslation::convertBlockImpl(
Block &bb,
929 bool ignoreArguments,
930 llvm::IRBuilderBase &builder,
931 bool recordInsertions) {
933 auto *subprogram = builder.GetInsertBlock()->getParent()->getSubprogram();
941 if (!ignoreArguments) {
943 unsigned numPredecessors =
944 std::distance(predecessors.begin(), predecessors.end());
946 auto wrappedType = arg.getType();
949 "block argument does not have an LLVM type");
951 llvm::PHINode *phi = builder.CreatePHI(type, numPredecessors);
957 for (
auto &op : bb) {
959 builder.SetCurrentDebugLocation(
960 debugTranslation->translateLoc(op.
getLoc(), subprogram));
962 if (failed(convertOperation(op, builder, recordInsertions)))
966 if (
auto iface = dyn_cast<BranchWeightOpInterface>(op))
985 llvm::Constant *cst) {
986 return (linkage == llvm::GlobalVariable::ExternalLinkage && !cst) ||
987 linkage == llvm::GlobalVariable::ExternalWeakLinkage;
993 llvm::GlobalValue *gv) {
994 if (dsoLocalRequested)
995 gv->setDSOLocal(
true);
1000 LogicalResult ModuleTranslation::convertGlobals() {
1004 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1006 llvm::Constant *cst =
nullptr;
1007 if (op.getValueOrNull()) {
1010 if (
auto strAttr = dyn_cast_or_null<StringAttr>(op.getValueOrNull())) {
1011 cst = llvm::ConstantDataArray::getString(
1012 llvmModule->getContext(), strAttr.getValue(),
false);
1013 type = cst->getType();
1020 auto linkage = convertLinkageToLLVM(op.getLinkage());
1021 auto addrSpace = op.getAddrSpace();
1027 if (!dropInitializer && !cst)
1029 else if (dropInitializer && cst)
1032 auto *var =
new llvm::GlobalVariable(
1033 *llvmModule, type, op.getConstant(), linkage, cst, op.getSymName(),
1035 op.getThreadLocal_() ? llvm::GlobalValue::GeneralDynamicTLSModel
1036 : llvm::GlobalValue::NotThreadLocal,
1039 if (std::optional<mlir::SymbolRefAttr> comdat = op.getComdat()) {
1040 auto selectorOp = cast<ComdatSelectorOp>(
1042 var->setComdat(comdatMapping.lookup(selectorOp));
1045 if (op.getUnnamedAddr().has_value())
1046 var->setUnnamedAddr(convertUnnamedAddrToLLVM(*op.getUnnamedAddr()));
1048 if (op.getSection().has_value())
1049 var->setSection(*op.getSection());
1053 std::optional<uint64_t> alignment = op.getAlignment();
1054 if (alignment.has_value())
1055 var->setAlignment(llvm::MaybeAlign(alignment.value()));
1057 var->setVisibility(convertVisibilityToLLVM(op.getVisibility_()));
1059 globalsMapping.try_emplace(op, var);
1062 if (op.getDbgExpr()) {
1063 llvm::DIGlobalVariableExpression *diGlobalExpr =
1064 debugTranslation->translateGlobalVariableExpression(op.getDbgExpr());
1065 llvm::DIGlobalVariable *diGlobalVar = diGlobalExpr->getVariable();
1066 var->addDebugInfo(diGlobalExpr);
1080 llvm::DIScope *scope = diGlobalVar->getScope();
1081 if (
auto *mod = dyn_cast_if_present<llvm::DIModule>(scope))
1082 scope = mod->getScope();
1083 else if (
auto *sp = dyn_cast_if_present<llvm::DISubprogram>(scope))
1084 scope = sp->getUnit();
1087 if (llvm::DICompileUnit *compileUnit =
1088 dyn_cast_if_present<llvm::DICompileUnit>(scope)) {
1091 allGVars[compileUnit].push_back(diGlobalExpr);
1099 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>()) {
1100 if (
Block *initializer = op.getInitializerBlock()) {
1101 llvm::IRBuilder<> builder(llvmModule->getContext());
1103 [[maybe_unused]]
int numConstantsHit = 0;
1104 [[maybe_unused]]
int numConstantsErased = 0;
1107 for (
auto &op : initializer->without_terminator()) {
1108 if (failed(convertOperation(op, builder)))
1121 if (
auto *agg = dyn_cast<llvm::ConstantAggregate>(cst)) {
1125 auto [iterator, inserted] =
1126 constantAggregateUseMap.try_emplace(agg, numUsers);
1129 iterator->second += numUsers;
1135 auto cst = dyn_cast<llvm::ConstantAggregate>(
lookupValue(v));
1138 auto iter = constantAggregateUseMap.find(cst);
1139 assert(iter != constantAggregateUseMap.end() &&
"constant not found");
1141 if (iter->second == 0) {
1144 if (cst->user_empty()) {
1145 cst->destroyConstant();
1146 numConstantsErased++;
1148 constantAggregateUseMap.erase(iter);
1153 ReturnOp ret = cast<ReturnOp>(initializer->getTerminator());
1154 llvm::Constant *cst =
1155 cast<llvm::Constant>(
lookupValue(ret.getOperand(0)));
1156 auto *global = cast<llvm::GlobalVariable>(
lookupGlobal(op));
1158 global->setInitializer(cst);
1162 for (
auto it : constantAggregateUseMap) {
1163 auto cst = it.first;
1164 cst->removeDeadConstantUsers();
1165 if (cst->user_empty()) {
1166 cst->destroyConstant();
1167 numConstantsErased++;
1171 LLVM_DEBUG(llvm::dbgs()
1172 <<
"Convert initializer for " << op.
getName() <<
"\n";
1173 llvm::dbgs() << numConstantsHit <<
" new constants hit\n";
1175 << numConstantsErased <<
" dangling constants erased\n";);
1181 auto ctorOp = dyn_cast<GlobalCtorsOp>(op);
1182 auto dtorOp = dyn_cast<GlobalDtorsOp>(op);
1183 if (!ctorOp && !dtorOp)
1185 auto range = ctorOp ? llvm::zip(ctorOp.getCtors(), ctorOp.getPriorities())
1186 :
llvm::zip(dtorOp.getDtors(), dtorOp.getPriorities());
1187 auto appendGlobalFn =
1188 ctorOp ? llvm::appendToGlobalCtors : llvm::appendToGlobalDtors;
1189 for (
auto symbolAndPriority : range) {
1191 cast<FlatSymbolRefAttr>(std::get<0>(symbolAndPriority)).getValue());
1192 appendGlobalFn(*llvmModule, f,
1193 cast<IntegerAttr>(std::get<1>(symbolAndPriority)).getInt(),
1198 for (
auto op :
getModuleBody(mlirModule).getOps<LLVM::GlobalOp>())
1199 if (failed(convertDialectAttributes(op, {})))
1204 for (
const auto &[compileUnit, globals] : allGVars) {
1205 compileUnit->replaceGlobalVariables(
1219 llvm::Function *llvmFunc,
1221 StringRef value = StringRef()) {
1222 auto kind = llvm::Attribute::getAttrKindFromName(key);
1224 llvmFunc->addFnAttr(key, value);
1228 if (llvm::Attribute::isIntAttrKind(kind)) {
1230 return emitError(loc) <<
"LLVM attribute '" << key <<
"' expects a value";
1233 if (!value.getAsInteger(0, result))
1234 llvmFunc->addFnAttr(
1237 llvmFunc->addFnAttr(key, value);
1242 return emitError(loc) <<
"LLVM attribute '" << key
1243 <<
"' does not expect a value, found '" << value
1246 llvmFunc->addFnAttr(kind);
1257 static LogicalResult
1259 llvm::Function *llvmFunc) {
1264 if (
auto stringAttr = dyn_cast<StringAttr>(attr)) {
1271 auto arrayAttr = dyn_cast<ArrayAttr>(attr);
1272 if (!arrayAttr || arrayAttr.size() != 2)
1274 <<
"expected 'passthrough' to contain string or array attributes";
1276 auto keyAttr = dyn_cast<StringAttr>(arrayAttr[0]);
1277 auto valueAttr = dyn_cast<StringAttr>(arrayAttr[1]);
1278 if (!keyAttr || !valueAttr)
1280 <<
"expected arrays within 'passthrough' to contain two strings";
1283 valueAttr.getValue())))
1289 LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
1292 blockMapping.clear();
1293 valueMapping.clear();
1294 branchMapping.clear();
1298 for (
auto [mlirArg, llvmArg] :
1299 llvm::zip(func.getArguments(), llvmFunc->args()))
1303 if (func.getPersonality()) {
1304 llvm::Type *ty = llvm::PointerType::getUnqual(llvmFunc->getContext());
1305 if (llvm::Constant *pfunc =
getLLVMConstant(ty, func.getPersonalityAttr(),
1306 func.getLoc(), *
this))
1307 llvmFunc->setPersonalityFn(pfunc);
1310 if (std::optional<StringRef> section = func.getSection())
1311 llvmFunc->setSection(*section);
1313 if (func.getArmStreaming())
1314 llvmFunc->addFnAttr(
"aarch64_pstate_sm_enabled");
1315 else if (func.getArmLocallyStreaming())
1316 llvmFunc->addFnAttr(
"aarch64_pstate_sm_body");
1317 else if (func.getArmStreamingCompatible())
1318 llvmFunc->addFnAttr(
"aarch64_pstate_sm_compatible");
1320 if (func.getArmNewZa())
1321 llvmFunc->addFnAttr(
"aarch64_new_za");
1322 else if (func.getArmInZa())
1323 llvmFunc->addFnAttr(
"aarch64_in_za");
1324 else if (func.getArmOutZa())
1325 llvmFunc->addFnAttr(
"aarch64_out_za");
1326 else if (func.getArmInoutZa())
1327 llvmFunc->addFnAttr(
"aarch64_inout_za");
1328 else if (func.getArmPreservesZa())
1329 llvmFunc->addFnAttr(
"aarch64_preserves_za");
1331 if (
auto targetCpu = func.getTargetCpu())
1332 llvmFunc->addFnAttr(
"target-cpu", *targetCpu);
1334 if (
auto tuneCpu = func.getTuneCpu())
1335 llvmFunc->addFnAttr(
"tune-cpu", *tuneCpu);
1337 if (
auto targetFeatures = func.getTargetFeatures())
1338 llvmFunc->addFnAttr(
"target-features", targetFeatures->getFeaturesString());
1340 if (
auto attr = func.getVscaleRange())
1341 llvmFunc->addFnAttr(llvm::Attribute::getWithVScaleRangeArgs(
1343 attr->getMaxRange().getInt()));
1345 if (
auto unsafeFpMath = func.getUnsafeFpMath())
1346 llvmFunc->addFnAttr(
"unsafe-fp-math", llvm::toStringRef(*unsafeFpMath));
1348 if (
auto noInfsFpMath = func.getNoInfsFpMath())
1349 llvmFunc->addFnAttr(
"no-infs-fp-math", llvm::toStringRef(*noInfsFpMath));
1351 if (
auto noNansFpMath = func.getNoNansFpMath())
1352 llvmFunc->addFnAttr(
"no-nans-fp-math", llvm::toStringRef(*noNansFpMath));
1354 if (
auto approxFuncFpMath = func.getApproxFuncFpMath())
1355 llvmFunc->addFnAttr(
"approx-func-fp-math",
1356 llvm::toStringRef(*approxFuncFpMath));
1358 if (
auto noSignedZerosFpMath = func.getNoSignedZerosFpMath())
1359 llvmFunc->addFnAttr(
"no-signed-zeros-fp-math",
1360 llvm::toStringRef(*noSignedZerosFpMath));
1362 if (
auto denormalFpMath = func.getDenormalFpMath())
1363 llvmFunc->addFnAttr(
"denormal-fp-math", *denormalFpMath);
1365 if (
auto denormalFpMathF32 = func.getDenormalFpMathF32())
1366 llvmFunc->addFnAttr(
"denormal-fp-math-f32", *denormalFpMathF32);
1368 if (
auto fpContract = func.getFpContract())
1369 llvmFunc->addFnAttr(
"fp-contract", *fpContract);
1372 if (FramePointerKindAttr attr = func.getFramePointerAttr())
1373 llvmFunc->addFnAttr(
"frame-pointer",
1374 LLVM::framePointerKind::stringifyFramePointerKind(
1375 (attr.getFramePointerKind())));
1378 llvm::LLVMContext &llvmContext = llvmFunc->getContext();
1379 for (
auto &bb : func) {
1380 auto *llvmBB = llvm::BasicBlock::Create(llvmContext);
1381 llvmBB->insertInto(llvmFunc);
1388 for (
Block *bb : blocks) {
1389 CapturingIRBuilder builder(llvmContext);
1390 if (failed(convertBlockImpl(*bb, bb->isEntryBlock(), builder,
1400 return convertDialectAttributes(func, {});
1403 LogicalResult ModuleTranslation::convertDialectAttributes(
1406 if (failed(iface.
amendOperation(op, instructions, attribute, *
this)))
1414 llvm::Function *llvmFunc) {
1415 if (!func.getMemoryEffects())
1418 MemoryEffectsAttr memEffects = func.getMemoryEffectsAttr();
1421 llvm::MemoryEffects newMemEffects =
1422 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
1423 convertModRefInfoToLLVM(memEffects.getArgMem()));
1424 newMemEffects |= llvm::MemoryEffects(
1425 llvm::MemoryEffects::Location::InaccessibleMem,
1426 convertModRefInfoToLLVM(memEffects.getInaccessibleMem()));
1428 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
1429 convertModRefInfoToLLVM(memEffects.getOther()));
1430 llvmFunc->setMemoryEffects(newMemEffects);
1435 llvm::Function *llvmFunc) {
1436 if (func.getNoInlineAttr())
1437 llvmFunc->addFnAttr(llvm::Attribute::NoInline);
1438 if (func.getAlwaysInlineAttr())
1439 llvmFunc->addFnAttr(llvm::Attribute::AlwaysInline);
1440 if (func.getOptimizeNoneAttr())
1441 llvmFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1442 if (func.getConvergentAttr())
1443 llvmFunc->addFnAttr(llvm::Attribute::Convergent);
1444 if (func.getNoUnwindAttr())
1445 llvmFunc->addFnAttr(llvm::Attribute::NoUnwind);
1446 if (func.getWillReturnAttr())
1447 llvmFunc->addFnAttr(llvm::Attribute::WillReturn);
1451 FailureOr<llvm::AttrBuilder>
1452 ModuleTranslation::convertParameterAttrs(LLVMFuncOp func,
int argIdx,
1453 DictionaryAttr paramAttrs) {
1454 llvm::AttrBuilder attrBuilder(llvmModule->getContext());
1457 for (
auto namedAttr : paramAttrs) {
1458 auto it = attrNameToKindMapping.find(namedAttr.getName());
1459 if (it != attrNameToKindMapping.end()) {
1460 llvm::Attribute::AttrKind llvmKind = it->second;
1463 .Case<TypeAttr>([&](
auto typeAttr) {
1464 attrBuilder.addTypeAttr(llvmKind,
convertType(typeAttr.getValue()));
1466 .Case<IntegerAttr>([&](
auto intAttr) {
1467 attrBuilder.addRawIntAttr(llvmKind, intAttr.getInt());
1469 .Case<UnitAttr>([&](
auto) { attrBuilder.addAttribute(llvmKind); });
1470 }
else if (namedAttr.getNameDialect()) {
1479 LogicalResult ModuleTranslation::convertFunctionSignatures() {
1482 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1483 llvm::FunctionCallee llvmFuncCst = llvmModule->getOrInsertFunction(
1485 cast<llvm::FunctionType>(
convertType(
function.getFunctionType())));
1486 llvm::Function *llvmFunc = cast<llvm::Function>(llvmFuncCst.getCallee());
1487 llvmFunc->setLinkage(convertLinkageToLLVM(
function.getLinkage()));
1488 llvmFunc->setCallingConv(convertCConvToLLVM(
function.getCConv()));
1496 if (std::optional<uint64_t> entryCount =
function.getFunctionEntryCount())
1497 llvmFunc->setEntryCount(entryCount.value());
1500 if (ArrayAttr allResultAttrs =
function.getAllResultAttrs()) {
1501 DictionaryAttr resultAttrs = cast<DictionaryAttr>(allResultAttrs[0]);
1502 FailureOr<llvm::AttrBuilder> attrBuilder =
1503 convertParameterAttrs(
function, -1, resultAttrs);
1504 if (failed(attrBuilder))
1506 llvmFunc->addRetAttrs(*attrBuilder);
1512 FailureOr<llvm::AttrBuilder> attrBuilder =
1513 convertParameterAttrs(
function, argIdx, argAttrs);
1514 if (failed(attrBuilder))
1516 llvmArg.addAttrs(*attrBuilder);
1522 function.getLoc(),
function.getPassthrough(), llvmFunc)))
1526 llvmFunc->setVisibility(convertVisibilityToLLVM(
function.getVisibility_()));
1529 if (std::optional<mlir::SymbolRefAttr> comdat =
function.getComdat()) {
1530 auto selectorOp = cast<ComdatSelectorOp>(
1532 llvmFunc->setComdat(comdatMapping.lookup(selectorOp));
1535 if (
auto gc =
function.getGarbageCollector())
1536 llvmFunc->setGC(gc->str());
1538 if (
auto unnamedAddr =
function.getUnnamedAddr())
1539 llvmFunc->setUnnamedAddr(convertUnnamedAddrToLLVM(*unnamedAddr));
1541 if (
auto alignment =
function.getAlignment())
1542 llvmFunc->setAlignment(llvm::MaybeAlign(*alignment));
1545 debugTranslation->translate(
function, *llvmFunc);
1551 LogicalResult ModuleTranslation::convertFunctions() {
1553 for (
auto function :
getModuleBody(mlirModule).getOps<LLVMFuncOp>()) {
1556 if (
function.isExternal()) {
1557 if (failed(convertDialectAttributes(
function, {})))
1562 if (failed(convertOneFunction(
function)))
1569 LogicalResult ModuleTranslation::convertComdats() {
1570 for (
auto comdatOp :
getModuleBody(mlirModule).getOps<ComdatOp>()) {
1571 for (
auto selectorOp : comdatOp.getOps<ComdatSelectorOp>()) {
1573 if (module->getComdatSymbolTable().contains(selectorOp.getSymName()))
1575 <<
"comdat selection symbols must be unique even in different "
1577 llvm::Comdat *comdat = module->getOrInsertComdat(selectorOp.getSymName());
1578 comdat->setSelectionKind(convertComdatToLLVM(selectorOp.getComdat()));
1579 comdatMapping.try_emplace(selectorOp, comdat);
1586 llvm::Instruction *inst) {
1587 if (llvm::MDNode *node = loopAnnotationTranslation->getAccessGroups(op))
1588 inst->setMetadata(llvm::LLVMContext::MD_access_group, node);
1593 auto [scopeIt, scopeInserted] =
1594 aliasScopeMetadataMapping.try_emplace(aliasScopeAttr,
nullptr);
1596 return scopeIt->second;
1597 llvm::LLVMContext &ctx = llvmModule->getContext();
1598 auto dummy = llvm::MDNode::getTemporary(ctx, std::nullopt);
1600 auto [domainIt, insertedDomain] = aliasDomainMetadataMapping.try_emplace(
1601 aliasScopeAttr.getDomain(),
nullptr);
1602 if (insertedDomain) {
1605 operands.push_back(dummy.get());
1606 if (StringAttr description = aliasScopeAttr.getDomain().getDescription())
1610 domainIt->second->replaceOperandWith(0, domainIt->second);
1613 assert(domainIt->second &&
"Scope's domain should already be valid");
1616 operands.push_back(dummy.get());
1617 operands.push_back(domainIt->second);
1618 if (StringAttr description = aliasScopeAttr.getDescription())
1622 scopeIt->second->replaceOperandWith(0, scopeIt->second);
1623 return scopeIt->second;
1629 nodes.reserve(aliasScopeAttrs.size());
1630 for (AliasScopeAttr aliasScopeAttr : aliasScopeAttrs)
1636 llvm::Instruction *inst) {
1637 auto populateScopeMetadata = [&](ArrayAttr aliasScopeAttrs,
unsigned kind) {
1638 if (!aliasScopeAttrs || aliasScopeAttrs.empty())
1641 llvm::to_vector(aliasScopeAttrs.getAsRange<AliasScopeAttr>()));
1642 inst->setMetadata(kind, node);
1645 populateScopeMetadata(op.getAliasScopesOrNull(),
1646 llvm::LLVMContext::MD_alias_scope);
1647 populateScopeMetadata(op.getNoAliasScopesOrNull(),
1648 llvm::LLVMContext::MD_noalias);
1651 llvm::MDNode *ModuleTranslation::getTBAANode(TBAATagAttr tbaaAttr)
const {
1652 return tbaaMetadataMapping.lookup(tbaaAttr);
1656 llvm::Instruction *inst) {
1657 ArrayAttr tagRefs = op.getTBAATagsOrNull();
1658 if (!tagRefs || tagRefs.empty())
1665 if (tagRefs.size() > 1) {
1666 op.
emitWarning() <<
"TBAA access tags were not translated, because LLVM "
1667 "IR only supports a single tag per instruction";
1671 llvm::MDNode *node = getTBAANode(cast<TBAATagAttr>(tagRefs[0]));
1672 inst->setMetadata(llvm::LLVMContext::MD_tbaa, node);
1681 assert(inst &&
"expected the operation to have a mapping to an instruction");
1684 llvm::LLVMContext::MD_prof,
1688 LogicalResult ModuleTranslation::createTBAAMetadata() {
1689 llvm::LLVMContext &ctx = llvmModule->getContext();
1701 walker.
addWalk([&](TBAARootAttr root) {
1702 tbaaMetadataMapping.insert(
1706 walker.
addWalk([&](TBAATypeDescriptorAttr descriptor) {
1709 for (TBAAMemberAttr member : descriptor.getMembers()) {
1710 operands.push_back(tbaaMetadataMapping.lookup(member.getTypeDesc()));
1718 walker.
addWalk([&](TBAATagAttr tag) {
1721 operands.push_back(tbaaMetadataMapping.lookup(tag.getBaseType()));
1722 operands.push_back(tbaaMetadataMapping.lookup(tag.getAccessType()));
1726 if (tag.getConstant())
1733 mlirModule->
walk([&](AliasAnalysisOpInterface analysisOpInterface) {
1734 if (
auto attr = analysisOpInterface.getTBAATagsOrNull())
1742 llvm::Instruction *inst) {
1743 LoopAnnotationAttr attr =
1745 .Case<LLVM::BrOp, LLVM::CondBrOp>(
1746 [](
auto branchOp) {
return branchOp.getLoopAnnotationAttr(); });
1749 llvm::MDNode *loopMD =
1750 loopAnnotationTranslation->translateLoopAnnotation(attr, op);
1751 inst->setMetadata(llvm::LLVMContext::MD_loop, loopMD);
1761 remapped.reserve(values.size());
1762 for (
Value v : values)
1769 ompBuilder = std::make_unique<llvm::OpenMPIRBuilder>(*llvmModule);
1770 ompBuilder->initialize();
1775 ompBuilder->setConfig(llvm::OpenMPIRBuilderConfig(
1783 return ompBuilder.get();
1787 llvm::DILocalScope *scope) {
1788 return debugTranslation->translateLoc(loc, scope);
1791 llvm::DIExpression *
1793 return debugTranslation->translateExpression(attr);
1796 llvm::DIGlobalVariableExpression *
1798 LLVM::DIGlobalVariableExpressionAttr attr) {
1799 return debugTranslation->translateGlobalVariableExpression(attr);
1803 return debugTranslation->translate(attr);
1808 return convertRoundingModeToLLVM(rounding);
1812 LLVM::FPExceptionBehavior exceptionBehavior) {
1813 return convertFPExceptionBehaviorToLLVM(exceptionBehavior);
1818 return llvmModule->getOrInsertNamedMetadata(name);
1821 void ModuleTranslation::StackFrame::anchor() {}
1823 static std::unique_ptr<llvm::Module>
1826 m->getContext()->getOrLoadDialect<LLVM::LLVMDialect>();
1827 auto llvmModule = std::make_unique<llvm::Module>(name, llvmContext);
1830 llvmModule->setNewDbgInfoFormatFlag(
false);
1831 if (
auto dataLayoutAttr =
1832 m->getDiscardableAttr(LLVM::LLVMDialect::getDataLayoutAttrName())) {
1833 llvmModule->setDataLayout(cast<StringAttr>(dataLayoutAttr).getValue());
1835 FailureOr<llvm::DataLayout> llvmDataLayout(llvm::DataLayout(
""));
1836 if (
auto iface = dyn_cast<DataLayoutOpInterface>(m)) {
1837 if (DataLayoutSpecInterface spec = iface.getDataLayoutSpec()) {
1841 }
else if (
auto mod = dyn_cast<ModuleOp>(m)) {
1842 if (DataLayoutSpecInterface spec = mod.getDataLayoutSpec()) {
1847 if (failed(llvmDataLayout))
1849 llvmModule->setDataLayout(*llvmDataLayout);
1851 if (
auto targetTripleAttr =
1852 m->getDiscardableAttr(LLVM::LLVMDialect::getTargetTripleAttrName()))
1853 llvmModule->setTargetTriple(cast<StringAttr>(targetTripleAttr).getValue());
1858 std::unique_ptr<llvm::Module>
1860 StringRef name,
bool disableVerification) {
1862 module->
emitOpError(
"can not be translated to an LLVMIR module");
1866 std::unique_ptr<llvm::Module> llvmModule =
1875 llvm::IRBuilder<> llvmBuilder(llvmContext);
1881 if (failed(translator.convertOperation(*module, llvmBuilder)))
1884 if (failed(translator.convertComdats()))
1886 if (failed(translator.convertFunctionSignatures()))
1888 if (failed(translator.convertGlobals()))
1890 if (failed(translator.createTBAAMetadata()))
1895 if (!isa<LLVM::LLVMFuncOp, LLVM::GlobalOp, LLVM::GlobalCtorsOp,
1896 LLVM::GlobalDtorsOp, LLVM::ComdatOp>(&o) &&
1898 failed(translator.convertOperation(o, llvmBuilder))) {
1906 if (failed(translator.convertFunctions()))
1914 if (!disableVerification &&
1915 llvm::verifyModule(*translator.llvmModule, &llvm::errs()))
1918 return std::move(translator.llvmModule);
static MLIRContext * getContext(OpFoldResult val)
static Value getPHISourceValue(Block *current, Block *pred, unsigned numArguments, unsigned index)
Get the SSA value passed to the current block from the terminator operation of its predecessor.
static llvm::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 Block & getModuleBody(Operation *module)
A helper method to get the single Block in an operation honoring LLVM's module requirements.
static void addRuntimePreemptionSpecifier(bool dsoLocalRequested, llvm::GlobalValue *gv)
Sets the runtime preemption specifier of gv to dso_local if dsoLocalRequested is true,...
static LogicalResult checkedAddLLVMFnAttribute(Location loc, llvm::Function *llvmFunc, StringRef key, StringRef value=StringRef())
Attempts to add an attribute identified by key, optionally with the given value to LLVM function llvm...
static void convertFunctionAttributes(LLVMFuncOp func, llvm::Function *llvmFunc)
Converts function attributes from func and attaches them to llvmFunc.
llvm::cl::opt< bool > UseNewDbgInfoFormat
static bool shouldDropGlobalInitializer(llvm::GlobalValue::LinkageTypes linkage, llvm::Constant *cst)
A helper method to decide if a constant must not be set as a global variable initializer.
static llvm::Type * getInnermostElementType(llvm::Type *type)
Returns the first non-sequential type nested in sequential types.
static std::unique_ptr< llvm::Module > prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext, StringRef name)
static llvm::Constant * convertDenseResourceElementsAttr(Location loc, DenseResourceElementsAttr denseResourceAttr, llvm::Type *llvmType, const ModuleTranslation &moduleTranslation)
Convert a dense resource elements attribute to an LLVM IR constant using its raw data storage if poss...
static void convertFunctionMemoryAttributes(LLVMFuncOp func, llvm::Function *llvmFunc)
Converts memory effect attributes from func and attaches them to llvmFunc.
static LogicalResult forwardPassthroughAttributes(Location loc, std::optional< ArrayAttr > attributes, llvm::Function *llvmFunc)
Attaches the attributes listed in the given array attribute to llvmFunc.
static llvm::Constant * buildSequentialConstant(ArrayRef< llvm::Constant * > &constants, ArrayRef< int64_t > shape, llvm::Type *type, Location loc)
Builds a constant of a sequential LLVM type type, potentially containing other sequential types recur...
The following classes enable support for parsing and printing resources within MLIR assembly formats.
ArrayRef< char > getData() const
Return the raw underlying data of this blob.
void addWalk(WalkFn< Attribute > &&fn)
Register a walk function for a given attribute or type.
WalkResult walk(T element)
Walk the given attribute/type, and recursively walk any sub elements.
Attributes are known-constant values of operations.
Block represents an ordered list of Operations.
Operation * getTerminator()
Get the terminator operation of this block.
iterator_range< pred_iterator > getPredecessors()
BlockArgListType getArguments()
The main mechanism for performing data layout queries.
std::optional< uint64_t > getTypeIndexBitwidth(Type t) const
Returns the bitwidth that should be used when performing index computations for the given pointer-lik...
uint64_t getTypePreferredAlignment(Type t) const
Returns the preferred of the given type in the current scope.
uint64_t getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
An attribute that represents a reference to a dense vector or tensor object.
std::enable_if_t<!std::is_base_of< Attribute, T >::value||std::is_same< Attribute, T >::value, T > getSplatValue() const
Return the splat value for this attribute.
int64_t getNumElements() const
Returns the number of elements held by this attribute.
bool isSplat() const
Returns true if this attribute corresponds to a splat, i.e.
ArrayRef< char > getRawData() const
Return the raw storage data held by this attribute.
ShapedType getType() const
Return the type of this ElementsAttr, guaranteed to be a vector or tensor with static shape.
const InterfaceType * getInterfaceFor(Object *obj) const
Get the interface for a given object, or null if one is not registered.
Base class for dialect interfaces providing translation to LLVM IR.
virtual LogicalResult convertOperation(Operation *op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) const
Hook for derived dialect interface to provide translation of the operations to LLVM IR.
virtual LogicalResult convertParameterAttr(LLVM::LLVMFuncOp function, int argIdx, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const
Acts on the given function operation using the interface implemented by the dialect of one of the fun...
virtual LogicalResult amendOperation(Operation *op, ArrayRef< llvm::Instruction * > instructions, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation) const
Acts on the given operation using the interface implemented by the dialect of one of the operation's ...
This class represents the base attribute for all debug info attributes.
Implementation class for module translation.
llvm::fp::ExceptionBehavior translateFPExceptionBehavior(LLVM::FPExceptionBehavior exceptionBehavior)
Translates the given LLVM FP exception behavior metadata.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
llvm::DIGlobalVariableExpression * translateGlobalVariableExpression(LLVM::DIGlobalVariableExpressionAttr attr)
Translates the given LLVM global variable expression metadata.
llvm::NamedMDNode * getOrInsertNamedModuleMetadata(StringRef name)
Gets the named metadata in the LLVM IR module being constructed, creating it if it does not exist.
llvm::Instruction * lookupBranch(Operation *op) const
Finds an LLVM IR instruction that corresponds to the given MLIR operation with successors.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
void mapFunction(StringRef name, llvm::Function *func)
Stores the mapping between a function name and its LLVM IR representation.
llvm::DILocation * translateLoc(Location loc, llvm::DILocalScope *scope)
Translates the given location.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
void setBranchWeightsMetadata(BranchWeightOpInterface op)
Sets LLVM profiling metadata for operations that have branch weights.
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
llvm::RoundingMode translateRoundingMode(LLVM::RoundingMode rounding)
Translates the given LLVM rounding mode metadata.
void setTBAAMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
Sets LLVM TBAA metadata for memory operations that have TBAA attributes.
llvm::DIExpression * translateExpression(LLVM::DIExpressionAttr attr)
Translates the given LLVM DWARF expression metadata.
llvm::OpenMPIRBuilder * getOpenMPBuilder()
Returns the OpenMP IR builder associated with the LLVM IR module being constructed.
llvm::CallInst * lookupCall(Operation *op) const
Finds an LLVM call instruction that corresponds to the given MLIR call operation.
llvm::Metadata * translateDebugInfo(LLVM::DINodeAttr attr)
Translates the given LLVM debug info metadata.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
llvm::MDNode * getOrCreateAliasScopes(ArrayRef< AliasScopeAttr > aliasScopeAttrs)
Returns the LLVM metadata corresponding to an array of mlir LLVM dialect alias scope attributes.
void mapBlock(Block *mlir, llvm::BasicBlock *llvm)
Stores the mapping between an MLIR block and LLVM IR basic block.
llvm::MDNode * getOrCreateAliasScope(AliasScopeAttr aliasScopeAttr)
Returns the LLVM metadata corresponding to a mlir LLVM dialect alias scope attribute.
void forgetMapping(Region ®ion)
Removes the mapping for blocks contained in the region and values defined in these blocks.
void setAliasScopeMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
void setAccessGroupsMetadata(AccessGroupOpInterface op, llvm::Instruction *inst)
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
void setLoopMetadata(Operation *op, llvm::Instruction *inst)
Sets LLVM loop metadata for branch operations that have a loop annotation attribute.
llvm::Type * translateType(Type type)
Translates the given MLIR LLVM dialect type to LLVM IR.
A helper class that converts LoopAnnotationAttrs and AccessGroupAttrs into corresponding llvm::MDNode...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
NamedAttribute represents a combination of a name and an Attribute value.
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
Value getOperand(unsigned idx)
Attribute getAttr(StringAttr name)
Return the specified attribute if present, null otherwise.
Block * getSuccessor(unsigned index)
unsigned getNumSuccessors()
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Location getLoc()
The source location the operation was defined or derived from.
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
OperationName getName()
The name of an operation is the key identifier for it.
dialect_attr_range getDialectAttrs()
Return a range corresponding to the dialect attributes for this operation.
operand_range getOperands()
Returns an iterator on the underlying Value's.
result_range getResults()
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
This class models how operands are forwarded to block arguments in control flow.
bool empty() const
Returns true if there are no successor operands.
static Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
use_iterator use_end() const
Type getType() const
Return the type of this value.
use_iterator use_begin() const
ArrayRef< T > asArrayRef() const
Include the generated interface declarations.
void connectPHINodes(Region ®ion, const ModuleTranslation &state)
For all blocks in the region that were converted to LLVM IR using the given ModuleTranslation,...
llvm::CallInst * createIntrinsicCall(llvm::IRBuilderBase &builder, llvm::Intrinsic::ID intrinsic, ArrayRef< llvm::Value * > args={}, ArrayRef< llvm::Type * > tys={})
Creates a call to an LLVM IR intrinsic function with the given arguments.
static llvm::DenseMap< llvm::StringRef, llvm::Attribute::AttrKind > getAttrNameToKindMapping()
Returns a dense map from LLVM attribute name to their kind in LLVM IR dialect.
llvm::Constant * getLLVMConstant(llvm::Type *llvmType, Attribute attr, Location loc, const ModuleTranslation &moduleTranslation)
Create an LLVM IR constant of llvmType from the MLIR attribute attr.
bool satisfiesLLVMModule(Operation *op)
LLVM requires some operations to be inside of a Module operation.
void legalizeDIExpressionsRecursively(Operation *op)
Register all known legalization patterns declared here and apply them to all ops in op.
bool isCompatibleType(Type type)
Returns true if the given type is compatible with the LLVM dialect.
void ensureDistinctSuccessors(Operation *op)
Make argument-taking successors of each block distinct.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
DictionaryAttr getArgAttrDict(FunctionOpInterface op, unsigned index)
Returns the dictionary attribute corresponding to the argument at 'index'.
Include the generated interface declarations.
std::unique_ptr< llvm::Module > translateModuleToLLVMIR(Operation *module, llvm::LLVMContext &llvmContext, llvm::StringRef name="LLVMDialectModule", bool disableVerification=false)
Translates a given LLVM dialect module into an LLVM IR module living in the given context.
SetVector< Block * > getBlocksSortedByDominance(Region ®ion)
Gets a list of blocks that is sorted according to dominance.
DataLayoutSpecInterface translateDataLayout(const llvm::DataLayout &dataLayout, MLIRContext *context)
Translate the given LLVM data layout into an MLIR equivalent using the DLTI dialect.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...