summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/cfgrtl.c34
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr54127.c16
4 files changed, 64 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dd2d1a37535..c5a80e1732b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2012-11-13 Jakub Jelinek <jakub@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.
+
2012-11-12 Jakub Jelinek <jakub@redhat.com>
* asan.c (instrument_builtin_call) <case BUILT_IN_BCOPY>: Fix up
@@ -11,7 +20,7 @@
2012-11-12 David Edelsohn <dje.gcc@gmail.com>
- * asan.c: Include tm_p.h
+ * asan.c: Include tm_p.h.
2012-11-12 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 1f601e51d03..8855bdf9861 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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f236a2f4d1b..8a369247cb0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-11-13 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/54127
+ * gcc.dg/torture/pr54127.c: New test.
+
2012-11-12 Steven Bosscher <steven@gcc.gnu.org>
Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/testsuite/gcc.dg/torture/pr54127.c b/gcc/testsuite/gcc.dg/torture/pr54127.c
new file mode 100644
index 00000000000..4f64998af0a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr54127.c
@@ -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:;
+}