diff options
author | segher <segher@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-12-11 00:27:14 +0000 |
---|---|---|
committer | segher <segher@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-12-11 00:27:14 +0000 |
commit | 7af735bee09f305906f31e7b5a51d5229fa49c5a (patch) | |
tree | dc15978b0076a05b78a6f5c3f29688925bde398f | |
parent | b1d369b60bc0dbf7008f931ad56cf5163ec63b93 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/shrink-wrap.c | 40 |
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); |