The PR is about selective scheduling not trying hard enough to find a neighbor block to stick the note list from an empty block being removed. Fixed by a) trying harder and b) making sure that if we fail to find the right place, we just drop the notes instead of asserting.

Tested on x86-64 and ia64, approved by Alexander offline. No test as it has quite insane number of flags that would likely stop reproducing the core issue in a few weeks.

Richard, Jakub, I can commit this to trunk today or to wait until the release. The patch is very safe and so can be committed in case we will need an RC2, if you want one bug less in a release, but I would feel equally happy to postpone it until 4.7.1 as the problematic situation is quite rare (and probably requires pipelining outer loops to trigger which is disabled with ia64/-O3).


2012-03-05  Andrey Belevantsev  <a...@ispras.ru>

        PR rtl-optimization/52250
        * sel-sched-ir.c (maybe_tidy_empty_bb): Try harder to find a bb
        to put note list into.  Unconditionally call move_bb_info.
        (move_bb_info): Do not assert the blocks being in the same region,
        just drop the note list if they are not.

diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index a93cd68..c53d2e1 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -3658,7 +3658,7 @@ sel_recompute_toporder (void)
 static bool
 maybe_tidy_empty_bb (basic_block bb)
-  basic_block succ_bb, pred_bb;
+  basic_block succ_bb, pred_bb, note_bb;
   VEC (basic_block, heap) *dom_bbs;
   edge e;
   edge_iterator ei;
@@ -3697,6 +3697,17 @@ maybe_tidy_empty_bb (basic_block bb)
   pred_bb = NULL;
   dom_bbs = NULL;

+  /* Save a pred/succ from the current region to attach the notes to.  */
+  note_bb = NULL;
+  FOR_EACH_EDGE (e, ei, bb->preds)
+    if (in_current_region_p (e->src))
+      {
+       note_bb = e->src;
+       break;
+      }
+  if (note_bb == NULL)
+    note_bb = succ_bb;
   /* Redirect all non-fallthru edges to the next bb.  */
   while (rescan_p)
@@ -3746,10 +3757,8 @@ maybe_tidy_empty_bb (basic_block bb)
       /* This is a block without fallthru predecessor.  Just delete it.  */
-      gcc_assert (pred_bb != NULL);
-      if (in_current_region_p (pred_bb))
-       move_bb_info (pred_bb, bb);
+      gcc_assert (note_bb);
+      move_bb_info (note_bb, bb);
       remove_empty_bb (bb, true);

@@ -5231,10 +5240,9 @@ sel_remove_bb (basic_block bb, bool remove_from_cfg_p)
 static void
 move_bb_info (basic_block merge_bb, basic_block empty_bb)
-  gcc_assert (in_current_region_p (merge_bb));
-  concat_note_lists (BB_NOTE_LIST (empty_bb),
-                    &BB_NOTE_LIST (merge_bb));
+  if (in_current_region_p (merge_bb))
+    concat_note_lists (BB_NOTE_LIST (empty_bb),
+                      &BB_NOTE_LIST (merge_bb));
   BB_NOTE_LIST (empty_bb) = NULL_RTX;


Reply via email to