[llvm] r336385 - [ORC] In CompileOnDemandLayer2, clone modules on to different contexts by

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 5 19:13:03 PDT 2018


No problem!

On Thu, Jul 5, 2018 at 7:02 PM Lang Hames <lhames at gmail.com> wrote:

> Looks like Heejin Ahn fixed this in r336389. Thanks Heejin!
>
> -- Lang.
>
> On Thu, Jul 5, 2018 at 6:57 PM Lang Hames <lhames at gmail.com> wrote:
>
>> It did. Sorry! Looking in to it now. I think it's just missing a
>> dependency.
>>
>> -- Lang.
>>
>> On Thu, Jul 5, 2018 at 2:07 PM Sean Fertile <sfertile at ca.ibm.com> wrote:
>>
>>> Hi Lang,
>>>
>>> I think this commit broke
>>> http://lab.llvm.org:8011/builders/clang-ppc64le-linux-multistage
>>>
>>> Thanks
>>> Sean
>>>
>>>
>>>
>>> ----- Original message -----
>>> From: Lang Hames via llvm-commits <llvm-commits at lists.llvm.org>
>>> Sent by: "llvm-commits" <llvm-commits-bounces at lists.llvm.org>
>>> To: llvm-commits at lists.llvm.org
>>> Cc:
>>> Subject: [llvm] r336385 - [ORC] In CompileOnDemandLayer2, clone modules
>>> on to different contexts by
>>> Date: Thu, Jul 5, 2018 3:06 PM
>>>
>>> Author: lhames
>>> Date: Thu Jul  5 12:01:27 2018
>>> New Revision: 336385
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=336385&view=rev
>>> Log:
>>> [ORC] In CompileOnDemandLayer2, clone modules on to different contexts by
>>> writing them to a buffer and re-loading them.
>>>
>>> Also introduces a multithreaded variant of SimpleCompiler
>>> (MultiThreadedSimpleCompiler) for compiling IR concurrently on multiple
>>> threads.
>>>
>>> These changes are required to JIT IR on multiple threads correctly.
>>>
>>> No test case yet. I will be looking at how to modify LLI / LLJIT to test
>>> multithreaded JIT support soon.
>>>
>>> Modified:
>>>     llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
>>>     llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileUtils.h
>>>     llvm/trunk/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
>>>
>>> Modified:
>>> llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h?rev=336385&r1=336384&r2=336385&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
>>> (original)
>>> +++ llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
>>> Thu Jul  5 12:01:27 2018
>>> @@ -93,15 +93,8 @@ private:
>>>    using StubManagersMap =
>>>        std::map<const VSO *, std::unique_ptr<IndirectStubsManager>>;
>>>
>>> -  using SymbolNameToDefinitionMap =
>>> -      IRMaterializationUnit::SymbolNameToDefinitionMap;
>>> -
>>>    IndirectStubsManager &getStubsManager(const VSO &V);
>>>
>>> -  std::unique_ptr<Module>
>>> -  extractFunctions(Module &M, const SymbolNameSet &SymbolNames,
>>> -                   const SymbolNameToDefinitionMap &SymbolToDefiniton);
>>> -
>>>    void emitExtractedFunctionsModule(MaterializationResponsibility R,
>>>                                      std::unique_ptr<Module> M,
>>>                                      std::shared_ptr<SymbolResolver>
>>> Resolver);
>>>
>>> Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileUtils.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileUtils.h?rev=336385&r1=336384&r2=336385&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileUtils.h (original)
>>> +++ llvm/trunk/include/llvm/ExecutionEngine/Orc/CompileUtils.h Thu Jul
>>>  5 12:01:27 2018
>>> @@ -16,6 +16,7 @@
>>>
>>>  #include "llvm/ADT/SmallVector.h"
>>>  #include "llvm/ExecutionEngine/ObjectCache.h"
>>> +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
>>>  #include "llvm/IR/LegacyPassManager.h"
>>>  #include "llvm/Object/Binary.h"
>>>  #include "llvm/Object/ObjectFile.h"
>>> @@ -35,24 +36,10 @@ class Module;
>>>
>>>  namespace orc {
>>>
>>> -/// Simple compile functor: Takes a single IR module and returns an
>>> -///        ObjectFile.
>>> +/// Simple compile functor: Takes a single IR module and returns an
>>> ObjectFile.
>>> +/// This compiler supports a single compilation thread and LLVMContext
>>> only.
>>> +/// For multithreaded compilation, use MultiThreadedSimpleCompiler
>>> below.
>>>  class SimpleCompiler {
>>> -private:
>>> -  class SmallVectorMemoryBuffer : public MemoryBuffer {
>>> -  public:
>>> -    SmallVectorMemoryBuffer(SmallVector<char, 0> Buffer)
>>> -        : Buffer(std::move(Buffer)) {
>>> -      init(this->Buffer.data(), this->Buffer.data() +
>>> this->Buffer.size(),
>>> -           false);
>>> -    }
>>> -
>>> -    BufferKind getBufferKind() const override { return
>>> MemoryBuffer_Malloc; }
>>> -
>>> -  private:
>>> -    SmallVector<char, 0> Buffer;
>>> -  };
>>> -
>>>  public:
>>>    using CompileResult = std::unique_ptr<MemoryBuffer>;
>>>
>>> @@ -114,6 +101,29 @@ private:
>>>    ObjectCache *ObjCache = nullptr;
>>>  };
>>>
>>> +/// A thread-safe version of SimpleCompiler.
>>> +///
>>> +/// This class creates a new TargetMachine and SimpleCompiler instance
>>> for each
>>> +/// compile.
>>> +class MultiThreadedSimpleCompiler {
>>> +public:
>>> +  MultiThreadedSimpleCompiler(JITTargetMachineBuilder JTMB,
>>> +                              ObjectCache *ObjCache = nullptr)
>>> +      : JTMB(std::move(JTMB)), ObjCache(ObjCache) {}
>>> +
>>> +  void setObjectCache(ObjectCache *ObjCache) { this->ObjCache =
>>> ObjCache; }
>>> +
>>> +  std::unique_ptr<MemoryBuffer> operator()(Module &M) {
>>> +    auto TM = cantFail(JTMB.createTargetMachine());
>>> +    SimpleCompiler C(*TM, ObjCache);
>>> +    return C(M);
>>> +  }
>>> +
>>> +private:
>>> +  JITTargetMachineBuilder JTMB;
>>> +  ObjectCache *ObjCache = nullptr;
>>> +};
>>> +
>>>  } // end namespace orc
>>>
>>>  } // end namespace llvm
>>>
>>> Modified: llvm/trunk/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp?rev=336385&r1=336384&r2=336385&view=diff
>>>
>>> ==============================================================================
>>> --- llvm/trunk/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp
>>> (original)
>>> +++ llvm/trunk/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp Thu Jul
>>>  5 12:01:27 2018
>>> @@ -8,9 +8,12 @@
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>>  #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
>>> +#include "llvm/Bitcode/BitcodeReader.h"
>>> +#include "llvm/Bitcode/BitcodeWriter.h"
>>>  #include "llvm/IR/Mangler.h"
>>>  #include "llvm/IR/Module.h"
>>>  #include "llvm/Support/raw_ostream.h"
>>> +#include "llvm/Transforms/Utils/Cloning.h"
>>>
>>>  using namespace llvm;
>>>  using namespace llvm::orc;
>>> @@ -68,36 +71,58 @@ static void extractAliases(Materializati
>>>    R.delegate(symbolAliases(std::move(Aliases)));
>>>  }
>>>
>>> -static std::unique_ptr<Module> extractGlobals(Module &M) {
>>> -  // FIXME: Add alias support.
>>> +static std::unique_ptr<Module>
>>> +extractAndClone(Module &M, LLVMContext &NewContext, StringRef Suffix,
>>> +                function_ref<bool(const GlobalValue *)>
>>> ShouldCloneDefinition) {
>>> +  SmallVector<char, 1> ClonedModuleBuffer;
>>>
>>> -  auto GlobalsModule = llvm::make_unique<Module>(
>>> -      (M.getName() + ".globals").str(), M.getContext());
>>> -  GlobalsModule->setDataLayout(M.getDataLayout());
>>> -
>>> -  ValueToValueMapTy VMap;
>>> -
>>> -  for (auto &GV : M.globals())
>>> -    if (!GV.isDeclaration() && !VMap.count(&GV))
>>> -      cloneGlobalVariableDecl(*GlobalsModule, GV, &VMap);
>>> -
>>> -  // Clone the module flags.
>>> -  cloneModuleFlagsMetadata(*GlobalsModule, M, VMap);
>>> -
>>> -  auto Materializer = createLambdaValueMaterializer([&](Value *V) ->
>>> Value * {
>>> -    if (auto *F = dyn_cast<Function>(V))
>>> -      return cloneFunctionDecl(*GlobalsModule, *F);
>>> -    return nullptr;
>>> -  });
>>> +  {
>>> +    std::set<GlobalValue *> ClonedDefsInSrc;
>>> +    ValueToValueMapTy VMap;
>>> +    auto Tmp = CloneModule(M, VMap, [&](const GlobalValue *GV) {
>>> +      if (ShouldCloneDefinition(GV)) {
>>> +        ClonedDefsInSrc.insert(const_cast<GlobalValue *>(GV));
>>> +        return true;
>>> +      }
>>> +      return false;
>>> +    });
>>> +
>>> +    for (auto *GV : ClonedDefsInSrc) {
>>> +      // Delete the definition and bump the linkage in the source
>>> module.
>>> +      if (isa<Function>(GV)) {
>>> +        auto &F = *cast<Function>(GV);
>>> +        F.deleteBody();
>>> +        F.setPersonalityFn(nullptr);
>>> +      } else if (isa<GlobalVariable>(GV)) {
>>> +        cast<GlobalVariable>(GV)->setInitializer(nullptr);
>>> +      } else
>>> +        llvm_unreachable("Unsupported global type");
>>> +
>>> +      GV->setLinkage(GlobalValue::ExternalLinkage);
>>> +    }
>>> +
>>> +    BitcodeWriter BCWriter(ClonedModuleBuffer);
>>>
>>> -  // Move the global variable initializers.
>>> -  for (auto &GV : M.globals()) {
>>> -    if (!GV.isDeclaration())
>>> -      moveGlobalVariableInitializer(GV, VMap, &Materializer);
>>> -    GV.setInitializer(nullptr);
>>> +    BCWriter.writeModule(*Tmp);
>>> +    BCWriter.writeSymtab();
>>> +    BCWriter.writeStrtab();
>>>    }
>>>
>>> -  return GlobalsModule;
>>> +  MemoryBufferRef ClonedModuleBufferRef(
>>> +      StringRef(ClonedModuleBuffer.data(), ClonedModuleBuffer.size()),
>>> +      "cloned module buffer");
>>> +
>>> +  auto ClonedModule =
>>> +      cantFail(parseBitcodeFile(ClonedModuleBufferRef, NewContext));
>>> +  ClonedModule->setModuleIdentifier((M.getName() + Suffix).str());
>>> +  return ClonedModule;
>>> +}
>>> +
>>> +static std::unique_ptr<Module> extractGlobals(Module &M,
>>> +                                              LLVMContext &NewContext) {
>>> +  return extractAndClone(M, NewContext, ".globals", [](const
>>> GlobalValue *GV) {
>>> +    return isa<GlobalVariable>(GV);
>>> +  });
>>>  }
>>>
>>>  namespace llvm {
>>> @@ -132,12 +157,29 @@ private:
>>>      //        original function definitions in the target VSO. All other
>>>      //        symbols should be looked up in the backing resolver.
>>>
>>> -    // Find the functions that have been requested.
>>>      auto RequestedSymbols = R.getRequestedSymbols();
>>>
>>> -    // Extract them into a new module.
>>> -    auto ExtractedFunctionsModule =
>>> -        Parent.extractFunctions(*M, RequestedSymbols,
>>> SymbolToDefinition);
>>> +    // Extract the requested functions into a new module.
>>> +    std::unique_ptr<Module> ExtractedFunctionsModule;
>>> +    if (!RequestedSymbols.empty()) {
>>> +      std::string Suffix;
>>> +      std::set<const GlobalValue *> FunctionsToClone;
>>> +      for (auto &Name : RequestedSymbols) {
>>> +        auto I = SymbolToDefinition.find(Name);
>>> +        assert(I != SymbolToDefinition.end() && I->second != nullptr &&
>>> +               "Should have a non-null definition");
>>> +        FunctionsToClone.insert(I->second);
>>> +        Suffix += ".";
>>> +        Suffix += *Name;
>>> +      }
>>> +
>>> +      std::lock_guard<std::mutex> Lock(SourceModuleMutex);
>>> +      ExtractedFunctionsModule =
>>> +          extractAndClone(*M, Parent.GetAvailableContext(), Suffix,
>>> +                          [&](const GlobalValue *GV) -> bool {
>>> +                            return FunctionsToClone.count(GV);
>>> +                          });
>>> +    }
>>>
>>>      // Build a new ExtractingIRMaterializationUnit to delegate the
>>> unrequested
>>>      // symbols to.
>>> @@ -162,8 +204,9 @@ private:
>>>            std::move(DelegatedSymbolToDefinition), Parent,
>>> BackingResolver));
>>>      }
>>>
>>> -    Parent.emitExtractedFunctionsModule(
>>> -        std::move(R), std::move(ExtractedFunctionsModule),
>>> BackingResolver);
>>> +    if (ExtractedFunctionsModule)
>>> +      Parent.emitExtractedFunctionsModule(
>>> +          std::move(R), std::move(ExtractedFunctionsModule),
>>> BackingResolver);
>>>    }
>>>
>>>    void discard(const VSO &V, SymbolStringPtr Name) override {
>>> @@ -173,6 +216,7 @@ private:
>>>                       "ExtractingIRMaterializationUnit");
>>>    }
>>>
>>> +  mutable std::mutex SourceModuleMutex;
>>>    CompileOnDemandLayer2 &Parent;
>>>    std::shared_ptr<SymbolResolver> BackingResolver;
>>>  };
>>> @@ -207,7 +251,7 @@ void CompileOnDemandLayer2::emit(Materia
>>>
>>>    extractAliases(R, *M, Mangle);
>>>
>>> -  auto GlobalsModule = extractGlobals(*M);
>>> +  auto GlobalsModule = extractGlobals(*M, GetAvailableContext());
>>>
>>>    // Delete the bodies of any available externally functions, rename the
>>>    // rest, and build the compile callbacks.
>>> @@ -221,6 +265,7 @@ void CompileOnDemandLayer2::emit(Materia
>>>
>>>      if (F.hasAvailableExternallyLinkage()) {
>>>        F.deleteBody();
>>> +      F.setPersonalityFn(nullptr);
>>>        continue;
>>>      }
>>>
>>> @@ -229,7 +274,10 @@ void CompileOnDemandLayer2::emit(Materia
>>>      F.setName(F.getName() + "$body");
>>>      auto StubDecl = cloneFunctionDecl(*M, F);
>>>      StubDecl->setName(StubUnmangledName);
>>> +    StubDecl->setPersonalityFn(nullptr);
>>> +    StubDecl->setLinkage(GlobalValue::ExternalLinkage);
>>>      F.replaceAllUsesWith(StubDecl);
>>> +
>>>      auto StubName = Mangle(StubUnmangledName);
>>>      auto BodyName = Mangle(F.getName());
>>>      if (auto CallbackAddr = CCMgr.getCompileCallback(
>>> @@ -302,52 +350,6 @@ IndirectStubsManager &CompileOnDemandLay
>>>    return *I->second;
>>>  }
>>>
>>> -std::unique_ptr<Module> CompileOnDemandLayer2::extractFunctions(
>>> -    Module &M, const SymbolNameSet &SymbolNames,
>>> -    const SymbolNameToDefinitionMap &SymbolToDefinition) {
>>> -  assert(!SymbolNames.empty() && "Can not extract an empty function
>>> set");
>>> -
>>> -  std::string ExtractedModName;
>>> -  {
>>> -    raw_string_ostream ExtractedModNameStream(ExtractedModName);
>>> -    ExtractedModNameStream << M.getName();
>>> -    for (auto &Name : SymbolNames)
>>> -      ExtractedModNameStream << "." << *Name;
>>> -  }
>>> -
>>> -  auto ExtractedFunctionsModule =
>>> -      llvm::make_unique<Module>(ExtractedModName,
>>> GetAvailableContext());
>>> -  ExtractedFunctionsModule->setDataLayout(M.getDataLayout());
>>> -
>>> -  ValueToValueMapTy VMap;
>>> -
>>> -  auto Materializer = createLambdaValueMaterializer([&](Value *V) ->
>>> Value * {
>>> -    GlobalValue *NewGV = nullptr;
>>> -    if (auto *F = dyn_cast<Function>(V))
>>> -      NewGV = cloneFunctionDecl(*ExtractedFunctionsModule, *F);
>>> -    else if (auto *GV = dyn_cast<GlobalVariable>(V))
>>> -      NewGV = cloneGlobalVariableDecl(*ExtractedFunctionsModule, *GV);
>>> -
>>> -    if (NewGV)
>>> -      NewGV->setLinkage(GlobalValue::ExternalLinkage);
>>> -    return NewGV;
>>> -  });
>>> -
>>> -  std::vector<std::pair<Function *, Function *>> OrigToNew;
>>> -  for (auto &FunctionName : SymbolNames) {
>>> -    assert(SymbolToDefinition.count(FunctionName) &&
>>> -           "No definition for symbol");
>>> -    auto *OrigF =
>>> cast<Function>(SymbolToDefinition.find(FunctionName)->second);
>>> -    auto *NewF = cloneFunctionDecl(*ExtractedFunctionsModule, *OrigF,
>>> &VMap);
>>> -    OrigToNew.push_back(std::make_pair(OrigF, NewF));
>>> -  }
>>> -
>>> -  for (auto &KV : OrigToNew)
>>> -    moveFunctionBody(*KV.first, VMap, &Materializer, KV.second);
>>> -
>>> -  return ExtractedFunctionsModule;
>>> -}
>>> -
>>>  void CompileOnDemandLayer2::emitExtractedFunctionsModule(
>>>      MaterializationResponsibility R, std::unique_ptr<Module> M,
>>>      std::shared_ptr<SymbolResolver> Resolver) {
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>>
>>>
>>>
>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180705/6ef4c1cd/attachment-0001.html>


More information about the llvm-commits mailing list