aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/function.c38
2 files changed, 29 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 801851b..eecd91b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@
2009-07-01 Richard Henderson <rth@redhat.com>
+ PR bootstrap/40347
+ * function.c (reposition_prologue_and_epilogue_notes): If epilogue
+ contained no insns, reposition note before last insn.
+
+2009-07-01 Richard Henderson <rth@redhat.com>
+
PR debug/40431
* dwarf2out.c (def_cfa_1): Revert 2009-06-11 change for
DW_CFA_def_cfa_offset and DW_CFA_def_cfa.
diff --git a/gcc/function.c b/gcc/function.c
index a0c45de..63fe835 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -5283,15 +5283,12 @@ reposition_prologue_and_epilogue_notes (void)
{
#if defined (HAVE_prologue) || defined (HAVE_epilogue) \
|| defined (HAVE_sibcall_epilogue)
- rtx insn, last, note;
- basic_block bb;
-
/* Since the hash table is created on demand, the fact that it is
non-null is a signal that it is non-empty. */
if (prologue_insn_hash != NULL)
{
size_t len = htab_elements (prologue_insn_hash);
- last = 0, note = 0;
+ rtx insn, last = NULL, note = NULL;
/* Scan from the beginning until we reach the last prologue insn. */
/* ??? While we do have the CFG intact, there are two problems:
@@ -5342,12 +5339,10 @@ reposition_prologue_and_epilogue_notes (void)
FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
{
- last = 0, note = 0;
- bb = e->src;
+ rtx insn, first = NULL, note = NULL;
+ basic_block bb = e->src;
- /* Scan from the beginning until we reach the first epilogue insn.
- Take the cue for whether this is a plain or sibcall epilogue
- from the kind of note we find first. */
+ /* Scan from the beginning until we reach the first epilogue insn. */
FOR_BB_INSNS (bb, insn)
{
if (NOTE_P (insn))
@@ -5355,20 +5350,33 @@ reposition_prologue_and_epilogue_notes (void)
if (NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG)
{
note = insn;
- if (last)
+ if (first != NULL)
break;
}
}
- else if (contains (insn, epilogue_insn_hash))
+ else if (first == NULL && contains (insn, epilogue_insn_hash))
{
- last = insn;
+ first = insn;
if (note != NULL)
break;
}
}
-
- if (last && note && PREV_INSN (last) != note)
- reorder_insns (note, note, PREV_INSN (last));
+
+ if (note)
+ {
+ /* If the function has a single basic block, and no real
+ epilogue insns (e.g. sibcall with no cleanup), the
+ epilogue note can get scheduled before the prologue
+ note. If we have frame related prologue insns, having
+ them scanned during the epilogue will result in a crash.
+ In this case re-order the epilogue note to just before
+ the last insn in the block. */
+ if (first == NULL)
+ first = BB_END (bb);
+
+ if (PREV_INSN (first) != note)
+ reorder_insns (note, note, PREV_INSN (first));
+ }
}
}
#endif /* HAVE_prologue or HAVE_epilogue */