1*9880d681SAndroid Build Coastguard Worker===================================================================== 2*9880d681SAndroid Build Coastguard WorkerBuilding a JIT: Adding Optimizations -- An introduction to ORC Layers 3*9880d681SAndroid Build Coastguard Worker===================================================================== 4*9880d681SAndroid Build Coastguard Worker 5*9880d681SAndroid Build Coastguard Worker.. contents:: 6*9880d681SAndroid Build Coastguard Worker :local: 7*9880d681SAndroid Build Coastguard Worker 8*9880d681SAndroid Build Coastguard Worker**This tutorial is under active development. It is incomplete and details may 9*9880d681SAndroid Build Coastguard Workerchange frequently.** Nonetheless we invite you to try it out as it stands, and 10*9880d681SAndroid Build Coastguard Workerwe welcome any feedback. 11*9880d681SAndroid Build Coastguard Worker 12*9880d681SAndroid Build Coastguard WorkerChapter 2 Introduction 13*9880d681SAndroid Build Coastguard Worker====================== 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard WorkerWelcome to Chapter 2 of the "Building an ORC-based JIT in LLVM" tutorial. In 16*9880d681SAndroid Build Coastguard Worker`Chapter 1 <BuildingAJIT1.html>`_ of this series we examined a basic JIT 17*9880d681SAndroid Build Coastguard Workerclass, KaleidoscopeJIT, that could take LLVM IR modules as input and produce 18*9880d681SAndroid Build Coastguard Workerexecutable code in memory. KaleidoscopeJIT was able to do this with relatively 19*9880d681SAndroid Build Coastguard Workerlittle code by composing two off-the-shelf *ORC layers*: IRCompileLayer and 20*9880d681SAndroid Build Coastguard WorkerObjectLinkingLayer, to do much of the heavy lifting. 21*9880d681SAndroid Build Coastguard Worker 22*9880d681SAndroid Build Coastguard WorkerIn this layer we'll learn more about the ORC layer concept by using a new layer, 23*9880d681SAndroid Build Coastguard WorkerIRTransformLayer, to add IR optimization support to KaleidoscopeJIT. 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard WorkerOptimizing Modules using the IRTransformLayer 26*9880d681SAndroid Build Coastguard Worker============================================= 27*9880d681SAndroid Build Coastguard Worker 28*9880d681SAndroid Build Coastguard WorkerIn `Chapter 4 <LangImpl4.html>`_ of the "Implementing a language with LLVM" 29*9880d681SAndroid Build Coastguard Workertutorial series the llvm *FunctionPassManager* is introduced as a means for 30*9880d681SAndroid Build Coastguard Workeroptimizing LLVM IR. Interested readers may read that chapter for details, but 31*9880d681SAndroid Build Coastguard Workerin short: to optimize a Module we create an llvm::FunctionPassManager 32*9880d681SAndroid Build Coastguard Workerinstance, configure it with a set of optimizations, then run the PassManager on 33*9880d681SAndroid Build Coastguard Workera Module to mutate it into a (hopefully) more optimized but semantically 34*9880d681SAndroid Build Coastguard Workerequivalent form. In the original tutorial series the FunctionPassManager was 35*9880d681SAndroid Build Coastguard Workercreated outside the KaleidoscopeJIT and modules were optimized before being 36*9880d681SAndroid Build Coastguard Workeradded to it. In this Chapter we will make optimization a phase of our JIT 37*9880d681SAndroid Build Coastguard Workerinstead. For now this will provide us a motivation to learn more about ORC 38*9880d681SAndroid Build Coastguard Workerlayers, but in the long term making optimization part of our JIT will yield an 39*9880d681SAndroid Build Coastguard Workerimportant benefit: When we begin lazily compiling code (i.e. deferring 40*9880d681SAndroid Build Coastguard Workercompilation of each function until the first time it's run), having 41*9880d681SAndroid Build Coastguard Workeroptimization managed by our JIT will allow us to optimize lazily too, rather 42*9880d681SAndroid Build Coastguard Workerthan having to do all our optimization up-front. 43*9880d681SAndroid Build Coastguard Worker 44*9880d681SAndroid Build Coastguard WorkerTo add optimization support to our JIT we will take the KaleidoscopeJIT from 45*9880d681SAndroid Build Coastguard WorkerChapter 1 and compose an ORC *IRTransformLayer* on top. We will look at how the 46*9880d681SAndroid Build Coastguard WorkerIRTransformLayer works in more detail below, but the interface is simple: the 47*9880d681SAndroid Build Coastguard Workerconstructor for this layer takes a reference to the layer below (as all layers 48*9880d681SAndroid Build Coastguard Workerdo) plus an *IR optimization function* that it will apply to each Module that 49*9880d681SAndroid Build Coastguard Workeris added via addModuleSet: 50*9880d681SAndroid Build Coastguard Worker 51*9880d681SAndroid Build Coastguard Worker.. code-block:: c++ 52*9880d681SAndroid Build Coastguard Worker 53*9880d681SAndroid Build Coastguard Worker class KaleidoscopeJIT { 54*9880d681SAndroid Build Coastguard Worker private: 55*9880d681SAndroid Build Coastguard Worker std::unique_ptr<TargetMachine> TM; 56*9880d681SAndroid Build Coastguard Worker const DataLayout DL; 57*9880d681SAndroid Build Coastguard Worker ObjectLinkingLayer<> ObjectLayer; 58*9880d681SAndroid Build Coastguard Worker IRCompileLayer<decltype(ObjectLayer)> CompileLayer; 59*9880d681SAndroid Build Coastguard Worker 60*9880d681SAndroid Build Coastguard Worker typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)> 61*9880d681SAndroid Build Coastguard Worker OptimizeFunction; 62*9880d681SAndroid Build Coastguard Worker 63*9880d681SAndroid Build Coastguard Worker IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer; 64*9880d681SAndroid Build Coastguard Worker 65*9880d681SAndroid Build Coastguard Worker public: 66*9880d681SAndroid Build Coastguard Worker typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle; 67*9880d681SAndroid Build Coastguard Worker 68*9880d681SAndroid Build Coastguard Worker KaleidoscopeJIT() 69*9880d681SAndroid Build Coastguard Worker : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), 70*9880d681SAndroid Build Coastguard Worker CompileLayer(ObjectLayer, SimpleCompiler(*TM)), 71*9880d681SAndroid Build Coastguard Worker OptimizeLayer(CompileLayer, 72*9880d681SAndroid Build Coastguard Worker [this](std::unique_ptr<Module> M) { 73*9880d681SAndroid Build Coastguard Worker return optimizeModule(std::move(M)); 74*9880d681SAndroid Build Coastguard Worker }) { 75*9880d681SAndroid Build Coastguard Worker llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); 76*9880d681SAndroid Build Coastguard Worker } 77*9880d681SAndroid Build Coastguard Worker 78*9880d681SAndroid Build Coastguard WorkerOur extended KaleidoscopeJIT class starts out the same as it did in Chapter 1, 79*9880d681SAndroid Build Coastguard Workerbut after the CompileLayer we introduce a typedef for our optimization function. 80*9880d681SAndroid Build Coastguard WorkerIn this case we use a std::function (a handy wrapper for "function-like" things) 81*9880d681SAndroid Build Coastguard Workerfrom a single unique_ptr<Module> input to a std::unique_ptr<Module> output. With 82*9880d681SAndroid Build Coastguard Workerour optimization function typedef in place we can declare our OptimizeLayer, 83*9880d681SAndroid Build Coastguard Workerwhich sits on top of our CompileLayer. 84*9880d681SAndroid Build Coastguard Worker 85*9880d681SAndroid Build Coastguard WorkerTo initialize our OptimizeLayer we pass it a reference to the CompileLayer 86*9880d681SAndroid Build Coastguard Workerbelow (standard practice for layers), and we initialize the OptimizeFunction 87*9880d681SAndroid Build Coastguard Workerusing a lambda that calls out to an "optimizeModule" function that we will 88*9880d681SAndroid Build Coastguard Workerdefine below. 89*9880d681SAndroid Build Coastguard Worker 90*9880d681SAndroid Build Coastguard Worker.. code-block:: c++ 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker // ... 93*9880d681SAndroid Build Coastguard Worker auto Resolver = createLambdaResolver( 94*9880d681SAndroid Build Coastguard Worker [&](const std::string &Name) { 95*9880d681SAndroid Build Coastguard Worker if (auto Sym = OptimizeLayer.findSymbol(Name, false)) 96*9880d681SAndroid Build Coastguard Worker return Sym.toRuntimeDyldSymbol(); 97*9880d681SAndroid Build Coastguard Worker return RuntimeDyld::SymbolInfo(nullptr); 98*9880d681SAndroid Build Coastguard Worker }, 99*9880d681SAndroid Build Coastguard Worker // ... 100*9880d681SAndroid Build Coastguard Worker 101*9880d681SAndroid Build Coastguard Worker.. code-block:: c++ 102*9880d681SAndroid Build Coastguard Worker 103*9880d681SAndroid Build Coastguard Worker // ... 104*9880d681SAndroid Build Coastguard Worker return OptimizeLayer.addModuleSet(std::move(Ms), 105*9880d681SAndroid Build Coastguard Worker make_unique<SectionMemoryManager>(), 106*9880d681SAndroid Build Coastguard Worker std::move(Resolver)); 107*9880d681SAndroid Build Coastguard Worker // ... 108*9880d681SAndroid Build Coastguard Worker 109*9880d681SAndroid Build Coastguard Worker.. code-block:: c++ 110*9880d681SAndroid Build Coastguard Worker 111*9880d681SAndroid Build Coastguard Worker // ... 112*9880d681SAndroid Build Coastguard Worker return OptimizeLayer.findSymbol(MangledNameStream.str(), true); 113*9880d681SAndroid Build Coastguard Worker // ... 114*9880d681SAndroid Build Coastguard Worker 115*9880d681SAndroid Build Coastguard Worker.. code-block:: c++ 116*9880d681SAndroid Build Coastguard Worker 117*9880d681SAndroid Build Coastguard Worker // ... 118*9880d681SAndroid Build Coastguard Worker OptimizeLayer.removeModuleSet(H); 119*9880d681SAndroid Build Coastguard Worker // ... 120*9880d681SAndroid Build Coastguard Worker 121*9880d681SAndroid Build Coastguard WorkerNext we need to replace references to 'CompileLayer' with references to 122*9880d681SAndroid Build Coastguard WorkerOptimizeLayer in our key methods: addModule, findSymbol, and removeModule. In 123*9880d681SAndroid Build Coastguard WorkeraddModule we need to be careful to replace both references: the findSymbol call 124*9880d681SAndroid Build Coastguard Workerinside our resolver, and the call through to addModuleSet. 125*9880d681SAndroid Build Coastguard Worker 126*9880d681SAndroid Build Coastguard Worker.. code-block:: c++ 127*9880d681SAndroid Build Coastguard Worker 128*9880d681SAndroid Build Coastguard Worker std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) { 129*9880d681SAndroid Build Coastguard Worker // Create a function pass manager. 130*9880d681SAndroid Build Coastguard Worker auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get()); 131*9880d681SAndroid Build Coastguard Worker 132*9880d681SAndroid Build Coastguard Worker // Add some optimizations. 133*9880d681SAndroid Build Coastguard Worker FPM->add(createInstructionCombiningPass()); 134*9880d681SAndroid Build Coastguard Worker FPM->add(createReassociatePass()); 135*9880d681SAndroid Build Coastguard Worker FPM->add(createGVNPass()); 136*9880d681SAndroid Build Coastguard Worker FPM->add(createCFGSimplificationPass()); 137*9880d681SAndroid Build Coastguard Worker FPM->doInitialization(); 138*9880d681SAndroid Build Coastguard Worker 139*9880d681SAndroid Build Coastguard Worker // Run the optimizations over all functions in the module being added to 140*9880d681SAndroid Build Coastguard Worker // the JIT. 141*9880d681SAndroid Build Coastguard Worker for (auto &F : *M) 142*9880d681SAndroid Build Coastguard Worker FPM->run(F); 143*9880d681SAndroid Build Coastguard Worker 144*9880d681SAndroid Build Coastguard Worker return M; 145*9880d681SAndroid Build Coastguard Worker } 146*9880d681SAndroid Build Coastguard Worker 147*9880d681SAndroid Build Coastguard WorkerAt the bottom of our JIT we add a private method to do the actual optimization: 148*9880d681SAndroid Build Coastguard Worker*optimizeModule*. This function sets up a FunctionPassManager, adds some passes 149*9880d681SAndroid Build Coastguard Workerto it, runs it over every function in the module, and then returns the mutated 150*9880d681SAndroid Build Coastguard Workermodule. The specific optimizations are the same ones used in 151*9880d681SAndroid Build Coastguard Worker`Chapter 4 <LangImpl4.html>`_ of the "Implementing a language with LLVM" 152*9880d681SAndroid Build Coastguard Workertutorial series. Readers may visit that chapter for a more in-depth 153*9880d681SAndroid Build Coastguard Workerdiscussion of these, and of IR optimization in general. 154*9880d681SAndroid Build Coastguard Worker 155*9880d681SAndroid Build Coastguard WorkerAnd that's it in terms of changes to KaleidoscopeJIT: When a module is added via 156*9880d681SAndroid Build Coastguard WorkeraddModule the OptimizeLayer will call our optimizeModule function before passing 157*9880d681SAndroid Build Coastguard Workerthe transformed module on to the CompileLayer below. Of course, we could have 158*9880d681SAndroid Build Coastguard Workercalled optimizeModule directly in our addModule function and not gone to the 159*9880d681SAndroid Build Coastguard Workerbother of using the IRTransformLayer, but doing so gives us another opportunity 160*9880d681SAndroid Build Coastguard Workerto see how layers compose. It also provides a neat entry point to the *layer* 161*9880d681SAndroid Build Coastguard Workerconcept itself, because IRTransformLayer turns out to be one of the simplest 162*9880d681SAndroid Build Coastguard Workerimplementations of the layer concept that can be devised: 163*9880d681SAndroid Build Coastguard Worker 164*9880d681SAndroid Build Coastguard Worker.. code-block:: c++ 165*9880d681SAndroid Build Coastguard Worker 166*9880d681SAndroid Build Coastguard Worker template <typename BaseLayerT, typename TransformFtor> 167*9880d681SAndroid Build Coastguard Worker class IRTransformLayer { 168*9880d681SAndroid Build Coastguard Worker public: 169*9880d681SAndroid Build Coastguard Worker typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT; 170*9880d681SAndroid Build Coastguard Worker 171*9880d681SAndroid Build Coastguard Worker IRTransformLayer(BaseLayerT &BaseLayer, 172*9880d681SAndroid Build Coastguard Worker TransformFtor Transform = TransformFtor()) 173*9880d681SAndroid Build Coastguard Worker : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} 174*9880d681SAndroid Build Coastguard Worker 175*9880d681SAndroid Build Coastguard Worker template <typename ModuleSetT, typename MemoryManagerPtrT, 176*9880d681SAndroid Build Coastguard Worker typename SymbolResolverPtrT> 177*9880d681SAndroid Build Coastguard Worker ModuleSetHandleT addModuleSet(ModuleSetT Ms, 178*9880d681SAndroid Build Coastguard Worker MemoryManagerPtrT MemMgr, 179*9880d681SAndroid Build Coastguard Worker SymbolResolverPtrT Resolver) { 180*9880d681SAndroid Build Coastguard Worker 181*9880d681SAndroid Build Coastguard Worker for (auto I = Ms.begin(), E = Ms.end(); I != E; ++I) 182*9880d681SAndroid Build Coastguard Worker *I = Transform(std::move(*I)); 183*9880d681SAndroid Build Coastguard Worker 184*9880d681SAndroid Build Coastguard Worker return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr), 185*9880d681SAndroid Build Coastguard Worker std::move(Resolver)); 186*9880d681SAndroid Build Coastguard Worker } 187*9880d681SAndroid Build Coastguard Worker 188*9880d681SAndroid Build Coastguard Worker void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); } 189*9880d681SAndroid Build Coastguard Worker 190*9880d681SAndroid Build Coastguard Worker JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { 191*9880d681SAndroid Build Coastguard Worker return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); 192*9880d681SAndroid Build Coastguard Worker } 193*9880d681SAndroid Build Coastguard Worker 194*9880d681SAndroid Build Coastguard Worker JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, 195*9880d681SAndroid Build Coastguard Worker bool ExportedSymbolsOnly) { 196*9880d681SAndroid Build Coastguard Worker return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); 197*9880d681SAndroid Build Coastguard Worker } 198*9880d681SAndroid Build Coastguard Worker 199*9880d681SAndroid Build Coastguard Worker void emitAndFinalize(ModuleSetHandleT H) { 200*9880d681SAndroid Build Coastguard Worker BaseLayer.emitAndFinalize(H); 201*9880d681SAndroid Build Coastguard Worker } 202*9880d681SAndroid Build Coastguard Worker 203*9880d681SAndroid Build Coastguard Worker TransformFtor& getTransform() { return Transform; } 204*9880d681SAndroid Build Coastguard Worker 205*9880d681SAndroid Build Coastguard Worker const TransformFtor& getTransform() const { return Transform; } 206*9880d681SAndroid Build Coastguard Worker 207*9880d681SAndroid Build Coastguard Worker private: 208*9880d681SAndroid Build Coastguard Worker BaseLayerT &BaseLayer; 209*9880d681SAndroid Build Coastguard Worker TransformFtor Transform; 210*9880d681SAndroid Build Coastguard Worker }; 211*9880d681SAndroid Build Coastguard Worker 212*9880d681SAndroid Build Coastguard WorkerThis is the whole definition of IRTransformLayer, from 213*9880d681SAndroid Build Coastguard Worker``llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h``, stripped of its 214*9880d681SAndroid Build Coastguard Workercomments. It is a template class with two template arguments: ``BaesLayerT`` and 215*9880d681SAndroid Build Coastguard Worker``TransformFtor`` that provide the type of the base layer and the type of the 216*9880d681SAndroid Build Coastguard Worker"transform functor" (in our case a std::function) respectively. This class is 217*9880d681SAndroid Build Coastguard Workerconcerned with two very simple jobs: (1) Running every IR Module that is added 218*9880d681SAndroid Build Coastguard Workerwith addModuleSet through the transform functor, and (2) conforming to the ORC 219*9880d681SAndroid Build Coastguard Workerlayer interface. The interface consists of one typedef and five methods: 220*9880d681SAndroid Build Coastguard Worker 221*9880d681SAndroid Build Coastguard Worker+------------------+-----------------------------------------------------------+ 222*9880d681SAndroid Build Coastguard Worker| Interface | Description | 223*9880d681SAndroid Build Coastguard Worker+==================+===========================================================+ 224*9880d681SAndroid Build Coastguard Worker| | Provides a handle that can be used to identify a module | 225*9880d681SAndroid Build Coastguard Worker| ModuleSetHandleT | set when calling findSymbolIn, removeModuleSet, or | 226*9880d681SAndroid Build Coastguard Worker| | emitAndFinalize. | 227*9880d681SAndroid Build Coastguard Worker+------------------+-----------------------------------------------------------+ 228*9880d681SAndroid Build Coastguard Worker| | Takes a given set of Modules and makes them "available | 229*9880d681SAndroid Build Coastguard Worker| | for execution. This means that symbols in those modules | 230*9880d681SAndroid Build Coastguard Worker| | should be searchable via findSymbol and findSymbolIn, and | 231*9880d681SAndroid Build Coastguard Worker| | the address of the symbols should be read/writable (for | 232*9880d681SAndroid Build Coastguard Worker| | data symbols), or executable (for function symbols) after | 233*9880d681SAndroid Build Coastguard Worker| | JITSymbol::getAddress() is called. Note: This means that | 234*9880d681SAndroid Build Coastguard Worker| addModuleSet | addModuleSet doesn't have to compile (or do any other | 235*9880d681SAndroid Build Coastguard Worker| | work) up-front. It *can*, like IRCompileLayer, act | 236*9880d681SAndroid Build Coastguard Worker| | eagerly, but it can also simply record the module and | 237*9880d681SAndroid Build Coastguard Worker| | take no further action until somebody calls | 238*9880d681SAndroid Build Coastguard Worker| | JITSymbol::getAddress(). In IRTransformLayer's case | 239*9880d681SAndroid Build Coastguard Worker| | addModuleSet eagerly applies the transform functor to | 240*9880d681SAndroid Build Coastguard Worker| | each module in the set, then passes the resulting set | 241*9880d681SAndroid Build Coastguard Worker| | of mutated modules down to the layer below. | 242*9880d681SAndroid Build Coastguard Worker+------------------+-----------------------------------------------------------+ 243*9880d681SAndroid Build Coastguard Worker| | Removes a set of modules from the JIT. Code or data | 244*9880d681SAndroid Build Coastguard Worker| removeModuleSet | defined in these modules will no longer be available, and | 245*9880d681SAndroid Build Coastguard Worker| | the memory holding the JIT'd definitions will be freed. | 246*9880d681SAndroid Build Coastguard Worker+------------------+-----------------------------------------------------------+ 247*9880d681SAndroid Build Coastguard Worker| | Searches for the named symbol in all modules that have | 248*9880d681SAndroid Build Coastguard Worker| | previously been added via addModuleSet (and not yet | 249*9880d681SAndroid Build Coastguard Worker| findSymbol | removed by a call to removeModuleSet). In | 250*9880d681SAndroid Build Coastguard Worker| | IRTransformLayer we just pass the query on to the layer | 251*9880d681SAndroid Build Coastguard Worker| | below. In our REPL this is our default way to search for | 252*9880d681SAndroid Build Coastguard Worker| | function definitions. | 253*9880d681SAndroid Build Coastguard Worker+------------------+-----------------------------------------------------------+ 254*9880d681SAndroid Build Coastguard Worker| | Searches for the named symbol in the module set indicated | 255*9880d681SAndroid Build Coastguard Worker| | by the given ModuleSetHandleT. This is just an optimized | 256*9880d681SAndroid Build Coastguard Worker| | search, better for lookup-speed when you know exactly | 257*9880d681SAndroid Build Coastguard Worker| | a symbol definition should be found. In IRTransformLayer | 258*9880d681SAndroid Build Coastguard Worker| findSymbolIn | we just pass this query on to the layer below. In our | 259*9880d681SAndroid Build Coastguard Worker| | REPL we use this method to search for functions | 260*9880d681SAndroid Build Coastguard Worker| | representing top-level expressions, since we know exactly | 261*9880d681SAndroid Build Coastguard Worker| | where we'll find them: in the top-level expression module | 262*9880d681SAndroid Build Coastguard Worker| | we just added. | 263*9880d681SAndroid Build Coastguard Worker+------------------+-----------------------------------------------------------+ 264*9880d681SAndroid Build Coastguard Worker| | Forces all of the actions required to make the code and | 265*9880d681SAndroid Build Coastguard Worker| | data in a module set (represented by a ModuleSetHandleT) | 266*9880d681SAndroid Build Coastguard Worker| | accessible. Behaves as if some symbol in the set had been | 267*9880d681SAndroid Build Coastguard Worker| | searched for and JITSymbol::getSymbolAddress called. This | 268*9880d681SAndroid Build Coastguard Worker| emitAndFinalize | is rarely needed, but can be useful when dealing with | 269*9880d681SAndroid Build Coastguard Worker| | layers that usually behave lazily if the user wants to | 270*9880d681SAndroid Build Coastguard Worker| | trigger early compilation (for example, to use idle CPU | 271*9880d681SAndroid Build Coastguard Worker| | time to eagerly compile code in the background). | 272*9880d681SAndroid Build Coastguard Worker+------------------+-----------------------------------------------------------+ 273*9880d681SAndroid Build Coastguard Worker 274*9880d681SAndroid Build Coastguard WorkerThis interface attempts to capture the natural operations of a JIT (with some 275*9880d681SAndroid Build Coastguard Workerwrinkles like emitAndFinalize for performance), similar to the basic JIT API 276*9880d681SAndroid Build Coastguard Workeroperations we identified in Chapter 1. Conforming to the layer concept allows 277*9880d681SAndroid Build Coastguard Workerclasses to compose neatly by implementing their behaviors in terms of the these 278*9880d681SAndroid Build Coastguard Workersame operations, carried out on the layer below. For example, an eager layer 279*9880d681SAndroid Build Coastguard Worker(like IRTransformLayer) can implement addModuleSet by running each module in the 280*9880d681SAndroid Build Coastguard Workerset through its transform up-front and immediately passing the result to the 281*9880d681SAndroid Build Coastguard Workerlayer below. A lazy layer, by contrast, could implement addModuleSet by 282*9880d681SAndroid Build Coastguard Workersquirreling away the modules doing no other up-front work, but applying the 283*9880d681SAndroid Build Coastguard Workertransform (and calling addModuleSet on the layer below) when the client calls 284*9880d681SAndroid Build Coastguard WorkerfindSymbol instead. The JIT'd program behavior will be the same either way, but 285*9880d681SAndroid Build Coastguard Workerthese choices will have different performance characteristics: Doing work 286*9880d681SAndroid Build Coastguard Workereagerly means the JIT takes longer up-front, but proceeds smoothly once this is 287*9880d681SAndroid Build Coastguard Workerdone. Deferring work allows the JIT to get up-and-running quickly, but will 288*9880d681SAndroid Build Coastguard Workerforce the JIT to pause and wait whenever some code or data is needed that hasn't 289*9880d681SAndroid Build Coastguard Workeralready been processed. 290*9880d681SAndroid Build Coastguard Worker 291*9880d681SAndroid Build Coastguard WorkerOur current REPL is eager: Each function definition is optimized and compiled as 292*9880d681SAndroid Build Coastguard Workersoon as it's typed in. If we were to make the transform layer lazy (but not 293*9880d681SAndroid Build Coastguard Workerchange things otherwise) we could defer optimization until the first time we 294*9880d681SAndroid Build Coastguard Workerreference a function in a top-level expression (see if you can figure out why, 295*9880d681SAndroid Build Coastguard Workerthen check out the answer below [1]_). In the next chapter, however we'll 296*9880d681SAndroid Build Coastguard Workerintroduce fully lazy compilation, in which function's aren't compiled until 297*9880d681SAndroid Build Coastguard Workerthey're first called at run-time. At this point the trade-offs get much more 298*9880d681SAndroid Build Coastguard Workerinteresting: the lazier we are, the quicker we can start executing the first 299*9880d681SAndroid Build Coastguard Workerfunction, but the more often we'll have to pause to compile newly encountered 300*9880d681SAndroid Build Coastguard Workerfunctions. If we only code-gen lazily, but optimize eagerly, we'll have a slow 301*9880d681SAndroid Build Coastguard Workerstartup (which everything is optimized) but relatively short pauses as each 302*9880d681SAndroid Build Coastguard Workerfunction just passes through code-gen. If we both optimize and code-gen lazily 303*9880d681SAndroid Build Coastguard Workerwe can start executing the first function more quickly, but we'll have longer 304*9880d681SAndroid Build Coastguard Workerpauses as each function has to be both optimized and code-gen'd when it's first 305*9880d681SAndroid Build Coastguard Workerexecuted. Things become even more interesting if we consider interproceedural 306*9880d681SAndroid Build Coastguard Workeroptimizations like inlining, which must be performed eagerly. These are 307*9880d681SAndroid Build Coastguard Workercomplex trade-offs, and there is no one-size-fits all solution to them, but by 308*9880d681SAndroid Build Coastguard Workerproviding composable layers we leave the decisions to the person implementing 309*9880d681SAndroid Build Coastguard Workerthe JIT, and make it easy for them to experiment with different configurations. 310*9880d681SAndroid Build Coastguard Worker 311*9880d681SAndroid Build Coastguard Worker`Next: Adding Per-function Lazy Compilation <BuildingAJIT3.html>`_ 312*9880d681SAndroid Build Coastguard Worker 313*9880d681SAndroid Build Coastguard WorkerFull Code Listing 314*9880d681SAndroid Build Coastguard Worker================= 315*9880d681SAndroid Build Coastguard Worker 316*9880d681SAndroid Build Coastguard WorkerHere is the complete code listing for our running example with an 317*9880d681SAndroid Build Coastguard WorkerIRTransformLayer added to enable optimization. To build this example, use: 318*9880d681SAndroid Build Coastguard Worker 319*9880d681SAndroid Build Coastguard Worker.. code-block:: bash 320*9880d681SAndroid Build Coastguard Worker 321*9880d681SAndroid Build Coastguard Worker # Compile 322*9880d681SAndroid Build Coastguard Worker clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orc native` -O3 -o toy 323*9880d681SAndroid Build Coastguard Worker # Run 324*9880d681SAndroid Build Coastguard Worker ./toy 325*9880d681SAndroid Build Coastguard Worker 326*9880d681SAndroid Build Coastguard WorkerHere is the code: 327*9880d681SAndroid Build Coastguard Worker 328*9880d681SAndroid Build Coastguard Worker.. literalinclude:: ../../examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h 329*9880d681SAndroid Build Coastguard Worker :language: c++ 330*9880d681SAndroid Build Coastguard Worker 331*9880d681SAndroid Build Coastguard Worker.. [1] When we add our top-level expression to the JIT, any calls to functions 332*9880d681SAndroid Build Coastguard Worker that we defined earlier will appear to the ObjectLinkingLayer as 333*9880d681SAndroid Build Coastguard Worker external symbols. The ObjectLinkingLayer will call the SymbolResolver 334*9880d681SAndroid Build Coastguard Worker that we defined in addModuleSet, which in turn calls findSymbol on the 335*9880d681SAndroid Build Coastguard Worker OptimizeLayer, at which point even a lazy transform layer will have to 336*9880d681SAndroid Build Coastguard Worker do its work. 337