Skip to content

Commit 188ede2

Browse files
committed
[ORC] Implement basic reoptimization.
1 parent 04af63b commit 188ede2

File tree

11 files changed

+650
-30
lines changed

11 files changed

+650
-30
lines changed

compiler-rt/lib/orc/common.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919

2020
/// This macro should be used to define tags that will be associated with
2121
/// handlers in the JIT process, and call can be used to define tags f
22-
#define ORC_RT_JIT_DISPATCH_TAG(X) \
23-
extern "C" char X; \
24-
char X = 0;
22+
#define ORC_RT_JIT_DISPATCH_TAG(X) \
23+
ORC_RT_INTERFACE char X; \
24+
char X = 0;
2525

2626
/// Opaque struct for external symbols.
2727
struct __orc_rt_Opaque {};

compiler-rt/lib/orc/elfnix_platform.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ using namespace orc_rt;
3030
using namespace orc_rt::elfnix;
3131

3232
// Declare function tags for functions in the JIT process.
33+
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_reoptimize_tag)
3334
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_push_initializers_tag)
3435
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_elfnix_symbol_lookup_tag)
3536

llvm/include/llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,10 @@ class JITLinkRedirectableSymbolManager : public RedirectableSymbolManager,
2525
public:
2626
/// Create redirection manager that uses JITLink based implementaion.
2727
static Expected<std::unique_ptr<RedirectableSymbolManager>>
28-
Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
29-
JITDylib &JD) {
28+
Create(ObjectLinkingLayer &ObjLinkingLayer, JITDylib &JD) {
3029
Error Err = Error::success();
3130
auto RM = std::unique_ptr<RedirectableSymbolManager>(
32-
new JITLinkRedirectableSymbolManager(ES, ObjLinkingLayer, JD, Err));
31+
new JITLinkRedirectableSymbolManager(ObjLinkingLayer, JD, Err));
3332
if (Err)
3433
return Err;
3534
return std::move(RM);
@@ -53,38 +52,40 @@ class JITLinkRedirectableSymbolManager : public RedirectableSymbolManager,
5352
constexpr static StringRef JumpStubTableName = "$IND_JUMP_";
5453
constexpr static StringRef StubPtrTableName = "$__IND_JUMP_PTRS";
5554

56-
JITLinkRedirectableSymbolManager(ExecutionSession &ES,
57-
ObjectLinkingLayer &ObjLinkingLayer,
55+
JITLinkRedirectableSymbolManager(ObjectLinkingLayer &ObjLinkingLayer,
5856
JITDylib &JD, Error &Err)
59-
: ES(ES), ObjLinkingLayer(ObjLinkingLayer), JD(JD),
60-
AnonymousPtrCreator(
61-
jitlink::getAnonymousPointerCreator(ES.getTargetTriple())),
62-
PtrJumpStubCreator(
63-
jitlink::getPointerJumpStubCreator(ES.getTargetTriple())) {
57+
: ObjLinkingLayer(ObjLinkingLayer), JD(JD),
58+
AnonymousPtrCreator(jitlink::getAnonymousPointerCreator(
59+
ObjLinkingLayer.getExecutionSession().getTargetTriple())),
60+
PtrJumpStubCreator(jitlink::getPointerJumpStubCreator(
61+
ObjLinkingLayer.getExecutionSession().getTargetTriple())) {
6462
if (!AnonymousPtrCreator || !PtrJumpStubCreator)
6563
Err = make_error<StringError>("Architecture not supported",
6664
inconvertibleErrorCode());
6765
if (Err)
6866
return;
69-
ES.registerResourceManager(*this);
67+
ObjLinkingLayer.getExecutionSession().registerResourceManager(*this);
7068
}
7169

72-
~JITLinkRedirectableSymbolManager() { ES.deregisterResourceManager(*this); }
70+
~JITLinkRedirectableSymbolManager() {
71+
ObjLinkingLayer.getExecutionSession().deregisterResourceManager(*this);
72+
}
7373

7474
StringRef JumpStubSymbolName(unsigned I) {
75-
return *ES.intern((JumpStubPrefix + Twine(I)).str());
75+
return *ObjLinkingLayer.getExecutionSession().intern(
76+
(JumpStubPrefix + Twine(I)).str());
7677
}
7778

7879
StringRef StubPtrSymbolName(unsigned I) {
79-
return *ES.intern((StubPtrPrefix + Twine(I)).str());
80+
return *ObjLinkingLayer.getExecutionSession().intern(
81+
(StubPtrPrefix + Twine(I)).str());
8082
}
8183

8284
unsigned GetNumAvailableStubs() const { return AvailableStubs.size(); }
8385

8486
Error redirectInner(JITDylib &TargetJD, const SymbolAddrMap &NewDests);
8587
Error grow(unsigned Need);
8688

87-
ExecutionSession &ES;
8889
ObjectLinkingLayer &ObjLinkingLayer;
8990
JITDylib &JD;
9091
jitlink::AnonymousPointerCreator AnonymousPtrCreator;
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
//===- ReOptimizeLayer.h - Re-optimization layer interface ------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Re-optimization layer interface.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
#ifndef LLVM_EXECUTIONENGINE_ORC_REOPTIMIZELAYER_H
13+
#define LLVM_EXECUTIONENGINE_ORC_REOPTIMIZELAYER_H
14+
15+
#include "llvm/ExecutionEngine/Orc/Core.h"
16+
#include "llvm/ExecutionEngine/Orc/Layer.h"
17+
#include "llvm/ExecutionEngine/Orc/Mangling.h"
18+
#include "llvm/ExecutionEngine/Orc/RedirectionManager.h"
19+
#include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
20+
#include "llvm/IR/IRBuilder.h"
21+
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
22+
#include "llvm/Transforms/Utils/Cloning.h"
23+
24+
namespace llvm {
25+
namespace orc {
26+
27+
class ReOptimizeLayer : public IRLayer, public ResourceManager {
28+
public:
29+
using ReOptMaterializationUnitID = uint64_t;
30+
31+
/// AddProfilerFunc will be called when ReOptimizeLayer emits the first
32+
/// version of a materialization unit in order to inject profiling code and
33+
/// reoptimization request code.
34+
using AddProfilerFunc = unique_function<Error(
35+
ReOptimizeLayer &Parent, ReOptMaterializationUnitID MUID,
36+
unsigned CurVersion, ThreadSafeModule &TSM)>;
37+
38+
/// ReOptimizeFunc will be called when ReOptimizeLayer reoptimization of a
39+
/// materialization unit was requested in order to reoptimize the IR module
40+
/// based on profile data. OldRT is the ResourceTracker that tracks the old
41+
/// function definitions. The OldRT must be kept alive until it can be
42+
/// guaranteed that every invocation of the old function definitions has been
43+
/// terminated.
44+
using ReOptimizeFunc = unique_function<Error(
45+
ReOptimizeLayer &Parent, ReOptMaterializationUnitID MUID,
46+
unsigned CurVersion, ResourceTrackerSP OldRT, ThreadSafeModule &TSM)>;
47+
48+
ReOptimizeLayer(ExecutionSession &ES, DataLayout &DL, IRLayer &BaseLayer,
49+
RedirectableSymbolManager &RM)
50+
: IRLayer(ES, BaseLayer.getManglingOptions()), ES(ES), Mangle(ES, DL),
51+
BaseLayer(BaseLayer), RSManager(RM), ReOptFunc(identity),
52+
ProfilerFunc(reoptimizeIfCallFrequent) {}
53+
54+
void setReoptimizeFunc(ReOptimizeFunc ReOptFunc) {
55+
this->ReOptFunc = std::move(ReOptFunc);
56+
}
57+
58+
void setAddProfilerFunc(AddProfilerFunc ProfilerFunc) {
59+
this->ProfilerFunc = std::move(ProfilerFunc);
60+
}
61+
62+
/// Registers reoptimize runtime dispatch handlers to given PlatformJD. The
63+
/// reoptimization request will not be handled if dispatch handler is not
64+
/// registered by using this function.
65+
Error reigsterRuntimeFunctions(JITDylib &PlatformJD);
66+
67+
/// Emits the given module. This should not be called by clients: it will be
68+
/// called by the JIT when a definition added via the add method is requested.
69+
void emit(std::unique_ptr<MaterializationResponsibility> R,
70+
ThreadSafeModule TSM) override;
71+
72+
static const uint64_t CallCountThreshold = 10;
73+
74+
/// Basic AddProfilerFunc that reoptimizes the function when the call count
75+
/// exceeds CallCountThreshold.
76+
static Error reoptimizeIfCallFrequent(ReOptimizeLayer &Parent,
77+
ReOptMaterializationUnitID MUID,
78+
unsigned CurVersion,
79+
ThreadSafeModule &TSM);
80+
81+
static Error identity(ReOptimizeLayer &Parent,
82+
ReOptMaterializationUnitID MUID, unsigned CurVersion,
83+
ResourceTrackerSP OldRT, ThreadSafeModule &TSM) {
84+
return Error::success();
85+
}
86+
87+
// Create IR reoptimize request fucntion call.
88+
static void createReoptimizeCall(Module &M, Instruction &IP,
89+
GlobalVariable *ArgBuffer);
90+
91+
Error handleRemoveResources(JITDylib &JD, ResourceKey K) override;
92+
void handleTransferResources(JITDylib &JD, ResourceKey DstK,
93+
ResourceKey SrcK) override;
94+
95+
private:
96+
class ReOptMaterializationUnitState {
97+
public:
98+
ReOptMaterializationUnitState() = default;
99+
ReOptMaterializationUnitState(ReOptMaterializationUnitID ID,
100+
ThreadSafeModule TSM)
101+
: ID(ID), TSM(std::move(TSM)) {}
102+
ReOptMaterializationUnitState(ReOptMaterializationUnitState &&Other)
103+
: ID(Other.ID), TSM(std::move(Other.TSM)), RT(std::move(Other.RT)),
104+
Reoptimizing(std::move(Other.Reoptimizing)),
105+
CurVersion(Other.CurVersion) {}
106+
107+
ReOptMaterializationUnitID getID() { return ID; }
108+
109+
const ThreadSafeModule &getThreadSafeModule() { return TSM; }
110+
111+
ResourceTrackerSP getResourceTracker() {
112+
std::unique_lock<std::mutex> Lock(Mutex);
113+
return RT;
114+
}
115+
116+
void setResourceTracker(ResourceTrackerSP RT) {
117+
std::unique_lock<std::mutex> Lock(Mutex);
118+
this->RT = RT;
119+
}
120+
121+
uint32_t getCurVersion() {
122+
std::unique_lock<std::mutex> Lock(Mutex);
123+
return CurVersion;
124+
}
125+
126+
bool tryStartReoptimize();
127+
void reoptimizeSucceeded();
128+
void reoptimizeFailed();
129+
130+
private:
131+
std::mutex Mutex;
132+
ReOptMaterializationUnitID ID;
133+
ThreadSafeModule TSM;
134+
ResourceTrackerSP RT;
135+
bool Reoptimizing = false;
136+
uint32_t CurVersion = 0;
137+
};
138+
139+
using SPSReoptimizeArgList =
140+
shared::SPSArgList<ReOptMaterializationUnitID, uint32_t>;
141+
using SendErrorFn = unique_function<void(Error)>;
142+
143+
Expected<SymbolMap> emitMUImplSymbols(ReOptMaterializationUnitState &MUState,
144+
uint32_t Version, JITDylib &JD,
145+
ThreadSafeModule TSM);
146+
147+
void rt_reoptimize(SendErrorFn SendResult, ReOptMaterializationUnitID MUID,
148+
uint32_t CurVersion);
149+
150+
static Expected<Constant *>
151+
createReoptimizeArgBuffer(Module &M, ReOptMaterializationUnitID MUID,
152+
uint32_t CurVersion);
153+
154+
ReOptMaterializationUnitState &
155+
createMaterializationUnitState(const ThreadSafeModule &TSM);
156+
157+
void
158+
registerMaterializationUnitResource(ResourceKey Key,
159+
ReOptMaterializationUnitState &State);
160+
161+
ReOptMaterializationUnitState &
162+
getMaterializationUnitState(ReOptMaterializationUnitID MUID);
163+
164+
ExecutionSession &ES;
165+
MangleAndInterner Mangle;
166+
IRLayer &BaseLayer;
167+
RedirectableSymbolManager &RSManager;
168+
169+
ReOptimizeFunc ReOptFunc;
170+
AddProfilerFunc ProfilerFunc;
171+
172+
std::mutex Mutex;
173+
std::map<ReOptMaterializationUnitID, ReOptMaterializationUnitState> MUStates;
174+
DenseMap<ResourceKey, DenseSet<ReOptMaterializationUnitID>> MUResources;
175+
ReOptMaterializationUnitID NextID = 1;
176+
};
177+
178+
} // namespace orc
179+
} // namespace llvm
180+
181+
#endif

llvm/include/llvm/ExecutionEngine/Orc/RedirectionManager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class RedirectableSymbolManager : public RedirectionManager {
6363
const SymbolMap &InitialDests) = 0;
6464
};
6565

66+
/// RedirectableMaterializationUnit materializes redirectable symbol
67+
/// by invoking RedirectableSymbolManager::emitRedirectableSymbols
6668
class RedirectableMaterializationUnit : public MaterializationUnit {
6769
public:
6870
RedirectableMaterializationUnit(RedirectableSymbolManager &RM,

llvm/lib/ExecutionEngine/Orc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ add_llvm_component_library(LLVMOrcJIT
5353
ThreadSafeModule.cpp
5454
RedirectionManager.cpp
5555
JITLinkRedirectableSymbolManager.cpp
56+
ReOptimizeLayer.cpp
5657
ADDITIONAL_HEADER_DIRS
5758
${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
5859

llvm/lib/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ using namespace llvm::orc;
1717
void JITLinkRedirectableSymbolManager::emitRedirectableSymbols(
1818
std::unique_ptr<MaterializationResponsibility> R,
1919
const SymbolAddrMap &InitialDests) {
20+
auto &ES = ObjLinkingLayer.getExecutionSession();
2021
std::unique_lock<std::mutex> Lock(Mutex);
2122
if (GetNumAvailableStubs() < InitialDests.size())
2223
if (auto Err = grow(InitialDests.size() - GetNumAvailableStubs())) {
@@ -37,21 +38,21 @@ void JITLinkRedirectableSymbolManager::emitRedirectableSymbols(
3738
R->failMaterialization();
3839
return;
3940
}
40-
dbgs() << *K << "\n";
4141
SymbolToStubs[&TargetJD][K] = StubID;
4242
NewSymbolDefs[K] = JumpStubs[StubID];
4343
NewSymbolDefs[K].setFlags(V.getFlags());
4444
Symbols.push_back(K);
4545
AvailableStubs.pop_back();
4646
}
4747

48-
if (auto Err = R->replace(absoluteSymbols(NewSymbolDefs))) {
48+
// FIXME: when this fails we can return stubs to the pool
49+
if (auto Err = redirectInner(TargetJD, InitialDests)) {
4950
ES.reportError(std::move(Err));
5051
R->failMaterialization();
5152
return;
5253
}
5354

54-
if (auto Err = redirectInner(TargetJD, InitialDests)) {
55+
if (auto Err = R->replace(absoluteSymbols(NewSymbolDefs))) {
5556
ES.reportError(std::move(Err));
5657
R->failMaterialization();
5758
return;
@@ -85,10 +86,10 @@ Error JITLinkRedirectableSymbolManager::redirectInner(
8586
StubHandle StubID = SymbolToStubs[&TargetJD].at(K);
8687
PtrWrites.push_back({StubPointers[StubID].getAddress(), V.getAddress()});
8788
}
88-
if (auto Err = ES.getExecutorProcessControl().getMemoryAccess().writePointers(
89-
PtrWrites))
90-
return Err;
91-
return Error::success();
89+
return ObjLinkingLayer.getExecutionSession()
90+
.getExecutorProcessControl()
91+
.getMemoryAccess()
92+
.writePointers(PtrWrites);
9293
}
9394

9495
Error JITLinkRedirectableSymbolManager::grow(unsigned Need) {
@@ -103,16 +104,18 @@ Error JITLinkRedirectableSymbolManager::grow(unsigned Need) {
103104
SymbolLookupSet LookupSymbols;
104105
DenseMap<SymbolStringPtr, ExecutorSymbolDef *> NewDefsMap;
105106

107+
auto &ES = ObjLinkingLayer.getExecutionSession();
106108
Triple TT = ES.getTargetTriple();
107109
auto G = std::make_unique<jitlink::LinkGraph>(
108110
"<INDIRECT STUBS>", TT, TT.isArch64Bit() ? 8 : 4,
109-
TT.isLittleEndian() ? support::little : support::big,
111+
TT.isLittleEndian() ? endianness::little : endianness::big,
110112
jitlink::getGenericEdgeKindName);
111113
auto &PointerSection =
112114
G->createSection(StubPtrTableName, MemProt::Write | MemProt::Read);
113115
auto &StubsSection =
114116
G->createSection(JumpStubTableName, MemProt::Exec | MemProt::Read);
115117

118+
// FIXME: We can batch the stubs into one block and use address to access them
116119
for (size_t I = OldSize; I < NewSize; I++) {
117120
auto Pointer = AnonymousPtrCreator(*G, PointerSection, nullptr, 0);
118121
if (auto Err = Pointer.takeError())

0 commit comments

Comments
 (0)