[llvm] r275518 - [Kaleidoscope][BuildingAJIT] Start filling in text for chapter 3.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 14 18:39:49 PDT 2016


Author: lhames
Date: Thu Jul 14 20:39:49 2016
New Revision: 275518

URL: http://llvm.org/viewvc/llvm-project?rev=275518&view=rev
Log:
[Kaleidoscope][BuildingAJIT] Start filling in text for chapter 3.

Modified:
    llvm/trunk/docs/tutorial/BuildingAJIT3.rst
    llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
    llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
    llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h

Modified: llvm/trunk/docs/tutorial/BuildingAJIT3.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/BuildingAJIT3.rst?rev=275518&r1=275517&r2=275518&view=diff
==============================================================================
--- llvm/trunk/docs/tutorial/BuildingAJIT3.rst (original)
+++ llvm/trunk/docs/tutorial/BuildingAJIT3.rst Thu Jul 14 20:39:49 2016
@@ -16,15 +16,136 @@ Welcome to Chapter 3 of the "Building an
 chapter discusses lazy JITing and shows you how to enable it by adding an ORC
 CompileOnDemand layer the JIT from `Chapter 2 <BuildingAJIT2.html>`_.
 
-**To be done:**
+Lazy Compilation
+================
+
+When we add a module to the KaleidoscopeJIT class described in Chapter 2 it is
+immediately optimized, compiled and linked for us by the IRTransformLayer,
+IRCompileLayer and ObjectLinkingLayer respectively. This scheme, where all the
+work to make a Module executable is done up front, is relatively simple to
+understand its performance characteristics are easy to reason about. However,
+it will lead to very high startup times if the amount of code to be compiled is
+large, and may also do a lot of unnecessary compilation if only a few compiled
+functions are ever called at runtime. A truly "just-in-time" compiler should
+allow us to defer the compilation of any given function until the moment that
+function is first called, improving launch times and eliminating redundant work.
+In fact, the ORC APIs provide us with a layer to lazily compile LLVM IR:
+*CompileOnDemandLayer*.
+
+The CompileOnDemandLayer conforms to the layer interface described in Chapter 2,
+but the addModuleSet method behaves quite differently from the layers we have
+seen so far: rather than doing any work up front, it just constructs a *stub*
+for each function in the module and arranges for the stub to trigger compilation
+of the actual function the first time it is called. Because stub functions are
+very cheap to produce CompileOnDemand's addModuleSet method runs very quickly,
+reducing the time required to launch the first function to be executed, and
+saving us from doing any redundant compilation. By conforming to the layer
+interface, CompileOnDemand can be easily added on top of our existing JIT class.
+We just need a few changes:
+
+.. code-block:: c++
+
+  ...
+  #include "llvm/ExecutionEngine/SectionMemoryManager.h"
+  #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+  #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+  ...
+
+  ...
+  class KaleidoscopeJIT {
+  private:
+    std::unique_ptr<TargetMachine> TM;
+    const DataLayout DL;
+    std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager;
+    ObjectLinkingLayer<> ObjectLayer;
+    IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
+
+    typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
+      OptimizeFunction;
+
+    IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
+    CompileOnDemandLayer<decltype(OptimizeLayer)> CODLayer;
+
+  public:
+    typedef decltype(CODLayer)::ModuleSetHandleT ModuleHandle;
 
-**(1) Describe lazy function-at-a-time JITing and how it differs from the kind
-of eager module-at-a-time JITing that we've been doing so far.**
+First we need to include the CompileOnDemandLayer.h header, then add two new
+members: a std::unique_ptr<CompileCallbackManager> and a CompileOnDemandLayer,
+to our class. The CompileCallbackManager is a utility that enables us to
+create re-entry points into the compiler for functions that we want to lazily
+compile. In the next chapter we'll be looking at this class in detail, but for
+now we'll be treating it as an opaque utility: We just need to pass a reference
+to it into our new CompileOnDemandLayer, and the layer will do all the work of
+setting up the callbacks using the callback manager we gave it.
 
-**(2) Discuss CompileCallbackManagers and IndirectStubManagers.**
 
-**(3) Describe CompileOnDemandLayer (automates these components and builds stubs
-and lazy compilation callbacks for IR) and how to add it to the JIT.**
+  KaleidoscopeJIT()
+      : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
+        CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
+        OptimizeLayer(CompileLayer,
+                      [this](std::unique_ptr<Module> M) {
+                        return optimizeModule(std::move(M));
+                      }),
+        CompileCallbackManager(
+            orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)),
+        CODLayer(OptimizeLayer,
+                 [this](Function &F) { return std::set<Function*>({&F}); },
+                 *CompileCallbackManager,
+                 orc::createLocalIndirectStubsManagerBuilder(
+                   TM->getTargetTriple())) {
+    llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
+  }
+
+Next we have to update our constructor to initialize the new members. To create
+an appropriate compile callback manager we use the
+createLocalCompileCallbackManager function, which takes a TargetMachine and a
+TargetAddress to call if it receives a request to compile an unknown function.
+In our simple JIT this situation is unlikely to come up, so we'll cheat and
+just pass '0' here. In a production quality JIT you could give the address of a
+function that throws an exception in order to unwind the JIT'd code stack.
+
+Now we can construct our CompileOnDemandLayer. Following the pattern from
+previous layers we start by passing a reference to the next layer down in our
+stack -- the OptimizeLayer. Next we need to supply a 'partitioning function':
+when a not-yet-compiled function is called, the CompileOnDemandLayer will call
+this function to ask us what we would like to compile. At a minimum we need to
+compile the function being called (given by the argument to the partitioning
+function), but we could also request that the CompileOnDemandLayer compile other
+functions that are unconditionally called (or highly likely to be called) from
+the function being called. For KaleidoscopeJIT we'll keep it simple and just
+request compilation of the function that was called. Next we pass a reference to
+our CompileCallbackManager. Finally, we need to supply an "indirect stubs
+manager builder". This is a function that constructs IndirectStubManagers, which
+are in turn used to build the stubs for each module. The CompileOnDemandLayer
+will call the indirect stub manager builder once for each call to addModuleSet,
+and use the resulting indirect stubs manager to create stubs for all functions
+in all modules added. If/when the module set is removed from the JIT the
+indirect stubs manager will be deleted, freeing any memory allocated to the
+stubs. We supply this function by using the
+createLocalIndirectStubsManagerBuilder utility.
+
+  // ...
+          if (auto Sym = CODLayer.findSymbol(Name, false))
+  // ...
+  return CODLayer.addModuleSet(std::move(Ms),
+                               make_unique<SectionMemoryManager>(),
+                               std::move(Resolver));
+  // ...
+
+  // ...
+  return CODLayer.findSymbol(MangledNameStream.str(), true);
+  // ...
+
+  // ...
+  CODLayer.removeModuleSet(H);
+  // ...
+
+Finally, we need to replace the references to OptimizeLayer in our addModule,
+findSymbol, and removeModule methods. With that, we're up and running.
+
+**To be done:**
+
+** Discuss CompileCallbackManagers and IndirectStubManagers in more detail.**
 
 Full Code Listing
 =================

Modified: llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h?rev=275518&r1=275517&r2=275518&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h (original)
+++ llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h Thu Jul 14 20:39:49 2016
@@ -42,7 +42,6 @@ class KaleidoscopeJIT {
 private:
   std::unique_ptr<TargetMachine> TM;
   const DataLayout DL;
-  std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager;
   ObjectLinkingLayer<> ObjectLayer;
   IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
 
@@ -50,6 +49,8 @@ private:
     OptimizeFunction;
 
   IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
+
+  std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager;
   CompileOnDemandLayer<decltype(OptimizeLayer)> CODLayer;
 
 public:
@@ -57,13 +58,13 @@ public:
 
   KaleidoscopeJIT()
       : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
-        CompileCallbackManager(
-            orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)),
         CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
         OptimizeLayer(CompileLayer,
                       [this](std::unique_ptr<Module> M) {
                         return optimizeModule(std::move(M));
                       }),
+        CompileCallbackManager(
+            orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)),
         CODLayer(OptimizeLayer,
                  [this](Function &F) { return std::set<Function*>({&F}); },
                  *CompileCallbackManager,

Modified: llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h?rev=275518&r1=275517&r2=275518&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h (original)
+++ llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h Thu Jul 14 20:39:49 2016
@@ -66,8 +66,6 @@ class KaleidoscopeJIT {
 private:
   std::unique_ptr<TargetMachine> TM;
   const DataLayout DL;
-  std::unique_ptr<JITCompileCallbackManager> CompileCallbackMgr;
-  std::unique_ptr<IndirectStubsManager> IndirectStubsMgr;
   ObjectLinkingLayer<> ObjectLayer;
   IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
 
@@ -76,19 +74,22 @@ private:
 
   IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
 
+  std::unique_ptr<JITCompileCallbackManager> CompileCallbackMgr;
+  std::unique_ptr<IndirectStubsManager> IndirectStubsMgr;
+
 public:
   typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle;
 
   KaleidoscopeJIT()
       : TM(EngineBuilder().selectTarget()),
         DL(TM->createDataLayout()),
-        CompileCallbackMgr(
-            orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)),
         CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
         OptimizeLayer(CompileLayer,
                       [this](std::unique_ptr<Module> M) {
                         return optimizeModule(std::move(M));
-                      }) {
+                      }),
+        CompileCallbackMgr(
+            orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)) {
     auto IndirectStubsMgrBuilder =
       orc::createLocalIndirectStubsManagerBuilder(TM->getTargetTriple());
     IndirectStubsMgr = IndirectStubsMgrBuilder();

Modified: llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h?rev=275518&r1=275517&r2=275518&view=diff
==============================================================================
--- llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h (original)
+++ llvm/trunk/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h Thu Jul 14 20:39:49 2016
@@ -69,11 +69,8 @@ typedef remote::OrcRemoteTargetClient<FD
 
 class KaleidoscopeJIT {
 private:
-  MyRemote &Remote;
   std::unique_ptr<TargetMachine> TM;
   const DataLayout DL;
-  JITCompileCallbackManager *CompileCallbackMgr;
-  std::unique_ptr<IndirectStubsManager> IndirectStubsMgr;
   ObjectLinkingLayer<> ObjectLayer;
   IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
 
@@ -82,18 +79,22 @@ private:
 
   IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
 
+  JITCompileCallbackManager *CompileCallbackMgr;
+  std::unique_ptr<IndirectStubsManager> IndirectStubsMgr;
+  MyRemote &Remote;
+
 public:
   typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle;
 
   KaleidoscopeJIT(MyRemote &Remote)
-      : Remote(Remote),
-        TM(EngineBuilder().selectTarget()),
+      : TM(EngineBuilder().selectTarget()),
         DL(TM->createDataLayout()),
         CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
         OptimizeLayer(CompileLayer,
                       [this](std::unique_ptr<Module> M) {
                         return optimizeModule(std::move(M));
-                      }) {
+                      }),
+        Remote(Remote) {
     auto CCMgrOrErr = Remote.enableCompileCallbacks(0);
     if (!CCMgrOrErr) {
       logAllUnhandledErrors(CCMgrOrErr.takeError(), errs(),




More information about the llvm-commits mailing list