blob: cb1f234aca50ba73c09227120963722fad3328f6 [file] [log] [blame]
//===------------------------------------------------------------*- 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);
}