issue #164 trying our ORC v2 apis, but optimzation is broken so disable for now

pull/168/head
Dibyendu Majumdar 5 years ago
parent ba66177cbe
commit e1298a4e95

@ -37,6 +37,12 @@
#define USE_ORC_JIT 0
#endif
#if LLVM_VERSION_MAJOR >= 8
#define USE_ORCv2_JIT 0
#else
#define USE_ORCv2_JIT 0
#endif
// In lua.c we include this just to get version numbers
// We cannot have C++ headers in that case
#ifdef __cplusplus
@ -71,7 +77,7 @@
#include "llvm/Support/FormattedStream.h"
#if USE_ORC_JIT
#if USE_ORC_JIT || USE_ORCv2_JIT
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
@ -81,6 +87,7 @@
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/IR/Mangler.h"
@ -88,8 +95,9 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Scalar/GVN.h"
#if LLVM_VERSION_MAJOR >= 7
#if LLVM_VERSION_MAJOR >= 8
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#endif
#endif

@ -389,10 +389,23 @@ class RaviJITStateFactory {
// All of the JIT information is held here
class RaviJITState {
friend class RaviJITModule;
#if USE_ORCv2_JIT
std::unique_ptr<llvm::orc::ExecutionSession> ES;
std::unique_ptr<llvm::orc::RTDyldObjectLinkingLayer> ObjectLayer;
std::unique_ptr<llvm::orc::IRCompileLayer> CompileLayer;
std::unique_ptr<llvm::orc::IRTransformLayer> OptimizeLayer;
std::unique_ptr<llvm::DataLayout> DL;
std::unique_ptr<llvm::orc::MangleAndInterner> Mangle;
std::unique_ptr<llvm::orc::ThreadSafeContext> Ctx;
#elif USE_ORC_JIT
// The LLVM Context
llvm::LLVMContext *context_;
#if USE_ORC_JIT
// From LLVM version5 onwards we use the new ORC apis
// The main benefit is that memory management is tighter,
// all the IR in modules get released after compilation
@ -432,7 +445,13 @@ class RaviJITState {
std::unique_ptr<CODLayerT> CompileOnDemandLayer;
#endif
#endif
#else
// Not ORC_JIT
// The LLVM Context
llvm::LLVMContext *context_;
#endif // USE_ORCv2_JIT
// The triple represents the host target
std::string triple_;
@ -483,22 +502,48 @@ class RaviJITState {
RaviJITState();
~RaviJITState();
#if USE_ORC_JIT
#if USE_ORCv2_JIT
llvm::LLVMContext &context() { return *Ctx->getContext(); }
static llvm::Expected<llvm::orc::ThreadSafeModule> optimizeModule(llvm::orc::ThreadSafeModule TSM, const llvm::orc::MaterializationResponsibility &R);
llvm::Error addModule(std::unique_ptr<llvm::Module> M);
llvm::Expected<llvm::JITEvaluatedSymbol> findSymbol(llvm::StringRef Name) {
return ES->lookup({&ES->getMainJITDylib()}, (*Mangle)(Name.str()));
}
const llvm::DataLayout &getDataLayout() const { return *DL; }
#elif USE_ORC_JIT
#if LLVM_VERSION_MAJOR >= 8
std::unique_ptr<llvm::Module> optimizeModule(std::unique_ptr<llvm::Module> M);
#else
std::shared_ptr<llvm::Module> optimizeModule(std::shared_ptr<llvm::Module> M);
#endif
llvm::TargetMachine &getTargetMachine() { return *TM; }
ModuleHandle addModule(std::unique_ptr<llvm::Module> M);
llvm::JITSymbol findSymbol(const std::string& Name);
void removeModule(ModuleHandle H);
llvm::LLVMContext &context() { return *context_; }
#else
// Not ORC JIT
llvm::LLVMContext &context() { return *context_; }
#endif
void addGlobalSymbol(const std::string &name, void *address);
void dump();
llvm::LLVMContext &context() { return *context_; }
LuaLLVMTypes *types() const { return types_; }
const std::string &triple() const { return triple_; }
bool is_auto() const { return auto_; }
@ -548,14 +593,13 @@ class RaviJITModule {
// The Context that owns this module
RaviJITState *owner_;
#if !USE_ORC_JIT
#if USE_ORCv2_JIT
// The LLVM Module within which the functions will be defined
llvm::Module *module_;
std::unique_ptr<llvm::Module> module_;
#elif USE_ORC_JIT
// The execution engine responsible for compiling the
// module
llvm::ExecutionEngine *engine_;
#else
// The LLVM Module within which the functions will be defined
std::unique_ptr<llvm::Module> module_;
@ -563,6 +607,16 @@ class RaviJITModule {
// then a handle is used to refer to it rather than the
// module, as the module may have been deleted by then
RaviJITState::ModuleHandle module_handle_;
#else
// The LLVM Module within which the functions will be defined
llvm::Module *module_;
// The execution engine responsible for compiling the
// module
llvm::ExecutionEngine *engine_;
#endif
// List of JIT functions in this module
@ -577,13 +631,14 @@ class RaviJITModule {
RaviJITModule(RaviJITState *owner);
~RaviJITModule();
#if !USE_ORC_JIT
#if !USE_ORC_JIT && !USE_ORCv2_JIT
llvm::Module *module() const { return module_; }
llvm::ExecutionEngine *engine() const { return engine_; }
#else
// Note that this can return nullptr
llvm::Module *module() const { return module_.get(); }
#endif
RaviJITState *owner() const { return owner_; }
void dump();
void dumpAssembly();
@ -653,7 +708,7 @@ class RaviJITFunction {
// Note that this can return nullptr
llvm::Module *module() const { return module_->module(); }
std::shared_ptr<RaviJITModule> raviModule() const { return module_; }
#if !USE_ORC_JIT
#if !USE_ORC_JIT && !USE_ORCv2_JIT
llvm::ExecutionEngine *engine() const { return module_->engine(); }
#endif
RaviJITState *owner() const { return module_->owner(); }

@ -141,6 +141,27 @@ RaviJITState::RaviJITState()
init++;
}
triple_ = llvm::sys::getProcessTriple();
#if USE_ORCv2_JIT
auto JTMB = llvm::orc::JITTargetMachineBuilder::detectHost();
auto dataLayout = JTMB->getDefaultDataLayoutForTarget();
ES = std::unique_ptr<llvm::orc::ExecutionSession>(new llvm::orc::ExecutionSession());
ObjectLayer = std::unique_ptr<llvm::orc::RTDyldObjectLinkingLayer>(new llvm::orc::RTDyldObjectLinkingLayer(*ES,
[]() { return llvm::make_unique<llvm::SectionMemoryManager>(); }));
CompileLayer = std::unique_ptr<llvm::orc::IRCompileLayer>(new llvm::orc::IRCompileLayer(*ES, *ObjectLayer, llvm::orc::ConcurrentIRCompiler(std::move(*JTMB))));
OptimizeLayer = std::unique_ptr<llvm::orc::IRTransformLayer>(new llvm::orc::IRTransformLayer(*ES, *CompileLayer, optimizeModule));
DL = std::unique_ptr<llvm::DataLayout>(new llvm::DataLayout(std::move(*dataLayout)));
Mangle = std::unique_ptr<llvm::orc::MangleAndInterner>(new llvm::orc::MangleAndInterner(*ES, *this->DL));
Ctx = std::unique_ptr<llvm::orc::ThreadSafeContext>(new llvm::orc::ThreadSafeContext(llvm::make_unique<llvm::LLVMContext>()));
ES->getMainJITDylib().setGenerator(
cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(*DL)));
types_ = new LuaLLVMTypes(*Ctx->getContext());
#else
#if defined(_WIN32) && (!defined(_WIN64) || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7)
// On Windows we get compilation error saying incompatible object format
// Reading posts on mailing lists I found that the issue is that COEFF
@ -166,7 +187,9 @@ RaviJITState::RaviJITState()
ObjectLayer =
std::unique_ptr<ObjectLayerT>(new ObjectLayerT([]() { return std::make_shared<llvm::SectionMemoryManager>(); }));
#endif
CompileLayer = std::unique_ptr<CompileLayerT>(new CompileLayerT(*ObjectLayer, llvm::orc::SimpleCompiler(*TM)));
#if LLVM_VERSION_MAJOR >= 8
OptimizeLayer = std::unique_ptr<OptimizerLayerT>(new OptimizerLayerT(
*CompileLayer, [this](std::unique_ptr<llvm::Module> M) { return optimizeModule(std::move(M)); }));
@ -181,10 +204,13 @@ RaviJITState::RaviJITState()
OptimizeLayer = std::unique_ptr<OptimizerLayerT>(new OptimizerLayerT(
*CompileLayer, [this](std::shared_ptr<llvm::Module> M) { return optimizeModule(std::move(M)); }));
#endif
#endif
types_ = new LuaLLVMTypes(*context_);
#endif // USE_ORCv2_JIT
for (int i = 0; global_syms[i].name != nullptr; i++) {
llvm::sys::DynamicLibrary::AddSymbol(global_syms[i].name, global_syms[i].address);
}
@ -195,23 +221,26 @@ RaviJITState::RaviJITState()
RaviJITState::~RaviJITState() {
assert(allocated_modules_ == 0);
delete types_;
#ifndef USE_ORCv2_JIT
delete context_;
#endif
}
#if USE_ORC_JIT
#if USE_ORC_JIT || USE_ORCv2_JIT
#if USE_ORCv2_JIT
llvm::Expected<llvm::orc::ThreadSafeModule> RaviJITState::optimizeModule(llvm::orc::ThreadSafeModule TSM, const llvm::orc::MaterializationResponsibility &R) {
#else
#if LLVM_VERSION_MAJOR >= 8
std::unique_ptr<llvm::Module> RaviJITState::optimizeModule(std::unique_ptr<llvm::Module> M) {
#else
std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(std::shared_ptr<llvm::Module> M) {
#endif
#if LLVM_VERSION_MAJOR > 3 || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
#endif
using llvm::legacy::FunctionPassManager;
using llvm::legacy::PassManager;
#else
using llvm::FunctionPassManager;
using llvm::PassManager;
#endif
#if !USE_ORCv2_JIT
if (get_verbosity() >= 1)
M->print(llvm::errs(), nullptr, false, true);
if (get_verbosity() >= 3)
@ -222,6 +251,7 @@ std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(std::shared_ptr<llvm:
TM->Options.EnableFastISel = 1;
else
TM->Options.EnableFastISel = 0;
#endif
// We use the PassManagerBuilder to setup optimization
// passes - the PassManagerBuilder allows easy configuration of
@ -230,58 +260,45 @@ std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(std::shared_ptr<llvm:
// dumped to stderr
llvm::PassManagerBuilder pmb;
#if USE_ORCv2_JIT
pmb.OptLevel = 2;
pmb.SizeLevel = 0;
#else
pmb.OptLevel = get_optlevel();
pmb.SizeLevel = get_sizelevel();
#endif
{
// Create a function pass manager for this engine
std::unique_ptr<FunctionPassManager> FPM(new FunctionPassManager(M.get()));
// Set up the optimizer pipeline. Start with registering info about how the
// target lays out data structures.
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 6
// LLVM 3.6.0 change
module_->setDataLayout(engine_->getDataLayout());
FPM->add(new llvm::DataLayoutPass());
#elif LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 5
// LLVM 3.5.0
auto target_layout = engine_->getTargetMachine()->getDataLayout();
module_->setDataLayout(target_layout);
FPM->add(new llvm::DataLayoutPass(*engine_->getDataLayout()));
#elif LLVM_VERSION_MAJOR > 3 || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
// Apparently no need to set DataLayout
#if USE_ORCv2_JIT
auto FPM = llvm::make_unique<FunctionPassManager>(TSM.getModule());
#else
#error Unsupported LLVM version
std::unique_ptr<FunctionPassManager> FPM(new FunctionPassManager(M.get()));
#endif
pmb.populateFunctionPassManager(*FPM);
FPM->doInitialization();
// Run the optimizations over all functions in the module being added to
// the JIT.
#if USE_ORCv2_JIT
for (auto &F : *TSM.getModule())
FPM->run(F);
#else
for (auto &F : *M)
FPM->run(F);
#endif
}
#if USE_ORCv2_JIT
std::unique_ptr<PassManager> MPM(new PassManager());
pmb.populateModulePassManager(*MPM);
MPM->run(*TSM.getModule());
return TSM;
#else
std::string codestr;
{
// In LLVM 3.7 for some reason the string is not saved
// until the stream is destroyed - even though there is a
// flush; so we introduce a scope here to ensure destruction
// of the stream
llvm::raw_string_ostream ostream(codestr);
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7
llvm::formatted_raw_ostream formatted_stream(ostream);
#else
llvm::buffer_ostream formatted_stream(ostream);
#endif
// Also in 3.7 the pass manager seems to hold on to the stream
// so we need to ensure that the stream outlives the pass manager
std::unique_ptr<PassManager> MPM(new PassManager());
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 6
MPM->add(new llvm::DataLayoutPass());
#elif LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 5
MPM->add(new llvm::DataLayoutPass(*engine_->getDataLayout()));
#endif
pmb.populateModulePassManager(*MPM);
for (int i = 0; get_verbosity() == 2 && i < 1; i++) {
@ -299,16 +316,12 @@ std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(std::shared_ptr<llvm:
}
}
MPM->run(*M);
// Note that in 3.7 this flus appears to have no effect
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 7
formatted_stream.flush();
#endif
}
if (get_verbosity() == 2 && codestr.length() > 0)
llvm::errs() << codestr << "\n";
return M;
#endif
}
#endif
@ -317,7 +330,12 @@ void RaviJITState::addGlobalSymbol(const std::string &name, void *address) {
llvm::sys::DynamicLibrary::AddSymbol(name, address);
}
#if USE_ORC_JIT
#if USE_ORCv2_JIT
llvm::Error RaviJITState::addModule(std::unique_ptr<llvm::Module> M) {
return OptimizeLayer->add(ES->getMainJITDylib(),
llvm::orc::ThreadSafeModule(std::move(M), *Ctx));
}
#elif USE_ORC_JIT
RaviJITState::ModuleHandle RaviJITState::addModule(std::unique_ptr<llvm::Module> M) {
#if LLVM_VERSION_MAJOR >= 8
// Create a new VModuleKey.
@ -399,7 +417,10 @@ RaviJITModule::RaviJITModule(RaviJITState *owner)
char buf[40];
snprintf(buf, sizeof buf, "ravi_module_%d", myid);
std::string moduleName(buf);
#if USE_ORC_JIT
#if USE_ORCv2_JIT
module_ = std::unique_ptr<llvm::Module>(new llvm::Module(moduleName, owner->context()));
module_->setDataLayout(owner_->getDataLayout());
#elif USE_ORC_JIT
module_ = std::unique_ptr<llvm::Module>(new llvm::Module(moduleName, owner->context()));
module_->setDataLayout(owner_->getTargetMachine().createDataLayout());
#else
@ -458,7 +479,7 @@ RaviJITModule::~RaviJITModule() {
// if engine was created then we don't need to delete the
// module as it would have been deleted by the engine
delete module_;
#else
#elif !USE_ORCv2_JIT
owner()->removeModule(module_handle_);
#endif
owner_->decr_allocated_modules();
@ -620,10 +641,12 @@ void RaviJITModule::finalize(bool doDump) {
// explicitly or a function such as MCJIT::getPointerToFunction
// is called which requires the code to have been generated.
engine_->finalizeObject();
#else
#elif !USE_ORCv2_JIT
// With ORC api, the module gets compiled when it is added
// The optimization passes are run via the callback
module_handle_ = owner()->addModule(std::move(module_));
#else
owner()->addModule(std::move(module_));
#endif
for (int i = 0; i < functions_.size(); i++) {
if (functions_[i] == nullptr)
@ -649,7 +672,11 @@ void RaviJITFunction::setFunctionPtr() {
if (function_) {
auto symbol = owner()->findSymbol(name());
if (symbol) {
#if USE_ORCv2_JIT
ptr_ = (void *)(intptr_t)(symbol->getAddress());
#else
ptr_ = (void *)(intptr_t)llvm::cantFail(symbol.getAddress());
#endif
*func_ptrptr_ = (lua_CFunction)ptr_;
}
}

Loading…
Cancel
Save