Hi! The following testcase was ICEing on powerpc64-linux. While force_nonfallthru_and_redirect properly adjusted the LABEL_REFs in asm goto from the old fallthru block to a new one, it didn't adjust LABEL_NUSES and didn't adjust JUMP_LABEL resp. REG_LABEL_TARGET.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk (and 4.7 after say a week)? 2012-11-12 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/54127 * cfgrtl.c (force_nonfallthru_and_redirect): When redirecting asm goto labels from BB_HEAD (e->dest) to target bb, decrement LABEL_NUSES of BB_HEAD (e->dest) and increment LABEL_NUSES of BB_HEAD (target) appropriately and adjust JUMP_LABEL and/or REG_LABEL_TARGET and REG_LABEL_OPERAND. * gcc.dg/torture/pr54127.c: New test. --- gcc/cfgrtl.c.jj 2012-11-05 08:55:21.000000000 +0100 +++ gcc/cfgrtl.c 2012-11-12 11:06:32.254919581 +0100 @@ -1424,14 +1424,46 @@ force_nonfallthru_and_redirect (edge e, && (note = extract_asm_operands (PATTERN (BB_END (e->src))))) { int i, n = ASM_OPERANDS_LABEL_LENGTH (note); + bool adjust_jump_target = false; for (i = 0; i < n; ++i) { if (XEXP (ASM_OPERANDS_LABEL (note, i), 0) == BB_HEAD (e->dest)) - XEXP (ASM_OPERANDS_LABEL (note, i), 0) = block_label (target); + { + LABEL_NUSES (XEXP (ASM_OPERANDS_LABEL (note, i), 0))--; + XEXP (ASM_OPERANDS_LABEL (note, i), 0) = block_label (target); + LABEL_NUSES (XEXP (ASM_OPERANDS_LABEL (note, i), 0))++; + adjust_jump_target = true; + } if (XEXP (ASM_OPERANDS_LABEL (note, i), 0) == BB_HEAD (target)) asm_goto_edge = true; } + if (adjust_jump_target) + { + rtx insn = BB_END (e->src), note; + rtx old_label = BB_HEAD (e->dest); + rtx new_label = BB_HEAD (target); + + if (JUMP_LABEL (insn) == old_label) + { + JUMP_LABEL (insn) = new_label; + note = find_reg_note (insn, REG_LABEL_TARGET, new_label); + if (note) + remove_note (insn, note); + } + else + { + note = find_reg_note (insn, REG_LABEL_TARGET, old_label); + if (note) + remove_note (insn, note); + if (JUMP_LABEL (insn) != new_label + && !find_reg_note (insn, REG_LABEL_TARGET, new_label)) + add_reg_note (insn, REG_LABEL_TARGET, new_label); + } + while ((note = find_reg_note (insn, REG_LABEL_OPERAND, old_label)) + != NULL_RTX) + XEXP (note, 0) = new_label; + } } if (EDGE_COUNT (e->src->succs) >= 2 || abnormal_edge_flags || asm_goto_edge) --- gcc/testsuite/gcc.dg/torture/pr54127.c.jj 2012-11-12 11:13:45.422433593 +0100 +++ gcc/testsuite/gcc.dg/torture/pr54127.c 2012-11-12 11:09:07.000000000 +0100 @@ -0,0 +1,16 @@ +/* PR rtl-optimization/54127 */ +/* { dg-do compile } */ + +extern void foo (void) __attribute__ ((__noreturn__)); + +void +bar (int x) +{ + if (x < 0) + foo (); + if (x == 0) + return; + __asm goto ("# %l[lab] %l[lab2]" : : : : lab, lab2); +lab:; +lab2:; +} Jakub