[LLVMdev] RFC: New EH representation for MSVC compatibility

Reid Kleckner rnk at google.com
Tue May 19 12:39:31 PDT 2015


On Mon, May 18, 2015 at 8:40 PM, Joseph Tremoulet <jotrem at microsoft.com>
wrote:

>  > I want to have separate normal and exceptional codepaths
>
> 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?
>

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. :-)

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.

> 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
>
> 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?
>

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.

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.


> > 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
>
> For one, it seems counterproductive to let tail merge think it can kick in
> when it's doomed to be undone.
>

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.


>  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  "pruning as many unreachable CFG
> edges as possible " 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.
>

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.

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.


> > I'm not married to reusing 'resume', other candidate names include
> 'unwind' and 'continue', and I'd like more ideas
>
> 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.
>
> 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'.
>
> For the resumes that end cleanups, something like 'endcleanup' might work.
>
> Names are hard…
>

'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.

Chatting around the office, we came up with 'recover' and 'unwind' for
ending catch and cleanup blocks respectively.

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.

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.

Some possible new syntax:

recover from label %maycatch.int to label %endcatchbb
unwind from label %cleanup.obj to label %nextaction
unwind from label %cleanup.obj    ; unwinds out of the function, hook it up
to the unwind edge of an inlined call site

For Itanium, tail merging is profitable and doable with phis, so we might
want to do this instead:

recover to label %endcatchbb
unwind i8* %ehptr to label %nextaction
unwind i8* %ehptr    ; unwinds out of the function, hook it up to the
unwind edge of an inlined call site

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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150519/abf5e16d/attachment.html>


More information about the llvm-dev mailing list