Commit 206604dc by Jakub Jelinek Committed by Jakub Jelinek

re PR debug/55094 (ICE in maybe_record_trace_start, at dwarf2cfi.c:2224)

	PR middle-end/55094
	* builtins.c (expand_builtin_trap): Add REG_ARGS_SIZE note
	on the trap insn for !ACCUMULATE_OUTGOING_ARGS.
	* cfgcleanup.c (outgoing_edges_match): Don't look at debug insns
	on the first old_insns_match_p call.  For !ACCUMULATE_OUTGOING_ARGS
	fail if the last real insn doesn't have REG_ARGS_SIZE note.

	* gcc.dg/pr55094.c: New test.

From-SVN: r193649
parent 1b845c6e
2012-11-20 Jakub Jelinek <jakub@redhat.com> 2012-11-20 Jakub Jelinek <jakub@redhat.com>
PR middle-end/55094
* builtins.c (expand_builtin_trap): Add REG_ARGS_SIZE note
on the trap insn for !ACCUMULATE_OUTGOING_ARGS.
* cfgcleanup.c (outgoing_edges_match): Don't look at debug insns
on the first old_insns_match_p call. For !ACCUMULATE_OUTGOING_ARGS
fail if the last real insn doesn't have REG_ARGS_SIZE note.
PR rtl-optimization/54921 PR rtl-optimization/54921
* cselib.h (fp_setter_insn): New prototype. * cselib.h (fp_setter_insn): New prototype.
* cselib.c (fp_setter_insn): New function. * cselib.c (fp_setter_insn): New function.
...@@ -4666,7 +4666,14 @@ expand_builtin_trap (void) ...@@ -4666,7 +4666,14 @@ expand_builtin_trap (void)
{ {
#ifdef HAVE_trap #ifdef HAVE_trap
if (HAVE_trap) if (HAVE_trap)
emit_insn (gen_trap ()); {
rtx insn = emit_insn (gen_trap ());
/* For trap insns when not accumulating outgoing args force
REG_ARGS_SIZE note to prevent crossjumping of calls with
different args sizes. */
if (!ACCUMULATE_OUTGOING_ARGS)
add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
}
else else
#endif #endif
emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0); emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
......
/* Control flow optimization code for GNU compiler. /* Control flow optimization code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011,
Free Software Foundation, Inc. 2012 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -1702,9 +1702,15 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2) ...@@ -1702,9 +1702,15 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
} }
} }
rtx last1 = BB_END (bb1);
rtx last2 = BB_END (bb2);
if (DEBUG_INSN_P (last1))
last1 = prev_nondebug_insn (last1);
if (DEBUG_INSN_P (last2))
last2 = prev_nondebug_insn (last2);
/* First ensure that the instructions match. There may be many outgoing /* First ensure that the instructions match. There may be many outgoing
edges so this test is generally cheaper. */ edges so this test is generally cheaper. */
if (old_insns_match_p (mode, BB_END (bb1), BB_END (bb2)) != dir_both) if (old_insns_match_p (mode, last1, last2) != dir_both)
return false; return false;
/* Search the outgoing edges, ensure that the counts do match, find possible /* Search the outgoing edges, ensure that the counts do match, find possible
...@@ -1713,10 +1719,14 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2) ...@@ -1713,10 +1719,14 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs)) if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs))
return false; return false;
bool nonfakeedges = false;
FOR_EACH_EDGE (e1, ei, bb1->succs) FOR_EACH_EDGE (e1, ei, bb1->succs)
{ {
e2 = EDGE_SUCC (bb2, ei.index); e2 = EDGE_SUCC (bb2, ei.index);
if ((e1->flags & EDGE_FAKE) == 0)
nonfakeedges = true;
if (e1->flags & EDGE_EH) if (e1->flags & EDGE_EH)
nehedges1++; nehedges1++;
...@@ -1734,6 +1744,18 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2) ...@@ -1734,6 +1744,18 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
|| (fallthru1 != 0) != (fallthru2 != 0)) || (fallthru1 != 0) != (fallthru2 != 0))
return false; return false;
/* If !ACCUMULATE_OUTGOING_ARGS, bb1 (and bb2) have no successors
and the last real insn doesn't have REG_ARGS_SIZE note, don't
attempt to optimize, as the two basic blocks might have different
REG_ARGS_SIZE depths. For noreturn calls and unconditional
traps there should be REG_ARG_SIZE notes, they could be missing
for __builtin_unreachable () uses though. */
if (!nonfakeedges
&& !ACCUMULATE_OUTGOING_ARGS
&& (!INSN_P (last1)
|| !find_reg_note (last1, REG_ARGS_SIZE, NULL)))
return false;
/* fallthru edges must be forwarded to the same destination. */ /* fallthru edges must be forwarded to the same destination. */
if (fallthru1) if (fallthru1)
{ {
......
2012-11-20 Jakub Jelinek <jakub@redhat.com> 2012-11-20 Jakub Jelinek <jakub@redhat.com>
PR middle-end/55094
* gcc.dg/pr55094.c: New test.
PR rtl-optimization/54921 PR rtl-optimization/54921
* gcc.dg/pr54921.c: New test. * gcc.dg/pr54921.c: New test.
......
/* PR middle-end/55094 */
/* { dg-do compile } */
/* { dg-options "-fcompare-debug -Os" } */
/* { dg-additional-options "-fomit-frame-pointer -fno-asynchronous-unwind-tables -mpreferred-stack-boundary=2" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
extern int fn (long);
int v;
int
foo (int x, long *y)
{
if (x)
{
fn (y[0]);
__builtin_trap ();
}
__builtin_trap ();
}
int
bar (int x, long *y)
{
if (x)
{
fn (y[0]);
v = 1;
__builtin_unreachable ();
}
v = 1;
__builtin_unreachable ();
}
int
baz (int x, long *y)
{
if (x)
{
fn (y[0]);
v = 1;
__builtin_unreachable ();
}
v = 1;
int w = 1;
__builtin_unreachable ();
}
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