diff options
Diffstat (limited to 'gcc/cfgrtl.c')
| -rw-r--r-- | gcc/cfgrtl.c | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 3c877c2..4c4b3b7 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -531,7 +531,26 @@ rtl_split_block (basic_block bb, void *insnp) insn = first_insn_after_basic_block_note (bb); if (insn) - insn = PREV_INSN (insn); + { + rtx next = insn; + + insn = PREV_INSN (insn); + + /* If the block contains only debug insns, insn would have + been NULL in a non-debug compilation, and then we'd end + up emitting a DELETED note. For -fcompare-debug + stability, emit the note too. */ + if (insn != BB_END (bb) + && DEBUG_INSN_P (next) + && DEBUG_INSN_P (BB_END (bb))) + { + while (next != BB_END (bb) && DEBUG_INSN_P (next)) + next = NEXT_INSN (next); + + if (next == BB_END (bb)) + emit_note_after (NOTE_INSN_DELETED, next); + } + } else insn = get_last_insn (); } @@ -566,11 +585,15 @@ rtl_merge_blocks (basic_block a, basic_block b) { rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a); rtx del_first = NULL_RTX, del_last = NULL_RTX; + rtx b_debug_start = b_end, b_debug_end = b_end; int b_empty = 0; if (dump_file) fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index); + while (DEBUG_INSN_P (b_end)) + b_end = PREV_INSN (b_debug_start = b_end); + /* If there was a CODE_LABEL beginning B, delete it. */ if (LABEL_P (b_head)) { @@ -636,9 +659,21 @@ rtl_merge_blocks (basic_block a, basic_block b) /* Reassociate the insns of B with A. */ if (!b_empty) { - update_bb_for_insn_chain (a_end, b_end, a); + update_bb_for_insn_chain (a_end, b_debug_end, a); - a_end = b_end; + a_end = b_debug_end; + } + else if (b_end != b_debug_end) + { + /* Move any deleted labels and other notes between the end of A + and the debug insns that make up B after the debug insns, + bringing the debug insns into A while keeping the notes after + the end of A. */ + if (NEXT_INSN (a_end) != b_debug_start) + reorder_insns_nobb (NEXT_INSN (a_end), PREV_INSN (b_debug_start), + b_debug_end); + update_bb_for_insn_chain (b_debug_start, b_debug_end, a); + a_end = b_debug_end; } df_bb_delete (b->index); @@ -2162,6 +2197,11 @@ purge_dead_edges (basic_block bb) bool found; edge_iterator ei; + if (DEBUG_INSN_P (insn) && insn != BB_HEAD (bb)) + do + insn = PREV_INSN (insn); + while ((DEBUG_INSN_P (insn) || NOTE_P (insn)) && insn != BB_HEAD (bb)); + /* If this instruction cannot trap, remove REG_EH_REGION notes. */ if (NONJUMP_INSN_P (insn) && (note = find_reg_note (insn, REG_EH_REGION, NULL))) @@ -2182,10 +2222,10 @@ purge_dead_edges (basic_block bb) latter can appear when nonlocal gotos are used. */ if (e->flags & EDGE_EH) { - if (can_throw_internal (BB_END (bb)) + if (can_throw_internal (insn) /* If this is a call edge, verify that this is a call insn. */ && (! (e->flags & EDGE_ABNORMAL_CALL) - || CALL_P (BB_END (bb)))) + || CALL_P (insn))) { ei_next (&ei); continue; @@ -2193,7 +2233,7 @@ purge_dead_edges (basic_block bb) } else if (e->flags & EDGE_ABNORMAL_CALL) { - if (CALL_P (BB_END (bb)) + if (CALL_P (insn) && (! (note = find_reg_note (insn, REG_EH_REGION, NULL)) || INTVAL (XEXP (note, 0)) >= 0)) { @@ -2771,7 +2811,8 @@ rtl_block_ends_with_call_p (basic_block bb) while (!CALL_P (insn) && insn != BB_HEAD (bb) && (keep_with_call_p (insn) - || NOTE_P (insn))) + || NOTE_P (insn) + || DEBUG_INSN_P (insn))) insn = PREV_INSN (insn); return (CALL_P (insn)); } |
