aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfgrtl.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2012-11-13 08:23:51 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2012-11-13 08:23:51 +0100
commit5d68b7e60b0b2f26624477ff0b7ef9f2595c9325 (patch)
treeeda1ced99836a0df02e841aa54853a4b335cfb58 /gcc/cfgrtl.c
parent42b04d70a11b1987f5c04eff067de7e4fa345d7c (diff)
downloadgcc-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.c34
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)