aboutsummaryrefslogtreecommitdiff
path: root/gcc/sel-sched.c
diff options
context:
space:
mode:
authoramonakov <amonakov@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-06 08:56:43 +0000
committeramonakov <amonakov@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-06 08:56:43 +0000
commitc6cff213327c7c1b67d851bed39a78d2f02d5948 (patch)
tree25cda3b1dd77a6abb9bee17215f7d7f9b96ba6e9 /gcc/sel-sched.c
parent9ebbbe7f6c2cf810ad840dfbf991c1c83a74906a (diff)
PR rtl-optimization/44919
* sel-sched.c (move_cond_jump): Remove assert, check that the several blocks case can only happen with mutually exclusive insns instead. Rewrite the movement code to support moving through several basic blocks. * g++.dg/opt/pr44919.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163904 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/sel-sched.c')
-rw-r--r--gcc/sel-sched.c70
1 files changed, 47 insertions, 23 deletions
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 0f02c0c9618..b3b1a802268 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -4875,18 +4875,35 @@ static void
move_cond_jump (rtx insn, bnd_t bnd)
{
edge ft_edge;
- basic_block block_from, block_next, block_new;
- rtx next, prev, link;
+ basic_block block_from, block_next, block_new, block_bnd, bb;
+ rtx next, prev, link, head;
- /* BLOCK_FROM holds basic block of the jump. */
block_from = BLOCK_FOR_INSN (insn);
+ block_bnd = BLOCK_FOR_INSN (BND_TO (bnd));
+ prev = BND_TO (bnd);
- /* Moving of jump should not cross any other jumps or
- beginnings of new basic blocks. */
- gcc_assert (block_from == BLOCK_FOR_INSN (BND_TO (bnd)));
+#ifdef ENABLE_CHECKING
+ /* Moving of jump should not cross any other jumps or beginnings of new
+ basic blocks. The only exception is when we move a jump through
+ mutually exclusive insns along fallthru edges. */
+ if (block_from != block_bnd)
+ {
+ bb = block_from;
+ for (link = PREV_INSN (insn); link != PREV_INSN (prev);
+ link = PREV_INSN (link))
+ {
+ if (INSN_P (link))
+ gcc_assert (sched_insns_conditions_mutex_p (insn, link));
+ if (BLOCK_FOR_INSN (link) && BLOCK_FOR_INSN (link) != bb)
+ {
+ gcc_assert (single_pred (bb) == BLOCK_FOR_INSN (link));
+ bb = BLOCK_FOR_INSN (link);
+ }
+ }
+ }
+#endif
/* Jump is moved to the boundary. */
- prev = BND_TO (bnd);
next = PREV_INSN (insn);
BND_TO (bnd) = insn;
@@ -4901,28 +4918,35 @@ move_cond_jump (rtx insn, bnd_t bnd)
gcc_assert (block_new->next_bb == block_next
&& block_from->next_bb == block_new);
- gcc_assert (BB_END (block_from) == insn);
-
- /* Move all instructions except INSN from BLOCK_FROM to
- BLOCK_NEW. */
- for (link = prev; link != insn; link = NEXT_INSN (link))
+ /* Move all instructions except INSN to BLOCK_NEW. */
+ bb = block_bnd;
+ head = BB_HEAD (block_new);
+ while (bb != block_from->next_bb)
{
- EXPR_ORIG_BB_INDEX (INSN_EXPR (link)) = block_new->index;
- df_insn_change_bb (link, block_new);
- }
+ rtx from, to;
+ from = bb == block_bnd ? prev : sel_bb_head (bb);
+ to = bb == block_from ? next : sel_bb_end (bb);
- /* Set correct basic block and instructions properties. */
- BB_END (block_new) = PREV_INSN (insn);
+ /* The jump being moved can be the first insn in the block.
+ In this case we don't have to move anything in this block. */
+ if (NEXT_INSN (to) != from)
+ {
+ reorder_insns (from, to, head);
- NEXT_INSN (PREV_INSN (prev)) = insn;
- PREV_INSN (insn) = PREV_INSN (prev);
+ for (link = to; link != head; link = PREV_INSN (link))
+ EXPR_ORIG_BB_INDEX (INSN_EXPR (link)) = block_new->index;
+ head = to;
+ }
+
+ /* Cleanup possibly empty blocks left. */
+ block_next = bb->next_bb;
+ if (bb != block_from)
+ maybe_tidy_empty_bb (bb);
+ bb = block_next;
+ }
/* Assert there is no jump to BLOCK_NEW, only fallthrough edge. */
gcc_assert (NOTE_INSN_BASIC_BLOCK_P (BB_HEAD (block_new)));
- PREV_INSN (prev) = BB_HEAD (block_new);
- NEXT_INSN (next) = NEXT_INSN (BB_HEAD (block_new));
- NEXT_INSN (BB_HEAD (block_new)) = prev;
- PREV_INSN (NEXT_INSN (next)) = next;
gcc_assert (!sel_bb_empty_p (block_from)
&& !sel_bb_empty_p (block_new));