Call llc, ld from within onnx-mlir. (#127)
* Call llc, ld from within onnx-mlir. * Rename EmitLLVMBC -> EmitLib., reorder header files * Edit comment. Co-authored-by: Gheorghe-Teodor Bercea <gt.bercea@gmail.com>
This commit is contained in:
parent
30a9070c8d
commit
4cdc0873ca
|
@ -11,6 +11,18 @@ add_executable(onnx-mlir
|
||||||
MainUtils.cpp
|
MainUtils.cpp
|
||||||
main.cpp)
|
main.cpp)
|
||||||
|
|
||||||
|
# Locate llc, which is needed for translating LLVM bitcode
|
||||||
|
# to object file.
|
||||||
|
if(NOT EXISTS "${LLVM_PROJ_BUILD}/bin/llc")
|
||||||
|
message(ERROR "Cannot find llc.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Get the compiler command name, the C++ compiler is needed to to translate
|
||||||
|
# object files to shared libraries.
|
||||||
|
get_filename_component(CXX_COMPILER_FILENAME ${CMAKE_CXX_COMPILER} NAME)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ExternalUtil.hpp.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/ExternalUtil.hpp)
|
||||||
|
|
||||||
set(ONNX_MLIR_LD_PRELOAD_onnx-mlir "" CACHE STRING "" FORCE)
|
set(ONNX_MLIR_LD_PRELOAD_onnx-mlir "" CACHE STRING "" FORCE)
|
||||||
whole_archive_link_mlir(onnx-mlir ${MLIRWholeArchiveLibs})
|
whole_archive_link_mlir(onnx-mlir ${MLIRWholeArchiveLibs})
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace onnx_mlir {
|
||||||
|
const std::string kLlcPath = "@LLVM_PROJ_BUILD@/bin/llc";
|
||||||
|
const std::string kCxxPath = "@CMAKE_CXX_COMPILER@";
|
||||||
|
const std::string kCxxFileName = "@CXX_COMPILER_FILENAME@";
|
||||||
|
const std::string kRuntimeDirPath = "@CMAKE_BINARY_DIR@/lib";
|
||||||
|
}
|
|
@ -8,9 +8,13 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "src/MainUtils.hpp"
|
#include <cstdio>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
#include "llvm/Support/Program.h"
|
||||||
|
|
||||||
|
#include "src/ExternalUtil.hpp"
|
||||||
|
#include "src/MainUtils.hpp"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
@ -43,14 +47,33 @@ void LoadMLIR(string inputFilename, mlir::MLIRContext &context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitLLVMBitCode(
|
void compileModuleToSharedLibrary(
|
||||||
const mlir::OwningModuleRef &module, string outputFilename) {
|
const mlir::OwningModuleRef &module, string outputBaseName) {
|
||||||
|
// Write LLVM bitcode.
|
||||||
|
string outputFilename = outputBaseName + ".bc";
|
||||||
error_code error;
|
error_code error;
|
||||||
llvm::raw_fd_ostream moduleBitcodeStream(
|
llvm::raw_fd_ostream moduleBitcodeStream(
|
||||||
outputFilename, error, llvm::sys::fs::F_None);
|
outputFilename, error, llvm::sys::fs::F_None);
|
||||||
llvm::WriteBitcodeToFile(
|
llvm::WriteBitcodeToFile(
|
||||||
*mlir::translateModuleToLLVMIR(*module), moduleBitcodeStream);
|
*mlir::translateModuleToLLVMIR(*module), moduleBitcodeStream);
|
||||||
moduleBitcodeStream.flush();
|
moduleBitcodeStream.flush();
|
||||||
|
|
||||||
|
// Compile bitcode to object file.
|
||||||
|
std::vector<std::string> llcArgs = {
|
||||||
|
"llc", "-filetype=obj", "-relocation-model=pic", outputFilename};
|
||||||
|
auto llcArgStrRefs =
|
||||||
|
std::vector<llvm::StringRef>(llcArgs.begin(), llcArgs.end());
|
||||||
|
llvm::sys::ExecuteAndWait(kLlcPath, llvm::makeArrayRef(llcArgStrRefs));
|
||||||
|
|
||||||
|
// Link with runtime.
|
||||||
|
// TODO(tjingrant): link with runtime library in LLVM, and make the shared
|
||||||
|
// library more self-contained.
|
||||||
|
std::vector<std::string> cxxArgs = {kCxxFileName, "-shared", "-fPIC",
|
||||||
|
outputBaseName + ".o", "-o", outputBaseName + ".so",
|
||||||
|
"-L" + kRuntimeDirPath, "-lcruntime", "-Wl,-rpath," + kRuntimeDirPath};
|
||||||
|
auto argsArrayRefVector =
|
||||||
|
std::vector<llvm::StringRef>(cxxArgs.begin(), cxxArgs.end());
|
||||||
|
llvm::sys::ExecuteAndWait(kCxxPath, llvm::makeArrayRef(argsArrayRefVector));
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerDialects() {
|
void registerDialects() {
|
||||||
|
@ -149,11 +172,10 @@ void emitOutputFiles(string outputBaseName, EmissionTargetType emissionTarget,
|
||||||
// outside the function code at the beginning of the file in which case the
|
// outside the function code at the beginning of the file in which case the
|
||||||
// elision of these constants is not strictly required. Elision is also not
|
// elision of these constants is not strictly required. Elision is also not
|
||||||
// necessary when emitting the .bc file.
|
// necessary when emitting the .bc file.
|
||||||
if (emissionTarget == EmitLLVMBC) {
|
if (emissionTarget == EmitLib) {
|
||||||
// Write LLVM bitcode to disk.
|
// Write LLVM bitcode to disk, compile & link.
|
||||||
string outputFilename = outputBaseName + ".bc";
|
compileModuleToSharedLibrary(module, outputBaseName);
|
||||||
EmitLLVMBitCode(module, outputFilename);
|
printf("Shared library %s.so has been compiled.", outputBaseName.c_str());
|
||||||
printf("LLVM bitcode written to %s\n", outputFilename.c_str());
|
|
||||||
} else {
|
} else {
|
||||||
// Emit the version with all constants included.
|
// Emit the version with all constants included.
|
||||||
outputCode(module, outputBaseName, ".onnx.mlir");
|
outputCode(module, outputBaseName, ".onnx.mlir");
|
||||||
|
|
|
@ -42,14 +42,14 @@ enum EmissionTargetType {
|
||||||
EmitONNXIR,
|
EmitONNXIR,
|
||||||
EmitMLIR,
|
EmitMLIR,
|
||||||
EmitLLVMIR,
|
EmitLLVMIR,
|
||||||
EmitLLVMBC,
|
EmitLib,
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoadMLIR(std::string inputFilename, mlir::MLIRContext &context,
|
void LoadMLIR(std::string inputFilename, mlir::MLIRContext &context,
|
||||||
mlir::OwningModuleRef &module);
|
mlir::OwningModuleRef &module);
|
||||||
|
|
||||||
void EmitLLVMBitCode(
|
void compileModuleToSharedLibrary(
|
||||||
const mlir::OwningModuleRef &module, std::string outputFilename);
|
const mlir::OwningModuleRef &module, std::string outputBaseName);
|
||||||
|
|
||||||
void registerDialects();
|
void registerDialects();
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,10 @@ int main(int argc, char *argv[]) {
|
||||||
clEnumVal(
|
clEnumVal(
|
||||||
EmitMLIR, "Lower model to MLIR built-in transformation dialect."),
|
EmitMLIR, "Lower model to MLIR built-in transformation dialect."),
|
||||||
clEnumVal(EmitLLVMIR, "Lower model to LLVM IR (LLVM dialect)."),
|
clEnumVal(EmitLLVMIR, "Lower model to LLVM IR (LLVM dialect)."),
|
||||||
clEnumVal(EmitLLVMBC, "Lower model to LLVM IR and emit (to file) "
|
clEnumVal(EmitLib, "Lower model to LLVM IR, emit (to file) "
|
||||||
"LLVM bitcode for model.")),
|
"LLVM bitcode for model, compile and link it to a "
|
||||||
llvm::cl::init(EmitLLVMBC), llvm::cl::cat(OnnxMlirOptions));
|
"shared library.")),
|
||||||
|
llvm::cl::init(EmitLib), llvm::cl::cat(OnnxMlirOptions));
|
||||||
|
|
||||||
llvm::cl::HideUnrelatedOptions(OnnxMlirOptions);
|
llvm::cl::HideUnrelatedOptions(OnnxMlirOptions);
|
||||||
llvm::cl::ParseCommandLineOptions(
|
llvm::cl::ParseCommandLineOptions(
|
||||||
|
|
|
@ -40,14 +40,6 @@ class DummyBackend(onnx.backend.base.Backend):
|
||||||
onnx.save(model, "temp_model.onnx")
|
onnx.save(model, "temp_model.onnx")
|
||||||
# Call frontend to process temp_model.onnx, bit code will be generated.
|
# Call frontend to process temp_model.onnx, bit code will be generated.
|
||||||
execute_commands([ONNX_MLIR, "temp_model.onnx"])
|
execute_commands([ONNX_MLIR, "temp_model.onnx"])
|
||||||
# Call llc to generate object file from bitcode.
|
|
||||||
execute_commands(
|
|
||||||
[LLC, "-filetype=obj", "-relocation-model=pic", "temp_model.bc"])
|
|
||||||
# Generate shared library from object file, linking with c runtime.
|
|
||||||
execute_commands([
|
|
||||||
CXX, "-shared", "-fPIC", "temp_model.o", "-o", "temp_model.so",
|
|
||||||
"-L" + RUNTIME_DIR, "-lcruntime", "-Wl,-rpath=" + RUNTIME_DIR,
|
|
||||||
])
|
|
||||||
return ExecutionSession("./temp_model.so", "_dyn_entry_point_main_graph")
|
return ExecutionSession("./temp_model.so", "_dyn_entry_point_main_graph")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -62,7 +54,6 @@ backend_test = onnx.backend.test.BackendTest(DummyBackend, __name__)
|
||||||
|
|
||||||
# Test directories:
|
# Test directories:
|
||||||
# https://github.com/onnx/onnx/tree/master/onnx/backend/test/data/node
|
# https://github.com/onnx/onnx/tree/master/onnx/backend/test/data/node
|
||||||
|
|
||||||
test_to_enable = [
|
test_to_enable = [
|
||||||
# Abs Op:
|
# Abs Op:
|
||||||
"test_abs_cpu",
|
"test_abs_cpu",
|
||||||
|
|
Loading…
Reference in New Issue