aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-11-20 09:38:11 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2012-11-20 09:38:11 +0100
commit206604dccdcd6b054c1c81d4e058b9ca4db8f1f0 (patch)
tree3f976d8db947ec504470f76bc3ab56713f7f77aa
parent1b845c6e70049828a6732f60e2eb03042cc6ff1b (diff)
downloadgcc-206604dccdcd6b054c1c81d4e058b9ca4db8f1f0.zip
gcc-206604dccdcd6b054c1c81d4e058b9ca4db8f1f0.tar.gz
gcc-206604dccdcd6b054c1c81d4e058b9ca4db8f1f0.tar.bz2
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/builtins.c9
-rw-r--r--gcc/cfgcleanup.c28
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.dg/pr55094.c45
5 files changed, 88 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d3b0200..9041558 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
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
* cselib.h (fp_setter_insn): New prototype.
* cselib.c (fp_setter_insn): New function.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index fbeac75..b0cab51 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4666,7 +4666,14 @@ expand_builtin_trap (void)
{
#ifdef 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
#endif
emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index eccbb41..94267b6e 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -1,7 +1,7 @@
/* Control flow optimization code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
- Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011,
+ 2012 Free Software Foundation, Inc.
This file is part of GCC.
@@ -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
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;
/* 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)
if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs))
return false;
+ bool nonfakeedges = false;
FOR_EACH_EDGE (e1, ei, bb1->succs)
{
e2 = EDGE_SUCC (bb2, ei.index);
+ if ((e1->flags & EDGE_FAKE) == 0)
+ nonfakeedges = true;
+
if (e1->flags & EDGE_EH)
nehedges1++;
@@ -1734,6 +1744,18 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
|| (fallthru1 != 0) != (fallthru2 != 0))
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. */
if (fallthru1)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 46eb0cd..86659e9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2012-11-20 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/55094
+ * gcc.dg/pr55094.c: New test.
+
PR rtl-optimization/54921
* gcc.dg/pr54921.c: New test.
diff --git a/gcc/testsuite/gcc.dg/pr55094.c b/gcc/testsuite/gcc.dg/pr55094.c
new file mode 100644
index 0000000..c445b1a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr55094.c
@@ -0,0 +1,45 @@
+/* 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 ();
+}