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

Reply via email to