<div dir="ltr">Hi all,<div><br></div>Ellis Hoag and I propose our work, Machine IR profile which is lightweight and scalable.<br>Please see the proposal below and the initial patch, <a href="https://reviews.llvm.org/D104060">https://reviews.llvm.org/D104060</a><br>It would be great to hear the feedback!<br><br><h2 class="gmail-remarkup-header" style="margin:0px 0px 0.75em;padding:0px;border:0px;font-size:28px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">Machine IR Profile (MIP)</h2><h4 class="gmail-remarkup-header" style="margin:0px 0px 0.75em;padding:0px;border:0px;font-size:22px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">tl;dr;</h4><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">This is a proposal to introduce a new instrumentation pass that can produce optimization profiles with a focus on binary size and runtime performance of the instrumented binaries.</p><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">Our instrumented binaries record machine function call counts, machine function timestamps, machine basic block coverage, and a subset of the dynamic call graph. There is also a more lightweight mode that only collects machine function coverage data that has negligible runtime overhead and a binary size increase of 2-5% for instrumented binaries.</p><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">This is just the first patch of the WIP MIP project. The full branch can be found at <a href="https://github.com/ellishg/llvm-project" class="gmail-remarkup-link" target="_blank" rel="noreferrer" style="text-decoration-line:none;color:rgb(19,108,178);margin-top:0px">https://github.com/ellishg/llvm-project</a></p><h3 class="gmail-remarkup-header" style="margin:1em 0px 0.75em;padding:0px;border:0px;font-size:24px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">Motivation</h3><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">In the mobile space, increasing binary size has an outsized impact on both runtime performance and download speed. Current instrumentation implementations such as XRay and GCov produce binaries that are too slow and too large to run on real mobile devices. We propose a new pass that injects instrumentation code at the machine ir level. At runtime, we write profile data to our custom <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere;margin-top:0px">__llvm_mipraw</tt> section that is eventually dumped to a <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere">.mipraw</tt> file. At buildtime, we emit a <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere">.mipmap</tt> file which we use to map function information to data in the <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere">.mipraw</tt> file. The result is that no redundant function info is stored in the binary, which allows our instrumentation to have minimal size overhead.</p><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">MIP has been implemented on ELF and Mach-O targets for x86_64, AArch64, and Armv7 with Thumb and Thumb2.</p><h3 class="gmail-remarkup-header" style="margin:1em 0px 0.75em;padding:0px;border:0px;font-size:24px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">Performance</h3><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">Our focus for now is on the performance and size of binaries that have injected instrumentation instead of binaries that have been optimized with instrumentation profiles. We collected some basic results from <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere;margin-top:0px">MultiSource/Benchmarks</tt> in <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere">llvm-test-suite</tt> for both MIP and clang’s instrumentation using the <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere">-fprofile-generate</tt> flag. It should be noted that this comparison is not fair because clang’s instrumentation collects much more data than just function coverage. However, we expect fully-featured MIP to have similar metrics.</p><h4 class="gmail-remarkup-header" style="margin:1em 0px 0.75em;padding:0px;border:0px;font-size:22px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">Instrumented Binary Size</h4><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">At the moment, we have implemented function coverage which injects one x86_64 instruction (7 bytes) and one byte of global data for each instrumented function, which should have minimal impact on binary size and runtime performance. In fact, our results show that we should expect MIP instrumented binaries to be only 2-5% larger. We contrast this with clang’s instrumentation, which can increase the binary size by 500-900%.</p><h4 class="gmail-remarkup-header" style="margin:1em 0px 0.75em;padding:0px;border:0px;font-size:22px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">Instrumented Execution Time</h4><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">We found that MIP had negligable execution time regressions when instrumented with MIP. Again, we can (unfairly) contrast this to <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere;margin-top:0px">-fprofile-generate</tt> which increased execution time by 1-40%.</p><h3 class="gmail-remarkup-header" style="margin:1em 0px 0.75em;padding:0px;border:0px;font-size:24px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif">Usage</h3><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">We use the <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere;margin-top:0px">-fmachine-profile-generate</tt> clang flag to produce an instrumented binary and then use <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere">llvm-objcopy</tt> to extract the <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere">.mipmap</tt> file.</p><div class="gmail-remarkup-code-block" style="margin:12px 0px;padding:0px;border:0px;white-space:pre;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px"><pre class="gmail-remarkup-code" style="margin-top:0px;margin-bottom:0px;padding:12px;border:0px;background:rgba(71,87,120,0.08);overflow:auto;border-radius:3px;white-space:pre-wrap;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:15px;font-family:Menlo,Consolas,Monaco,monospace"><span class="gmail-gp" style="color:rgb(0,0,128);margin-top:0px">$ clang -g -fmachine-profile-generate main.cpp</span>
<span class="gmail-gp" style="color:rgb(0,0,128)">$ llvm-objcopy --dump-section=__llvm_mipmap=default.mipmap a.out /dev/null</span>
<span class="gmail-gp" style="color:rgb(0,0,128)">$ llvm-strip -g a.out -o a.out.stripped</span></pre></div><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">This will produce the instrumented binary a.out and a map file <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere;margin-top:0px">default.mipmap</tt>.</p><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">When we run the binary, it will produce a <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere;margin-top:0px">default.mipraw</tt> file containing the profile data for that run.</p><div class="gmail-remarkup-code-block" style="margin:12px 0px;padding:0px;border:0px;white-space:pre;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px"><pre class="gmail-remarkup-code" style="margin-top:0px;margin-bottom:0px;padding:12px;border:0px;background:rgba(71,87,120,0.08);overflow:auto;border-radius:3px;white-space:pre-wrap;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:15px;font-family:Menlo,Consolas,Monaco,monospace"><span class="gmail-gp" style="color:rgb(0,0,128);margin-top:0px">$ ./a.out.stripped</span>
<span class="gmail-gp" style="color:rgb(0,0,128)">$ ls</span>
<span class="gmail-go" style="color:rgb(128,128,128)">a.out    default.mipmap    default.mipraw    main.cpp</span></pre></div><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">Then we use our custom tool to postprocess the raw profile and produce the final profile <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere;margin-top:0px">default.mip</tt>.</p><div class="gmail-remarkup-code-block" style="margin:12px 0px;padding:0px;border:0px;white-space:pre;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px"><pre class="gmail-remarkup-code" style="margin-top:0px;margin-bottom:0px;padding:12px;border:0px;background:rgba(71,87,120,0.08);overflow:auto;border-radius:3px;white-space:pre-wrap;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:15px;font-family:Menlo,Consolas,Monaco,monospace"><span class="gmail-gp" style="color:rgb(0,0,128);margin-top:0px">$ llvm-mipdata create -p default.mip default.mipmap</span>
<span class="gmail-gp" style="color:rgb(0,0,128)">$ llvm-mipdata merge -p default.mip default.mipraw</span></pre></div><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">If our binary has debug info, we can use it to report source information along with the profile data.</p><div class="gmail-remarkup-code-block" style="margin:12px 0px;padding:0px;border:0px;white-space:pre;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px"><pre class="gmail-remarkup-code" style="margin-top:0px;margin-bottom:0px;padding:12px;border:0px;background:rgba(71,87,120,0.08);overflow:auto;border-radius:3px;white-space:pre-wrap;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:15px;font-family:Menlo,Consolas,Monaco,monospace"><span class="gmail-gp" style="color:rgb(0,0,128);margin-top:0px">$ llvm-mipdata show -p default.mip --debug a.out</span>
<span class="gmail-go" style="color:rgb(128,128,128)">_Z3fooi</span>
<span class="gmail-go" style="color:rgb(128,128,128)">  Source Info: /home/main.cpp:9</span>
<span class="gmail-go" style="color:rgb(128,128,128)">  Call Count: 0</span>
<span class="gmail-go" style="color:rgb(128,128,128)">  Block Coverage:</span>
<span class="gmail-go" style="color:rgb(128,128,128)">     COLD COLD COLD COLD COLD</span>
<span class="gmail-go" style="color:rgb(128,128,128)"></span>
<span class="gmail-go" style="color:rgb(128,128,128)">_Z3bari</span>
<span class="gmail-go" style="color:rgb(128,128,128)">  Source Info: /home/main.cpp:16</span>
<span class="gmail-go" style="color:rgb(128,128,128)">  Call Count: 1</span>
<span class="gmail-go" style="color:rgb(128,128,128)">  Block Coverage:</span>
<span class="gmail-go" style="color:rgb(128,128,128)">     HOT  HOT  COLD HOT  HOT</span></pre></div><p style="margin:0px 0px 12px;padding:0px;border:0px;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px">Finally, we can consume the profile using the clang flag <tt class="gmail-remarkup-monospaced" style="background:rgba(71,87,120,0.1);padding:1px 4px;border-radius:3px;white-space:pre-wrap;line-break:anywhere;margin-top:0px">-fmachine-profile-use=</tt> to produce a profile-optimized binary.</p><div class="gmail-remarkup-code-block" style="margin:12px 0px 0px;padding:0px;border:0px;white-space:pre;color:rgb(0,0,0);font-family:"Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px"><pre class="gmail-remarkup-code" style="margin-top:0px;margin-bottom:0px;padding:12px;border:0px;background:rgba(71,87,120,0.08);overflow:auto;border-radius:3px;white-space:pre-wrap;font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:11px;line-height:15px;font-family:Menlo,Consolas,Monaco,monospace"><span class="gmail-gp" style="color:rgb(0,0,128);margin-top:0px">$ clang -fmachine-profile-use=default.mip main.cpp</span></pre></div></div>