Index: a/gcc/cfgcleanup.c =================================================================== --- a/gcc/cfgcleanup.c (revision 315947) +++ b/gcc/cfgcleanup.c (working copy) @@ -1179,13 +1179,19 @@ flow_find_head_matching_sequence (basic_ while (true) { - - /* Ignore notes. */ + /* Ignore notes, except NOTE_INSN_EPILOGUE_BEG. */ while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1)) - i1 = NEXT_INSN (i1); - + { + if (NOTE_P (i1) && NOTE_KIND (i1) == NOTE_INSN_EPILOGUE_BEG) + break; + i1 = NEXT_INSN (i1); + } while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2)) - i2 = NEXT_INSN (i2); + { + if (NOTE_P (i2) && NOTE_KIND (i2) == NOTE_INSN_EPILOGUE_BEG) + break; + i2 = NEXT_INSN (i2); + } if (NOTE_P (i1) || NOTE_P (i2) || JUMP_P (i1) || JUMP_P (i2)) Index: a/gcc/cfglayout.c =================================================================== --- a/gcc/cfglayout.c (revision 315947) +++ b/gcc/cfglayout.c (working copy) @@ -1295,6 +1295,16 @@ cfg_layout_initialize (unsigned int flag bb->flags |= BB_NON_LOCAL_GOTO_TARGET; } + FOR_EACH_BB (bb) + { + rtx insn; + FOR_BB_INSNS (bb, insn) + if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG) + { + bb->flags |= BB_EPILOGUE_BEGIN; + break; + } + } cleanup_cfg (CLEANUP_CFGLAYOUT | flags); } Index: a/gcc/basic-block.h =================================================================== --- a/gcc/basic-block.h (revision 315947) +++ b/gcc/basic-block.h (working copy) @@ -332,7 +332,11 @@ enum bb_flags /* Set on blocks that cannot be threaded through. Only used in cfgcleanup.c. */ - BB_NONTHREADABLE_BLOCK = 1 << 11 + BB_NONTHREADABLE_BLOCK = 1 << 11, + + /* Set on blocks that have a NOTE_INSN_EPILOGUE_BEGIN. + Only used in cfglayout mode. */ + BB_EPILOGUE_BEGIN = 1 << 12 }; /* Dummy flag for convenience in the hot/cold partitioning code. */ Index: a/gcc/cfgrtl.c =================================================================== --- a/gcc/cfgrtl.c (revision 315947) +++ b/gcc/cfgrtl.c (working copy) @@ -2707,7 +2707,10 @@ cfg_layout_can_merge_blocks_p (basic_blo not allow us to redirect an edge by replacing a table jump. */ && (!JUMP_P (BB_END (a)) || ((!optimize || reload_completed) - ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a))))); + ? simplejump_p (BB_END (a)) : onlyjump_p (BB_END (a)))) + /* Don't separate a NOTE_INSN_EPILOGUE_BEG from its returnjump. */ + && (!(b->flags & BB_EPILOGUE_BEGIN) + || returnjump_p (BB_END (b)))); } /* Merge block A and B. The blocks must be mergeable. */