mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-28 16:01:00 +08:00
re PR middle-end/42245 (ICE in verify_backedges for 197.parser with sel-sched)
2010-01-14 Andrey Belevantsev <abel@ispras.ru> Alexander Monakov <amonakov@ispras.ru> PR middle-end/42245 * sel-sched-ir.c (sel_recompute_toporder): New. Use it... (maybe_tidy_empty_bb): ... here. Make static. Add new argument. Update all callers. (tidy_control_flow): ... and here. Recompute topological order of basic blocks in region if necessary. (sel_redirect_edge_and_branch): Change return type. Return true if topological order might have been invalidated. (purge_empty_blocks): Export and move from... * sel-sched.c (purge_empty_blocks): ... here. * sel-sched-ir.h (sel_redirect_edge_and_branch): Update prototype. (maybe_tidy_empty_bb): Delete prototype. (purge_empty_blocks): Declare. * gcc.dg/pr42245.c: New. * gcc.dg/pr42245-2.c: New. From-SVN: r155890
This commit is contained in:
parent
0666ff4e33
commit
b59ab5709e
@ -1,6 +1,23 @@
|
||||
2010-01-14 Andrey Belevantsev <abel@ispras.ru>
|
||||
Alexander Monakov <amonakov@ispras.ru>
|
||||
|
||||
PR middle-end/42245
|
||||
* sel-sched-ir.c (sel_recompute_toporder): New. Use it...
|
||||
(maybe_tidy_empty_bb): ... here. Make static. Add new
|
||||
argument. Update all callers.
|
||||
(tidy_control_flow): ... and here. Recompute topological order
|
||||
of basic blocks in region if necessary.
|
||||
(sel_redirect_edge_and_branch): Change return type. Return true
|
||||
if topological order might have been invalidated.
|
||||
(purge_empty_blocks): Export and move from...
|
||||
* sel-sched.c (purge_empty_blocks): ... here.
|
||||
* sel-sched-ir.h (sel_redirect_edge_and_branch): Update prototype.
|
||||
(maybe_tidy_empty_bb): Delete prototype.
|
||||
(purge_empty_blocks): Declare.
|
||||
|
||||
2010-01-14 Andrey Belevantsev <abel@ispras.ru>
|
||||
|
||||
PR rtl-optimization/42294
|
||||
PR rtl-optimization/42249
|
||||
* sel-sched.c (try_replace_dest_reg): When chosen register
|
||||
and original register is the same, do not bail out early, but
|
||||
still check all original insns for validity of replacing destination
|
||||
|
@ -3503,9 +3503,36 @@ verify_backedges (void)
|
||||
|
||||
/* Functions to work with control flow. */
|
||||
|
||||
/* Recompute BLOCK_TO_BB and BB_FOR_BLOCK for current region so that blocks
|
||||
are sorted in topological order (it might have been invalidated by
|
||||
redirecting an edge). */
|
||||
static void
|
||||
sel_recompute_toporder (void)
|
||||
{
|
||||
int i, n, rgn;
|
||||
int *postorder, n_blocks;
|
||||
|
||||
postorder = XALLOCAVEC (int, n_basic_blocks);
|
||||
n_blocks = post_order_compute (postorder, false, false);
|
||||
|
||||
rgn = CONTAINING_RGN (BB_TO_BLOCK (0));
|
||||
for (n = 0, i = n_blocks - 1; i >= 0; i--)
|
||||
if (CONTAINING_RGN (postorder[i]) == rgn)
|
||||
{
|
||||
BLOCK_TO_BB (postorder[i]) = n;
|
||||
BB_TO_BLOCK (n) = postorder[i];
|
||||
n++;
|
||||
}
|
||||
|
||||
/* Assert that we updated info for all blocks. We may miss some blocks if
|
||||
this function is called when redirecting an edge made a block
|
||||
unreachable, but that block is not deleted yet. */
|
||||
gcc_assert (n == RGN_NR_BLOCKS (rgn));
|
||||
}
|
||||
|
||||
/* Tidy the possibly empty block BB. */
|
||||
bool
|
||||
maybe_tidy_empty_bb (basic_block bb)
|
||||
static bool
|
||||
maybe_tidy_empty_bb (basic_block bb, bool recompute_toporder_p)
|
||||
{
|
||||
basic_block succ_bb, pred_bb;
|
||||
edge e;
|
||||
@ -3552,7 +3579,7 @@ maybe_tidy_empty_bb (basic_block bb)
|
||||
|
||||
if (!(e->flags & EDGE_FALLTHRU))
|
||||
{
|
||||
sel_redirect_edge_and_branch (e, succ_bb);
|
||||
recompute_toporder_p |= sel_redirect_edge_and_branch (e, succ_bb);
|
||||
rescan_p = true;
|
||||
break;
|
||||
}
|
||||
@ -3572,6 +3599,9 @@ maybe_tidy_empty_bb (basic_block bb)
|
||||
remove_empty_bb (bb, true);
|
||||
}
|
||||
|
||||
if (recompute_toporder_p)
|
||||
sel_recompute_toporder ();
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
verify_backedges ();
|
||||
#endif
|
||||
@ -3589,7 +3619,7 @@ tidy_control_flow (basic_block xbb, bool full_tidying)
|
||||
insn_t first, last;
|
||||
|
||||
/* First check whether XBB is empty. */
|
||||
changed = maybe_tidy_empty_bb (xbb);
|
||||
changed = maybe_tidy_empty_bb (xbb, false);
|
||||
if (changed || !full_tidying)
|
||||
return changed;
|
||||
|
||||
@ -3640,22 +3670,45 @@ tidy_control_flow (basic_block xbb, bool full_tidying)
|
||||
/* Also this jump is not at the scheduling boundary. */
|
||||
&& !IN_CURRENT_FENCE_P (BB_END (xbb->prev_bb)))
|
||||
{
|
||||
bool recompute_toporder_p;
|
||||
/* Clear data structures of jump - jump itself will be removed
|
||||
by sel_redirect_edge_and_branch. */
|
||||
clear_expr (INSN_EXPR (BB_END (xbb->prev_bb)));
|
||||
sel_redirect_edge_and_branch (EDGE_SUCC (xbb->prev_bb, 0), xbb);
|
||||
recompute_toporder_p
|
||||
= sel_redirect_edge_and_branch (EDGE_SUCC (xbb->prev_bb, 0), xbb);
|
||||
|
||||
gcc_assert (EDGE_SUCC (xbb->prev_bb, 0)->flags & EDGE_FALLTHRU);
|
||||
|
||||
/* It can turn out that after removing unused jump, basic block
|
||||
that contained that jump, becomes empty too. In such case
|
||||
remove it too. */
|
||||
if (sel_bb_empty_p (xbb->prev_bb))
|
||||
changed = maybe_tidy_empty_bb (xbb->prev_bb);
|
||||
changed = maybe_tidy_empty_bb (xbb->prev_bb, recompute_toporder_p);
|
||||
else if (recompute_toporder_p)
|
||||
sel_recompute_toporder ();
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/* Purge meaningless empty blocks in the middle of a region. */
|
||||
void
|
||||
purge_empty_blocks (void)
|
||||
{
|
||||
/* Do not attempt to delete preheader. */
|
||||
int i = sel_is_loop_preheader_p (BASIC_BLOCK (BB_TO_BLOCK (0))) ? 1 : 0;
|
||||
|
||||
while (i < current_nr_blocks)
|
||||
{
|
||||
basic_block b = BASIC_BLOCK (BB_TO_BLOCK (i));
|
||||
|
||||
if (maybe_tidy_empty_bb (b, false))
|
||||
continue;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Rip-off INSN from the insn stream. When ONLY_DISCONNECT is true,
|
||||
do not delete insn's data, because it will be later re-emitted.
|
||||
Return true if we have removed some blocks afterwards. */
|
||||
@ -5355,8 +5408,9 @@ sel_redirect_edge_and_branch_force (edge e, basic_block to)
|
||||
sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP);
|
||||
}
|
||||
|
||||
/* A wrapper for redirect_edge_and_branch. */
|
||||
void
|
||||
/* A wrapper for redirect_edge_and_branch. Return TRUE if blocks connected by
|
||||
redirected edge are in reverse topological order. */
|
||||
bool
|
||||
sel_redirect_edge_and_branch (edge e, basic_block to)
|
||||
{
|
||||
bool latch_edge_p;
|
||||
@ -5364,6 +5418,7 @@ sel_redirect_edge_and_branch (edge e, basic_block to)
|
||||
int prev_max_uid;
|
||||
rtx jump;
|
||||
edge redirected;
|
||||
bool recompute_toporder_p = false;
|
||||
|
||||
latch_edge_p = (pipelining_p
|
||||
&& current_loop_nest
|
||||
@ -5383,9 +5438,18 @@ sel_redirect_edge_and_branch (edge e, basic_block to)
|
||||
gcc_assert (loop_latch_edge (current_loop_nest));
|
||||
}
|
||||
|
||||
/* In rare situations, the topological relation between the blocks connected
|
||||
by the redirected edge can change (see PR42245 for an example). Update
|
||||
block_to_bb/bb_to_block. */
|
||||
if (CONTAINING_RGN (e->src->index) == CONTAINING_RGN (to->index)
|
||||
&& BLOCK_TO_BB (e->src->index) > BLOCK_TO_BB (to->index))
|
||||
recompute_toporder_p = true;
|
||||
|
||||
jump = find_new_jump (src, NULL, prev_max_uid);
|
||||
if (jump)
|
||||
sel_init_new_insn (jump, INSN_INIT_TODO_LUID | INSN_INIT_TODO_SIMPLEJUMP);
|
||||
|
||||
return recompute_toporder_p;
|
||||
}
|
||||
|
||||
/* This variable holds the cfg hooks used by the selective scheduler. */
|
||||
|
@ -1613,11 +1613,11 @@ extern bool tidy_control_flow (basic_block, bool);
|
||||
extern void free_bb_note_pool (void);
|
||||
|
||||
extern void sel_remove_empty_bb (basic_block, bool, bool);
|
||||
extern bool maybe_tidy_empty_bb (basic_block bb);
|
||||
extern void purge_empty_blocks (void);
|
||||
extern basic_block sel_split_edge (edge);
|
||||
extern basic_block sel_create_recovery_block (insn_t);
|
||||
extern void sel_merge_blocks (basic_block, basic_block);
|
||||
extern void sel_redirect_edge_and_branch (edge, basic_block);
|
||||
extern bool sel_redirect_edge_and_branch (edge, basic_block);
|
||||
extern void sel_redirect_edge_and_branch_force (edge, basic_block);
|
||||
extern void sel_init_pipelining (void);
|
||||
extern void sel_finish_pipelining (void);
|
||||
|
@ -6765,24 +6765,6 @@ setup_current_loop_nest (int rgn)
|
||||
gcc_assert (LOOP_MARKED_FOR_PIPELINING_P (current_loop_nest));
|
||||
}
|
||||
|
||||
/* Purge meaningless empty blocks in the middle of a region. */
|
||||
static void
|
||||
purge_empty_blocks (void)
|
||||
{
|
||||
/* Do not attempt to delete preheader. */
|
||||
int i = sel_is_loop_preheader_p (BASIC_BLOCK (BB_TO_BLOCK (0))) ? 1 : 0;
|
||||
|
||||
while (i < current_nr_blocks)
|
||||
{
|
||||
basic_block b = BASIC_BLOCK (BB_TO_BLOCK (i));
|
||||
|
||||
if (maybe_tidy_empty_bb (b))
|
||||
continue;
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute instruction priorities for current region. */
|
||||
static void
|
||||
sel_compute_priorities (int rgn)
|
||||
|
@ -1,6 +1,12 @@
|
||||
2010-01-14 Alexander Monakov <amonakov@ispras.ru>
|
||||
|
||||
PR rtl-optimization/42294
|
||||
PR middle-end/42245
|
||||
* gcc.dg/pr42245.c: New.
|
||||
* gcc.dg/pr42245-2.c: New.
|
||||
|
||||
2010-01-14 Alexander Monakov <amonakov@ispras.ru>
|
||||
|
||||
PR rtl-optimization/42249
|
||||
* gcc.dg/pr42249.c: New.
|
||||
|
||||
2010-01-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
Loading…
x
Reference in New Issue
Block a user