diff options
author | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-11-13 08:23:51 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-11-13 08:23:51 +0100 |
commit | 5d68b7e60b0b2f26624477ff0b7ef9f2595c9325 (patch) | |
tree | eda1ced99836a0df02e841aa54853a4b335cfb58 /gcc/cfgrtl.c | |
parent | 42b04d70a11b1987f5c04eff067de7e4fa345d7c (diff) | |
download | gcc-5d68b7e60b0b2f26624477ff0b7ef9f2595c9325.zip gcc-5d68b7e60b0b2f26624477ff0b7ef9f2595c9325.tar.gz gcc-5d68b7e60b0b2f26624477ff0b7ef9f2595c9325.tar.bz2 |
re PR rtl-optimization/54127 (ICE in maybe_record_trace_start with asm goto, --target=powerpc-unknown-linux-gnu)
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.
From-SVN: r193470
Diffstat (limited to 'gcc/cfgrtl.c')
-rw-r--r-- | gcc/cfgrtl.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 1f601e5..8855bdf 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1424,14 +1424,46 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label) && (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) |