| //===------------------------------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements methods from LLVMImportInterface. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "mlir/Target/LLVMIR/LLVMImportInterface.h" |
| #include "mlir/Target/LLVMIR/ModuleImport.h" |
| |
| using namespace mlir; |
| using namespace mlir::LLVM; |
| using namespace mlir::LLVM::detail; |
| |
| LogicalResult mlir::LLVMImportInterface::convertUnregisteredIntrinsic( |
| OpBuilder &builder, llvm::CallInst *inst, |
| LLVM::ModuleImport &moduleImport) { |
| StringRef intrinName = inst->getCalledFunction()->getName(); |
| |
| SmallVector<llvm::Value *> args(inst->args()); |
| ArrayRef<llvm::Value *> llvmOperands(args); |
| |
| SmallVector<llvm::OperandBundleUse> llvmOpBundles; |
| llvmOpBundles.reserve(inst->getNumOperandBundles()); |
| for (unsigned i = 0; i < inst->getNumOperandBundles(); ++i) |
| llvmOpBundles.push_back(inst->getOperandBundleAt(i)); |
| |
| SmallVector<Value> mlirOperands; |
| SmallVector<NamedAttribute> mlirAttrs; |
| if (failed(moduleImport.convertIntrinsicArguments( |
| llvmOperands, llvmOpBundles, /*requiresOpBundles=*/false, |
| /*immArgPositions=*/{}, /*immArgAttrNames=*/{}, mlirOperands, |
| mlirAttrs))) |
| return failure(); |
| |
| Type resultType = moduleImport.convertType(inst->getType()); |
| auto op = CallIntrinsicOp::create( |
| builder, moduleImport.translateLoc(inst->getDebugLoc()), |
| isa<LLVMVoidType>(resultType) ? TypeRange{} : TypeRange{resultType}, |
| StringAttr::get(builder.getContext(), intrinName), |
| ValueRange{mlirOperands}, FastmathFlagsAttr{}); |
| |
| moduleImport.setFastmathFlagsAttr(inst, op); |
| moduleImport.convertArgAndResultAttrs(inst, op); |
| |
| // Update importer tracking of results. |
| unsigned numRes = op.getNumResults(); |
| if (numRes == 1) |
| moduleImport.mapValue(inst) = op.getResult(0); |
| else if (numRes == 0) |
| moduleImport.mapNoResultOp(inst); |
| else |
| return op.emitError( |
| "expected at most one result from target intrinsic call"); |
| |
| return success(); |
| } |
| |
| /// Converts the LLVM intrinsic to an MLIR operation if a conversion exists. |
| /// Returns failure otherwise. |
| LogicalResult mlir::LLVMImportInterface::convertIntrinsic( |
| OpBuilder &builder, llvm::CallInst *inst, |
| LLVM::ModuleImport &moduleImport) const { |
| // Lookup the dialect interface for the given intrinsic. |
| // Verify the intrinsic identifier maps to an actual intrinsic. |
| llvm::Intrinsic::ID intrinId = inst->getIntrinsicID(); |
| assert(intrinId != llvm::Intrinsic::not_intrinsic); |
| |
| // First lookup the intrinsic across different dialects for known |
| // supported conversions, examples include arm-neon, nvm-sve, etc. |
| Dialect *dialect = nullptr; |
| |
| if (!moduleImport.useUnregisteredIntrinsicsOnly()) |
| dialect = intrinsicToDialect.lookup(intrinId); |
| |
| // No specialized (supported) intrinsics, attempt to generate a generic |
| // version via llvm.call_intrinsic (if available). |
| if (!dialect) |
| return convertUnregisteredIntrinsic(builder, inst, moduleImport); |
| |
| // Dispatch the conversion to the dialect interface. |
| const LLVMImportDialectInterface *iface = getInterfaceFor(dialect); |
| assert(iface && "expected to find a dialect interface"); |
| return iface->convertIntrinsic(builder, inst, moduleImport); |
| } |