Hi, On Wed, 28 Feb 2018, Jeff Law wrote:
> The single successor test was strictly my paranoia WRT abnormal/EH edges. > > I don't immediately see why the CFG would be incorrect if the successor > of the setjmp block has multiple preds. Actually, without further conditions I don't see how it would be safe for the successor to have multiple preds. We might have this situation: bb1: ret = setjmp bb2: x0 = phi <x1 (bb1), foo(bbX)> As you noted the second "return" from setjmp is precisely after the setjmp call itself, i.e. on the edge bb1->bb2. Simply regarding it as landing at the start of bb2 it becomes unclear from which edge bb2 was entered and hence the runtime model of PHI nodes breaks down. So, the mental model would be that a hypothetical setjmp_receiver (which isn't hypothetical for SJLJ) would have to be inserted on the bb1->bb2 edge. From then normal edge insertion routines take over: because the bb1-setjmp block only has a single successor (I know it currently doesn't, bear with me) it's actually inserted at the end of bb1 (so that edge doesn't need splitting), which is indeed what you want. Except that to have a target for the abnormal edges the setjmp_receiver needs to start its own basic block, so you'd need to create a new edge, which then implicitely creates the situation that the successor of the setjmp block only has a single predecessor (until you add the abnormal edges to the receiver of course): bb1 : setjmp; /* fallthrough */ bb1': ret = setjmp_receiver /* fallthrough */ bg2 : x0 = phi<x1(bb1'), foo(bbX)> While this models what actually happens with setjmp quite fine it poses the problem that nothing must be moved between setjmp and setjmp_receiver, so it seems indeed better to leave them as just one instruction. But the edge modelling needs to ensure that the above runtime model is followed, and so needs to ensure that the actual target of the abnormal edge doesn't have multiple predecessors (before adding the abnormal edge that is), so the edge must be split I think. Actually I wonder if it weren't better to regard return-twice functions like COND_EXPR, and always create two outgoing edges of such blocks, one the normal first-return, the other the (abnormal) second-return. The target block of that second-return would then also be the target of all function calls potentially calling longjmp, and so on. That target block would then only have abnormal predecessors, and your problem would have also gone away. In addition a setjmp call would then be normally eliminable by unreachable-code analysis (and the second-return target block as well eventually) This would also naturally deal with the problem, that while the real second return is after the setjmp call it happens before the setting of the return value. Ciao, Michael.