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
This commit is contained in:
Richard Henderson 2010-01-06 10:34:31 -08:00 committed by Richard Henderson
parent 6209a13e20
commit e67271bd65
3 changed files with 68 additions and 112 deletions

View 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

View 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))
note_list = 0;
if (head == tail && !INSN_P (head))
return;
next_tail = NEXT_INSN (tail);
prev = PREV_INSN (head);
for (insn = head; insn != next_tail; insn = next)
{
rtx next = NEXT_INSN (insn);
basic_block bb = BLOCK_FOR_INSN (insn);
next = NEXT_INSN (insn);
if (!NOTE_P (insn))
{
prev = insn;
continue;
}
/* Delete the note from its current position. */
if (prev)
NEXT_INSN (prev) = next;
if (next)
PREV_INSN (next) = prev;
switch (NOTE_KIND (insn))
{
case NOTE_INSN_BASIC_BLOCK:
prev = insn;
continue;
if (bb)
{
/* Basic block can begin with either LABEL or
NOTE_INSN_BASIC_BLOCK. */
gcc_assert (BB_HEAD (bb) != insn);
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 */
/* Check if we are removing last insn in the BB. */
if (BB_END (bb) == insn)
BB_END (bb) = prev;
}
default:
remove_insn (insn);
/* 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);
/* 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;
}
insn = next;
gcc_assert ((sel_sched_p () || insn != tail) && insn != head);
}
if (insn == tail)
{
gcc_assert (sel_sched_p ());
return prev;
}
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)
{

View File

@ -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); }