re PR rtl-optimization/36419 (Wrong unwind info with -Os -fasynchronous-unwind-tables)
authorJakub Jelinek <jakub@gcc.gnu.org>
Thu, 10 Jul 2008 07:39:54 +0000 (09:39 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 10 Jul 2008 07:39:54 +0000 (09:39 +0200)
PR rtl-optimization/36419
* combine-stack-adj.c (adjust_frame_related_expr): New function.
(combine_stack_adjustments_for_block): Call it if needed.  Delete
correct insn.
* dwarf2out.c (dwarf2out_frame_debug_expr): Adjust
DW_CFA_GNU_args_size if CSA pass merged some adjustments into
prologue sp adjustment.

* g++.dg/eh/async-unwind1.C: New test.

From-SVN: r137689

gcc/ChangeLog
gcc/combine-stack-adj.c
gcc/dwarf2out.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/async-unwind1.C [new file with mode: 0644]

index 3e9ce90d36c3a5f1a9d7f69b7da65f018668fa70..c5b36ecbf6ccbda58026b3e79ada1f984eab9c5c 100644 (file)
@@ -1,12 +1,20 @@
+2008-07-10  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/36419
+       * combine-stack-adj.c (adjust_frame_related_expr): New function.
+       (combine_stack_adjustments_for_block): Call it if needed.  Delete
+       correct insn.
+       * dwarf2out.c (dwarf2out_frame_debug_expr): Adjust
+       DW_CFA_GNU_args_size if CSA pass merged some adjustments into
+       prologue sp adjustment.
+
 2008-07-10  Peter Maydell  <pmaydell@chiark.greenend.org.uk>
 
        PR other/28322
-       * opts.c (print_ignored_options): report postponed diagnostics for
+       * opts.c (print_ignored_options): Report postponed diagnostics for
        unknown -Wno-* options as warnings, not errors.
-       (postpone_unknown_option_error): renamed to
-       postpone_unknown_option_warning.
-       * gcc.dg/pr28322-2.c: check that emitted diagnostic for -Wno-foobar
-       is a warning and not an error.
+       (postpone_unknown_option_error): Renamed to...
+       (postpone_unknown_option_warning): ... this.
 
 2008-07-09  Doug Kwan  <dougkwan@google.com>
 
index bf7cccf2df755e5fc4ce6c69cf8878188ef19c26..afcb35b33ea5a5dbc1a45202ef4999ec0a3f2d1c 100644 (file)
@@ -1,6 +1,6 @@
 /* Combine stack adjustments.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -272,6 +272,72 @@ record_stack_memrefs (rtx *xp, void *data)
   return 0;
 }
 
+/* Adjust or create REG_FRAME_RELATED_EXPR note when merging a stack
+   adjustment into a frame related insn.  */
+
+static void
+adjust_frame_related_expr (rtx last_sp_set, rtx insn,
+                          HOST_WIDE_INT this_adjust)
+{
+  rtx note = find_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, NULL_RTX);
+  rtx new_expr = NULL_RTX;
+
+  if (note == NULL_RTX && RTX_FRAME_RELATED_P (insn))
+    return;
+
+  if (note
+      && GET_CODE (XEXP (note, 0)) == SEQUENCE
+      && XVECLEN (XEXP (note, 0), 0) >= 2)
+    {
+      rtx expr = XEXP (note, 0);
+      rtx last = XVECEXP (expr, 0, XVECLEN (expr, 0) - 1);
+      int i;
+
+      if (GET_CODE (last) == SET
+         && RTX_FRAME_RELATED_P (last) == RTX_FRAME_RELATED_P (insn)
+         && SET_DEST (last) == stack_pointer_rtx
+         && GET_CODE (SET_SRC (last)) == PLUS
+         && XEXP (SET_SRC (last), 0) == stack_pointer_rtx
+         && GET_CODE (XEXP (SET_SRC (last), 1)) == CONST_INT)
+       {
+         XEXP (SET_SRC (last), 1)
+           = GEN_INT (INTVAL (XEXP (SET_SRC (last), 1)) + this_adjust);
+         return;
+       }
+
+      new_expr = gen_rtx_SEQUENCE (VOIDmode,
+                                  rtvec_alloc (XVECLEN (expr, 0) + 1));
+      for (i = 0; i < XVECLEN (expr, 0); i++)
+       XVECEXP (new_expr, 0, i) = XVECEXP (expr, 0, i);
+    }
+  else
+    {
+      new_expr = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2));
+      if (note)
+       XVECEXP (new_expr, 0, 0) = XEXP (note, 0);
+      else
+       {
+         rtx expr = copy_rtx (single_set_for_csa (last_sp_set));
+
+         XEXP (SET_SRC (expr), 1)
+           = GEN_INT (INTVAL (XEXP (SET_SRC (expr), 1)) - this_adjust);
+         RTX_FRAME_RELATED_P (expr) = 1;
+         XVECEXP (new_expr, 0, 0) = expr;
+       }
+    }
+
+  XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1)
+    = copy_rtx (single_set_for_csa (insn));
+  RTX_FRAME_RELATED_P (XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1))
+    = RTX_FRAME_RELATED_P (insn);
+  if (note)
+    XEXP (note, 0) = new_expr;
+  else
+    REG_NOTES (last_sp_set)
+      = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, new_expr,
+                          REG_NOTES (last_sp_set));
+}
+
 /* Subroutine of combine_stack_adjustments, called for each basic block.  */
 
 static void
@@ -343,6 +409,9 @@ combine_stack_adjustments_for_block (basic_block bb)
                                                  last_sp_adjust + this_adjust,
                                                  this_adjust))
                    {
+                     if (RTX_FRAME_RELATED_P (last_sp_set))
+                       adjust_frame_related_expr (last_sp_set, insn,
+                                                  this_adjust);
                      /* It worked!  */
                      delete_insn (insn);
                      last_sp_adjust += this_adjust;
@@ -373,7 +442,7 @@ combine_stack_adjustments_for_block (basic_block bb)
                 deallocation+allocation conspired to cancel, we can
                 delete the old deallocation insn.  */
              if (last_sp_set && last_sp_adjust == 0)
-               delete_insn (insn);
+               delete_insn (last_sp_set);
              free_csa_memlist (memlist);
              memlist = NULL;
              last_sp_set = insn;
index 80bdc0a4bb0eaf63ec5cc6e20ab78c7a294c1d96..46ab10481d54950f9699ce54f6e885c991619359 100644 (file)
@@ -1579,6 +1579,32 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
              && (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE)
              && (RTX_FRAME_RELATED_P (elem) || par_index == 0))
            dwarf2out_frame_debug_expr (elem, label);
+         else if (GET_CODE (elem) == SET
+                  && par_index != 0
+                  && !RTX_FRAME_RELATED_P (elem))
+           {
+             /* Stack adjustment combining might combine some post-prologue
+                stack adjustment into a prologue stack adjustment.  */
+             HOST_WIDE_INT offset = stack_adjust_offset (elem);
+
+             if (offset != 0)
+               {
+                 if (cfa.reg == STACK_POINTER_REGNUM)
+                   cfa.offset += offset;
+
+#ifndef STACK_GROWS_DOWNWARD
+                 offset = -offset;
+#endif
+
+                 args_size += offset;
+                 if (args_size < 0)
+                   args_size = 0;
+
+                 def_cfa_1 (label, &cfa);
+                 if (flag_asynchronous_unwind_tables)
+                   dwarf2out_args_size (label, args_size);
+               }
+           }
        }
       return;
     }
index 7518595c77578f3b21b51ef308704956d6f0770c..3c15329230727fe2b5345657632d0331576aecf6 100644 (file)
@@ -1,3 +1,14 @@
+2008-07-10  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/36419
+       * g++.dg/eh/async-unwind1.C: New test.
+
+2008-07-10  Peter Maydell  <pmaydell@chiark.greenend.org.uk>
+
+       PR other/28322
+       * gcc.dg/pr28322-2.c: Check that emitted diagnostic for -Wno-foobar
+       is a warning and not an error.
+
 2008-07-09  Ian Lance Taylor  <iant@google.com>
 
        * gcc.dg/no-asm-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/eh/async-unwind1.C b/gcc/testsuite/g++.dg/eh/async-unwind1.C
new file mode 100644 (file)
index 0000000..69b2c34
--- /dev/null
@@ -0,0 +1,61 @@
+// PR rtl-optimization/36419
+// { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } }
+// { dg-options "-Os -fasynchronous-unwind-tables -mpreferred-stack-boundary=4" }
+
+extern "C" void abort ();
+
+int v = -1;
+unsigned int n;
+
+__attribute__((noinline, used))
+void foo (int a, int)
+{
+  if (v < 0)
+    v = ((unsigned long) &a) & 15;
+  else if ((((unsigned long) &a) & 15) != v)
+    abort ();
+  if (n++ == 0)
+    throw 1;
+}
+
+__attribute__((noinline, used))
+void baz (int a, int, int, int, int, int, int)
+{
+  if (v < 0)
+    v = ((unsigned long) &a) & 15;
+  else if ((((unsigned long) &a) & 15) != v)
+    abort ();
+  if (n++ == 0)
+    throw 1;
+}
+
+struct A { A () { }; ~A (); char c[24]; };
+
+__attribute__((noinline))
+A::~A ()
+{
+  asm volatile ("" : : : "memory");
+}
+
+__attribute__((noinline))
+void bar ()
+{
+  A a;
+  try
+    {
+      foo (1, 2);
+      baz (3, 4, 5, 6, 7, 8, 9);
+    }
+  catch (...)
+    {
+    }
+  foo (1, 2);
+  baz (3, 4, 5, 6, 7, 8, 9);
+}
+
+int
+main ()
+{
+  bar ();
+  return 0;
+}