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 ();
}
{
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))
{
/* 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);
end = tmp;
/* Include any barriers that may follow the basic block. */
- tmp = next_nonnote_insn (end);
+ tmp = next_nonnote_insn_bb (end);
while (tmp && BARRIER_P (tmp))
{
end = tmp;
- tmp = next_nonnote_insn (end);
+ tmp = next_nonnote_insn_bb (end);
}
return end;
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)))
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;
}
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))
{
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));
}