]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/gcc-tumbl.git/commitdiff
Backported from mainline
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Feb 2013 14:00:12 +0000 (14:00 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Feb 2013 14:00:12 +0000 (14:00 +0000)
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.

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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@195650 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 158998f0bb004c99ce904a2a89e02df87da04a40..53e33b52cad477ef7e109e3ae6949b3cb6934148 100644 (file)
@@ -1,6 +1,15 @@
 2013-02-01  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       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.
+
        2012-11-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/55236
index 04980ccad55ac59ae2ec30116645d5287190389a..7e4eed19dda9d3d77267c9f86e47fcdf3d0e652f 100644 (file)
@@ -4721,7 +4721,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 b59cf7bc9f0ebbaec00482b7282412b0a363d398..6ff161425fe76df7996c73971cd96e6d44b4541d 100644 (file)
@@ -1487,6 +1487,8 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
   edge fallthru1 = 0, fallthru2 = 0;
   edge e1, e2;
   edge_iterator ei;
+  rtx last1, last2;
+  bool nonfakeedges;
 
   /* If we performed shrink-wrapping, edges to the EXIT_BLOCK_PTR can
      only be distinguished for JUMP_INSNs.  The two paths may differ in
@@ -1695,9 +1697,15 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
        }
     }
 
+  last1 = BB_END (bb1);
+  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
@@ -1706,10 +1714,14 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
   if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs))
     return false;
 
+  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++;
 
@@ -1727,6 +1739,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 3a2707ec3917f3eae6b8366e876dfde69ed2234a..95b93040e4598f4923674f0e2ad2c47cd0aa9720 100644 (file)
@@ -1,6 +1,11 @@
 2013-02-01  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2012-11-20  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/55094
+       * gcc.dg/pr55094.c: New test.
+
        2012-11-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/55236
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 ();
+}