summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/sel-sched-ir.c80
-rw-r--r--gcc/sel-sched-ir.h4
-rw-r--r--gcc/sel-sched.c18
-rw-r--r--gcc/testsuite/ChangeLog8
5 files changed, 99 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b4ebd0b20a3..fda47c64143 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index e864eb40c7a..ad1dcb212de 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -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. */
diff --git a/gcc/sel-sched-ir.h b/gcc/sel-sched-ir.h
index 1950a65e77f..db2989b6111 100644
--- a/gcc/sel-sched-ir.h
+++ b/gcc/sel-sched-ir.h
@@ -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);
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index 27c0f21ea3b..4ca8ab22f85 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a407fb72536..855b25673f8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>