diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/LLJIT.cpp | 77 | ||||
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/TaskDispatch.cpp | 47 |
3 files changed, 96 insertions, 30 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp index efafca9..4081bc8 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp @@ -63,7 +63,7 @@ SelfExecutorProcessControl::Create( if (!D) { #if LLVM_ENABLE_THREADS - D = std::make_unique<DynamicThreadPoolTaskDispatcher>(); + D = std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt); #else D = std::make_unique<InPlaceTaskDispatcher>(); #endif diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp index 79adda5..53f13a6 100644 --- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp +++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp @@ -667,6 +667,37 @@ Error LLJITBuilderState::prepareForConstruction() { return JTMBOrErr.takeError(); } + if ((ES || EPC) && NumCompileThreads) + return make_error<StringError>( + "NumCompileThreads cannot be used with a custom ExecutionSession or " + "ExecutorProcessControl", + inconvertibleErrorCode()); + +#if !LLVM_ENABLE_THREADS + if (NumCompileThreads) + return make_error<StringError>( + "LLJIT num-compile-threads is " + Twine(NumCompileThreads) + + " but LLVM was compiled with LLVM_ENABLE_THREADS=Off", + inconvertibleErrorCode()); +#endif // !LLVM_ENABLE_THREADS + + bool ConcurrentCompilationSettingDefaulted = !SupportConcurrentCompilation; + if (!SupportConcurrentCompilation) { +#if LLVM_ENABLE_THREADS + SupportConcurrentCompilation = NumCompileThreads || ES || EPC; +#else + SupportConcurrentCompilation = false; +#endif // LLVM_ENABLE_THREADS + } else { +#if !LLVM_ENABLE_THREADS + if (*SupportConcurrentCompilation) + return make_error<StringError>( + "LLJIT concurrent compilation support requested, but LLVM was built " + "with LLVM_ENABLE_THREADS=Off", + inconvertibleErrorCode()); +#endif // !LLVM_ENABLE_THREADS + } + LLVM_DEBUG({ dbgs() << " JITTargetMachineBuilder is " << JITTargetMachineBuilderPrinter(*JTMB, " ") @@ -684,11 +715,13 @@ Error LLJITBuilderState::prepareForConstruction() { << (CreateCompileFunction ? "Yes" : "No") << "\n" << " Custom platform-setup function: " << (SetUpPlatform ? "Yes" : "No") << "\n" - << " Number of compile threads: " << NumCompileThreads; - if (!NumCompileThreads) - dbgs() << " (code will be compiled on the execution thread)\n"; + << " Support concurrent compilation: " + << (*SupportConcurrentCompilation ? "Yes" : "No"); + if (ConcurrentCompilationSettingDefaulted) + dbgs() << " (defaulted based on ES / EPC)\n"; else dbgs() << "\n"; + dbgs() << " Number of compile threads: " << NumCompileThreads << "\n"; }); // Create DL if not specified. @@ -705,7 +738,19 @@ Error LLJITBuilderState::prepareForConstruction() { dbgs() << "ExecutorProcessControl not specified, " "Creating SelfExecutorProcessControl instance\n"; }); - if (auto EPCOrErr = SelfExecutorProcessControl::Create()) + + std::unique_ptr<TaskDispatcher> D = nullptr; +#if LLVM_ENABLE_THREADS + if (*SupportConcurrentCompilation) { + std::optional<size_t> NumThreads = std ::nullopt; + if (NumCompileThreads) + NumThreads = NumCompileThreads; + D = std::make_unique<DynamicThreadPoolTaskDispatcher>(NumThreads); + } else + D = std::make_unique<InPlaceTaskDispatcher>(); +#endif // LLVM_ENABLE_THREADS + if (auto EPCOrErr = + SelfExecutorProcessControl::Create(nullptr, std::move(D), nullptr)) EPC = std::move(*EPCOrErr); else return EPCOrErr.takeError(); @@ -790,8 +835,6 @@ Error LLJITBuilderState::prepareForConstruction() { } LLJIT::~LLJIT() { - if (CompileThreads) - CompileThreads->wait(); if (auto Err = ES->endSession()) ES->reportError(std::move(Err)); } @@ -916,9 +959,8 @@ LLJIT::createCompileFunction(LLJITBuilderState &S, if (S.CreateCompileFunction) return S.CreateCompileFunction(std::move(JTMB)); - // Otherwise default to creating a SimpleCompiler, or ConcurrentIRCompiler, - // depending on the number of threads requested. - if (S.NumCompileThreads > 0) + // If using a custom EPC then use a ConcurrentIRCompiler by default. + if (*S.SupportConcurrentCompilation) return std::make_unique<ConcurrentIRCompiler>(std::move(JTMB)); auto TM = JTMB.createTargetMachine(); @@ -970,21 +1012,8 @@ LLJIT::LLJIT(LLJITBuilderState &S, Error &Err) std::make_unique<IRTransformLayer>(*ES, *TransformLayer); } - if (S.NumCompileThreads > 0) { + if (*S.SupportConcurrentCompilation) InitHelperTransformLayer->setCloneToNewContextOnEmit(true); - CompileThreads = std::make_unique<DefaultThreadPool>( - hardware_concurrency(S.NumCompileThreads)); - ES->setDispatchTask([this](std::unique_ptr<Task> T) { - // FIXME: We should be able to use move-capture here, but ThreadPool's - // AsyncTaskTys are std::functions rather than unique_functions - // (because MSVC's std::packaged_tasks don't support move-only types). - // Fix this when all the above gets sorted out. - CompileThreads->async([UnownedT = T.release()]() mutable { - std::unique_ptr<Task> T(UnownedT); - T->run(); - }); - }); - } if (S.SetupProcessSymbolsJITDylib) { if (auto ProcSymsJD = S.SetupProcessSymbolsJITDylib(*this)) { @@ -1240,7 +1269,7 @@ LLLazyJIT::LLLazyJIT(LLLazyJITBuilderState &S, Error &Err) : LLJIT(S, Err) { CODLayer = std::make_unique<CompileOnDemandLayer>( *ES, *InitHelperTransformLayer, *LCTMgr, std::move(ISMBuilder)); - if (S.NumCompileThreads > 0) + if (*S.SupportConcurrentCompilation) CODLayer->setCloneToNewContextOnEmit(true); } diff --git a/llvm/lib/ExecutionEngine/Orc/TaskDispatch.cpp b/llvm/lib/ExecutionEngine/Orc/TaskDispatch.cpp index 11a9998..4ac2a42 100644 --- a/llvm/lib/ExecutionEngine/Orc/TaskDispatch.cpp +++ b/llvm/lib/ExecutionEngine/Orc/TaskDispatch.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/TaskDispatch.h" +#include "llvm/ExecutionEngine/Orc/Core.h" namespace llvm { namespace orc { @@ -24,16 +25,52 @@ void InPlaceTaskDispatcher::shutdown() {} #if LLVM_ENABLE_THREADS void DynamicThreadPoolTaskDispatcher::dispatch(std::unique_ptr<Task> T) { + bool IsMaterializationTask = isa<MaterializationTask>(*T); + { std::lock_guard<std::mutex> Lock(DispatchMutex); + + if (IsMaterializationTask) { + + // If this is a materialization task and there are too many running + // already then queue this one up and return early. + if (MaxMaterializationThreads && + NumMaterializationThreads == *MaxMaterializationThreads) { + MaterializationTaskQueue.push_back(std::move(T)); + return; + } + + // Otherwise record that we have a materialization task running. + ++NumMaterializationThreads; + } + ++Outstanding; } - std::thread([this, T = std::move(T)]() mutable { - T->run(); - std::lock_guard<std::mutex> Lock(DispatchMutex); - --Outstanding; - OutstandingCV.notify_all(); + std::thread([this, T = std::move(T), IsMaterializationTask]() mutable { + while (true) { + + // Run the task. + T->run(); + + std::lock_guard<std::mutex> Lock(DispatchMutex); + if (!MaterializationTaskQueue.empty()) { + // If there are any materialization tasks running then steal that work. + T = std::move(MaterializationTaskQueue.front()); + MaterializationTaskQueue.pop_front(); + if (!IsMaterializationTask) { + ++NumMaterializationThreads; + IsMaterializationTask = true; + } + } else { + // Otherwise decrement work counters. + if (IsMaterializationTask) + --NumMaterializationThreads; + --Outstanding; + OutstandingCV.notify_all(); + return; + } + } }).detach(); } |