Commit 3b5fda81 by Jakub Jelinek Committed by Jakub Jelinek

re PR middle-end/44071 (ICE with asm goto and __builtin_unreachable())

	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.

From-SVN: r159288
parent 3895ec53
2010-05-11 Jakub Jelinek <jakub@redhat.com> 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 PR c++/44059
* config/elfos.h (ASM_DECLARE_OBJECT_NAME): Use qnu_unique_object * config/elfos.h (ASM_DECLARE_OBJECT_NAME): Use qnu_unique_object
even for DECL_ONE_ONLY DECL_ARTIFICIAL !TREE_READONLY decls. even for DECL_ONE_ONLY DECL_ARTIFICIAL !TREE_READONLY decls.
......
...@@ -1999,6 +1999,25 @@ try_optimize_cfg (int mode) ...@@ -1999,6 +1999,25 @@ try_optimize_cfg (int mode)
&& single_succ_edge (ENTRY_BLOCK_PTR)->dest != b)) && single_succ_edge (ENTRY_BLOCK_PTR)->dest != b))
{ {
c = b->prev_bb; 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); delete_basic_block (b);
if (!(mode & CLEANUP_CFGLAYOUT)) if (!(mode & CLEANUP_CFGLAYOUT))
changed = true; changed = true;
......
/* Basic block reordering routines for the GNU compiler. /* 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -861,8 +861,11 @@ fixup_reorder_chain (void) ...@@ -861,8 +861,11 @@ fixup_reorder_chain (void)
} }
else if (extract_asm_operands (PATTERN (bb_end_insn)) != NULL) else if (extract_asm_operands (PATTERN (bb_end_insn)) != NULL)
{ {
/* If the old fallthru is still next, nothing to do. */ /* If the old fallthru is still next or if
if (bb->aux == e_fall->dest 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) || e_fall->dest == EXIT_BLOCK_PTR)
continue; continue;
......
...@@ -994,6 +994,9 @@ patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb) ...@@ -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)) && !find_reg_note (insn, REG_LABEL_TARGET, new_label))
add_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 else
{ {
...@@ -1407,7 +1410,22 @@ rtl_split_edge (edge edge_in) ...@@ -1407,7 +1410,22 @@ rtl_split_edge (edge edge_in)
gcc_assert (redirected); gcc_assert (redirected);
} }
else 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; return bb;
} }
......
2010-05-11 Jakub Jelinek <jakub@redhat.com> 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 PR c++/44062
* c-c++-common/Wunused-var-7.c: New test. * c-c++-common/Wunused-var-7.c: New test.
* g++.dg/warn/Wunused-var-9.C: New test. * g++.dg/warn/Wunused-var-9.C: New test.
......
/* 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;
}
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment