On Tue, 6 Mar 2018, Richard Biener wrote:
> > bb1
> > ret = setjmp(buf)
> > | \ bb-recv
> > | ----------------\
> > | ret = setjmp_receiver
> > | /
> > normal /---------------/
> > path /
> > | /
> > bb-succ
> > None of these edges would be abnormal. bb-recv would be the target for
> > edges from all calls that might call longjmp(buf). Those edges might need
> > to be abnormal. As the above CFG reflects all runtime effects precisely,
> > but not which instructions are used to achieve them the expansion to RTL
> > will be special.
> Why do you still have the edge from setjmp to the setjmp receiver?
Ah, yes, that needs explanation. Without that edge the receiver hangs in
the air, so to speak. But all effects that happened before the setjmp
invocation also have happened before the second return, so the
setjmp_receiver needs to be dominated by the setjmp call, and that
requires and CFG edge. A different way of thinking about this is that
both "calls" need VDEF/VUSE, and the VUSE of setjmp_receiver needs to be
the VDEF of the setjmp, so again that edge needs to be there for ordering
reasons. At least that's the obvious way of ordering. Thinking harder
might make the edge unnecessary after all: all paths leading to longjmps
need to go through a setjmp, so the call->receiver edges are already
ordered behind setjmp calls (though not necessarily dominated by them), so
the receiver is, and so we might be fine. I'd have to paint some pictures
on our board to see how this behaves with multiple reaching setjmps.
> In your scheme ret is set twice on the longjmp return path, no?
No, it's set once on the first-return path, and once on the second-return
path (from longjmp to setjmp_receiver, which sets ret, the set of the
setjmp call isn't done on the second-return path). Which is indeed what
happens in reality, the return register is set once on first-return and
once on second-return.
> That is, you have the same issue left as we have with EH returns from a
> stmt with a LHS.
I don't see that, which problem?
> We currently have two outgoing edges from setjmp, one which feeds back
> to right before the setjmp call via the abnormal dispatcher (so it looks
> like a loop). Jeffs change will make it two outgoing edges to the same
> single successor, one dispatched through the abnormal dispatcher (that
> also nicely gets around the limitation of only having a single edge
> between two blocks...)
The crucial thing that needs to happen is that all paths from longjmp to
the normal successor of the setjmp call contain an assignment to LHS.
The edges out of setjmp aren't the important thing for this, the
destination of edges from the dispatcher are (because that's the one
targeted by the longjmp calls). And IIUC Jeffs patch makes those edges
target something after the LHS-set, and this can't be right. Make the
dispatcher set an LHS (and hence have one per setjmp, not one per
function) and you're effectively ending up with my proposal above.