Hi! While the cleanup_barriers runs after cleaning up BLOCK_FOR_INSNs, some targets like i?86/x86_64 choose to populate it again during machine reorg and some target don't free it at the end of machine reorg. This patch updates cleanup_barrier pass, so that it adjusts basic block boundaries and BLOCK_FOR_INSNs in that case, so that we don't crash during final pass.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2015-01-22 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/61058 * jump.c (cleanup_barriers): Update basic block boundaries if BLOCK_FOR_INSN is non-NULL on PREV. * gcc.dg/pr61058.c: New test. --- gcc/jump.c.jj 2015-01-15 20:25:30.000000000 +0100 +++ gcc/jump.c 2015-01-22 16:32:11.677709401 +0100 @@ -168,7 +168,27 @@ cleanup_barriers (void) if (BARRIER_P (prev)) delete_insn (insn); else if (prev != PREV_INSN (insn)) - reorder_insns_nobb (insn, insn, prev); + { + basic_block bb = BLOCK_FOR_INSN (prev); + rtx_insn *end = PREV_INSN (insn); + reorder_insns_nobb (insn, insn, prev); + if (bb) + { + /* If the backend called in machine reorg compute_bb_for_insn + and didn't free_bb_for_insn again, preserve basic block + boundaries. Move the end of basic block to PREV since + it is followed by a barrier now, and clear BLOCK_FOR_INSN + on the following notes. */ + BB_END (bb) = prev; + do + { + prev = NEXT_INSN (prev); + if (prev != insn && BLOCK_FOR_INSN (prev) == bb) + BLOCK_FOR_INSN (prev) = NULL; + } + while (prev != end); + } + } } } return 0; --- gcc/testsuite/gcc.dg/pr61058.c.jj 2015-01-22 16:19:16.507023479 +0100 +++ gcc/testsuite/gcc.dg/pr61058.c 2015-01-22 16:19:16.507023479 +0100 @@ -0,0 +1,10 @@ +/* PR rtl-optimization/61058 */ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-additional-options "-fno-asynchronous-unwind-tables -mtune=atom" { target i?86-*-* x86_64-*-* } } */ + +void +foo (void) +{ + __builtin_unreachable (); +} Jakub