<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Apr 15, 2016 at 1:43 AM, Mehdi Amini <span dir="ltr"><<a href="mailto:mehdi.amini@apple.com">mehdi.amini@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word">Hi Teresa, <div><br></div><div>Thanks for summarizing and formalizing our discussion on IRC.</div><div><br><div><span class="gmail-gmail-gmail-gmail-"><blockquote type="cite"><div>On Apr 14, 2016, at 7:08 AM, Teresa Johnson via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:</div><br><div><div dir="ltr"><div>Hi all,</div><div><br></div><div>Below is a proposal for refining the way we communicate between the ThinLTO link step (the combined indexing step) and the backend processes that do the actual importing and other summary-based optimizations in a distributed backend process.</div><div><br></div><div>Mehdi, let me know if this addresses your concerns.</div><div><br></div><div>Peter, PTAL from the standpoint of any summary extensions needed for CFI and make sure they can fit into this model.</div><div><br></div><div>Thanks,</div><div>Teresa</div><br><br>Background<div>----------------<br><br>Recent patch D18945/r266125 ([ThinLTO] Only compute imports for current module in FunctionImport pass) triggered a discussion (mostly over IRC) on how best to determine import/export decisions in distributed back end compiles.<br><br>Import and export decisions are made by traversing the combined index. The actual importing happens in the FunctionImporter class, which is passed the set of values to import. The importer class is either invoked directly on each backend compile, which happens in the threads launched in the libLTO path, or via the FunctionImportPass.<br><br>The pass is currently used by the opt tool, by the gold-plugin when it launches ThinLTO threads for single machine parallelism, and via clang when invoked with a bitcode input file and the -fthinlto-index= option. The latter was added in r254927 to enable launching a ThinLTO backend compile in a separate distributed build process.<br><br>Before r266125, the FunctionImportPass was walking the entire index, but ignoring the import results for all but the current module, and not using the exports list. The reason to do the full index walk is that eventually we can minimize the required static promotions in the current module (based on whether its defined values are imported elsewhere). However, this was costing a lot of compile time in each backend thread. On the other hand, Mehdi would like to use the pass for testing via the opt tool, and planned to eventually add the support for using the computed export lists to guide promotion. Therefore, the other invocations (in the gold-plugin and from clang for the distributed back ends) will need to either invoke the FunctionImporter directly (as in libLTO), passing in the import/export information, or use a new pass interface that consumes the necessary info to compute this information.<br><br>Eventually the import/export decisions should be made a single time in the thin link step (as is currently done for libLTO which doesn’t use the pass), along with any other global summary-based decisions. The advantage is that each backend isn’t doing redundant computation, and I believe it is safer to make global decisions affecting correctness (e.g. promotion) a single time. For the gold-plugin launched threads, it should be straightforward to use the libLTO approach of computing these decisions and passing the relevant information to each backend thread via a direct invocation of the FunctionImporter, instead of using the FunctionImportPass.<br><br>However, for distributed build backends, if the decisions are to be made a single time in the thin link step, summary based decisions need to be serialized out in order to be used by the FunctionImporter in each backend process (which could be invoked directly from clang, or via a possibly modified FunctionImportPass interface). My original plan was to mark linkage changes determined globally (such as promotion decisions) in the combined index itself for consumption in each back end. But an advantage of serializing out just the necessary info for each module is that the entire combined index wouldn’t need to be staged to each distributed build node.<br></div></div></div></blockquote><div><br></div></span><div>staged... and parsed!</div></div></div></div></blockquote><div><br></div><div>Yes, that is another benefit of the smaller index.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><span class="gmail-gmail-gmail-gmail-"><div><br></div><br><blockquote type="cite"><div><div dir="ltr"><div><br>Individual Module Index Files</div><div>---------------------------------------<br><br>Rather than define a new format for serializing out the globally determined information from the thin link step, we can continue to use the combined index file format. However, we can create an individual “combined” index file for each module. This better enables passing along any summary information useful for backend compilations beyond just import and export lists, which can include other linkage optimizations, and information for transformations such as CFI. It also enables leverage of much of the existing combined index bitcode interfaces and data structures.<br><br>An overview on what is included in an individual “primary” module’s index file:<br>  1) Module symbol table only includes modules imported into the primary module.<br>  2) Summary section only includes summaries for value definitions that should be imported, as well as for definitions in the primary module.</div><div>  3) Any desired linkage changes for both the primary module and imported defs are recorded in the summary entry linkage fields.<br><br>Note that 1 and 2 ensure that nothing can be imported beyond those values marked promoted during the global thin link (important since that possibly requires promotion in the exporting module). Any value that is imported as a declaration (because it did not have a summary entry as per 2 above), and that has local linkage, should automatically be promoted when importing (its primary module’s index would include a summary with the promoted linkage recorded).<br></div></div></div></blockquote><div><br></div></span><div>Missing: "export list", i.e. which symbols needs to be preserved in this module (all the others can be turned into internal).</div></div></div></div></blockquote><div><br></div><div>I don't think we need an explicit export list to do this, just note it in the linkage type. I had only covered parts of that below - noting which locals need to be promoted by marking them as having external linkage (A), and which could be internalized when then have only a couple external accesses through importing and internalization (C), but didn't cover the case where there were no external accesses. Added that below.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><span class="gmail-gmail-gmail-gmail-"><div><br></div><br><blockquote type="cite"><div><div dir="ltr"><div><br>Linkage Changes</div><div>-----------------------<br><br>As described above, the linkage changes determined by the global index walk in the thin link step will be marked in the summary entries (in all individual index files containing that symbol). The back end will compare the linkage types in the index to those in the materialized bitcode (both in the primary module and in any definitions being imported) and make the necessary adjustments.<br><br><br>Some possibilities include:<br><br>A. Promotion: Index will indicate external linkage, so local value will be promoted and renamed. For imported declarations, any that are local will be promoted.<br><br>B. Avoiding promotion by forced import: Used when the thin link step determines it is better to force an import of a static definition and leave it static. The index will indicate local linkage, so linkage type in IR will not be changed when it is imported (or when compiling the exporting module).<br><br>C. Internalization by forced import: If an external symbol has 1 or only a very small number of external references, and all referring modules decide to import that definition, the thin link analysis could decide that it is better to leave all copies local. The index would indicate local linkage, and the linkage type in the IR would then be changed to local when it is imported (and when compiling the exporting module) </div></div></div></blockquote></span></div></div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><span class="gmail-gmail-gmail-gmail-"><blockquote type="cite"><div><div dir="ltr"><div><br>D. LinkOnce -> Weak/AvailableExternally: This is a compile time optimization to avoid unnecessarily keeping multiple copies of a LinkOnce value. Linkage is marked in index, and again adjusted in the backends since it will be different than the initial linkage after parsing.<br></div></div></div></blockquote></span></div></div></div></blockquote><div> E. Internalization when there is no external access: If an external symbol has no external references, it can be internalized. The index will indicate local linkage, and the linkage type in the IR would then be changed to local whencompiling the exporting module.</div><div><br></div><div>(This should go up between B and C actually, I will reorder them in the master doc I'll post to <a href="https://sites.google.com/site/llvmthinlto/">https://sites.google.com/site/llvmthinlto/</a> later today)</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><span class="gmail-gmail-gmail-gmail-"><br><blockquote type="cite"><div><div dir="ltr"><div><br>Note that pcc has made a proposal to do some of the ThinLTO promotion and renaming up front  in the compile step, so that some functions can be eagerly compiled into text (see <a href="http://lists.llvm.org/pipermail/llvm-dev/2016-April/098081.html">http://lists.llvm.org/pipermail/llvm-dev/2016-April/098081.html</a>). However, that will only apply to locals referenced by functions that are deemed unlikely to import or be exported. The remaining locals can still be promoted lazily.<br><br>Importing Strategy</div><div>------------------------<br><br>Strategy 1: Import exactly those defs for which we have summaries<br><br>Could use simplified/reduced summaries that strip the ref/call edges, since they won’t be used by the backends.<br><br>Strategy 2: Allow the importer some flexibility to modify import decisions<br><br>In case we find situations where it is better to let the importer to adjust decisions based on full information (not yet known whether we need this flexibility, but I don’t want to remove this possibility until after more performance tuning is done on large apps). The modified decisions must be legal based on the linkage changes decided on during the thin link step (described in A-D in prior section):<br>   A. Promotion - Since we can only import at most the values for which we were given summaries, which were known to be exported at link time, we can safely ratchet down the amount of importing without rendering those promotion decisions incorrect (some promotions may have been unnecessary if we decide not to import something, but they are not wrong from a correctness standpoint).<br>   B&C. Avoiding promotion or internalization decisions - these rely on forced import of the local or (to be) internalized values. Simply force import anything with a summary that is marked as having local linkage in the summary.<br>   D. LinkOnce -> Weak/AvailableExternally - these are not based on importing and are unaffected by the importer’s decisions.<br><br>Incremental Builds</div><div>-------------------------<br><br>A backend compilation needs to be rebuilt when it’s individual “combined” index changes (it includes the module hashes of all relevant modules, including the importing module, as well as all linkage decisions).<br></div></div></div></blockquote><div><br></div></span><div>... or when the compiler itself changes :)</div></div></blockquote><div><br></div><div>Sure, didn't mention that here since it is not affected by ThinLTO. I'll add it for completeness though.</div><div><br></div><div>Thanks,</div><div>Teresa</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><span class="gmail-gmail-gmail-gmail-HOEnZb"><font color="#888888"><div><br></div><div><br></div><div><br></div><div>-- </div><div>Mehdi</div><div><br></div></font></span></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><span style="font-family:times;font-size:medium"><table cellspacing="0" cellpadding="0"><tbody><tr style="color:rgb(85,85,85);font-family:sans-serif;font-size:small"><td nowrap style="border-top-style:solid;border-top-color:rgb(213,15,37);border-top-width:2px">Teresa Johnson |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(51,105,232);border-top-width:2px"> Software Engineer |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(0,153,57);border-top-width:2px"> <a href="mailto:tejohnson@google.com">tejohnson@google.com</a> |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(238,178,17);border-top-width:2px"> 408-460-2413</td></tr></tbody></table></span></div>
</div></div>