summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-11 00:27:14 +0000
committersegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-11 00:27:14 +0000
commit7af735bee09f305906f31e7b5a51d5229fa49c5a (patch)
treedc15978b0076a05b78a6f5c3f29688925bde398f
parentb1d369b60bc0dbf7008f931ad56cf5163ec63b93 (diff)
downloadgcc-7af735bee09f305906f31e7b5a51d5229fa49c5a.tar.gz
Fix shrink-wrapping bug (PR67778, PR68634)
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, because then we will never need to duplicate that block (it will always be executed with prologue). 2015-12-11 Segher Boessenkool <segher@kernel.crashing.org> PR rtl-optimization/67778 PR rtl-optimization/68634 * shrink-wrap.c (try_shrink_wrapping): Add a comment about why we want to put the prologue earlier. When determining if an earlier block is suitable, make sure it dominates every block reachable from it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231552 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/shrink-wrap.c40
2 files changed, 43 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d6622299cdc..ab875851c89 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2015-12-11 Segher Boessenkool <segher@kernel.crashing.org>
+ PR rtl-optimization/67778
+ PR rtl-optimization/68634
+ * shrink-wrap.c (try_shrink_wrapping): Add a comment about why we want
+ to put the prologue earlier. When determining if an earlier block is
+ suitable, make sure it dominates every block reachable from it.
+
+2015-12-11 Segher Boessenkool <segher@kernel.crashing.org>
+
PR rtl-optimization/68814
* rtlanal.c (set_noop_p): Use BITS_BIG_ENDIAN instead of
BYTES_BIG_ENDIAN.
diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c
index 3a1df845e20..f65b0c3e550 100644
--- a/gcc/shrink-wrap.c
+++ b/gcc/shrink-wrap.c
@@ -744,36 +744,66 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
vec.quick_push (e->dest);
}
- vec.release ();
-
if (dump_file)
fprintf (dump_file, "Avoiding non-duplicatable blocks, PRO is now %d\n",
pro->index);
/* If we can move PRO back without having to duplicate more blocks, do so.
+ We do this because putting the prologue earlier is better for scheduling.
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. PRE needs
+ to dominate every block reachable from itself. */
if (pro != entry)
{
calculate_dominance_info (CDI_POST_DOMINATORS);
+ bitmap bb_tmp = BITMAP_ALLOC (NULL);
+ bitmap_copy (bb_tmp, bb_with);
basic_block last_ok = pro;
+ vec.truncate (0);
+
while (pro != entry)
{
basic_block pre = get_immediate_dominator (CDI_DOMINATORS, pro);
if (!dominated_by_p (CDI_POST_DOMINATORS, pre, pro))
break;
+ if (bitmap_set_bit (bb_tmp, pre->index))
+ vec.quick_push (pre);
+
+ bool ok = true;
+ while (!vec.is_empty ())
+ {
+ basic_block bb = vec.pop ();
+ bitmap_set_bit (bb_tmp, pre->index);
+
+ if (!dominated_by_p (CDI_DOMINATORS, bb, pre))
+ {
+ ok = false;
+ break;
+ }
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (!bitmap_bit_p (bb_with, e->dest->index)
+ && bitmap_set_bit (bb_tmp, e->dest->index))
+ vec.quick_push (e->dest);
+ }
+
+ if (ok && can_get_prologue (pre, prologue_clobbered))
+ last_ok = pre;
+
pro = pre;
- if (can_get_prologue (pro, prologue_clobbered))
- last_ok = pro;
}
+
pro = last_ok;
+ BITMAP_FREE (bb_tmp);
free_dominance_info (CDI_POST_DOMINATORS);
}
+ vec.release ();
+
if (dump_file)
fprintf (dump_file, "Bumping back to anticipatable blocks, PRO is now %d\n",
pro->index);