If purge_addressof_1 fails to remove addressofs in notes, remove the notes
authorNick Clifton <nickc@cygnus.com>
Fri, 5 Nov 1999 10:11:40 +0000 (10:11 +0000)
committerNick Clifton <nickc@gcc.gnu.org>
Fri, 5 Nov 1999 10:11:40 +0000 (10:11 +0000)
instead.

From-SVN: r30414

gcc/ChangeLog
gcc/function.c

index 59145c0cbdd31469f9952b7fd4251b0ad6df3deb..8be07eae1d4c1105802e5e0189104456b56562c0 100644 (file)
@@ -1,3 +1,13 @@
+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.
+
 1999-11-05  Andreas Jaeger  <aj@suse.de>
 
        * genoutput.c (null_operand =): Initialize all fields.
index 07dd0b103d03399edad9186e19a6862f1e3a28be..c9b4e20de86346b2a3b97fbc2e10c43ec1ddffbc 100644 (file)
@@ -268,8 +268,9 @@ static int all_blocks               PROTO((tree, tree *));
 static int *record_insns       PROTO((rtx)) ATTRIBUTE_UNUSED;
 static int contains            PROTO((rtx, int *));
 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));
@@ -2765,9 +2766,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;
@@ -2778,13 +2780,14 @@ purge_addressof_1 (loc, insn, force, store, ht)
   RTX_CODE code;
   int i, j;
   const 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);
 
@@ -2793,9 +2796,9 @@ purge_addressof_1 (loc, insn, force, store, ht)
      memory.  */
   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;
     }
 
   else if (code == ADDRESSOF && GET_CODE (XEXP (x, 0)) == MEM)
@@ -2807,7 +2810,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);
@@ -2818,7 +2821,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)
@@ -2853,7 +2856,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. */
@@ -2896,8 +2899,14 @@ purge_addressof_1 (loc, insn, force, store, ht)
                    return;
                  }
 
-             /* 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));
@@ -2989,7 +2998,7 @@ purge_addressof_1 (loc, insn, force, store, ht)
                                      purge_bitfield_addressof_replacements));
 
              /* We replaced with a reg -- all done.  */
-             return;
+             return true;
            }
        }
 
@@ -3007,13 +3016,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;
        }
@@ -3028,9 +3037,9 @@ purge_addressof_1 (loc, insn, force, store, ht)
     }
   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. */
@@ -3038,11 +3047,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.  */
@@ -3162,6 +3173,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.  */
@@ -3190,9 +3211,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.  */