diff options
author | Richard Henderson <rth@redhat.com> | 2010-01-06 10:34:31 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2010-01-06 10:34:31 -0800 |
commit | e67271bd6571e2a3c6adc842350571e59b5a1f86 (patch) | |
tree | 690ad37d4cb1af3217c4867f5546cc48b0c4e34a /gcc | |
parent | 6209a13e202b97e040f91e57281a2c23e0022bea (diff) | |
download | gcc-e67271bd6571e2a3c6adc842350571e59b5a1f86.zip gcc-e67271bd6571e2a3c6adc842350571e59b5a1f86.tar.gz gcc-e67271bd6571e2a3c6adc842350571e59b5a1f86.tar.bz2 |
re PR middle-end/41883 (ICE from '-O -fprofile-arcs -fsched2-use-superblocks -ftree-vrp -fschedule-insns2 -freorder-blocks')
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/haifa-sched.c | 166 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr42396.c | 7 |
3 files changed, 69 insertions, 113 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6435d2a..e8aa64b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 204fab6..de75286 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -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, ¬e_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 index 0000000..b3b7e4e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr42396.c @@ -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); } |