| //===------------------------------------------------------------*- 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); | |
| } |