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