]> gcc.gnu.org Git - gcc.git/commitdiff
re PR debug/50132 (ICE: in maybe_record_trace_start, at dwarf2cfi.c:2234 with -fno...
authorRichard Henderson <rth@redhat.com>
Thu, 25 Aug 2011 18:57:48 +0000 (11:57 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 25 Aug 2011 18:57:48 +0000 (11:57 -0700)
PR 50132
PR 49864
        * cfgcleanup.c (old_insns_match_p): Don't allow cross-jump for
        non-constant stack adjutment.
        * expr.c (find_args_size_adjust): Break out from ...
        (fixup_args_size_notes): ... here.
        * rtl.h (find_args_size_adjust): Declare.

From-SVN: r178084

gcc/ChangeLog
gcc/cfgcleanup.c
gcc/expr.c
gcc/rtl.h
gcc/testsuite/gcc.dg/pr50132.c [new file with mode: 0644]

index 1da50b432218585996321e01559a20b97056a293..df92093b9b6248eb6cc4aff7726e02d9f43f2d3c 100644 (file)
@@ -1,3 +1,13 @@
+2011-08-25  Richard Henderson  <rth@redhat.com>
+
+       PR 50132
+       PR 49864
+       * cfgcleanup.c (old_insns_match_p): Don't allow cross-jump for
+       non-constant stack adjutment.
+       * expr.c (find_args_size_adjust): Break out from ...
+       (fixup_args_size_notes): ... here.
+       * rtl.h (find_args_size_adjust): Declare.
+
 2011-08-25  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (isa): Add sse2, sse2_noavx, sse3,
index 717301354e730d25d98a0764eeb4be16b16d9406..396057cc19b348fba5fadad24ef361c537f44bc0 100644 (file)
@@ -1081,11 +1081,20 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
   /* ??? Do not allow cross-jumping between different stack levels.  */
   p1 = find_reg_note (i1, REG_ARGS_SIZE, NULL);
   p2 = find_reg_note (i2, REG_ARGS_SIZE, NULL);
-  if (p1)
-    p1 = XEXP (p1, 0);
-  if (p2)
-    p2 = XEXP (p2, 0);
-  if (!rtx_equal_p (p1, p2))
+  if (p1 && p2)
+    {
+      p1 = XEXP (p1, 0);
+      p2 = XEXP (p2, 0);
+      if (!rtx_equal_p (p1, p2))
+        return dir_none;
+
+      /* ??? Worse, this adjustment had better be constant lest we
+         have differing incoming stack levels.  */
+      if (!frame_pointer_needed
+          && find_args_size_adjust (i1) == HOST_WIDE_INT_MIN)
+       return dir_none;
+    }
+  else if (p1 || p2)
     return dir_none;
 
   p1 = PATTERN (i1);
index ee16b6a469ea8dd774ad0b69241842997127bcc5..a6746d1b50e87ff1ad97caedaa8dd9c76ab2140b 100644 (file)
@@ -3548,131 +3548,151 @@ mem_autoinc_base (rtx mem)
    verified, via immediate operand or auto-inc.  If the adjustment
    cannot be trivially extracted, the return value is INT_MIN.  */
 
-int
-fixup_args_size_notes (rtx prev, rtx last, int end_args_size)
+HOST_WIDE_INT
+find_args_size_adjust (rtx insn)
 {
-  int args_size = end_args_size;
-  bool saw_unknown = false;
-  rtx insn;
+  rtx dest, set, pat;
+  int i;
 
-  for (insn = last; insn != prev; insn = PREV_INSN (insn))
-    {
-      rtx dest, set, pat;
-      HOST_WIDE_INT this_delta = 0;
-      int i;
+  pat = PATTERN (insn);
+  set = NULL;
 
-      if (!NONDEBUG_INSN_P (insn))
-       continue;
-      pat = PATTERN (insn);
-      set = NULL;
+  /* Look for a call_pop pattern.  */
+  if (CALL_P (insn))
+    {
+      /* We have to allow non-call_pop patterns for the case
+        of emit_single_push_insn of a TLS address.  */
+      if (GET_CODE (pat) != PARALLEL)
+       return 0;
 
-      /* Look for a call_pop pattern.  */
-      if (CALL_P (insn))
+      /* All call_pop have a stack pointer adjust in the parallel.
+        The call itself is always first, and the stack adjust is
+        usually last, so search from the end.  */
+      for (i = XVECLEN (pat, 0) - 1; i > 0; --i)
        {
-          /* We have to allow non-call_pop patterns for the case
-            of emit_single_push_insn of a TLS address.  */
-         if (GET_CODE (pat) != PARALLEL)
-           continue;
-
-         /* All call_pop have a stack pointer adjust in the parallel.
-            The call itself is always first, and the stack adjust is
-            usually last, so search from the end.  */
-         for (i = XVECLEN (pat, 0) - 1; i > 0; --i)
-           {
-             set = XVECEXP (pat, 0, i);
-             if (GET_CODE (set) != SET)
-               continue;
-             dest = SET_DEST (set);
-             if (dest == stack_pointer_rtx)
-               break;
-           }
-         /* We'd better have found the stack pointer adjust.  */
-         if (i == 0)
+         set = XVECEXP (pat, 0, i);
+         if (GET_CODE (set) != SET)
            continue;
-         /* Fall through to process the extracted SET and DEST
-            as if it was a standalone insn.  */
+         dest = SET_DEST (set);
+         if (dest == stack_pointer_rtx)
+           break;
        }
-      else if (GET_CODE (pat) == SET)
-       set = pat;
-      else if ((set = single_set (insn)) != NULL)
-       ;
-      else if (GET_CODE (pat) == PARALLEL)
+      /* We'd better have found the stack pointer adjust.  */
+      if (i == 0)
+       return 0;
+      /* Fall through to process the extracted SET and DEST
+        as if it was a standalone insn.  */
+    }
+  else if (GET_CODE (pat) == SET)
+    set = pat;
+  else if ((set = single_set (insn)) != NULL)
+    ;
+  else if (GET_CODE (pat) == PARALLEL)
+    {
+      /* ??? Some older ports use a parallel with a stack adjust
+        and a store for a PUSH_ROUNDING pattern, rather than a
+        PRE/POST_MODIFY rtx.  Don't force them to update yet...  */
+      /* ??? See h8300 and m68k, pushqi1.  */
+      for (i = XVECLEN (pat, 0) - 1; i >= 0; --i)
        {
-         /* ??? Some older ports use a parallel with a stack adjust
-            and a store for a PUSH_ROUNDING pattern, rather than a
-            PRE/POST_MODIFY rtx.  Don't force them to update yet...  */
-         /* ??? See h8300 and m68k, pushqi1.  */
-         for (i = XVECLEN (pat, 0) - 1; i >= 0; --i)
-           {
-             set = XVECEXP (pat, 0, i);
-             if (GET_CODE (set) != SET)
-               continue;
-             dest = SET_DEST (set);
-             if (dest == stack_pointer_rtx)
-               break;
-
-             /* We do not expect an auto-inc of the sp in the parallel.  */
-             gcc_checking_assert (mem_autoinc_base (dest)
-                                  != stack_pointer_rtx);
-             gcc_checking_assert (mem_autoinc_base (SET_SRC (set))
-                                  != stack_pointer_rtx);
-           }
-         if (i < 0)
+         set = XVECEXP (pat, 0, i);
+         if (GET_CODE (set) != SET)
            continue;
+         dest = SET_DEST (set);
+         if (dest == stack_pointer_rtx)
+           break;
+
+         /* We do not expect an auto-inc of the sp in the parallel.  */
+         gcc_checking_assert (mem_autoinc_base (dest) != stack_pointer_rtx);
+         gcc_checking_assert (mem_autoinc_base (SET_SRC (set))
+                              != stack_pointer_rtx);
        }
+      if (i < 0)
+       return 0;
+    }
+  else
+    return 0;
+
+  dest = SET_DEST (set);
+
+  /* Look for direct modifications of the stack pointer.  */
+  if (REG_P (dest) && REGNO (dest) == STACK_POINTER_REGNUM)
+    {
+      /* Look for a trivial adjustment, otherwise assume nothing.  */
+      /* Note that the SPU restore_stack_block pattern refers to
+        the stack pointer in V4SImode.  Consider that non-trivial.  */
+      if (SCALAR_INT_MODE_P (GET_MODE (dest))
+         && GET_CODE (SET_SRC (set)) == PLUS
+         && XEXP (SET_SRC (set), 0) == stack_pointer_rtx
+         && CONST_INT_P (XEXP (SET_SRC (set), 1)))
+       return INTVAL (XEXP (SET_SRC (set), 1));
+      /* ??? Reload can generate no-op moves, which will be cleaned
+        up later.  Recognize it and continue searching.  */
+      else if (rtx_equal_p (dest, SET_SRC (set)))
+       return 0;
       else
-       continue;
-      dest = SET_DEST (set);
-
-      /* Look for direct modifications of the stack pointer.  */
-      if (REG_P (dest) && REGNO (dest) == STACK_POINTER_REGNUM)
-       {
-         gcc_assert (!saw_unknown);
-         /* Look for a trivial adjustment, otherwise assume nothing.  */
-         /* Note that the SPU restore_stack_block pattern refers to
-            the stack pointer in V4SImode.  Consider that non-trivial.  */
-         if (SCALAR_INT_MODE_P (GET_MODE (dest))
-             && GET_CODE (SET_SRC (set)) == PLUS
-             && XEXP (SET_SRC (set), 0) == stack_pointer_rtx
-             && CONST_INT_P (XEXP (SET_SRC (set), 1)))
-           this_delta = INTVAL (XEXP (SET_SRC (set), 1));
-         /* ??? Reload can generate no-op moves, which will be cleaned
-            up later.  Recognize it and continue searching.  */
-         else if (rtx_equal_p (dest, SET_SRC (set)))
-           this_delta = 0;
-         else
-           saw_unknown = true;
-       }
+       return HOST_WIDE_INT_MIN;
+    }
+  else
+    {
+      rtx mem, addr;
+
       /* Otherwise only think about autoinc patterns.  */
-      else if (mem_autoinc_base (dest) == stack_pointer_rtx)
+      if (mem_autoinc_base (dest) == stack_pointer_rtx)
        {
-         rtx addr = XEXP (dest, 0);
-         gcc_assert (!saw_unknown);
-         switch (GET_CODE (addr))
-           {
-           case PRE_INC:
-           case POST_INC:
-             this_delta = GET_MODE_SIZE (GET_MODE (dest));
-             break;
-           case PRE_DEC:
-           case POST_DEC:
-             this_delta = -GET_MODE_SIZE (GET_MODE (dest));
-             break;
-           case PRE_MODIFY:
-           case POST_MODIFY:
-             addr = XEXP (addr, 1);
-             gcc_assert (GET_CODE (addr) == PLUS);
-             gcc_assert (XEXP (addr, 0) == stack_pointer_rtx);
-             gcc_assert (CONST_INT_P (XEXP (addr, 1)));
-             this_delta = INTVAL (XEXP (addr, 1));
-             break;
-           default:
-             gcc_unreachable ();
-           }
+         mem = dest;
+         gcc_checking_assert (mem_autoinc_base (SET_SRC (set))
+                              != stack_pointer_rtx);
        }
+      else if (mem_autoinc_base (SET_SRC (set)) == stack_pointer_rtx)
+       mem = SET_SRC (set);
       else
+       return 0;
+
+      addr = XEXP (mem, 0);
+      switch (GET_CODE (addr))
+       {
+       case PRE_INC:
+       case POST_INC:
+         return GET_MODE_SIZE (GET_MODE (mem));
+       case PRE_DEC:
+       case POST_DEC:
+         return -GET_MODE_SIZE (GET_MODE (mem));
+       case PRE_MODIFY:
+       case POST_MODIFY:
+         addr = XEXP (addr, 1);
+         gcc_assert (GET_CODE (addr) == PLUS);
+         gcc_assert (XEXP (addr, 0) == stack_pointer_rtx);
+         gcc_assert (CONST_INT_P (XEXP (addr, 1)));
+         return INTVAL (XEXP (addr, 1));
+       default:
+         gcc_unreachable ();
+       }
+    }
+}
+
+int
+fixup_args_size_notes (rtx prev, rtx last, int end_args_size)
+{
+  int args_size = end_args_size;
+  bool saw_unknown = false;
+  rtx insn;
+
+  for (insn = last; insn != prev; insn = PREV_INSN (insn))
+    {
+      HOST_WIDE_INT this_delta;
+
+      if (!NONDEBUG_INSN_P (insn))
+       continue;
+
+      this_delta = find_args_size_adjust (insn);
+      if (this_delta == 0)
        continue;
 
+      gcc_assert (!saw_unknown);
+      if (this_delta == HOST_WIDE_INT_MIN)
+       saw_unknown = true;
+
       add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (args_size));
 #ifdef STACK_GROWS_DOWNWARD
       this_delta = -this_delta;
index e8aa7aba002441a040679417bd6206ff86753a01..7f863899f64e36741a36a6c0a82739db3324075e 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2508,6 +2508,7 @@ extern void emit_jump (rtx);
 /* In expr.c */
 extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT,
                           unsigned int, int);
+extern HOST_WIDE_INT find_args_size_adjust (rtx);
 extern int fixup_args_size_notes (rtx, rtx, int);
 
 /* In cfgrtl.c */
diff --git a/gcc/testsuite/gcc.dg/pr50132.c b/gcc/testsuite/gcc.dg/pr50132.c
new file mode 100644 (file)
index 0000000..84a9c73
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -fno-asynchronous-unwind-tables -g" } */
+
+void bar (long double n);
+
+void foo (int c)
+{
+  if (c)
+    bar (0);
+}
This page took 0.177516 seconds and 5 git commands to generate.