After shrink-wrapping has found the "tightest fit" for where to place the prologue, it tries move it earlier (so that frame saves are run earlier) -- but without copying any more basic blocks.
Unfortunately a candidate block we select can be inside a loop, and we will still allow it (because the loop always exits via our previously chosen block). We can do that just fine if we make a duplicate of the block, but we do not want to here. So we need to detect this situation. We can place the prologue at a previous block PRE only if PRE dominates every block reachable from it. This is a bit hard / expensive to compute, so instead this patch allows a block PRE only if PRE does not post-dominate any of its successors (other than itself). Tested on the two testcases from the PRs. Also regression checked on powerpc64-linux. Is this okay for trunk? Segher 2015-12-02 Segher Boessenkool <seg...@kernel.crashing.org> * shrink-wrap.c (try_shrink_wrapping): Disallow moving the prologue back into a loop. --- gcc/shrink-wrap.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c index 3a1df84..fe33652 100644 --- a/gcc/shrink-wrap.c +++ b/gcc/shrink-wrap.c @@ -752,7 +752,11 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with, /* If we can move PRO back without having to duplicate more blocks, do so. We can move back to a block PRE if every path from PRE will eventually - need a prologue, that is, PRO is a post-dominator of PRE. */ + need a prologue, that is, PRO is a post-dominator of PRE. We might + need to duplicate PRE if there is any path from a successor of PRE back + to PRE, so don't allow that either (but self-loops are fine, as are any + other loops entirely dominated by PRE; this in general seems too + expensive to check for, for such an uncommon case). */ if (pro != entry) { @@ -765,9 +769,20 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with, if (!dominated_by_p (CDI_POST_DOMINATORS, pre, pro)) break; + bool ok = true; + + if (!can_get_prologue (pre, prologue_clobbered)) + ok = false; + + FOR_EACH_EDGE (e, ei, pre->succs) + if (e->dest != pre + && dominated_by_p (CDI_POST_DOMINATORS, e->dest, pre)) + ok = false; + + if (ok) + last_ok = pre; + pro = pre; - if (can_get_prologue (pro, prologue_clobbered)) - last_ok = pro; } pro = last_ok; -- 1.9.3