Skip to content

Commit

Permalink
"Reapply "[llvm-jitlink] Use concurrent linking by default." with mor…
Browse files Browse the repository at this point in the history
…e fixes.

This reapplies edca1d9 which was reverted in 7ec139a due to bot
failures.

LocalDependencyPropagation.s is updated to use -num-threads=0 in order to
avoid interleaving debugging output.

ELFNixPlatform.h is updated to protect the deferred runtime function calls
map during bootstrap.
  • Loading branch information
lhames committed Jan 2, 2025
1 parent 23ec9ee commit 0965515
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 11 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/ExecutionEngine/Orc/ELFNixPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ class ELFNixPlatform : public Platform {
RuntimeFunction *func1, RuntimeFunction *func2,
const shared::WrapperFunctionCall::ArgDataBufferType &arg1,
const shared::WrapperFunctionCall::ArgDataBufferType &arg2) {
std::lock_guard<std::mutex> Lock(Mutex);
auto &argList = DeferredRTFnMap[std::make_pair(func1, func2)];
argList.emplace_back(arg1, arg2);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# REQUIRES: asserts
# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -filetype=obj -o %t %s
# RUN: llvm-jitlink -debug-only=orc -noexec -abs _external_func=0x1 \
# RUN: -entry=_foo %t 2>&1 | FileCheck %s
# RUN: llvm-jitlink -debug-only=orc -num-threads=0 -noexec \
# RUN: -abs _external_func=0x1 -entry=_foo %t 2>&1 | FileCheck %s
#
# Check that simplification eliminates dependencies on symbols in this unit,
# and correctly propagates dependencies on symbols outside the unit (including
# via locally scoped symbols). In this test _baz depends on _foo indirectly via
# the local symbol _bar. Initially we expect _baz to depend on _foo, and _foo
# on _external_func, after simplification we expect both to depend on
# _external_func only.
# _external_func only.

# CHECK: In main emitting {{.*}}_foo{{.*}}
# CHECK-NEXT: Initial dependencies:
Expand Down
2 changes: 2 additions & 0 deletions llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ static Expected<Symbol &> getCOFFStubTarget(LinkGraph &G, Block &B) {

namespace llvm {
Error registerCOFFGraphInfo(Session &S, LinkGraph &G) {
std::lock_guard<std::mutex> Lock(S.M);

auto FileName = sys::path::filename(G.getName());
if (S.FileInfos.count(FileName)) {
return make_error<StringError>("When -check is passed, file names must be "
Expand Down
2 changes: 2 additions & 0 deletions llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ static Error registerSymbol(LinkGraph &G, Symbol &Sym, Session::FileInfo &FI,
namespace llvm {

Error registerELFGraphInfo(Session &S, LinkGraph &G) {
std::lock_guard<std::mutex> Lock(S.M);

auto FileName = sys::path::filename(G.getName());
if (S.FileInfos.count(FileName)) {
return make_error<StringError>("When -check is passed, file names must be "
Expand Down
2 changes: 2 additions & 0 deletions llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ static Expected<Symbol &> getMachOStubTarget(LinkGraph &G, Block &B) {
namespace llvm {

Error registerMachOGraphInfo(Session &S, LinkGraph &G) {
std::lock_guard<std::mutex> Lock(S.M);

auto FileName = sys::path::filename(G.getName());
if (S.FileInfos.count(FileName)) {
return make_error<StringError>("When -check is passed, file names must be "
Expand Down
56 changes: 48 additions & 8 deletions llvm/tools/llvm-jitlink/llvm-jitlink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
cl::desc("input files"),
cl::cat(JITLinkCategory));

static cl::opt<size_t> MaterializationThreads(
"num-threads", cl::desc("Number of materialization threads to use"),
cl::init(std::numeric_limits<size_t>::max()), cl::cat(JITLinkCategory));

static cl::list<std::string>
LibrarySearchPaths("L",
cl::desc("Add dir to the list of library search paths"),
Expand Down Expand Up @@ -400,6 +404,7 @@ bool lazyLinkingRequested() {
}

static Error applyHarnessPromotions(Session &S, LinkGraph &G) {
std::lock_guard<std::mutex> Lock(S.M);

// If this graph is part of the test harness there's nothing to do.
if (S.HarnessFiles.empty() || S.HarnessFiles.count(G.getName()))
Expand Down Expand Up @@ -450,7 +455,11 @@ static Error applyHarnessPromotions(Session &S, LinkGraph &G) {
return Error::success();
}

static void dumpSectionContents(raw_ostream &OS, LinkGraph &G) {
static void dumpSectionContents(raw_ostream &OS, Session &S, LinkGraph &G) {
std::lock_guard<std::mutex> Lock(S.M);

outs() << "Relocated section contents for " << G.getName() << ":\n";

constexpr orc::ExecutorAddrDiff DumpWidth = 16;
static_assert(isPowerOf2_64(DumpWidth), "DumpWidth must be a power of two");

Expand Down Expand Up @@ -842,7 +851,7 @@ static Expected<std::unique_ptr<ExecutorProcessControl>> launchExecutor() {
S.CreateMemoryManager = createSharedMemoryManager;

return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
std::make_unique<DynamicThreadPoolTaskDispatcher>(MaterializationThreads),
std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
#endif
}
Expand Down Expand Up @@ -984,10 +993,16 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
auto PageSize = sys::Process::getPageSize();
if (!PageSize)
return PageSize.takeError();
std::unique_ptr<TaskDispatcher> Dispatcher;
if (MaterializationThreads == 0)
Dispatcher = std::make_unique<InPlaceTaskDispatcher>();
else
Dispatcher = std::make_unique<DynamicThreadPoolTaskDispatcher>(
MaterializationThreads);

EPC = std::make_unique<SelfExecutorProcessControl>(
std::make_shared<SymbolStringPool>(),
std::make_unique<InPlaceTaskDispatcher>(), std::move(TT), *PageSize,
createInProcessMemoryManager());
std::make_shared<SymbolStringPool>(), std::move(Dispatcher),
std::move(TT), *PageSize, createInProcessMemoryManager());
}

Error Err = Error::success();
Expand Down Expand Up @@ -1221,6 +1236,7 @@ void Session::modifyPassConfig(LinkGraph &G, PassConfiguration &PassConfig) {

if (ShowGraphsRegex)
PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error {
std::lock_guard<std::mutex> Lock(M);
// Print graph if ShowLinkGraphs is specified-but-empty, or if
// it contains the given graph.
if (ShowGraphsRegex->match(G.getName())) {
Expand All @@ -1239,9 +1255,8 @@ void Session::modifyPassConfig(LinkGraph &G, PassConfiguration &PassConfig) {
[this](LinkGraph &G) { return applyHarnessPromotions(*this, G); });

if (ShowRelocatedSectionContents)
PassConfig.PostFixupPasses.push_back([](LinkGraph &G) -> Error {
outs() << "Relocated section contents for " << G.getName() << ":\n";
dumpSectionContents(outs(), G);
PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error {
dumpSectionContents(outs(), *this, G);
return Error::success();
});

Expand Down Expand Up @@ -1613,6 +1628,31 @@ static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {
}
}

if (MaterializationThreads == std::numeric_limits<size_t>::max()) {
if (auto HC = std::thread::hardware_concurrency())
MaterializationThreads = HC;
else {
errs() << "Warning: std::thread::hardware_concurrency() returned 0, "
"defaulting to -threads=1.\n";
MaterializationThreads = 1;
}
}

if (!!OutOfProcessExecutor.getNumOccurrences() ||
!!OutOfProcessExecutorConnect.getNumOccurrences()) {
if (NoExec)
return make_error<StringError>("-noexec cannot be used with " +
OutOfProcessExecutor.ArgStr + " or " +
OutOfProcessExecutorConnect.ArgStr,
inconvertibleErrorCode());

if (MaterializationThreads == 0)
return make_error<StringError>("-threads=0 cannot be used with " +
OutOfProcessExecutor.ArgStr + " or " +
OutOfProcessExecutorConnect.ArgStr,
inconvertibleErrorCode());
}

// Only one of -oop-executor and -oop-executor-connect can be used.
if (!!OutOfProcessExecutor.getNumOccurrences() &&
!!OutOfProcessExecutorConnect.getNumOccurrences())
Expand Down

0 comments on commit 0965515

Please sign in to comment.