diff options
author | Richard Henderson <rth@redhat.com> | 2009-07-01 16:21:17 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2009-07-01 16:21:17 -0700 |
commit | 997704f18b252a1063f514a716fbf6b636f62620 (patch) | |
tree | 2863da00a857ad078f33c3cdf9b6b6552c38c036 /gcc/function.c | |
parent | 9f2af3cef8463e296639cfaa5811c38b2dabeae5 (diff) | |
download | gcc-997704f18b252a1063f514a716fbf6b636f62620.zip gcc-997704f18b252a1063f514a716fbf6b636f62620.tar.gz gcc-997704f18b252a1063f514a716fbf6b636f62620.tar.bz2 |
re PR bootstrap/40347 (i386-darwin ICEs while building libgcc during stage2)
PR bootstrap/40347
* function.c (reposition_prologue_and_epilogue_notes): If epilogue
contained no insns, reposition note before last insn.
From-SVN: r149158
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 38 |
1 files changed, 23 insertions, 15 deletions
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 */ |