]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix an abort in purge_addressof_1
authorBernd Schmidt <bernds@redhat.com>
Wed, 4 Apr 2001 13:26:24 +0000 (13:26 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Wed, 4 Apr 2001 13:26:24 +0000 (13:26 +0000)
From-SVN: r41080

gcc/ChangeLog
gcc/function.c

index d12f8e2b8ca80224b9f4729493e8ce286d50de0b..cf9174ea0e5a43837684a2180e7d5c463a6526f2 100644 (file)
@@ -1,3 +1,14 @@
+2001-04-04  Bernd Schmidt  <bernds@redhat.com>
+
+       Fri Nov  5 10:07:25 1999  Nick Clifton  <nickc@cygnus.com>
+       * function.c (is_addressof): New function.  Returns true if
+       the given piece of RTL is an ADDRESSOF.
+       (purge_addressof_1): Make boolean.  Return false if the
+       ADDRESSOFs could not be purged.
+       (purge_addressof): If ADDRESSOFs could not be purged from the
+       notes attached to an insn, remove the offending note(s),
+       unless they are attached to a libcall.
+
 2001-04-03  Bernd Schmidt  <bernds@redhat.com>
 
        2001-03-16  Jakub Jelinek  <jakub@redhat.com>
index edd0bca121681f598221db33e0187b4eb7124e95..5a7a2e2ed32e676bb7f0c403b99f2503a3ba40e7 100644 (file)
@@ -513,8 +513,9 @@ static int *record_insns    PROTO((rtx));
 static int contains            PROTO((rtx, int *));
 #endif /* HAVE_prologue || HAVE_epilogue */
 static void put_addressof_into_stack PROTO((rtx, struct hash_table *));
-static void purge_addressof_1  PROTO((rtx *, rtx, int, int, 
+static boolean purge_addressof_1 PROTO((rtx *, rtx, int, int, 
                                       struct hash_table *));
+static int is_addressof                PROTO ((rtx *, void *));
 static struct hash_entry *insns_for_mem_newfunc PROTO((struct hash_entry *,
                                                       struct hash_table *,
                                                       hash_table_key));
@@ -3055,9 +3056,10 @@ static rtx purge_addressof_replacements;
 
 /* Helper function for purge_addressof.  See if the rtx expression at *LOC
    in INSN needs to be changed.  If FORCE, always put any ADDRESSOFs into
-   the stack.  */
+   the stack.  If the function returns FALSE then the replacement could not
+   be made.  */
 
-static void
+static boolean
 purge_addressof_1 (loc, insn, force, store, ht)
      rtx *loc;
      rtx insn;
@@ -3068,13 +3070,14 @@ purge_addressof_1 (loc, insn, force, store, ht)
   RTX_CODE code;
   int i, j;
   char *fmt;
+  boolean result = true;
 
   /* Re-start here to avoid recursion in common cases.  */
  restart:
 
   x = *loc;
   if (x == 0)
-    return;
+    return true;
 
   code = GET_CODE (x);
 
@@ -3087,7 +3090,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
 
       if (validate_change (insn, loc, sub, 0)
          || validate_replace_rtx (x, sub, insn))
-       return;
+       return true;
   
       start_sequence ();
       sub = force_operand (sub, NULL_RTX);
@@ -3098,7 +3101,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
       insns = gen_sequence ();
       end_sequence ();
       emit_insn_before (insns, insn);
-      return;
+      return true;
     }
   else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force)
     {
@@ -3117,7 +3120,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
          && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
        {
          put_addressof_into_stack (XEXP (x, 0), ht);
-         return;
+         return true;
        }
       else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub))
        {
@@ -3136,7 +3139,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
                if (rtx_equal_p (x, XEXP (tem, 0)))
                  {
                    *loc = XEXP (XEXP (tem, 1), 0);
-                   return;
+                   return true;
                  }
 
              /* See comment for purge_addressof_replacements. */
@@ -3176,11 +3179,17 @@ purge_addressof_1 (loc, insn, force, store, ht)
                      z = gen_lowpart (GET_MODE (x), z);
 
                    *loc = z;
-                   return;
+                   return true;
                  }
 
-             /* There should always be such a replacement.  */
-             abort ();
+             /* Sometimes we may not be able to find the replacement.  For
+                example when the original insn was a MEM in a wider mode,
+                and the note is part of a sign extension of a narrowed
+                version of that MEM.  Gcc testcase compile/990829-1.c can
+                generate an example of this siutation.  Rather than complain
+                we return false, which will prompt our caller to remove the
+                offending note.  */
+             return false;
            }
 
          size_x = GET_MODE_BITSIZE (GET_MODE (x));
@@ -3266,7 +3275,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
                                      purge_bitfield_addressof_replacements));
 
              /* We replaced with a reg -- all done.  */
-             return;
+             return true;
            }
        }
       else if (validate_change (insn, loc, sub, 0))
@@ -3283,13 +3292,13 @@ purge_addressof_1 (loc, insn, force, store, ht)
                if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
                  {
                    XEXP (XEXP (tem, 1), 0) = sub;
-                   return;
+                   return true;
                  }
              purge_addressof_replacements
                = gen_rtx (EXPR_LIST, VOIDmode, XEXP (x, 0),
                           gen_rtx_EXPR_LIST (VOIDmode, sub,
                                              purge_addressof_replacements));
-             return;
+             return true;
            }
          goto restart;
        }
@@ -3299,13 +3308,13 @@ purge_addressof_1 (loc, insn, force, store, ht)
   else if (code == ADDRESSOF)
     {
       put_addressof_into_stack (x, ht);
-      return;
+      return true;
     }
   else if (code == SET)
     {
-      purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht);
-      purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht);
-      return;
+      result = purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht);
+      result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht);
+      return result;
     }
 
   /* Scan all subexpressions. */
@@ -3313,11 +3322,13 @@ purge_addressof_1 (loc, insn, force, store, ht)
   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     {
       if (*fmt == 'e')
-       purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht);
+       result &= purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht);
       else if (*fmt == 'E')
        for (j = 0; j < XVECLEN (x, i); j++)
-         purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht);
+         result &= purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht);
     }
+
+  return result;
 }
 
 /* Return a new hash table entry in HT.  */
@@ -3437,6 +3448,16 @@ compute_insns_for_mem (insns, last_insn, ht)
        }
 }
 
+/* Helper function for purge_addressof called through for_each_rtx.
+   Returns true iff the rtl is an ADDRESSOF.  */
+static int
+is_addressof (rtl, data)
+     rtx * rtl;
+     void * data ATTRIBUTE_UNUSED;
+{
+  return GET_CODE (* rtl) == ADDRESSOF;
+}
+
 /* Eliminate all occurrences of ADDRESSOF from INSNS.  Elide any remaining
    (MEM (ADDRESSOF)) patterns, and force any needed registers into the
    stack.  */
@@ -3465,9 +3486,30 @@ purge_addressof (insns)
     if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
        || GET_CODE (insn) == CALL_INSN)
       {
-       purge_addressof_1 (&PATTERN (insn), insn,
-                          asm_noperands (PATTERN (insn)) > 0, 0, &ht);
-       purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0, &ht);
+       if (! purge_addressof_1 (&PATTERN (insn), insn,
+                                asm_noperands (PATTERN (insn)) > 0, 0, &ht))
+         /* If we could not replace the ADDRESSOFs in the insn,
+            something is wrong.  */
+         abort ();
+       
+       if (! purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0, &ht))
+         {
+           /* If we could not replace the ADDRESSOFs in the insn's notes,
+              we can just remove the offending notes instead.  */
+           rtx note;
+
+           for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+             {
+               /* If we find a REG_RETVAL note then the insn is a libcall.
+                  Such insns must have REG_EQUAL notes as well, in order
+                  for later passes of the compiler to work.  So it is not
+                  safe to delete the notes here, and instead we abort.  */
+               if (REG_NOTE_KIND (note) == REG_RETVAL)
+                 abort ();
+               if (for_each_rtx (& note, is_addressof, NULL))
+                 remove_note (insn, note);
+             }
+         }
       }
 
   /* Clean up.  */