<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><font class="Apple-style-span" face="Courier">Here is a proposal that I mentioned sometime ago. Any thoughts,comments or </font></div><div><font class="Apple-style-span" face="Courier">suggestions on this proposal would be appreciated.</font></div><div><font class="Apple-style-span" face="Courier">-</font></div><div><font class="Apple-style-span" face="Courier">Devang</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">//===----------------------------------------------------------------------===//</font></div><div><font class="Apple-style-span" face="Courier">//                          Function Notes (or Traits)</font></div><div><font class="Apple-style-span" face="Courier">//===----------------------------------------------------------------------===//</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">This document describes the motivation and semantics of encoding function Notes</font></div><div><font class="Apple-style-span" face="Courier">in the LLVM IR.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">//===----------------------------------------------------------------------===//</font></div><div><font class="Apple-style-span" face="Courier">// The problem</font></div><div><font class="Apple-style-span" face="Courier">//</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">Link Time Optimization</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The llvm-gcc supports Link Time Optimization (LTO) at optimization level -O4 on</font></div><div><font class="Apple-style-span" face="Courier">platforms where the linker support is available. This optimization level also </font></div><div><font class="Apple-style-span" face="Courier">enables -O3 level optimization passes at the compile time. The -O3 optimization </font></div><div><font class="Apple-style-span" face="Courier">level enables aggressive inlining which may sacrifice code size for the code </font></div><div><font class="Apple-style-span" face="Courier">performance. Now, the llvm-gcc also supports optimize for size, -Os. However, </font></div><div><font class="Apple-style-span" face="Courier">right now there is not any way today to select optimize for size during link </font></div><div><font class="Apple-style-span" face="Courier">time optimizations. At link time, the optimizer (LTO) may receive input LLVM </font></div><div><font class="Apple-style-span" face="Courier">IR files that are compiled and optimized using various optimization choices. </font></div><div><font class="Apple-style-span" face="Courier">Today, there is not any way to communicate these optimization choices to LTO, </font></div><div><font class="Apple-style-span" face="Courier">which is a limitation. </font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">Code Generation</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The LLVM code generator supports various target specific choices, for example </font></div><div><font class="Apple-style-span" face="Courier">optimizer for size, enable exception handling, eliminate frame pointer etc.. </font></div><div><font class="Apple-style-span" face="Courier">The llvm-gcc selects these choices based on the command line arguments and </font></div><div><font class="Apple-style-span" face="Courier">default settings for the target. However, this information is not preserved in </font></div><div><font class="Apple-style-span" face="Courier">llvm IR. This means, the llvm IR generated by llvm-gcc does not contain enough </font></div><div><font class="Apple-style-span" face="Courier">information to independently reproduce llvm code generator behaviors using stand</font></div><div><font class="Apple-style-span" face="Courier">alone tools like llc.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The Inliner</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The GCC compiler supports inliner specific attributes, e.g. noinline,</font></div><div><font class="Apple-style-span" face="Courier">always_inline. These attributes instruct the inliner to take special actions for</font></div><div><font class="Apple-style-span" face="Courier">the function that specifies them. This information is not properly encoded in </font></div><div><font class="Apple-style-span" face="Courier">LLVM IR, which means the llvm inliner is not informed about such special </font></div><div><font class="Apple-style-span" face="Courier">requests, for example always_inline. Today, llvm-gcc respects GCC’s noinline </font></div><div><font class="Apple-style-span" face="Courier">attribute but the current solution is not ideal. </font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">//===----------------------------------------------------------------------===//</font></div><div><font class="Apple-style-span" face="Courier">// Proposed solution</font></div><div><font class="Apple-style-span" face="Courier">//</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The proposed solution to this problem to encode Function Notes in the IR. </font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">define void @f()  notes("opt-size,pic,noinline") { ... }</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">Here, the notes include a comma separated list of strings. Note, the notes are </font></div><div><font class="Apple-style-span" face="Courier">only attached to functions definitions. They are not attached to call or invoke</font></div><div><font class="Apple-style-span" face="Courier">instructions. All supported notes must be documented in LLVM language reference.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The LLVM passes are responsible to take appropriate actions based on Function </font></div><div><font class="Apple-style-span" face="Courier">Notes associated with function definition. For example, </font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">define void @fn1()  notes("opt-size=1") { ... }</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The function fn1() is being optimized for size without losing significant </font></div><div><font class="Apple-style-span" face="Courier">performance. The inliner will update inlining threshold for fn1() such that the </font></div><div><font class="Apple-style-span" face="Courier">functions called by fn1() are checked for size threshold for fn1() while being </font></div><div><font class="Apple-style-span" face="Courier">inlined inside fn1(). If the function fn1() is itself inlined somewhere, for </font></div><div><font class="Apple-style-span" face="Courier">example bar(), then the inlining threshold for bar() will be the deciding factor. </font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">define void @fn2()  notes("opt-size=2") { ... }</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The function fn2() is aggressively optimized for size. The code generator may </font></div><div><font class="Apple-style-span" face="Courier">sacrifice performance while selecting instructions. The inliner will aggressively </font></div><div><font class="Apple-style-span" face="Courier">reduce inlining threshold.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">define void @fn3() notes("noinline") { ... }</font></div><div><font class="Apple-style-span" face="Courier">define void @fn4() notes("always_inline") { ... }</font></div><div><font class="Apple-style-span" face="Courier">define void @fn5() notes("noinline,always_inline") { ... }</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">Here the inliner is instructed to not inline function fn3() anywhere and inline </font></div><div><font class="Apple-style-span" face="Courier">function fn4() everywhere. The function fn5() is malformed and it should be </font></div><div><font class="Apple-style-span" face="Courier">rejected by the verifier.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">define void @fn6()  notes("opt-size=1,noinline") { ... }</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">This is valid. The inliner is instructed to not inline fn6() here.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The target CPU specific features can be encoded as function notes.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">define void @fn7() notes("x86.sse3") { ... }</font></div><div><font class="Apple-style-span" face="Courier">define void @fn8() notes("x86.no-sse") { ... }</font></div><div><font class="Apple-style-span" face="Courier">define void @fn9() notes("arm.no-thumb") { ... }</font></div><div><font class="Apple-style-span" face="Courier">define void @fn10() notes("arm.force-thumb") { ... }</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The fn7() note "sse3" instructs the x86 code generator to use SSE3 instructions </font></div><div><font class="Apple-style-span" face="Courier">in fn7() whereas the code generator should not use SSE instructions for function</font></div><div><font class="Apple-style-span" face="Courier">fn8(). </font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">The Function Notes are not a place for all the llvm-gcc command line options.  </font></div><div><font class="Apple-style-span" face="Courier">Each note should represent function specific choice or an option for LLVM </font></div><div><font class="Apple-style-span" face="Courier">passes. For example, optimize for size is appropriate because it instructions </font></div><div><font class="Apple-style-span" face="Courier">the LLVM passes to make appropriate choices and update their thresholds. It is </font></div><div><font class="Apple-style-span" face="Courier">appropriate to encode -ffast-math related choices here. It is not appropriate </font></div><div><font class="Apple-style-span" face="Courier">to include -O4 as a function note.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">//===----------------------------------------------------------------------===//</font></div><div><font class="Apple-style-span" face="Courier">// Implementation Overview</font></div><div><font class="Apple-style-span" face="Courier">//</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><font class="Apple-style-span" face="Courier">[0] Implement llvm::Function Note store and access interface.</font></div><div><font class="Apple-style-span" face="Courier">[1] Update LLVM Asm Parser to recognize Function Notes.</font></div><div><font class="Apple-style-span" face="Courier">[2] Update LLVM Printer to print Function Notes.</font></div><div><font class="Apple-style-span" face="Courier">[3] Update LLVM BitCode Reader and Writer to handle Function Notes.</font></div><div><font class="Apple-style-span" face="Courier">[4] Update optimization passes to recognize "opt-size" property</font></div><div><font class="Apple-style-span" face="Courier">    Update the inliner to recognize "noinline" and "always_inline" Notes.</font></div><div><font class="Apple-style-span" face="Courier">[5] Many code generation choices are encoded as global variables in </font></div><div><font class="Apple-style-span" face="Courier">    TargetOptions.h. Update code generation passes to read these choices from </font></div><div><font class="Apple-style-span" face="Courier">    function notes and eliminate these global variables.</font></div><div><font class="Apple-style-span" face="Courier">[6] Update LTO to merge function Notes from various IR files appropriately.</font></div><div><font class="Apple-style-span" face="Courier"><br></font></div><div><br></div></body></html>