summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-05-11 18:17:43 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-05-11 18:17:43 +0000
commitdcb172b4aee2541920b5793aa338e40824f521b4 (patch)
tree1cb4796f120b34f94f9e016946901fdcba7136f8 /gcc
parent6834c43a3100068ce10f4b1b60c5bbb486e2a353 (diff)
downloadgcc-dcb172b4aee2541920b5793aa338e40824f521b4.tar.gz
PR middle-end/44071
* cfglayout.c (fixup_reorder_chain): Allow asm goto to have no fallthru edge. * cfgcleanup.c (try_optimize_cfg): When in cfglayout mode optimizing away empty bb with no successors, move over its footer chain to fallthru predecessor. * cfgrtl.c (patch_jump_insn): Update also REG_LABEL_OPERAND. (rtl_split_edge): For asm goto call patch_jump_insn even if splitting fallthru edge. * c-c++-common/asmgoto-4.c: New test. * gcc.target/i386/pr44071.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159288 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/cfgcleanup.c19
-rw-r--r--gcc/cfglayout.c9
-rw-r--r--gcc/cfgrtl.c20
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/c-c++-common/asmgoto-4.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/pr44071.c103
7 files changed, 205 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 16f56b89d03..24f210b3cc6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
2010-05-11 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/44071
+ * cfglayout.c (fixup_reorder_chain): Allow asm goto to have
+ no fallthru edge.
+ * cfgcleanup.c (try_optimize_cfg): When in cfglayout mode
+ optimizing away empty bb with no successors, move over its
+ footer chain to fallthru predecessor.
+ * cfgrtl.c (patch_jump_insn): Update also REG_LABEL_OPERAND.
+ (rtl_split_edge): For asm goto call patch_jump_insn even if
+ splitting fallthru edge.
+
PR c++/44059
* config/elfos.h (ASM_DECLARE_OBJECT_NAME): Use qnu_unique_object
even for DECL_ONE_ONLY DECL_ARTIFICIAL !TREE_READONLY decls.
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index dc6c245b950..75f56519a26 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -1999,6 +1999,25 @@ try_optimize_cfg (int mode)
&& single_succ_edge (ENTRY_BLOCK_PTR)->dest != b))
{
c = b->prev_bb;
+ if ((mode & CLEANUP_CFGLAYOUT)
+ && EDGE_COUNT (b->preds) > 0
+ && b->il.rtl->footer
+ && BARRIER_P (b->il.rtl->footer))
+ {
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, b->preds)
+ if (e->flags & EDGE_FALLTHRU)
+ {
+ if (e->src->il.rtl->footer == NULL)
+ {
+ e->src->il.rtl->footer = b->il.rtl->footer;
+ b->il.rtl->footer = NULL;
+ }
+ break;
+ }
+ }
delete_basic_block (b);
if (!(mode & CLEANUP_CFGLAYOUT))
changed = true;
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index 9d23b16c116..7ba289f1a58 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -1,5 +1,5 @@
/* Basic block reordering routines for the GNU compiler.
- Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
@@ -861,8 +861,11 @@ fixup_reorder_chain (void)
}
else if (extract_asm_operands (PATTERN (bb_end_insn)) != NULL)
{
- /* If the old fallthru is still next, nothing to do. */
- if (bb->aux == e_fall->dest
+ /* If the old fallthru is still next or if
+ asm goto doesn't have a fallthru (e.g. when followed by
+ __builtin_unreachable ()), nothing to do. */
+ if (! e_fall
+ || bb->aux == e_fall->dest
|| e_fall->dest == EXIT_BLOCK_PTR)
continue;
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 7fb1873f53b..abdbf9d8598 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -994,6 +994,9 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
&& !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;
}
else
{
@@ -1407,7 +1410,22 @@ rtl_split_edge (edge edge_in)
gcc_assert (redirected);
}
else
- redirect_edge_succ (edge_in, bb);
+ {
+ if (edge_in->src != ENTRY_BLOCK_PTR)
+ {
+ /* For asm goto even splitting of fallthru edge might
+ need insn patching, as other labels might point to the
+ old label. */
+ rtx last = BB_END (edge_in->src);
+ if (last
+ && JUMP_P (last)
+ && edge_in->dest != EXIT_BLOCK_PTR
+ && extract_asm_operands (PATTERN (last)) != NULL_RTX
+ && patch_jump_insn (last, before, bb))
+ df_set_bb_dirty (edge_in->src);
+ }
+ redirect_edge_succ (edge_in, bb);
+ }
return bb;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8a74fd13476..ee0fab84ca2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2010-05-11 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/44071
+ * c-c++-common/asmgoto-4.c: New test.
+ * gcc.target/i386/pr44071.c: New test.
+
PR c++/44062
* c-c++-common/Wunused-var-7.c: New test.
* g++.dg/warn/Wunused-var-9.C: New test.
diff --git a/gcc/testsuite/c-c++-common/asmgoto-4.c b/gcc/testsuite/c-c++-common/asmgoto-4.c
new file mode 100644
index 00000000000..4532bf196ee
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asmgoto-4.c
@@ -0,0 +1,44 @@
+/* PR middle-end/44071 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+static inline int
+f1 (void)
+{
+ asm goto ("" : : : : l1, l2);
+ __builtin_unreachable ();
+ l1:
+ return 1;
+ l2:
+ return 0;
+}
+
+int
+b1 (int x)
+{
+ if (f1 () || x == 6)
+ x = 1;
+ else
+ x = 2;
+ return x;
+}
+
+static inline int
+f2 (void)
+{
+ asm goto ("" : : : : l1, l2);
+ l1:
+ return 1;
+ l2:
+ return 0;
+}
+
+int
+b2 (int x)
+{
+ if (f2 () || x == 6)
+ x = 1;
+ else
+ x = 2;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr44071.c b/gcc/testsuite/gcc.target/i386/pr44071.c
new file mode 100644
index 00000000000..514c5e2fd2c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr44071.c
@@ -0,0 +1,103 @@
+/* PR middle-end/44071 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+static inline int
+f1 (void)
+{
+ asm goto ("jmp %l[l1]" : : : : l1, l2);
+ __builtin_unreachable ();
+ l1:
+ return 1;
+ l2:
+ return 0;
+}
+
+__attribute__((noinline)) int
+b1 (int x)
+{
+ if (f1 () || x == 6)
+ x = 1;
+ else
+ x = 2;
+ return x;
+}
+
+static inline int
+f2 (void)
+{
+ asm goto ("jmp %l[l2]" : : : : l1, l2);
+ __builtin_unreachable ();
+ l1:
+ return 1;
+ l2:
+ return 0;
+}
+
+__attribute__((noinline)) int
+b2 (int x)
+{
+ if (f2 () || x == 6)
+ x = 1;
+ else
+ x = 2;
+ return x;
+}
+
+static inline int
+f3 (void)
+{
+ asm goto ("jmp %l[l1]" : : : : l1, l2);
+ l1:
+ return 1;
+ l2:
+ return 0;
+}
+
+__attribute__((noinline)) int
+b3 (int x)
+{
+ if (f3 () || x == 6)
+ x = 1;
+ else
+ x = 2;
+ return x;
+}
+
+static inline int
+f4 (void)
+{
+ asm goto ("jmp %l[l2]" : : : : l1, l2);
+ l1:
+ return 1;
+ l2:
+ return 0;
+}
+
+__attribute__((noinline)) int
+b4 (int x)
+{
+ if (f4 () || x == 6)
+ x = 1;
+ else
+ x = 2;
+ return x;
+}
+
+extern void abort (void);
+
+int
+main (void)
+{
+ int x;
+ asm ("" : "=r" (x) : "0" (0));
+ if (b1 (x) != 1 || b1 (x + 6) != 1)
+ abort ();
+ if (b2 (x) != 2 || b2 (x + 6) != 1)
+ abort ();
+ if (b3 (x) != 1 || b3 (x + 6) != 1)
+ abort ();
+ if (b4 (x) != 2 || b4 (x + 6) != 1)
+ abort ();
+ return 0;
+}