From 2e36ddf6717638b80f2fcdedcda4b3de054df842 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Fri, 12 Jun 2015 21:31:15 +0000 Subject: [PATCH] [Orc] Fix a bug in the CompileOnDemand layer where stub decls were not cloned into partitions. Also, add an option to clone stub definitions (not just decls) into partitions: these definitions could be inlined in some places to avoid the overhead of calling via the stub. Found by inspection - no test case yet, although I plan to add a unit test for this once the CompileOnDemand layer refactoring settles down. llvm-svn: 239640 --- .../ExecutionEngine/Orc/CompileOnDemandLayer.h | 49 ++++++++++++++++------ llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp | 2 - llvm/tools/lli/OrcLazyJIT.h | 2 +- 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index d631e1d..d4e6b19 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -46,23 +46,39 @@ private: // variables. class GlobalDeclMaterializer : public ValueMaterializer { public: - GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {} + typedef std::set StubSet; + + GlobalDeclMaterializer(Module &Dst, const StubSet *StubsToClone = nullptr) + : Dst(Dst), StubsToClone(StubsToClone) {} + Value* materializeValueFor(Value *V) final { if (auto *GV = dyn_cast(V)) return cloneGlobalVariableDecl(Dst, *GV); - else if (auto *F = dyn_cast(V)) - return cloneFunctionDecl(Dst, *F); + else if (auto *F = dyn_cast(V)) { + auto *ClonedF = cloneFunctionDecl(Dst, *F); + if (StubsToClone && StubsToClone->count(F)) { + GlobalVariable *FnBodyPtr = + createImplPointer(*ClonedF->getType(), *ClonedF->getParent(), + ClonedF->getName() + "$orc_addr", nullptr); + makeStub(*ClonedF, *FnBodyPtr); + ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage); + ClonedF->addFnAttr(Attribute::AlwaysInline); + } + return ClonedF; + } // Else. return nullptr; } private: Module &Dst; + const StubSet *StubsToClone; }; typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; struct LogicalModuleResources { std::shared_ptr SourceModule; + std::set StubsToClone; }; struct LogicalDylibResources { @@ -83,8 +99,10 @@ public: typedef typename LogicalDylibList::iterator ModuleSetHandleT; /// @brief Construct a compile-on-demand layer instance. - CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr) - : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {} + CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr, + bool CloneStubsIntoPartitions) + : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr), + CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} /// @brief Add a module to the compile-on-demand layer. template findSymbol(Name); }; - LDLResources.Partitioner = + LDResources.Partitioner = [](Function &F) { std::set Partition; Partition.insert(&F); @@ -152,7 +170,8 @@ private: // Create a logical module handle for SrcM within the logical dylib. auto LMH = LD.createLogicalModule(); - LD.getLogicalModuleResources(LMH).SourceModule = SrcM; + auto &LMResources = LD.getLogicalModuleResources(LMH); + LMResources.SourceModule = SrcM; // Create the GVs-and-stubs module. auto GVsAndStubsM = llvm::make_unique( @@ -171,6 +190,10 @@ private: if (F.isDeclaration()) continue; + // Record all functions defined by this module. + if (CloneStubsIntoPartitions) + LMResources.StubsToClone.insert(&F); + // For each definition: create a callback, a stub, and a function body // pointer. Initialize the function body pointer to point at the callback, // and set the callback to compile the function body. @@ -274,7 +297,8 @@ private: BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD, LogicalModuleHandle LMH, const std::set &Partition) { - Module &SrcM = *LD.getLogicalModuleResources(LMH).SourceModule; + auto &LMResources = LD.getLogicalModuleResources(LMH); + Module &SrcM = *LMResources.SourceModule; // Create the module. std::string NewName(SrcM.getName()); @@ -286,7 +310,7 @@ private: auto M = llvm::make_unique(NewName, SrcM.getContext()); M->setDataLayout(SrcM.getDataLayout()); ValueToValueMapTy VMap; - GlobalDeclMaterializer GDM(*M); + GlobalDeclMaterializer GDM(*M, &LMResources.StubsToClone); // Create decls in the new module. for (auto *F : Partition) @@ -294,7 +318,7 @@ private: // Move the function bodies. for (auto *F : Partition) - moveFunctionBody(*F, VMap); + moveFunctionBody(*F, VMap, &GDM); // Create memory manager and symbol resolver. auto MemMgr = llvm::make_unique(); @@ -320,6 +344,7 @@ private: BaseLayerT &BaseLayer; CompileCallbackMgrT &CompileCallbackMgr; LogicalDylibList LogicalDylibs; + bool CloneStubsIntoPartitions; }; } // End namespace orc. diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index 4ed8730..b439810e 100644 --- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -30,8 +30,6 @@ Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr) { GlobalVariable* createImplPointer(PointerType &PT, Module &M, const Twine &Name, Constant *Initializer) { - if (!Initializer) - Initializer = Constant::getNullValue(&PT); auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage, Initializer, Name, nullptr, GlobalValue::NotThreadLocal, 0, true); diff --git a/llvm/tools/lli/OrcLazyJIT.h b/llvm/tools/lli/OrcLazyJIT.h index 2919c08..2f7a019 100644 --- a/llvm/tools/lli/OrcLazyJIT.h +++ b/llvm/tools/lli/OrcLazyJIT.h @@ -55,7 +55,7 @@ public: CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)), IRDumpLayer(CompileLayer, createDebugDumper()), CCMgr(BuildCallbackMgr(IRDumpLayer, CCMgrMemMgr, Context)), - CODLayer(IRDumpLayer, *CCMgr), + CODLayer(IRDumpLayer, *CCMgr, false), CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {} ~OrcLazyJIT() { -- 2.7.4