llvm-project/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
Bruno Cardoso Lopes 5265412c13
[MLIR][LLVMIR] Import: add flag to prefer using unregistered intrinsics (#130685)
Currently, there is no common mechanism for supported intrinsics to be
generically annotated with arg and ret attributes. Since there are many
supported intrinsics around different dialects, the amount of work to
teach all them about these attributes is not trivial (though it would be
nice in the long term).

This PR adds a new flag `-prefer-unregistered-intrinsics` that can be
used alongside `--import-llvm` to always use `llvm.intrinsic_call`
during import time (ignoring dialect hooks for custom intrinsic
support).

Using this flag allow us to roundtrip the LLVM IR while eliminating a
whole set of differences coming from lack of arg/ret attributes on
supported intrinsics.

Note `convertIntrinsic` has to be moved to an implementation file
because it queries into `moduleImport` state, which is a fwd declaration
in `LLVMImportInterface.h`
2025-03-14 18:04:32 -07:00

85 lines
3.3 KiB
C++

//===- ConvertFromLLVMIR.cpp - MLIR to LLVM IR conversion -----------------===//
//
// 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 the function that registers the translation between
// LLVM IR and the MLIR LLVM dialect.
//
//===----------------------------------------------------------------------===//
#include "mlir/Dialect/DLTI/DLTI.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/Target/LLVMIR/Dialect/All.h"
#include "mlir/Target/LLVMIR/Import.h"
#include "mlir/Tools/mlir-translate/Translation.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/SourceMgr.h"
using namespace mlir;
namespace mlir {
void registerFromLLVMIRTranslation() {
static llvm::cl::opt<bool> emitExpensiveWarnings(
"emit-expensive-warnings",
llvm::cl::desc("Emit expensive warnings during LLVM IR import "
"(discouraged: testing only!)"),
llvm::cl::init(false));
static llvm::cl::opt<bool> dropDICompositeTypeElements(
"drop-di-composite-type-elements",
llvm::cl::desc(
"Avoid translating the elements of DICompositeTypes during "
"the LLVM IR import (discouraged: testing only!)"),
llvm::cl::init(false));
static llvm::cl::opt<bool> preferUnregisteredIntrinsics(
"prefer-unregistered-intrinsics",
llvm::cl::desc(
"Prefer translating all intrinsics into llvm.call_intrinsic instead "
"of using dialect supported intrinsics"),
llvm::cl::init(false));
TranslateToMLIRRegistration registration(
"import-llvm", "Translate LLVMIR to MLIR",
[](llvm::SourceMgr &sourceMgr,
MLIRContext *context) -> OwningOpRef<Operation *> {
llvm::SMDiagnostic err;
llvm::LLVMContext llvmContext;
std::unique_ptr<llvm::Module> llvmModule =
llvm::parseIR(*sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID()),
err, llvmContext);
if (!llvmModule) {
std::string errStr;
llvm::raw_string_ostream errStream(errStr);
err.print(/*ProgName=*/"", errStream);
emitError(UnknownLoc::get(context)) << errStr;
return {};
}
if (llvm::verifyModule(*llvmModule, &llvm::errs()))
return nullptr;
// Debug records are not currently supported in the LLVM IR translator.
if (llvmModule->IsNewDbgInfoFormat)
llvmModule->convertFromNewDbgValues();
return translateLLVMIRToModule(
std::move(llvmModule), context, emitExpensiveWarnings,
dropDICompositeTypeElements, /*loadAllDialects=*/true,
preferUnregisteredIntrinsics);
},
[](DialectRegistry &registry) {
// Register the DLTI dialect used to express the data layout
// specification of the imported module.
registry.insert<DLTIDialect>();
// Register all dialects that implement the LLVMImportDialectInterface
// including the LLVM dialect.
registerAllFromLLVMIRTranslations(registry);
});
}
} // namespace mlir