]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/41883 (ICE from '-O -fprofile-arcs -fsched2-use-superblocks -ftree...
authorRichard Henderson <rth@redhat.com>
Wed, 6 Jan 2010 18:34:31 +0000 (10:34 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 6 Jan 2010 18:34:31 +0000 (10:34 -0800)
PR middle-end/41883
* haifa-sched.c (add_to_note_list): Merge into ...
(concat_note_lists): ... here, and ...
(unlink_other_notes, rm_other_notes): Merge into...
(remove_notes): ... here.  Create REG_SAVE_NOTEs for
NOTE_INSN_EPILOGUE_BEG.

From-SVN: r155680

gcc/ChangeLog
gcc/haifa-sched.c
gcc/testsuite/gcc.dg/pr42396.c [new file with mode: 0644]

index 6435d2a5533d1b55fe2e6a02790b5f45e4447255..e8aa64b4127e806ee39d9c03ddd259bf86cea461 100644 (file)
@@ -1,3 +1,12 @@
+2010-01-06  Richard Henderson  <rth@redhat.com>
+
+       PR middle-end/41883
+       * haifa-sched.c (add_to_note_list): Merge into ...
+       (concat_note_lists): ... here, and ...
+       (unlink_other_notes, rm_other_notes): Merge into...
+       (remove_notes): ... here.  Create REG_SAVE_NOTEs for
+       NOTE_INSN_EPILOGUE_BEG.  
+
 2010-01-06  Richard Guenther  <rguenther@suse.de>
 
        * ipa-inline.c (cgraph_decide_inlining_incrementally): Do
index 204fab6aff94ec189e1d0e5acfa5dd02e00a6fb6..de75286ef282c757962bfb2a773115554797d387 100644 (file)
@@ -1,6 +1,6 @@
 /* Instruction scheduling pass.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
@@ -1803,89 +1803,87 @@ schedule_insn (rtx insn)
 
 /* Functions for handling of notes.  */
 
-/* Insert the INSN note at the end of the notes list.  */
-static void
-add_to_note_list (rtx insn, rtx *note_list_end_p)
-{
-  PREV_INSN (insn) = *note_list_end_p;
-  if (*note_list_end_p)
-    NEXT_INSN (*note_list_end_p) = insn;
-  *note_list_end_p = insn;
-}
-
 /* Add note list that ends on FROM_END to the end of TO_ENDP.  */
 void
 concat_note_lists (rtx from_end, rtx *to_endp)
 {
   rtx from_start;
 
+  /* It's easy when have nothing to concat.  */
   if (from_end == NULL)
-    /* It's easy when have nothing to concat.  */
     return;
 
+  /* It's also easy when destination is empty.  */
   if (*to_endp == NULL)
-    /* It's also easy when destination is empty.  */
     {
       *to_endp = from_end;
       return;
     }
 
   from_start = from_end;
-  /* A note list should be traversed via PREV_INSN.  */
   while (PREV_INSN (from_start) != NULL)
     from_start = PREV_INSN (from_start);
 
-  add_to_note_list (from_start, to_endp);
+  PREV_INSN (from_start) = *to_endp;
+  NEXT_INSN (*to_endp) = from_start;
   *to_endp = from_end;
 }
 
-/* Delete notes beginning with INSN and put them in the chain
-   of notes ended by NOTE_LIST.
-   Returns the insn following the notes.  */
-static rtx
-unlink_other_notes (rtx insn, rtx tail)
+/* Delete notes between HEAD and TAIL and put them in the chain
+   of notes ended by NOTE_LIST.  */
+void
+remove_notes (rtx head, rtx tail)
 {
-  rtx prev = PREV_INSN (insn);
+  rtx next_tail, prev, insn, next;
 
-  while (insn != tail && NOTE_NOT_BB_P (insn))
-    {
-      rtx next = NEXT_INSN (insn);
-      basic_block bb = BLOCK_FOR_INSN (insn);
-
-      /* Delete the note from its current position.  */
-      if (prev)
-       NEXT_INSN (prev) = next;
-      if (next)
-       PREV_INSN (next) = prev;
+  note_list = 0;
+  if (head == tail && !INSN_P (head))
+    return;
 
-      if (bb)
-        {
-          /* Basic block can begin with either LABEL or
-             NOTE_INSN_BASIC_BLOCK.  */
-          gcc_assert (BB_HEAD (bb) != insn);
+  next_tail = NEXT_INSN (tail);
+  prev = PREV_INSN (head);
+  for (insn = head; insn != next_tail; insn = next)
+    {
+      next = NEXT_INSN (insn);
+      if (!NOTE_P (insn))
+       {
+         prev = insn;
+         continue;
+       }
 
-          /* Check if we are removing last insn in the BB.  */
-          if (BB_END (bb) == insn)
-            BB_END (bb) = prev;
-        }
+      switch (NOTE_KIND (insn))
+       {
+       case NOTE_INSN_BASIC_BLOCK:
+         prev = insn;
+         continue;
 
-      /* See sched_analyze to see how these are handled.  */
-      if (NOTE_KIND (insn) != NOTE_INSN_EH_REGION_BEG
-         && NOTE_KIND (insn) != NOTE_INSN_EH_REGION_END)
-        add_to_note_list (insn, &note_list);
+       case NOTE_INSN_EPILOGUE_BEG:
+         if (insn != tail)
+           {
+             remove_insn (insn);
+             add_reg_note (next, REG_SAVE_NOTE,
+                           GEN_INT (NOTE_INSN_EPILOGUE_BEG));
+             break;
+           }
+         /* FALLTHRU */
 
-      insn = next;
-    }
+       default:
+         remove_insn (insn);
+
+         /* Add the note to list that ends at NOTE_LIST.  */
+         PREV_INSN (insn) = note_list;
+         NEXT_INSN (insn) = NULL_RTX;
+         if (note_list)
+           NEXT_INSN (note_list) = insn;
+         note_list = insn;
+         break;
+       }
 
-  if (insn == tail)
-    {
-      gcc_assert (sel_sched_p ());
-      return prev;
+      gcc_assert ((sel_sched_p () || insn != tail) && insn != head);
     }
-
-  return insn;
 }
 
+
 /* Return the head and tail pointers of ebb starting at BEG and ending
    at END.  */
 void
@@ -1939,62 +1937,6 @@ no_real_insns_p (const_rtx head, const_rtx tail)
   return 1;
 }
 
-/* Delete notes between HEAD and TAIL and put them in the chain
-   of notes ended by NOTE_LIST.  */
-static void
-rm_other_notes (rtx head, rtx tail)
-{
-  rtx next_tail;
-  rtx insn;
-
-  note_list = 0;
-  if (head == tail && (! INSN_P (head)))
-    return;
-
-  next_tail = NEXT_INSN (tail);
-  for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
-    {
-      rtx prev;
-
-      /* Farm out notes, and maybe save them in NOTE_LIST.
-         This is needed to keep the debugger from
-         getting completely deranged.  */
-      if (NOTE_NOT_BB_P (insn))
-       {
-         prev = insn;
-         insn = unlink_other_notes (insn, next_tail);
-
-         gcc_assert ((sel_sched_p ()
-                      || prev != tail) && prev != head && insn != next_tail);
-       }
-    }
-}
-
-/* Same as above, but also process REG_SAVE_NOTEs of HEAD.  */
-void
-remove_notes (rtx head, rtx tail)
-{
-  /* rm_other_notes only removes notes which are _inside_ the
-     block---that is, it won't remove notes before the first real insn
-     or after the last real insn of the block.  So if the first insn
-     has a REG_SAVE_NOTE which would otherwise be emitted before the
-     insn, it is redundant with the note before the start of the
-     block, and so we have to take it out.  */
-  if (INSN_P (head))
-    {
-      rtx note;
-
-      for (note = REG_NOTES (head); note; note = XEXP (note, 1))
-       if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
-         remove_note (head, note);
-    }
-
-  /* Remove remaining note insns from the block, save them in
-     note_list.  These notes are restored at the end of
-     schedule_block ().  */
-  rm_other_notes (head, tail);
-}
-
 /* Restore-other-notes: NOTE_LIST is the end of a chain of notes
    previously found among the insns.  Insert them just before HEAD.  */
 rtx
@@ -2315,11 +2257,9 @@ debug_ready_list (struct ready_list *ready)
   fprintf (sched_dump, "\n");
 }
 
-/* Search INSN for REG_SAVE_NOTE note pairs for
-   NOTE_INSN_EHREGION_{BEG,END}; and convert them back into
-   NOTEs.  The REG_SAVE_NOTE note following first one is contains the
-   saved value for NOTE_BLOCK_NUMBER which is useful for
-   NOTE_INSN_EH_REGION_{BEG,END} NOTEs.  */
+/* Search INSN for REG_SAVE_NOTE notes and convert them back into insn
+   NOTEs.  This is used for NOTE_INSN_EPILOGUE_BEG, so that sched-ebb
+   replaces the epilogue note in the correct basic block.  */
 void
 reemit_notes (rtx insn)
 {
diff --git a/gcc/testsuite/gcc.dg/pr42396.c b/gcc/testsuite/gcc.dg/pr42396.c
new file mode 100644 (file)
index 0000000..b3b7e4e
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -ftracer -fsched2-use-superblocks" } */
+
+static int i;
+extern void baz(int);
+void foo() { i = 3; }
+void bar() { baz(i ? 2 : 1); }