re PR debug/55094 (ICE in maybe_record_trace_start, at dwarf2cfi.c:2224)
authorJakub Jelinek <jakub@redhat.com>
Tue, 20 Nov 2012 08:38:11 +0000 (09:38 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 20 Nov 2012 08:38:11 +0000 (09:38 +0100)
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

gcc/ChangeLog
gcc/builtins.c
gcc/cfgcleanup.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr55094.c [new file with mode: 0644]

index d3b02002f01f54a97f375e372401d7954ff8dbc3..9041558ff5f18533c64923983032864740d14d3d 100644 (file)
@@ -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.
index fbeac7517c61beec0d67e00718d85af531b802c7..b0cab51556ef9436f755874a0852194a5e77d58f 100644 (file)
@@ -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);
index eccbb411f8ff7853c093dee5cebb5b25fac57da2..94267b6e15da0816d5a4197db13e357fa623dc6f 100644 (file)
@@ -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)
     {
index 46eb0cde84301e295ad0ca055756466b0bee2f1c..86659e9a4db7a5681bf6c5ee971c4b136ea4a10f 100644 (file)
@@ -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 (file)
index 0000000..c445b1a
--- /dev/null
@@ -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 ();
+}