1//===------------------------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements methods from LLVMImportInterface.
10//
11//===----------------------------------------------------------------------===//
12
13#include "mlir/Target/LLVMIR/LLVMImportInterface.h"
14#include "mlir/Target/LLVMIR/ModuleImport.h"
15
16using namespace mlir;
17using namespace mlir::LLVM;
18using namespace mlir::LLVM::detail;
19
20LogicalResult mlir::LLVMImportInterface::convertUnregisteredIntrinsic(
21 OpBuilder &builder, llvm::CallInst *inst,
22 LLVM::ModuleImport &moduleImport) {
23 StringRef intrinName = inst->getCalledFunction()->getName();
24
25 SmallVector<llvm::Value *> args(inst->args());
26 ArrayRef<llvm::Value *> llvmOperands(args);
27
28 SmallVector<llvm::OperandBundleUse> llvmOpBundles;
29 llvmOpBundles.reserve(N: inst->getNumOperandBundles());
30 for (unsigned i = 0; i < inst->getNumOperandBundles(); ++i)
31 llvmOpBundles.push_back(Elt: inst->getOperandBundleAt(Index: i));
32
33 SmallVector<Value> mlirOperands;
34 SmallVector<NamedAttribute> mlirAttrs;
35 if (failed(Result: moduleImport.convertIntrinsicArguments(
36 values: llvmOperands, opBundles: llvmOpBundles, requiresOpBundles: false, immArgPositions: {}, immArgAttrNames: {}, valuesOut&: mlirOperands, attrsOut&: mlirAttrs)))
37 return failure();
38
39 Type resultType = moduleImport.convertType(type: inst->getType());
40 auto op = builder.create<::mlir::LLVM::CallIntrinsicOp>(
41 location: moduleImport.translateLoc(loc: inst->getDebugLoc()),
42 args: isa<LLVMVoidType>(Val: resultType) ? TypeRange{} : TypeRange{resultType},
43 args: StringAttr::get(context: builder.getContext(), bytes: intrinName),
44 args: ValueRange{mlirOperands}, args: FastmathFlagsAttr{});
45
46 moduleImport.setFastmathFlagsAttr(inst, op);
47
48 ArrayAttr argsAttr, resAttr;
49 moduleImport.convertParameterAttributes(call: inst, argsAttr, resAttr, builder);
50 op.setArgAttrsAttr(argsAttr);
51 op.setResAttrsAttr(resAttr);
52
53 // Update importer tracking of results.
54 unsigned numRes = op.getNumResults();
55 if (numRes == 1)
56 moduleImport.mapValue(value: inst) = op.getResult(i: 0);
57 else if (numRes == 0)
58 moduleImport.mapNoResultOp(inst);
59 else
60 return op.emitError(
61 message: "expected at most one result from target intrinsic call");
62
63 return success();
64}
65
66/// Converts the LLVM intrinsic to an MLIR operation if a conversion exists.
67/// Returns failure otherwise.
68LogicalResult mlir::LLVMImportInterface::convertIntrinsic(
69 OpBuilder &builder, llvm::CallInst *inst,
70 LLVM::ModuleImport &moduleImport) const {
71 // Lookup the dialect interface for the given intrinsic.
72 // Verify the intrinsic identifier maps to an actual intrinsic.
73 llvm::Intrinsic::ID intrinId = inst->getIntrinsicID();
74 assert(intrinId != llvm::Intrinsic::not_intrinsic);
75
76 // First lookup the intrinsic across different dialects for known
77 // supported conversions, examples include arm-neon, nvm-sve, etc.
78 Dialect *dialect = nullptr;
79
80 if (!moduleImport.useUnregisteredIntrinsicsOnly())
81 dialect = intrinsicToDialect.lookup(Val: intrinId);
82
83 // No specialized (supported) intrinsics, attempt to generate a generic
84 // version via llvm.call_intrinsic (if available).
85 if (!dialect)
86 return convertUnregisteredIntrinsic(builder, inst, moduleImport);
87
88 // Dispatch the conversion to the dialect interface.
89 const LLVMImportDialectInterface *iface = getInterfaceFor(obj: dialect);
90 assert(iface && "expected to find a dialect interface");
91 return iface->convertIntrinsic(builder, inst, moduleImport);
92}
93

source code of mlir/lib/Target/LLVMIR/LLVMImportInterface.cpp