llvm-project/mlir/lib/CAPI/ExecutionEngine/ExecutionEngine.cpp
Uday Bondhugula 185ce8cdfc [MLIR][PYTHON] Provide opt level for ExecutionEngine Python binding
Provide an option to specify optimization level when creating an
ExecutionEngine via the MLIR JIT Python binding. Not only is the
specified optimization level used for code generation, but all LLVM
optimization passes at the optimization level are also run prior to
machine code generation (akin to the mlir-cpu-runner tool).

Default opt level continues to remain at level two (-O2).

Contributions in part from Prashant Kumar <prashantk@polymagelabs.com>
as well.

Differential Revision: https://reviews.llvm.org/D102551
2021-05-16 13:58:49 +05:30

94 lines
3.4 KiB
C++

//===- ExecutionEngine.cpp - C API for MLIR JIT ---------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "mlir-c/ExecutionEngine.h"
#include "mlir/CAPI/ExecutionEngine.h"
#include "mlir/CAPI/IR.h"
#include "mlir/CAPI/Support.h"
#include "mlir/ExecutionEngine/OptUtils.h"
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
#include "llvm/ExecutionEngine/Orc/Mangling.h"
#include "llvm/Support/TargetSelect.h"
using namespace mlir;
extern "C" MlirExecutionEngine mlirExecutionEngineCreate(MlirModule op,
int optLevel) {
static bool initOnce = [] {
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
return true;
}();
(void)initOnce;
mlir::registerLLVMDialectTranslation(*unwrap(op)->getContext());
auto tmBuilderOrError = llvm::orc::JITTargetMachineBuilder::detectHost();
if (!tmBuilderOrError) {
llvm::errs() << "Failed to create a JITTargetMachineBuilder for the host\n";
return MlirExecutionEngine{nullptr};
}
auto tmOrError = tmBuilderOrError->createTargetMachine();
if (!tmOrError) {
llvm::errs() << "Failed to create a TargetMachine for the host\n";
return MlirExecutionEngine{nullptr};
}
// Create a transformer to run all LLVM optimization passes at the
// specified optimization level.
auto llvmOptLevel = static_cast<llvm::CodeGenOpt::Level>(optLevel);
auto transformer = mlir::makeLLVMPassesTransformer(
/*passes=*/{}, llvmOptLevel, /*targetMachine=*/tmOrError->get());
auto jitOrError = ExecutionEngine::create(
unwrap(op), /*llvmModuleBuilder=*/{}, transformer, llvmOptLevel);
if (!jitOrError) {
consumeError(jitOrError.takeError());
return MlirExecutionEngine{nullptr};
}
return wrap(jitOrError->release());
}
extern "C" void mlirExecutionEngineDestroy(MlirExecutionEngine jit) {
delete (unwrap(jit));
}
extern "C" MlirLogicalResult
mlirExecutionEngineInvokePacked(MlirExecutionEngine jit, MlirStringRef name,
void **arguments) {
const std::string ifaceName = ("_mlir_ciface_" + unwrap(name)).str();
llvm::Error error = unwrap(jit)->invokePacked(
ifaceName, MutableArrayRef<void *>{arguments, (size_t)0});
if (error)
return wrap(failure());
return wrap(success());
}
extern "C" void *mlirExecutionEngineLookup(MlirExecutionEngine jit,
MlirStringRef name) {
auto expectedFPtr = unwrap(jit)->lookup(unwrap(name));
if (!expectedFPtr)
return nullptr;
return reinterpret_cast<void *>(*expectedFPtr);
}
extern "C" void mlirExecutionEngineRegisterSymbol(MlirExecutionEngine jit,
MlirStringRef name,
void *sym) {
unwrap(jit)->registerSymbols([&](llvm::orc::MangleAndInterner interner) {
llvm::orc::SymbolMap symbolMap;
symbolMap[interner(unwrap(name))] =
llvm::JITEvaluatedSymbol::fromPointer(sym);
return symbolMap;
});
}
extern "C" void mlirExecutionEngineDumpToObjectFile(MlirExecutionEngine jit,
MlirStringRef name) {
unwrap(jit)->dumpToObjectFile(unwrap(name));
}