<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Sebastiano,<div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">What I want to do now is to trigger the recompilation of a specific<br>class method (i.e., function in the IR Module), and perform some IR<br>transformations before the function is compiled. Then, I would like to<br>point the old function to the new version (through the<br>IndirectStubManager).<br>The questions are:<br>1. How can I trigger the re-optimization and re-compilation from the<br>existing ExecutionSession? Is there a method in the<br>CompileOnDemandLayer that allows it?<br></blockquote><div><br></div><div>There is no off-the-shelf support for this yet. The usual solution is to use an IR pass to insert a counter for each unoptimized function and a corresponding increment / check in the function entry block. I.e.:</div><div><br></div><div><font face="monospace">define void @foo() {</font></div><div><font face="monospace">entry:</font></div><div><font face="monospace">body:</font></div><div><font face="monospace">  ; ... </font></div><div><font face="monospace">  ret void</font></div><div><font face="monospace">}</font></div><div><br></div><div>becomes</div><div><br></div><div><font face="monospace">@foo_counter = global i64 0</font></div><div><font face="monospace"><br></font></div><div><div style="color:rgb(0,0,0)"><font face="monospace">declare void @optimize_function(i8 *)</font></div><div style="color:rgb(0,0,0)"> </div></div><div><font face="monospace">define void @foo() {<br></font></div><div><font face="monospace">entry:</font></div><div><font face="monospace">  %counter = load i64, i64* @foo_counter</font></div><div><font face="monospace">  %counter.1 = add i64 counter, 1</font></div><div><font face="monospace">  store i64 %counter.1, i64* @foo_counter</font></div><div><font face="monospace">  %should_optimize_foo = icmp eq i64 %counter.1, 1000</font></div><div><font face="monospace">  br i1 %should_optimize_foo, label %optimize, label %old_entry</font></div><div><font face="monospace">optimize:<br></font></div><div><font face="monospace">  call void @optimize_function(i8* bitcast (void ()* @foo to i8*)</font><span style="font-family:monospace">)</span></div><div><font face="monospace">  br label %old_entry</font></div><div><font face="monospace"><br></font></div><div><font face="monospace">old_entry:</font></div><div><font face="monospace">body:</font></div><div><font face="monospace">  ; ...</font></div><div><font face="monospace">  ret void</font></div><div><font face="monospace">}</font></div><div><br></div><div>Then you would implement <i>optimize_function</i> directly in your JIT process and make it available to JIT'd code (either by reflecting process symbols using a DynamicLibrarySearchGenerator, or by adding it using an absoluteSymbols call). You can use the address passed to <i>optimize_function</i> to identify the function to be optimized. You will also need to give the function a new name (e.g. foo_optimized) to avoid name clashes.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">2. Do I need to "manually" update the trampoline through the<br>IndirectStubManager, or it is automatically done once the new function<br>is compiled?</blockquote></div><div><br></div><div>Yes: In optimize_function you should look up the address of foo_optimized, then use the IndirectStubManager to update the stub with:</div><div>ISM.updatePointer("foo", foo_optimized_address);</div><div><br></div><div>There are a couple of gotchas here:</div><div><br></div><div>(1) You'll need to set up different compilers for your optimized and unoptimized functions. There are a few ways that you can do that, but one of the easiest would be to create your own IRCompileLayer (copying the existing code -- it's quite short) and then inspect the names of the functions being passed. If it ends in "_optimized" you turn the optimization level up.</div><div><br></div><div>(2) The updatePointer method uses linker mangled names. On Linux these are the same as the C / LLVM-IR function names, but on macOS you have to add an underscore prefix, and on Windows there are a couple of different prefix schemes.</div><div><br></div><div>This is just a rough overview, but I'm happy to help with any more specific questions as they come up. Also, in the future I'd love to see ORC grow some off-the-shelf support for this, so if you're ever interested in working on that please let me know.</div><div><br></div><div>Regards,</div><div>Lang.</div></div></div></div></div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Nov 29, 2020 at 9:25 AM Sebastiano Miano via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Dear all,<br>
I am recently playing a little bit with the ORC JIT APIs with the goal<br>
of creating a prototype of a JIT compiler that loads the IR module of<br>
a C++ class, compiles it and instantiates the class.<br>
During the execution, I would like to replace some class methods by<br>
recompiling them with an optimized version.<br>
<br>
I have started from the latest version of the KaleidoscopeJIT, using<br>
the CompileOnDemandLayer to perform a lazy compilation of the class.<br>
I have managed successfully to load the code and instantiate the<br>
object, by getting the pointer of a "factory" method in the IR Module<br>
that returns the object itself.<br>
<br>
What I want to do now is to trigger the recompilation of a specific<br>
class method (i.e., function in the IR Module), and perform some IR<br>
transformations before the function is compiled. Then, I would like to<br>
point the old function to the new version (through the<br>
IndirectStubManager).<br>
The questions are:<br>
1. How can I trigger the re-optimization and re-compilation from the<br>
existing ExecutionSession? Is there a method in the<br>
CompileOnDemandLayer that allows it?<br>
2. Do I need to "manually" update the trampoline through the<br>
IndirectStubManager, or it is automatically done once the new function<br>
is compiled?<br>
<br>
Thanks a lot,<br>
Sebastiano<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>