Hi! The barriers pass wants to put a BARRIER from after a noreturn call in between the call and NOTE_INSN_CALL_ARG_LOCATION, but as the note no longer is BB_END (the call is), it happens to extend BB_END to the BARRIER which later breaks the md reorg pass.
dwarf2out.c seems to handle a BARRIER in between the call and related NOTE_INSN_CALL_ARG_LOCATION resp. NOTE_INSN_VAR_LOCATION/c just fine, only NOTE_INSN_CALL_ARG_LOCATION needs to go first. My first fix was to the barriers pass to allow NOTE_INSN_CALL_ARG_LOCATION in between the CALL_INSN and BARRIER, but I think I prefer to put the BARRIER first from the beginning. Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2012-12-07 Jakub Jelinek <ja...@redhat.com> PR middle-end/43631 PR bootstrap/55615 * var-tracking.c (emit_note_insn_var_location): If insn is followed by BARRIER, put note after the BARRIER. (next_non_note_insn_var_location): Skip over BARRIERs. (emit_notes_in_bb): If call is followed by BARRIER, put note after the BARRIER. * g++.dg/other/pr43631.C: New test. --- gcc/var-tracking.c.jj 2012-12-06 15:37:30.000000000 +0100 +++ gcc/var-tracking.c 2012-12-07 13:00:32.713116052 +0100 @@ -8538,7 +8538,10 @@ emit_note_insn_var_location (void **varp if (where != EMIT_NOTE_BEFORE_INSN) { - note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn); + rtx after = insn; + while (NEXT_INSN (after) && BARRIER_P (NEXT_INSN (after))) + after = NEXT_INSN (after); + note = emit_note_after (NOTE_INSN_VAR_LOCATION, after); if (where == EMIT_NOTE_AFTER_CALL_INSN) NOTE_DURING_CALL_P (note) = true; } @@ -8892,9 +8895,11 @@ next_non_note_insn_var_location (rtx ins while (insn) { insn = NEXT_INSN (insn); - if (insn == 0 - || !NOTE_P (insn) - || NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION) + if (insn == 0) + break; + if (BARRIER_P (insn)) + continue; + if (!NOTE_P (insn) || NOTE_KIND (insn) != NOTE_INSN_VAR_LOCATION) break; } @@ -8923,7 +8928,7 @@ emit_notes_in_bb (basic_block bb, datafl dataflow_set_clear_at_call (set); emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set->vars); { - rtx arguments = mo->u.loc, *p = &arguments, note; + rtx arguments = mo->u.loc, *p = &arguments, note, after; while (*p) { XEXP (XEXP (*p, 0), 1) @@ -8947,7 +8952,10 @@ emit_notes_in_bb (basic_block bb, datafl else *p = XEXP (*p, 1); } - note = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, insn); + after = insn; + while (NEXT_INSN (after) && BARRIER_P (NEXT_INSN (after))) + after = NEXT_INSN (after); + note = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, after); NOTE_VAR_LOCATION (note) = arguments; /* If insn is BB_END of some bb, make sure the note doesn't have BLOCK_FOR_INSN set. The notes don't --- gcc/testsuite/g++.dg/other/pr43631.C.jj 2012-12-07 12:12:35.557226106 +0100 +++ gcc/testsuite/g++.dg/other/pr43631.C 2012-12-07 12:13:48.170822223 +0100 @@ -0,0 +1,15 @@ +// PR middle-end/43631 +// { dg-do compile } +// { dg-options "-g -O2" } +// { dg-additional-options "-mtune=atom" { target i?86-*-* x86_64-*-* } } + +typedef void (*T) (); +struct S { T t; }; +void bar (T) __attribute__ ((__noreturn__)); +S *p; + +void +foo () +{ + try { bar (p->t); } catch (...) { throw 1; } +} Jakub