backport: re PR middle-end/42245 (ICE in verify_backedges for 197.parser with sel-sched)

Backport from mainline:
 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.

From-SVN: r163504
This commit is contained in:
Andrey Belevantsev 2010-08-24 12:57:18 +04:00 committed by Andrey Belevantsev
parent ca8c82b82e
commit 8b97cddde8
5 changed files with 107 additions and 32 deletions

View File

@ -1,9 +1,29 @@
2010-08-24 Andrey Belevantsev <abel@ispras.ru>
Backport from mainline:
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-08-24 Andrey Belevantsev <abel@ispras.ru>
Backport from mainline:
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

View File

@ -3500,9 +3500,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;
@ -3549,7 +3576,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;
}
@ -3569,6 +3596,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
@ -3585,7 +3615,7 @@ tidy_control_flow (basic_block xbb, bool full_tidying)
bool changed = true;
/* 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;
@ -3622,24 +3652,47 @@ 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;
}
/* 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.
/* 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. */
bool
sel_remove_insn (insn_t insn, bool only_disconnect, bool full_tidying)
@ -5322,8 +5375,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;
@ -5331,6 +5385,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
@ -5350,9 +5405,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. */

View File

@ -1574,11 +1574,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);

View File

@ -6492,24 +6492,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)

View File

@ -3,7 +3,16 @@
Backport from mainline:
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-08-24 Andrey Belevantsev <abel@ispras.ru>
Backport from mainline:
2010-01-14 Alexander Monakov <amonakov@ispras.ru>
PR rtl-optimization/42249
* gcc.dg/pr42249.c: New.
2010-08-24 Andrey Belevantsev <abel@ispras.ru>