diff options
author | amonakov <amonakov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-09-06 08:56:43 +0000 |
---|---|---|
committer | amonakov <amonakov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-09-06 08:56:43 +0000 |
commit | c6cff213327c7c1b67d851bed39a78d2f02d5948 (patch) | |
tree | 25cda3b1dd77a6abb9bee17215f7d7f9b96ba6e9 /gcc/sel-sched.c | |
parent | 9ebbbe7f6c2cf810ad840dfbf991c1c83a74906a (diff) | |
download | gcc-c6cff213327c7c1b67d851bed39a78d2f02d5948.tar.gz |
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.c | 70 |
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)); |