9bool ReOptimizeLayer::ReOptMaterializationUnitState::tryStartReoptimize() {
10 std::unique_lock<std::mutex> Lock(Mutex);
18void ReOptimizeLayer::ReOptMaterializationUnitState::reoptimizeSucceeded() {
19 std::unique_lock<std::mutex> Lock(Mutex);
20 assert(Reoptimizing &&
"Tried to mark unstarted reoptimization as done");
25void ReOptimizeLayer::ReOptMaterializationUnitState::reoptimizeFailed() {
26 std::unique_lock<std::mutex> Lock(Mutex);
27 assert(Reoptimizing &&
"Tried to mark unstarted reoptimization as done");
41 if (!SPSArgs::serialize(OB, MUID, CurVersion)) {
43 <<
"Reoptimization error: could not serialize reoptimization arguments";
47 JITDispatch(JITDispatchCtx, Tag, ArgBytes.data(), ArgBytes.size())};
50 errs() <<
"Reoptimization error: " << ErrMsg <<
"\naborting.\n";
57 auto Ctx = std::make_unique<LLVMContext>();
58 auto Mod = std::make_unique<Module>(
"orc-rt-lite-reoptimize.ll", *Ctx);
59 Mod->setDataLayout(
DL);
72 VoidTy, {VoidPtrTy, VoidPtrTy, VoidPtrTy, Int64Ty, Int32Ty},
false);
77 ConstantInt::get(Int8Ty, 0),
"__orc_rt_reoptimize_tag");
85 "__orc_rt_reoptimize",
Mod.get());
88 auto ArgIt = ReOptimizeFn->arg_begin();
89 Value *MUID = &*ArgIt++;
91 Value *CurVersion = &*ArgIt;
92 CurVersion->
setName(
"CurVersion");
96 Builder.SetInsertPoint(Entry);
102 {{ES.intern(rt::DispatchName), &JITDispatchSym},
103 {ES.intern(rt::DispatchCtxName), &JITDispatchCtxSym}}))
108 ConstantInt::get(
IntPtrTy, JITDispatchSym.getValue()), VoidPtrTy);
110 ConstantInt::get(
IntPtrTy, JITDispatchCtxSym.getValue()), VoidPtrTy);
117 Value *ReoptimizeTagPtr = Builder.CreatePointerCast(ReoptimizeTag, VoidPtrTy);
121 HelperFnTy, HelperFnAddr,
122 {JITDispatchPtr, JITDispatchCtxPtr, ReoptimizeTagPtr, MUID, CurVersion});
125 Builder.CreateRetVoid();
127 return BaseLayer.
add(PlatformJD,
134 WFs[Mangle(
"__orc_rt_reoptimize_tag")] =
135 ES.wrapAsyncWithSPS<ReoptimizeSPSSig>(
this,
136 &ReOptimizeLayer::rt_reoptimize);
137 return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
142 auto &JD = R->getTargetJITDylib();
144 bool HasNonCallable =
false;
145 for (
auto &KV : R->getSymbols()) {
146 auto &Flags = KV.second;
147 if (!Flags.isCallable())
148 HasNonCallable =
true;
151 if (HasNonCallable) {
152 BaseLayer.emit(std::move(R), std::move(TSM));
156 auto &MUState = createMaterializationUnitState(TSM);
159 registerMaterializationUnitResource(Key, MUState);
161 ES.reportError(std::move(Err));
162 R->failMaterialization();
167 ProfilerFunc(*
this, MUState.getID(), MUState.getCurVersion(), TSM)) {
168 ES.reportError(std::move(Err));
169 R->failMaterialization();
174 emitMUImplSymbols(MUState, MUState.getCurVersion(), JD, std::move(TSM));
176 ES.reportError(InitialDests.takeError());
177 R->failMaterialization();
181 RSManager.emitRedirectableSymbols(std::move(R), std::move(*InitialDests));
194 if (
F.isDeclaration())
196 auto &BB =
F.getEntryBlock();
197 auto *IP = &*BB.getFirstInsertionPt();
213ReOptimizeLayer::emitMUImplSymbols(ReOptMaterializationUnitState &MUState,
218 MangleAndInterner Mangle(ES, M.getDataLayout());
220 if (!F.isDeclaration()) {
221 std::string NewName =
222 (F.getName() +
".__def__." + Twine(Version)).str();
223 RenamedMap[Mangle(F.getName())] = Mangle(NewName);
229 auto RT = JD.createResourceTracker();
231 JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
235 MUState.setResourceTracker(RT);
238 for (
auto [K, V] : RenamedMap)
239 LookupSymbols.
add(V);
244 if (
auto Err = ImplSymbols.takeError())
248 for (
auto [K, V] : RenamedMap)
254void ReOptimizeLayer::rt_reoptimize(SendErrorFn SendResult,
256 uint32_t CurVersion) {
257 auto &MUState = getMaterializationUnitState(MUID);
258 if (CurVersion < MUState.getCurVersion() || !MUState.tryStartReoptimize()) {
264 auto OldRT = MUState.getResourceTracker();
265 auto &JD = OldRT->getJITDylib();
267 if (
auto Err = ReOptFunc(*
this, MUID, CurVersion + 1, OldRT, TSM)) {
268 ES.reportError(std::move(Err));
269 MUState.reoptimizeFailed();
275 emitMUImplSymbols(MUState, CurVersion + 1, JD, std::move(TSM));
277 ES.reportError(SymbolDests.takeError());
278 MUState.reoptimizeFailed();
283 if (
auto Err = RSManager.redirect(JD, std::move(*SymbolDests))) {
284 ES.reportError(std::move(Err));
285 MUState.reoptimizeFailed();
290 MUState.reoptimizeSucceeded();
300 if (!ReoptimizeFunc) {
301 std::vector<Type *> ArgTys = {MUIDTy, VersionTy};
305 "__orc_rt_reoptimize", &M);
307 Constant *MUIDArg = ConstantInt::get(MUIDTy, MUID,
false);
308 Constant *CurVersionArg = ConstantInt::get(VersionTy, CurVersion,
false);
310 (void)IRB.
CreateCall(ReoptimizeFunc, {MUIDArg, CurVersionArg});
313ReOptimizeLayer::ReOptMaterializationUnitState &
314ReOptimizeLayer::createMaterializationUnitState(
const ThreadSafeModule &TSM) {
315 std::unique_lock<std::mutex> Lock(
Mutex);
317 MUStates.emplace(MUID,
320 return MUStates.at(MUID);
323ReOptimizeLayer::ReOptMaterializationUnitState &
325 std::unique_lock<std::mutex> Lock(
Mutex);
326 return MUStates.at(MUID);
329void ReOptimizeLayer::registerMaterializationUnitResource(
331 std::unique_lock<std::mutex> Lock(
Mutex);
332 MUResources[
Key].insert(State.getID());
336 std::unique_lock<std::mutex> Lock(Mutex);
337 for (
auto MUID : MUResources[K])
338 MUStates.erase(MUID);
340 MUResources.erase(K);
346 std::unique_lock<std::mutex> Lock(Mutex);
347 MUResources[DstK].insert_range(MUResources[SrcK]);
348 MUResources.erase(SrcK);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void orc_rt_lite_reoptimize_helper(shared::CWrapperFunctionBuffer(*JITDispatch)(void *Ctx, void *Tag, const char *Data, size_t Size), void *JITDispatchCtx, void *Tag, uint64_t MUID, uint32_t CurVersion)
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const Function & getFunction() const
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
A Module instance is used to store all the information related to an LLVM module.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
LLVM Value Representation.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder, SymbolLookupSet Symbols, SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies)
Search the given JITDylibs for the given symbols.
DenseMap< SymbolStringPtr, JITDispatchHandlerFunction > JITDispatchHandlerAssociationMap
A map associating tag names with asynchronous wrapper function implementations in the JIT.
Represents an address in the executor process.
virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM)
Add a MaterializatinoUnit representing the given IR to the JITDylib targeted by the given tracker.
const IRSymbolMapper::ManglingOptions *& getManglingOptions() const
Get the mangling options for this layer.
Represents a JIT'd dynamic library.
Error registerRuntimeFunctions(JITDylib &PlatformJD)
Registers reoptimize runtime dispatch handlers to given PlatformJD.
ReOptimizeLayer(ExecutionSession &ES, DataLayout &DL, IRLayer &BaseLayer, RedirectableSymbolManager &RM)
void emit(std::unique_ptr< MaterializationResponsibility > R, ThreadSafeModule TSM) override
Emits the given module.
static void createReoptimizeCall(Module &M, Instruction &IP, ReOptMaterializationUnitID MUID, unsigned CurVersion)
uint64_t ReOptMaterializationUnitID
void handleTransferResources(JITDylib &JD, ResourceKey DstK, ResourceKey SrcK) override
This function will be called inside the session lock.
Error addOrcRTLiteSupport(JITDylib &PlatformJD, const DataLayout &DL)
Add ORC Runtime-lite support for reoptimization to PlatformJD.
static Error reoptimizeIfCallFrequent(ReOptimizeLayer &Parent, ReOptMaterializationUnitID MUID, unsigned CurVersion, ThreadSafeModule &TSM)
Basic AddProfilerFunc that reoptimizes the function when the call count exceeds CallCountThreshold.
Error handleRemoveResources(JITDylib &JD, ResourceKey K) override
This function will be called outside the session lock.
static const uint64_t CallCountThreshold
A set of symbols to look up, each associated with a SymbolLookupFlags value.
SymbolLookupSet & add(SymbolStringPtr Name, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)
Add an element to the set.
An LLVM Module together with a shared ThreadSafeContext.
decltype(auto) withModuleDo(Func &&F)
Locks the associated ThreadSafeContext and calls the given function on the contained Module.
A utility class for serializing to a blob from a variadic list.
Output char buffer with overflow check.
C++ wrapper function buffer: Same as CWrapperFunctionBuffer but auto-releases memory.
const char * getOutOfBandError() const
If this value is an out-of-band error then this returns the error message, otherwise returns nullptr.
static WrapperFunctionBuffer allocate(size_t Size)
Create a WrapperFunctionBuffer with the given size and return a pointer to the underlying memory.
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib * > JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
LLVM_ABI void lookupAndRecordAddrs(unique_function< void(Error)> OnRecorded, ExecutionSession &ES, LookupKind K, const JITDylibSearchOrder &SearchOrder, std::vector< std::pair< SymbolStringPtr, ExecutorAddr * > > Pairs, SymbolLookupFlags LookupFlags=SymbolLookupFlags::RequiredSymbol)
Record addresses of the given symbols in the given ExecutorAddrs.
DenseMap< SymbolStringPtr, ExecutorSymbolDef > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
LLVM_ABI ThreadSafeModule cloneToNewContext(const ThreadSafeModule &TSMW, GVPredicate ShouldCloneDef=GVPredicate(), GVModifier UpdateClonedDefSource=GVModifier())
Clones the given module on to a new context.
@ Resolved
Queried, materialization begun.
SmartMutex< false > Mutex
Mutex - A standard, always enforced mutex.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Mod
The access may modify the value stored in memory.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...