<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, May 18, 2015 at 12:03 PM, Joseph Tremoulet <span dir="ltr"><<a href="mailto:jotrem@microsoft.com" target="_blank">jotrem@microsoft.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div lang="EN-US" link="blue" vlink="purple">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Hi,<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Thanks for sending this out. We're looking forward to seeing this come about, since we need funclet separation for LLILC as well (and I have cycles to spend
on it, if that would be helpful).<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Some questions about the new proposal:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">- Do the new forms of resume have any implied read/write side-effects, or do they work just like a branch? In particular, I'm wondering what prevents reordering
a call across a resume. Is this just something that code motion optimizations are expected to check for explicitly to avoid introducing UB per the "Executing such an invoke [or call] that does not transitively unwind to the correct catchend block has undefined
behavior" rule?</span></p></div></div></blockquote><div><br></div><div>Yes, crossing a resume from a catchblock ends the lifetime of the exception object, so I'd say that's a "writes escaped memory" constraint. That said, a resume after a cleanupblock doesn't, but I'm not sure it's worth having this kind of fine-grained analysis. I'm OK teaching SimplifyCFG to combine cleanupblocks and leaving it at that.</div><div> <span style="color:rgb(31,73,125);font-family:Calibri,sans-serif;font-size:11pt"> </span></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div lang="EN-US" link="blue" vlink="purple"><div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">- Does LLVM already have other examples of terminators that are glued to the top of their basic blocks, or will these be the first? I ask because it's a somewhat
nonstandard thing (a block in the CFG that can't have instructions added to it) that any code placement algorithms (PRE, PGO probe insertion, Phi elimination, RA spill/copy placement, etc.) may need to be adjusted for. The adjustments aren't terrible (conceptually
it's no worse than having unsplittable edges from each of the block's preds to each of its succs), but it's something to be aware of.</span></p></div></div></blockquote><div><br></div><div>No, LLVM doesn't have anything like this yet. It does have unsplittable critical edges, which can come from indirectbr and the unwind edge of an invoke. I don't think it'll be too hard to teach transforms how to deal with one more, but maybe that's unrealistic youthful optimism. :)</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div lang="EN-US" link="blue" vlink="purple"><div><p class="MsoNormal"></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">- Since this will require auditing any code with special processing of resume instructions to make sure it handles the new resume forms correctly, I wonder
if it might be helpful to give resume (or the new forms of it) a different name, since then it would be immediately clear which code has/hasn't been updated to the new model.</span></p></div></div></blockquote><div><br></div><div>There aren't that many references to ResumeInst across LLVM, so I'm not too scared. I'm not married to reusing 'resume', other candidate names include 'unwind' and 'continue', and I'd like more ideas.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div lang="EN-US" link="blue" vlink="purple"><div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">- Is the idea that a resume (of the sort that resumes normal execution) ends only one catch/cleanup, or that it can end any number of them? Did you consider
having it end a single one, and giving it a source that references (in a non-flow-edge-inducing way) the related catchend? If you did that, then:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">+ The code to find a funclet region could terminate with confidence when it reaches this sort of resume, and<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">+ Resumes which exit different catches would have different sources and thus couldn't be merged, reducing the need to undo tail-merging with code duplication
in EH preparation (by blocking the tail-merging in the first place)</span></p></div></div></blockquote><div><br></div><div>We already have something like this for cleanupblocks because the resume target and unwind label of the cleanupblock must match. It isn't as strong as having a reference to the catchblock itself, because tail merging could kick in like you mention. Undoing this would be and currently is the job of WinEHPrepare. I guess I felt like the extra representational complexity wasn't worth the confidence that it would buy us.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div lang="EN-US" link="blue" vlink="purple">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">- What is the plan for cleanup/__finally code that may be executed on either normal paths or EH paths? One could imagine a number of options here:<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">+ require the IR producer to duplicate code for EH vs non-EH paths<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">+ duplicate code for EH vs non-EH paths during EH preparation<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">+ use resume to exit these even on the non-EH paths; code doesn't need to be duplicated (but could and often would be as an optimization for hot/non-EH paths),
and normal paths could call the funclet at the end of the day<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">and it isn't clear to me which you're suggesting. Requiring duplication can worst-case quadratically expand the code (in that if you have n levels of cleanup-inside-cleanup-inside-cleanup-…,
and each cleanup has k code bytes outside the next-inner cleanup, after duplication you'll have k*n + k*(n-1) + … or O(k*n^2) bytes total [compared to k*n before duplication]), which I'd think could potentially be a problem in pathological inputs.</span></p></div></blockquote><div><br></div><div>I want to have separate normal and exceptional codepaths, but at -O0 all the cleanup work should be bundled up in a function that gets called from both those paths.</div><div><br></div><div>Today, for C++ destructors, we emit two calls to the destructor: one on the normal path and one on the EH path. For __finally, we outline the finally body early in clang and emit two calls to it as before, but passing in the frameaddress as an argument. I think this is a great place to be. It keeps our -O0 code size small, simplifies the implementation, and allows us to inline one or both call sites if we think it's profitable.</div></div></div></div>