19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/InlineAsm.h"
21 #include "llvm/IR/MDBuilder.h"
22 #include "llvm/IR/MatrixBuilder.h"
23 #include "llvm/IR/Operator.h"
29 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
32 using llvmFMF = llvm::FastMathFlags;
33 using FuncT = void (llvmFMF::*)(bool);
34 const std::pair<FastmathFlags, FuncT> handlers[] = {
36 {FastmathFlags::nnan, &llvmFMF::setNoNaNs},
37 {FastmathFlags::ninf, &llvmFMF::setNoInfs},
38 {FastmathFlags::nsz, &llvmFMF::setNoSignedZeros},
39 {FastmathFlags::arcp, &llvmFMF::setAllowReciprocal},
41 {FastmathFlags::afn, &llvmFMF::setApproxFunc},
42 {FastmathFlags::reassoc, &llvmFMF::setAllowReassoc},
45 llvm::FastMathFlags ret;
46 ::mlir::LLVM::FastmathFlags fmfMlir = op.getFastmathAttr().getValue();
47 for (
auto it : handlers)
48 if (bitEnumContainsAll(fmfMlir, it.first))
49 (ret.*(it.second))(
true);
56 llvm::append_range(position, indices);
61 static std::string
diagStr(
const llvm::Type *type) {
63 llvm::raw_string_ostream os(str);
77 allArgTys.push_back(moduleTranslation.
convertType(type));
81 resTy = llvm::Type::getVoidTy(module->getContext());
89 getIntrinsicInfoTableEntries(
id, table);
93 if (llvm::Intrinsic::matchIntrinsicSignature(ft, tableRef,
95 llvm::Intrinsic::MatchIntrinsicTypesResult::MatchIntrinsicTypes_Match) {
97 <<
diagStr(ft) <<
" to overloaded intrinsic " << op.getIntrinAttr()
98 <<
" does not match any of the overloads";
102 return llvm::Intrinsic::getDeclaration(module,
id, overloadedArgTysRef);
109 llvm::Module *module = builder.GetInsertBlock()->getModule();
111 llvm::Function::lookupIntrinsicID(op.getIntrinAttr());
114 << op.getIntrinAttr();
116 llvm::Function *fn =
nullptr;
117 if (llvm::Intrinsic::isOverloaded(
id)) {
124 fn = llvm::Intrinsic::getDeclaration(module,
id, {});
128 const llvm::Type *intrinType =
130 ? llvm::Type::getVoidTy(module->getContext())
132 if (intrinType != fn->getReturnType()) {
134 <<
diagStr(intrinType) <<
" but " << op.getIntrinAttr()
135 <<
" actually returns " <<
diagStr(fn->getReturnType());
140 if (!fn->getFunctionType()->isVarArg() &&
144 <<
" expects " << fn->arg_size();
146 if (fn->getFunctionType()->isVarArg() &&
150 << op.getIntrinAttr() <<
" expects at least " << fn->arg_size();
153 for (
unsigned i = 0, e = fn->arg_size(); i != e; ++i) {
154 const llvm::Type *expected = fn->getArg(i)->getType();
155 const llvm::Type *actual =
157 if (actual != expected) {
159 << i <<
" has type " <<
diagStr(actual) <<
" but "
160 << op.getIntrinAttr() <<
" expects " <<
diagStr(expected);
164 FastmathFlagsInterface itf = op;
175 llvm::IRBuilderBase &builder,
177 llvm::Module *llvmModule = moduleTranslation.
getLLVMModule();
178 llvm::LLVMContext &context = llvmModule->getContext();
179 llvm::NamedMDNode *linkerMDNode =
180 llvmModule->getOrInsertNamedMetadata(
"llvm.linker.options");
182 MDNodes.reserve(
options.size());
183 for (
auto s :
options.getAsRange<StringAttr>()) {
185 MDNodes.push_back(MDNode);
189 linkerMDNode->addOperand(listMDNode);
196 llvm::IRBuilder<>::FastMathFlagGuard fmfGuard(builder);
197 if (
auto fmf = dyn_cast<FastmathFlagsInterface>(opInst))
200 #include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
201 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
207 if (
auto callOp = dyn_cast<LLVM::CallOp>(opInst)) {
208 auto operands = moduleTranslation.
lookupValues(callOp.getOperands());
210 llvm::CallInst *call;
211 if (
auto attr = callOp.getCalleeAttr()) {
212 call = builder.CreateCall(
215 llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
216 moduleTranslation.
convertType(callOp.getCalleeFunctionType()));
217 call = builder.CreateCall(calleeType, operandsRef.front(),
218 operandsRef.drop_front());
220 call->setCallingConv(convertCConvToLLVM(callOp.getCConv()));
229 else if (!call->getType()->isVoidTy())
231 moduleTranslation.
mapCall(callOp, call);
235 if (
auto inlineAsmOp = dyn_cast<LLVM::InlineAsmOp>(opInst)) {
239 llvm::append_range(operandTypes, inlineAsmOp.getOperands().getTypes());
242 if (inlineAsmOp.getNumResults() == 0) {
245 assert(inlineAsmOp.getNumResults() == 1);
246 resultType = inlineAsmOp.getResultTypes()[0];
249 llvm::InlineAsm *inlineAsmInst =
250 inlineAsmOp.getAsmDialect()
252 static_cast<llvm::FunctionType *
>(
254 inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
255 inlineAsmOp.getHasSideEffects(),
256 inlineAsmOp.getIsAlignStack(),
257 convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
260 inlineAsmOp.getAsmString(),
261 inlineAsmOp.getConstraints(),
262 inlineAsmOp.getHasSideEffects(),
263 inlineAsmOp.getIsAlignStack());
264 llvm::CallInst *inst = builder.CreateCall(
266 moduleTranslation.
lookupValues(inlineAsmOp.getOperands()));
267 if (
auto maybeOperandAttrs = inlineAsmOp.getOperandAttrs()) {
268 llvm::AttributeList attrList;
273 DictionaryAttr dAttr = cast<DictionaryAttr>(attr);
275 cast<TypeAttr>(dAttr.get(InlineAsmOp::getElementTypeAttrName()));
277 llvm::Type *ty = moduleTranslation.
convertType(tAttr.getValue());
278 b.addTypeAttr(llvm::Attribute::ElementType, ty);
282 attrList = attrList.addAttributesAtIndex(
285 inst->setAttributes(attrList);
293 if (
auto invOp = dyn_cast<LLVM::InvokeOp>(opInst)) {
294 auto operands = moduleTranslation.
lookupValues(invOp.getCalleeOperands());
296 llvm::InvokeInst *result;
298 result = builder.CreateInvoke(
300 moduleTranslation.
lookupBlock(invOp.getSuccessor(0)),
301 moduleTranslation.
lookupBlock(invOp.getSuccessor(1)), operandsRef);
303 llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
304 moduleTranslation.
convertType(invOp.getCalleeFunctionType()));
305 result = builder.CreateInvoke(
306 calleeType, operandsRef.front(),
307 moduleTranslation.
lookupBlock(invOp.getSuccessor(0)),
308 moduleTranslation.
lookupBlock(invOp.getSuccessor(1)),
309 operandsRef.drop_front());
311 result->setCallingConv(convertCConvToLLVM(invOp.getCConv()));
312 moduleTranslation.
mapBranch(invOp, result);
314 if (invOp->getNumResults() != 0) {
318 return success(result->getType()->isVoidTy());
321 if (
auto lpOp = dyn_cast<LLVM::LandingpadOp>(opInst)) {
322 llvm::Type *ty = moduleTranslation.
convertType(lpOp.getType());
323 llvm::LandingPadInst *lpi =
324 builder.CreateLandingPad(ty, lpOp.getNumOperands());
325 lpi->setCleanup(lpOp.getCleanup());
328 for (llvm::Value *operand :
331 if (
auto *constOperand = dyn_cast<llvm::Constant>(operand))
332 lpi->addClause(constOperand);
334 moduleTranslation.
mapValue(lpOp.getResult(), lpi);
340 if (
auto brOp = dyn_cast<LLVM::BrOp>(opInst)) {
341 llvm::BranchInst *branch =
342 builder.CreateBr(moduleTranslation.
lookupBlock(brOp.getSuccessor()));
343 moduleTranslation.
mapBranch(&opInst, branch);
347 if (
auto condbrOp = dyn_cast<LLVM::CondBrOp>(opInst)) {
348 llvm::BranchInst *branch = builder.CreateCondBr(
349 moduleTranslation.
lookupValue(condbrOp.getOperand(0)),
350 moduleTranslation.
lookupBlock(condbrOp.getSuccessor(0)),
351 moduleTranslation.
lookupBlock(condbrOp.getSuccessor(1)));
352 moduleTranslation.
mapBranch(&opInst, branch);
356 if (
auto switchOp = dyn_cast<LLVM::SwitchOp>(opInst)) {
357 llvm::SwitchInst *switchInst = builder.CreateSwitch(
358 moduleTranslation.
lookupValue(switchOp.getValue()),
359 moduleTranslation.
lookupBlock(switchOp.getDefaultDestination()),
360 switchOp.getCaseDestinations().size());
363 if (!switchOp.getCaseValues())
366 auto *ty = llvm::cast<llvm::IntegerType>(
367 moduleTranslation.
convertType(switchOp.getValue().getType()));
369 llvm::zip(llvm::cast<DenseIntElementsAttr>(*switchOp.getCaseValues()),
370 switchOp.getCaseDestinations()))
375 moduleTranslation.
mapBranch(&opInst, switchInst);
382 if (
auto addressOfOp = dyn_cast<LLVM::AddressOfOp>(opInst)) {
383 LLVM::GlobalOp global =
384 addressOfOp.getGlobal(moduleTranslation.
symbolTable());
385 LLVM::LLVMFuncOp
function =
386 addressOfOp.getFunction(moduleTranslation.
symbolTable());
389 assert((global ||
function) &&
390 "referencing an undefined global or function");
393 addressOfOp.getResult(),
405 class LLVMDialectLLVMIRTranslationInterface
413 convertOperation(
Operation *op, llvm::IRBuilderBase &builder,
421 registry.
insert<LLVM::LLVMDialect>();
423 dialect->addInterfaces<LLVMDialectLLVMIRTranslationInterface>();
static SmallVector< unsigned > extractPosition(ArrayRef< int64_t > indices)
Convert the value of a DenseI64ArrayAttr to a vector of unsigned indices.
static std::string diagStr(const llvm::Type *type)
Convert an LLVM type to a string for printing in diagnostics.
static FailureOr< llvm::Function * > getOverloadedDeclaration(CallIntrinsicOp op, llvm::Intrinsic::ID id, llvm::Module *module, LLVM::ModuleTranslation &moduleTranslation)
Get the declaration of an overloaded llvm intrinsic.
static LogicalResult convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Builder for LLVM_CallIntrinsicOp.
static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op)
static void convertLinkerOptionsOp(ArrayAttr options, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::ManagedStatic< PassManagerOptions > options
static void contract(RootOrderingGraph &graph, ArrayRef< Value > cycle, const DenseMap< Value, unsigned > &parentDepths, DenseMap< Value, Value > &actualSource, DenseMap< Value, Value > &actualTarget)
Contracts the specified cycle in the given graph in-place.
Attributes are known-constant values of operations.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
void addExtension(std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
This class provides support for representing a failure result, or a valid value of type T.
A symbol reference with a reference path containing a single element.
Base class for dialect interfaces providing translation to LLVM IR.
LLVMTranslationDialectInterface(Dialect *dialect)
Implementation class for module translation.
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
void mapCall(Operation *mlir, llvm::CallInst *llvm)
Stores a mapping between an MLIR call operation and a corresponding LLVM call instruction.
void mapBranch(Operation *mlir, llvm::Instruction *llvm)
Stores the mapping between an MLIR operation with successors and a corresponding LLVM IR instruction.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
void setTBAAMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
Sets LLVM TBAA metadata for memory operations that have TBAA attributes.
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.
void setAliasScopeMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
void setAccessGroupsMetadata(AccessGroupOpInterface op, llvm::Instruction *inst)
MLIRContext & getContext()
Returns the MLIR context of the module being translated.
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.
MLIRContext is the top-level object for a collection of MLIR operations.
void appendDialectRegistry(const DialectRegistry ®istry)
Append the contents of the given dialect registry to the registry associated with this context.
Operation is the basic unit of execution within MLIR.
AttrClass getAttrOfType(StringAttr name)
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
unsigned getNumOperands()
operand_type_range getOperandTypes()
result_type_range getResultTypes()
operand_range getOperands()
Returns an iterator on the underlying Value's.
result_range getResults()
unsigned getNumResults()
Return the number of results held by this operation.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Type front()
Return first type in the range.
Type getType() const
Return the type of this value.
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.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
void registerLLVMDialectTranslation(DialectRegistry ®istry)
Register the LLVM dialect and the translation from it to the LLVM IR in the given registry;.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.