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

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