<div dir="ltr">This example is pretty compelling, but I still think I want to limit the scope of this change to not include this feature. It's probably reasonable to hold onto the idea as future work, though. In the meantime, frontends can decide for themselves whether they want code size or stronger optimization of cleanups by doing early outlining or not.<div><br></div><div><div>The only way we can hit the quadratic growth from clang is if someone is nesting inside SEH __finally blocks, at which point I'm pretty OK letting that get bloated. If we're not going to use the construct in Clang, LLVM passes won't see it as often, and it'll stay buggy longer.</div><div><div><br></div><div>The version of this feature that I like so far is probably entercleanup / endcleanup, something along these lines:</div><div><br></div><div>try {</div><div> f(1);<br>} finally {<br> f(2);</div><div>}</div><div><br></div><div> invoke void @f(i32 1)</div><div> to label %cont unwind label %cleanup</div><div>cont:</div><div> entercleanup label %cleanup</div><div>return:</div><div> ret void</div><div>cleanup:</div><div> cleanupblock ; unwind label would go here if there were an action</div><div> call void @f(i32 2)</div><div> endcleanup from label %cleanup to label %return ; unwind label would go here if there were an action</div></div></div><div><br></div><div>The endcleanup instruction would use 'to' and 'unwind' label operands to mirror the structure of an invoke. In fact, endcleanup is almost nicer than 'unwind'. Maybe we should use that.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 19, 2015 at 7:19 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><span class="">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">>
</span>Most passes would see the cleanupblock instruction and run the other way<span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u><u></u></span></p>
</span><p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">1) That statement surprises me. I would have expected the cleanupblock instruction to look pretty benign; it doesn't have any side-effects, does it? And its
only source is a label reference? Likewise, I would have expected unwind to pretty much just look like a branch<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">2) Regardless, I certainly do agree that optimizations have less freedom when sharing the IR for the cleanup between the EH and non-EH paths, because of the
impact on the flow-graph (the tail of the non-EH path now looks like it could have been reached from any point in the 'try' where an exception was raised without completing the 'try'), which is why I think it's an important optimization to do the duplication
… I just want there to be a fallback that's guaranteed to be correct and avoid explosive code growth for the pathological cases.<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">Regarding your suggestion to have the normal path branch into the finally (after the cleanupblock) and back out, it delays the duplication to EH preparation,
but still requires duplication. I want something like that but where EH preparation can also rewrite the non-EH paths to call the funclet, and to do that robustly I think we'd need to wed the cleanupblock to that %finally label and wed that conditional branch
to the unwind.<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">Regarding how bad the growth can be, the problem case is finally-inside-finally, not try-inside-try:<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:"Courier New";color:black">foo() {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> expr1;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> } finally {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> expr2;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> } finally {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> expr3;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> } finally {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> try {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> expr4;<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> } finally<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> …<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black"> }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New";color:black">}<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">With duplication, the non-EH path through
</span><span style="font-size:11.0pt;font-family:"Courier New";color:black">foo</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> will include each of
</span><span style="font-size:11.0pt;font-family:"Courier New";color:black">expr1</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> through
</span><span style="font-size:11.0pt;font-family:"Courier New";color:black">exprn</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">. The outermost funclet will include (in its non-EH path) each of
</span><span style="font-size:11.0pt;font-family:"Courier New";color:black">expr2</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> through
</span><span style="font-size:11.0pt;font-family:"Courier New";color:black">exprn</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">. The next funclet will include each of
</span><span style="font-size:11.0pt;font-family:"Courier New";color:black">expr3</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> through
</span><span style="font-size:11.0pt;font-family:"Courier New";color:black">exprn</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">. Etc.<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">Another problem I'd have relying on early inlining is that when the CLR asks the LLILC Jit to jit one method, it expects the result to be one method (plus funclets),
not n methods…<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<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">-Joseph<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"><a name="14d6f1e0dd1f6b8c__MailEndCompose"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"><u></u> <u></u></span></a></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif"">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif""> Reid Kleckner [mailto:<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>]
<br>
<b>Sent:</b> Tuesday, May 19, 2015 7:26 PM</span></p><div><div class="h5"><br>
<b>To:</b> Joseph Tremoulet<br>
<b>Cc:</b> LLVM Developers Mailing List; Bill Wendling; Nick Lewycky; Kaylor, Andrew<br>
<b>Subject:</b> Re: [LLVMdev] RFC: New EH representation for MSVC compatibility<u></u><u></u></div></div><p></p><div><div class="h5">
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<div>
<p class="MsoNormal">I think adding transitions to cleanupblocks on the normal execution path would be an optimization barrier. Most passes would see the cleanupblock instruction and run the other way. It's definitely appealing from the perspective of getting
the smallest possible code, but I'm OK with having no more than two copies of everything in the finally block.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">I think with the addition of the 'from' label we can just use shared basic blocks without runaway code duplication, like so:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">try {<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> f();<br>
} finally {<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> do_finally();<br>
}<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal"> ...<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> invoke void @f()<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> to label %cont unwind label %cleanup<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">cont:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> br label %finally<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">cleanup:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> cleanupblock<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> br label %finally<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">finally:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> %abnormal = phi i1 [true, %cleanup], [false, %cont]<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> call void @do_finally()<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> br i1 %abnormal, label %finally.unwind, label %finally.normal<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">finally.unwind:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> unwind from label %cleanupblock<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">finally.normal:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> ret void<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">With two reachability checks we can see that cleanup, finally, and finally.unwind are the only BBs in the finally funclet, and only finally is shared. We can duplicate it in WinEHPrepare and fix up the CFG to reflect that. I don't think
the quadratic case is possible, even in a nested case like:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">try {<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> try {<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> f();<br>
} finally {<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> do_finally(1);<br>
}<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">} finally {<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> do_finally(2);<br>
}<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">We'll end up with four calls to do_finally in this example. Does that seem OK?<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">If that much duplication isn't OK, you can also have your frontend do early outlining without using frameescape. Instead of passing the frame pointer, it would pass the address of each escaped local variable. If the cleanup is simple, it'll
be inlined and some locals may be eliminated, and if not, the outlined funclet will only contain a single call with lots of lea+push pairs.<u></u><u></u></p>
</div>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<p class="MsoNormal">On Tue, May 19, 2015 at 2:22 PM, Joseph Tremoulet <<a href="mailto:jotrem@microsoft.com" target="_blank">jotrem@microsoft.com</a>> wrote:<u></u><u></u></p>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">>
</span>teach the inliner how to undo framerecover and let the optimization fall out that way<u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">You'd still have the problem that the referenced variables were frameescaped and appear to be read/written
at unrelated calls.</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> </span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">>
</span>__finally is pretty rare<u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">`__finally` may be rare in SEH code, but `finally` is quite common in .Net code, so we're going to
need a solution that avoids early `finally` outlining for the same reasons we're avoiding early `catch` outlining.</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">While we do need something that's amenable to duplicating `finally` code on hot/non-EH paths (since
this is an important optimization for .Net code), I think there also needs to be a path that can be taken for very cold code / very large cleanups / very deeply-nested cleanups to avoid quadratic code expansion on those cases. Early outlining of just those
cases could maybe be made to work, but would require that the decision be made early; it would be much more palatable to make the decision in the natural course of optimization (e.g. some sort of tail duplication).</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">So I think we should have a way to enter/exit cleanup blocks on non-EH paths.</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">The smallest change to your proposal that comes to mind which would allow this would be:</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> - a normal branch can target a cleanupblock</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> - the resume/unwind terminator that ends a cleanup would have another optional target label (%normalsucc).
The semantics would be that the EH edge to %nextaction would be taken if the cleanupblock were entered by an EH edge, and the normal edge to %normalsucc would be taken otherwise.</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> - converting this to landingpads would manifest an i1 that would need to be set before branching
to the cleanupblock, and turn the unwind/resume into a condbr on that</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> - codegen for windows could turn the branch to cleanupblock into a call to the handler followed
by a jump to the %normalsucc</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">A change that I'd consider preferable since it avoids the need for an auxiliary switch in the non-EH
code would be:</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> - some new terminator along the lines of 'entercleanup %cleanupblock recover to %recoverblock',
rather than a plain branch, can target cleanupblocks</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> - the resume/unwind terminator that ends a cleanup would have any number of additional successors,
and just like the rule that the EH target must match the %nextaction referenced on the cleanupblock, the non-EH targets would need to match one of the %recoverblocks specified on one of the entercleanups targeting the cleanupblock</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> - converting this to landingpads would manifest an int that would need to be set before branching
to the cleanupblock, and turn the unwind/resume into a switch</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> - codegen for windows could turn entercleanup into a call to the handler followed by a jump to
the %recoverblock</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Those are the first two options that come to mind, anyway. I'm sure there are other options, but
the key points are:</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">1) can avoid early outlining of finally bodies, and</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">2) can avoid runaway code expansions</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> </span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Regarding naming, I like your new suggestions (though the changes I'm suggesting to cleanup-ending
terminators are a mix between recover and unwind… FWIW, 'endfinally' would be a natural name for that in my world
</span><span style="font-size:11.0pt;font-family:Wingdings;color:#1f497d">J</span><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">. Personally I wouldn't hate something verbose like recover_or_unwind for the forms that may be
doing either. 'endcleanup' also comes to mind.).</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> </span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Thanks</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">-Joseph</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> </span><u></u><u></u></p>
<p class="MsoNormal"><a name="14d6f1e0dd1f6b8c_14d6e0e1601cce0c__MailEndCompose"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> </span></a><u></u><u></u></p>
<p class="MsoNormal"><b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif"">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri","sans-serif""> Reid Kleckner [mailto:<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>]
<br>
<b>Sent:</b> Tuesday, May 19, 2015 3:40 PM<br>
<b>To:</b> Joseph Tremoulet<br>
<b>Cc:</b> LLVM Developers Mailing List; Bill Wendling; Nick Lewycky; Kaylor, Andrew<br>
<b>Subject:</b> Re: [LLVMdev] RFC: New EH representation for MSVC compatibility</span><u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<div>
<div>
<p class="MsoNormal">On Mon, May 18, 2015 at 8:40 PM, Joseph Tremoulet <<a href="mailto:jotrem@microsoft.com" target="_blank">jotrem@microsoft.com</a>> wrote:<u></u><u></u></p>
</div>
<div>
<div>
<div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">>
</span>I want to have separate normal and exceptional codepaths<u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">I assume you at least mean that's what you'll be doing in Clang's initial IR generation. Do you
also mean to impose this as a restriction on other IR generators, and as a property that IR transformations must preserve? I.e., is this something that EH preparation can assume?</span><u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">EH preparation should not assume that each basic block lives in exactly one funclet. People seem to get really upset when I suggest that we change the language rules to maintain
that invariant. :-)<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Instead, the EH preparation pass is responsible for establishing that invariant by duplicating blocks, but it should be *way* easier with real basic block terminator instructions
to mark handler transitions.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">>
</span>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<u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">But then you have to frameescape any __finally-referenced local before optimization, and doesn't
that defeat the purpose of delaying funclet outlining to EH preparation?</span><u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">True. I'm not committed to this approach, I just want to preserve functionality until we implement the de-commoning part of EH preparation, which I figured we could do later, since
it's one of the more obscure corner cases.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Also, __finally is pretty rare, so it's not too crazy to teach the inliner how to undo framerecover and let the optimization fall out that way.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">>
</span>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<u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">For one, it seems counterproductive to let tail merge think it can kick in when it's doomed to be
undone.</span><u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">I'm only saying that the tail merging is legal, and not that it is desirable. We can teach simplifycfg that tail merging 'resume' instructions is a waste of time, for example.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">For another, if we're talking about a setup where EH paths might mingle with non-EH paths but the
funclet will only be invoked for the EH cases, then I believe this would help the "</span>pruning as many unreachable CFG edges as possible<span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d"> " step be more effective -- after finding
out which blocks are reachable from a catch/cleanup, you could intersect that with the set of blocks from which a corresponding resume can be reached. Any funclet blocks ending in condbr/switch that only wind up with one successor in the funclet could then
have their terminators rewritten as unconditional branches, without needing to recover dataflow and chase constants through phis and resolve compares/switches and all that.</span><u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">For discussion purposes, let's imagine that 'resume' takes a 'from' label which must be an EH block (it starts with one of these new instructions). The nice thing about using a
label here is that, unlike most SSA values, labels cannot be phi'd. Now tail merging will have to give up or insert an i1 ph and a conditional branch on the resume instruction, which realistically it won't since it's not a clear win.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Originally, I was thinking that this extra funclet cloning precision wasn't worth it, because we'd arrange the frontend and optimizers to make it unlikely, but I'm coming around
to it. It mirrors the EH pointer value required by Itanium EH.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border:none;border-left:solid #cccccc 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-top:5.0pt;margin-right:0in;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">></span> I'm not married to reusing 'resume', other candidate names include 'unwind' and 'continue',
and I'd like more ideas<u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">The first thing that comes to mind is 'endatch/exitcatch', but to use that you'd need to rename other
things since it would be confusing vis-à-vis catchendblock and lack symmetry with catchblock that isn't prefixed with begin/enter.</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">You could consider 'filter' (or 'filterblock') for 'catchblock', since conceptually it plays the
role of a filter (typically one which consults type information; I've seen such things called "typetestfilter" before). Or 'dispatch'/'dispatchblock'/'exceptiondispatch'/'dispatchexception' (isn't that what Clang names the blocks it creates for the explicit
dispatch code?); 'catchendblock' would then be something like 'unwinddispatch' or 'continuedispatch' or 'resumedispatch' and the resume that returns to normal execution could be 'exitdispatch' or 'exitcatch' or even 'uncatch'.</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">For the resumes that end cleanups, something like 'endcleanup' might work.</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1f497d">Names are hard…</span><u></u><u></u></p>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">'dispatch' might work for the instruction which transitions from a cleanup to the next EH block. :) I don't really see how to work filter in, especially since we've already used
it for landingpad filters, which exist to support exception specifications.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Chatting around the office, we came up with 'recover' and 'unwind' for ending catch and cleanup blocks respectively.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">A 'recover' instruction would end a catch block, and would target the block where the exception is over. This instruction would modify memory, because it destroys the exception
object. <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">An 'unwind' instruction would end a cleanup block, and would target the next action. I like this because I talk a lot about "unwind edges" in the CFG, and a cleanup finishing feels
like an unwind edge. I could also see 'dispatch' here.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Some possible new syntax:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">recover from label %<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__maycatch.int&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=Mfk2qtn1LTDThVkh6-oGglNfMADXfJdty4_bhmuhMHA&m=tMwK_Xt5hbbgdVLgXkuhG3JlU0CYHDTiWmOrpGwGMnU&s=_KjpdwoGLsa41bExszBKlOJq-PrJD54GSnHudA6GMi0&e=" target="_blank">maycatch.int</a> to label %endcatchbb<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">unwind from label %cleanup.obj to label %nextaction<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">unwind from label %cleanup.obj ; unwinds out of the function, hook it up to the unwind edge of an inlined call site<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">For Itanium, tail merging is profitable and doable with phis, so we might want to do this instead:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">recover to label %endcatchbb<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">unwind i8* %ehptr to label %nextaction<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">unwind i8* %ehptr ; unwinds out of the function, hook it up to the unwind edge of an inlined call site<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Itanium requires threading the active exception pointer through to the next action or _Unwind_Resume, so it passes along an SSA value. MSVC needs this weird kind of control dependence
instead. We could drop the 'from' token as unnecessary, but I want to make it easier to reason about the textual representation.<u></u><u></u></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
</div></div></div>
</div>
</blockquote></div><br></div>