mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-04 17:56:53 +00:00
Reapply r343058 with a fix for -DLLVM_ENABLE_THREADS=OFF.
Modifies lit to add a 'thread_support' feature that can be used in lit test REQUIRES clauses. The thread_support flag is set if -DLLVM_ENABLE_THREADS=ON and unset if -DLLVM_ENABLE_THREADS=OFF. The lit flag is used to disable the multiple-compile-threads-basic.ll testcase when threading is disabled. llvm-svn: 343122
This commit is contained in:
parent
0678fedbb1
commit
17fb5edbbb
@ -22,7 +22,7 @@
|
||||
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Support/ThreadPool.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
@ -30,11 +30,19 @@ namespace orc {
|
||||
/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
|
||||
class LLJIT {
|
||||
public:
|
||||
/// Create an LLJIT instance.
|
||||
static Expected<std::unique_ptr<LLJIT>>
|
||||
Create(std::unique_ptr<TargetMachine> TM, DataLayout DL);
|
||||
|
||||
/// Returns a reference to the ExecutionSession for this JIT instance.
|
||||
/// Destruct this instance. If a multi-threaded instance, waits for all
|
||||
/// compile threads to complete.
|
||||
~LLJIT();
|
||||
|
||||
/// Create an LLJIT instance.
|
||||
/// If NumCompileThreads is not equal to zero, creates a multi-threaded
|
||||
/// LLJIT with the given number of compile threads.
|
||||
static Expected<std::unique_ptr<LLJIT>>
|
||||
Create(JITTargetMachineBuilder JTMB, DataLayout DL,
|
||||
unsigned NumCompileThreads = 0);
|
||||
|
||||
/// Returns the ExecutionSession for this instance.
|
||||
ExecutionSession &getExecutionSession() { return *ES; }
|
||||
|
||||
/// Returns a reference to the JITDylib representing the JIT'd main program.
|
||||
@ -91,9 +99,15 @@ public:
|
||||
RTDyldObjectLinkingLayer2 &getObjLinkingLayer() { return ObjLinkingLayer; }
|
||||
|
||||
protected:
|
||||
|
||||
/// Create an LLJIT instance with a single compile thread.
|
||||
LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM,
|
||||
DataLayout DL);
|
||||
|
||||
/// Create an LLJIT instance with multiple compile threads.
|
||||
LLJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
|
||||
DataLayout DL, unsigned NumCompileThreads);
|
||||
|
||||
std::unique_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K);
|
||||
|
||||
std::string mangle(StringRef UnmangledName);
|
||||
@ -105,8 +119,8 @@ protected:
|
||||
std::unique_ptr<ExecutionSession> ES;
|
||||
JITDylib &Main;
|
||||
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
DataLayout DL;
|
||||
std::unique_ptr<ThreadPool> CompileThreads;
|
||||
|
||||
RTDyldObjectLinkingLayer2 ObjLinkingLayer;
|
||||
IRCompileLayer2 CompileLayer;
|
||||
@ -118,9 +132,13 @@ protected:
|
||||
/// compilation of LLVM IR.
|
||||
class LLLazyJIT : public LLJIT {
|
||||
public:
|
||||
|
||||
/// Create an LLLazyJIT instance.
|
||||
/// If NumCompileThreads is not equal to zero, creates a multi-threaded
|
||||
/// LLLazyJIT with the given number of compile threads.
|
||||
static Expected<std::unique_ptr<LLLazyJIT>>
|
||||
Create(std::unique_ptr<TargetMachine> TM, DataLayout DL);
|
||||
Create(JITTargetMachineBuilder JTMB, DataLayout DL,
|
||||
unsigned NumCompileThreads = 0);
|
||||
|
||||
/// Set an IR transform (e.g. pass manager pipeline) to run on each function
|
||||
/// when it is compiled.
|
||||
@ -137,11 +155,19 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Create a single-threaded LLLazyJIT instance.
|
||||
LLLazyJIT(std::unique_ptr<ExecutionSession> ES,
|
||||
std::unique_ptr<TargetMachine> TM, DataLayout DL,
|
||||
std::unique_ptr<LazyCallThroughManager> LCTMgr,
|
||||
std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
|
||||
|
||||
// Create a multi-threaded LLLazyJIT instance.
|
||||
LLLazyJIT(std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
|
||||
DataLayout DL, unsigned NumCompileThreads,
|
||||
std::unique_ptr<LazyCallThroughManager> LCTMgr,
|
||||
std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder);
|
||||
|
||||
std::unique_ptr<LazyCallThroughManager> LCTMgr;
|
||||
std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder;
|
||||
|
||||
|
@ -12,13 +12,45 @@
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// A SimpleCompiler that owns its TargetMachine.
|
||||
class TMOwningSimpleCompiler : public llvm::orc::SimpleCompiler {
|
||||
public:
|
||||
TMOwningSimpleCompiler(std::unique_ptr<llvm::TargetMachine> TM)
|
||||
: llvm::orc::SimpleCompiler(*TM), TM(std::move(TM)) {}
|
||||
private:
|
||||
// FIXME: shared because std::functions (and thus
|
||||
// IRCompileLayer2::CompileFunction) are not moveable.
|
||||
std::shared_ptr<llvm::TargetMachine> TM;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
LLJIT::~LLJIT() {
|
||||
if (CompileThreads)
|
||||
CompileThreads->wait();
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<LLJIT>>
|
||||
LLJIT::Create(std::unique_ptr<TargetMachine> TM, DataLayout DL) {
|
||||
LLJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
|
||||
unsigned NumCompileThreads) {
|
||||
|
||||
if (NumCompileThreads == 0) {
|
||||
// If NumCompileThreads == 0 then create a single-threaded LLJIT instance.
|
||||
auto TM = JTMB.createTargetMachine();
|
||||
if (!TM)
|
||||
return TM.takeError();
|
||||
return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
|
||||
std::move(*TM), std::move(DL)));
|
||||
}
|
||||
|
||||
return std::unique_ptr<LLJIT>(new LLJIT(llvm::make_unique<ExecutionSession>(),
|
||||
std::move(TM), std::move(DL)));
|
||||
std::move(JTMB), std::move(DL),
|
||||
NumCompileThreads));
|
||||
}
|
||||
|
||||
Error LLJIT::defineAbsolute(StringRef Name, JITEvaluatedSymbol Sym) {
|
||||
@ -52,12 +84,35 @@ Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
|
||||
LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES,
|
||||
std::unique_ptr<TargetMachine> TM, DataLayout DL)
|
||||
: ES(std::move(ES)), Main(this->ES->createJITDylib("main")),
|
||||
TM(std::move(TM)), DL(std::move(DL)),
|
||||
DL(std::move(DL)),
|
||||
ObjLinkingLayer(*this->ES,
|
||||
[this](VModuleKey K) { return getMemoryManager(K); }),
|
||||
CompileLayer(*this->ES, ObjLinkingLayer, SimpleCompiler(*this->TM)),
|
||||
CompileLayer(*this->ES, ObjLinkingLayer, TMOwningSimpleCompiler(std::move(TM))),
|
||||
CtorRunner(Main), DtorRunner(Main) {}
|
||||
|
||||
LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES,
|
||||
JITTargetMachineBuilder JTMB, DataLayout DL,
|
||||
unsigned NumCompileThreads)
|
||||
: ES(std::move(ES)), Main(this->ES->createJITDylib("main")),
|
||||
DL(std::move(DL)),
|
||||
ObjLinkingLayer(*this->ES,
|
||||
[this](VModuleKey K) { return getMemoryManager(K); }),
|
||||
CompileLayer(*this->ES, ObjLinkingLayer, MultiThreadedSimpleCompiler(std::move(JTMB))),
|
||||
CtorRunner(Main), DtorRunner(Main) {
|
||||
assert(NumCompileThreads != 0 &&
|
||||
"Multithreaded LLJIT instance can not be created with 0 threads");
|
||||
|
||||
CompileThreads = llvm::make_unique<ThreadPool>(NumCompileThreads);
|
||||
this->ES->setDispatchMaterialization([this](JITDylib &JD, std::unique_ptr<MaterializationUnit> MU) {
|
||||
// FIXME: Switch to move capture once we have c++14.
|
||||
auto SharedMU = std::shared_ptr<MaterializationUnit>(std::move(MU));
|
||||
auto Work = [SharedMU, &JD]() {
|
||||
SharedMU->doMaterialize(JD);
|
||||
};
|
||||
CompileThreads->async(std::move(Work));
|
||||
});
|
||||
}
|
||||
|
||||
std::unique_ptr<RuntimeDyld::MemoryManager>
|
||||
LLJIT::getMemoryManager(VModuleKey K) {
|
||||
return llvm::make_unique<SectionMemoryManager>();
|
||||
@ -90,10 +145,11 @@ void LLJIT::recordCtorDtors(Module &M) {
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<LLLazyJIT>>
|
||||
LLLazyJIT::Create(std::unique_ptr<TargetMachine> TM, DataLayout DL) {
|
||||
LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
|
||||
unsigned NumCompileThreads) {
|
||||
auto ES = llvm::make_unique<ExecutionSession>();
|
||||
|
||||
const Triple &TT = TM->getTargetTriple();
|
||||
const Triple &TT = JTMB.getTargetTriple();
|
||||
|
||||
auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, 0);
|
||||
if (!LCTMgr)
|
||||
@ -105,9 +161,18 @@ LLLazyJIT::Create(std::unique_ptr<TargetMachine> TM, DataLayout DL) {
|
||||
std::string("No indirect stubs manager builder for ") + TT.str(),
|
||||
inconvertibleErrorCode());
|
||||
|
||||
return std::unique_ptr<LLLazyJIT>(
|
||||
new LLLazyJIT(std::move(ES), std::move(TM), std::move(DL),
|
||||
std::move(*LCTMgr), std::move(ISMBuilder)));
|
||||
if (NumCompileThreads == 0) {
|
||||
auto TM = JTMB.createTargetMachine();
|
||||
if (!TM)
|
||||
return TM.takeError();
|
||||
return std::unique_ptr<LLLazyJIT>(
|
||||
new LLLazyJIT(std::move(ES), std::move(*TM), std::move(DL),
|
||||
std::move(*LCTMgr), std::move(ISMBuilder)));
|
||||
}
|
||||
|
||||
return std::unique_ptr<LLLazyJIT>(new LLLazyJIT(
|
||||
std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads,
|
||||
std::move(*LCTMgr), std::move(ISMBuilder)));
|
||||
}
|
||||
|
||||
Error LLLazyJIT::addLazyIRModule(JITDylib &JD, ThreadSafeModule TSM) {
|
||||
@ -133,5 +198,15 @@ LLLazyJIT::LLLazyJIT(
|
||||
CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
|
||||
std::move(ISMBuilder)) {}
|
||||
|
||||
LLLazyJIT::LLLazyJIT(
|
||||
std::unique_ptr<ExecutionSession> ES, JITTargetMachineBuilder JTMB,
|
||||
DataLayout DL, unsigned NumCompileThreads,
|
||||
std::unique_ptr<LazyCallThroughManager> LCTMgr,
|
||||
std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder)
|
||||
: LLJIT(std::move(ES), std::move(JTMB), std::move(DL), NumCompileThreads),
|
||||
LCTMgr(std::move(LCTMgr)), TransformLayer(*this->ES, CompileLayer),
|
||||
CODLayer(*this->ES, TransformLayer, *this->LCTMgr,
|
||||
std::move(ISMBuilder)) {}
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
@ -8,6 +8,7 @@ llvm_canonicalize_cmake_booleans(
|
||||
HAVE_LIBXAR
|
||||
LLVM_ENABLE_DIA_SDK
|
||||
LLVM_ENABLE_FFI
|
||||
LLVM_ENABLE_THREADS
|
||||
BUILD_SHARED_LIBS
|
||||
LLVM_LINK_LLVM_DYLIB
|
||||
)
|
||||
|
@ -0,0 +1,19 @@
|
||||
; RUN: lli -jit-kind=orc-lazy -compile-threads=2 -thread-entry hello %s | FileCheck %s
|
||||
; REQUIRES: thread_support
|
||||
;
|
||||
; CHECK: Hello
|
||||
|
||||
@.str = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1
|
||||
|
||||
define void @hello() {
|
||||
entry:
|
||||
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str, i32 0, i32 0))
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i32 @printf(i8*, ...)
|
||||
|
||||
define i32 @main(i32 %argc, i8** %argv) {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
@ -319,6 +319,9 @@ if not re.match(r'^x86_64.*-(windows-gnu|windows-msvc)', config.target_triple):
|
||||
if config.have_libxar:
|
||||
config.available_features.add('xar')
|
||||
|
||||
if config.enable_threads:
|
||||
config.available_features.add('thread_support')
|
||||
|
||||
if config.llvm_libxml2_enabled == '1':
|
||||
config.available_features.add('libxml2')
|
||||
|
||||
|
@ -37,6 +37,7 @@ config.have_zlib = @HAVE_LIBZ@
|
||||
config.have_libxar = @HAVE_LIBXAR@
|
||||
config.have_dia_sdk = @LLVM_ENABLE_DIA_SDK@
|
||||
config.enable_ffi = @LLVM_ENABLE_FFI@
|
||||
config.enable_threads = @LLVM_ENABLE_THREADS@
|
||||
config.build_shared_libs = @BUILD_SHARED_LIBS@
|
||||
config.link_llvm_dylib = @LLVM_LINK_LLVM_DYLIB@
|
||||
config.llvm_libxml2_enabled = "@LLVM_LIBXML2_ENABLED@"
|
||||
|
@ -97,6 +97,17 @@ namespace {
|
||||
"orc-lazy",
|
||||
"Orc-based lazy JIT.")));
|
||||
|
||||
cl::opt<unsigned>
|
||||
LazyJITCompileThreads("compile-threads",
|
||||
cl::desc("Choose the number of compile threads "
|
||||
"(jit-kind=orc-lazy only)"),
|
||||
cl::init(0));
|
||||
|
||||
cl::list<std::string>
|
||||
ThreadEntryPoints("thread-entry",
|
||||
cl::desc("calls the given entry-point on a new thread "
|
||||
"(jit-kind=orc-lazy only)"));
|
||||
|
||||
// The MCJIT supports building for a target address space separate from
|
||||
// the JIT compilation process. Use a forked process and a copying
|
||||
// memory manager with IPC to execute using this functionality.
|
||||
@ -363,6 +374,19 @@ int main(int argc, char **argv, char * const *envp) {
|
||||
|
||||
if (UseJITKind == JITKind::OrcLazy)
|
||||
return runOrcLazyJIT(argv[0]);
|
||||
else {
|
||||
// Make sure nobody used an orc-lazy specific option accidentally.
|
||||
|
||||
if (LazyJITCompileThreads != 0) {
|
||||
errs() << "-compile-threads requires -jit-kind=orc-lazy\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!ThreadEntryPoints.empty()) {
|
||||
errs() << "-thread-entry requires -jit-kind=orc-lazy\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
LLVMContext Context;
|
||||
|
||||
@ -745,11 +769,11 @@ int runOrcLazyJIT(const char *ProgName) {
|
||||
reportError(Err, ProgName);
|
||||
|
||||
const auto &TT = MainModule.getModule()->getTargetTriple();
|
||||
orc::JITTargetMachineBuilder TMD =
|
||||
orc::JITTargetMachineBuilder JTMB =
|
||||
TT.empty() ? ExitOnErr(orc::JITTargetMachineBuilder::detectHost())
|
||||
: orc::JITTargetMachineBuilder(Triple(TT));
|
||||
|
||||
TMD.setArch(MArch)
|
||||
JTMB.setArch(MArch)
|
||||
.setCPU(getCPUStr())
|
||||
.addFeatures(getFeatureList())
|
||||
.setRelocationModel(RelocModel.getNumOccurrences()
|
||||
@ -758,9 +782,13 @@ int runOrcLazyJIT(const char *ProgName) {
|
||||
.setCodeModel(CMModel.getNumOccurrences()
|
||||
? Optional<CodeModel::Model>(CMModel)
|
||||
: None);
|
||||
auto TM = ExitOnErr(TMD.createTargetMachine());
|
||||
auto DL = TM->createDataLayout();
|
||||
auto J = ExitOnErr(orc::LLLazyJIT::Create(std::move(TM), DL));
|
||||
DataLayout DL("");
|
||||
{
|
||||
// Create a throwaway TargetMachine to get the data layout.
|
||||
auto TM = ExitOnErr(JTMB.createTargetMachine());
|
||||
DL = TM->createDataLayout();
|
||||
}
|
||||
auto J = ExitOnErr(orc::LLLazyJIT::Create(std::move(JTMB), DL, LazyJITCompileThreads));
|
||||
|
||||
auto Dump = createDebugDumper();
|
||||
|
||||
@ -807,6 +835,16 @@ int runOrcLazyJIT(const char *ProgName) {
|
||||
// Run any static constructors.
|
||||
ExitOnErr(J->runConstructors());
|
||||
|
||||
// Run any -thread-entry points.
|
||||
std::vector<std::thread> AltEntryThreads;
|
||||
for (auto &ThreadEntryPoint : ThreadEntryPoints) {
|
||||
auto EntryPointSym = ExitOnErr(J->lookup(ThreadEntryPoint));
|
||||
typedef void (*EntryPointPtr)();
|
||||
auto EntryPoint =
|
||||
reinterpret_cast<EntryPointPtr>(static_cast<uintptr_t>(EntryPointSym.getAddress()));
|
||||
AltEntryThreads.push_back(std::thread([EntryPoint]() { EntryPoint(); }));
|
||||
}
|
||||
|
||||
// Run main.
|
||||
auto MainSym = ExitOnErr(J->lookup("main"));
|
||||
typedef int (*MainFnPtr)(int, const char *[]);
|
||||
@ -817,8 +855,12 @@ int runOrcLazyJIT(const char *ProgName) {
|
||||
reinterpret_cast<MainFnPtr>(static_cast<uintptr_t>(MainSym.getAddress()));
|
||||
auto Result = Main(ArgV.size(), (const char **)ArgV.data());
|
||||
|
||||
ExitOnErr(J->runDestructors());
|
||||
// Wait for -entry-point threads.
|
||||
for (auto &AltEntryThread : AltEntryThreads)
|
||||
AltEntryThread.join();
|
||||
|
||||
// Run destructors.
|
||||
ExitOnErr(J->runDestructors());
|
||||
CXXRuntimeOverrides.runDestructors();
|
||||
|
||||
return Result;
|
||||
|
Loading…
Reference in New Issue
Block a user