annotate docs/tutorial/BuildingAJIT2.rst @ 121:803732b1fca8

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