OSDN Git Service

* gcc.c-torture/execute/ieee/ieee.exp: Change sh-*-* to sh*-*-*.
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index e741718..af0141f 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by John Carr (jfc@mit.edu).
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -59,7 +59,7 @@ Boston, MA 02111-1307, USA.  */
 
    To see whether two alias sets can point to the same memory, we must
    see if either alias set is a subset of the other. We need not trace
-   past immediate decendents, however, since we propagate all
+   past immediate descendents, however, since we propagate all
    grandchildren up one level.
 
    Alias set zero is implicitly a superset of all other alias sets.
@@ -72,7 +72,7 @@ typedef struct alias_set_entry
   HOST_WIDE_INT alias_set;
 
   /* The children of the alias set.  These are not just the immediate
-     children, but, in fact, all decendents.  So, if we have:
+     children, but, in fact, all descendents.  So, if we have:
 
        struct T { struct S s; float f; } 
 
@@ -99,7 +99,7 @@ static int can_address_p              PARAMS ((tree));
 static rtx find_base_value             PARAMS ((rtx));
 static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx));
 static int insert_subset_children       PARAMS ((splay_tree_node, void*));
-static tree find_base_decl            PARAMS ((tree));
+static tree find_base_decl             PARAMS ((tree));
 static alias_set_entry get_alias_set_entry PARAMS ((HOST_WIDE_INT));
 static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, rtx, rtx,
                                                      int (*) (rtx, int)));
@@ -276,24 +276,6 @@ alias_sets_conflict_p (set1, set2)
   return 0;
 }
 \f
-/* Set the alias set of MEM to SET.  */
-
-void
-set_mem_alias_set (mem, set)
-     rtx mem;
-     HOST_WIDE_INT set;
-{
-  /* We would like to do this test but can't yet since when converting a
-     REG to a MEM, the alias set field is undefined.  */
-#if 0
-  /* If the new and old alias sets don't conflict, something is wrong.  */
-  if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
-    abort ();
-#endif
-
-  MEM_ALIAS_SET (mem) = set;
-}
-\f
 /* Return 1 if TYPE is a RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE and has
    has any readonly fields.  If any of the fields have types that
    contain readonly fields, return true as well.  */
@@ -399,7 +381,6 @@ find_base_decl (t)
     case '3':
       d0 = find_base_decl (TREE_OPERAND (t, 0));
       d1 = find_base_decl (TREE_OPERAND (t, 1));
-      d0 = find_base_decl (TREE_OPERAND (t, 0));
       d2 = find_base_decl (TREE_OPERAND (t, 2));
 
       /* Set any nonzero values from the last, then from the first.  */
@@ -477,7 +458,6 @@ HOST_WIDE_INT
 get_alias_set (t)
      tree t;
 {
-  tree orig_t;
   HOST_WIDE_INT set;
 
   /* If we're not doing any alias analysis, just assume everything
@@ -489,49 +469,106 @@ get_alias_set (t)
     return 0;
 
   /* We can be passed either an expression or a type.  This and the
-     language-specific routine may make mutually-recursive calls to
-     each other to figure out what to do.  At each juncture, we see if
-     this is a tree that the language may need to handle specially.
-     First handle things that aren't types and start by removing nops
-     since we care only about the actual object.  */
+     language-specific routine may make mutually-recursive calls to each other
+     to figure out what to do.  At each juncture, we see if this is a tree
+     that the language may need to handle specially.  First handle things that
+     aren't types.  */
   if (! TYPE_P (t))
     {
-      while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
-            || TREE_CODE (t) == NON_LVALUE_EXPR)
-       t = TREE_OPERAND (t, 0);
-
-      /* Now give the language a chance to do something but record what we
-        gave it this time.  */
-      orig_t = t;
-      if ((set = lang_get_alias_set (t)) != -1)
-       return set;
-
-      /* Now loop the same way as get_inner_reference and get the alias
-        set to use.  Pick up the outermost object that we could have
-        a pointer to.  */
-      while (handled_component_p (t) && ! can_address_p (t))
-       t = TREE_OPERAND (t, 0);
+      tree inner = t;
+      tree placeholder_ptr = 0;
+
+      /* First see if the actual object referenced is an INDIRECT_REF from a
+        restrict-qualified pointer or a "void *".  Start by removing nops
+        since we care only about the actual object.  Also replace
+        PLACEHOLDER_EXPRs.  */
+      while (((TREE_CODE (inner) == NOP_EXPR
+              || TREE_CODE (inner) == CONVERT_EXPR)
+             && (TYPE_MODE (TREE_TYPE (inner))
+                 == TYPE_MODE (TREE_TYPE (TREE_OPERAND (inner, 0)))))
+            || TREE_CODE (inner) == NON_LVALUE_EXPR
+            || TREE_CODE (inner) == PLACEHOLDER_EXPR
+            || handled_component_p (inner))
+       {
+         if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
+           inner = find_placeholder (inner, &placeholder_ptr);
+         else
+           inner = TREE_OPERAND (inner, 0);
+       }
 
-      if (TREE_CODE (t) == INDIRECT_REF)
+      /* Check for accesses through restrict-qualified pointers.  */
+      if (TREE_CODE (inner) == INDIRECT_REF)
        {
-         /* Check for accesses through restrict-qualified pointers.  */
-         tree decl = find_base_decl (TREE_OPERAND (t, 0));
+         tree decl = find_base_decl (TREE_OPERAND (inner, 0));
 
          if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
-           /* We use the alias set indicated in the declaration.  */
-           return DECL_POINTER_ALIAS_SET (decl);
+           {
+             /* If we haven't computed the actual alias set, do it now. */
+             if (DECL_POINTER_ALIAS_SET (decl) == -2)
+               {
+                 /* No two restricted pointers can point at the same thing.
+                    However, a restricted pointer can point at the same thing
+                    as an unrestricted pointer, if that unrestricted pointer
+                    is based on the restricted pointer.  So, we make the
+                    alias set for the restricted pointer a subset of the
+                    alias set for the type pointed to by the type of the
+                    decl.  */
+                 HOST_WIDE_INT pointed_to_alias_set
+                   = get_alias_set (TREE_TYPE (TREE_TYPE (decl)));
+
+                 if (pointed_to_alias_set == 0)
+                   /* It's not legal to make a subset of alias set zero.  */
+                   ;
+                 else
+                   {
+                     DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
+                     record_alias_subset  (pointed_to_alias_set,
+                                           DECL_POINTER_ALIAS_SET (decl));
+                   }
+               }
+
+             /* We use the alias set indicated in the declaration.  */
+             return DECL_POINTER_ALIAS_SET (decl);
+           }
 
          /* If we have an INDIRECT_REF via a void pointer, we don't
             know anything about what that might alias.  */
-         if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE)
+         else if (TREE_CODE (TREE_TYPE (inner)) == VOID_TYPE)
            return 0;
        }
 
-      /* Give the language another chance to do something special.  */
-      if (orig_t != t
-         && (set = lang_get_alias_set (t)) != -1)
+      /* Otherwise, pick up the outermost object that we could have a pointer
+        to, processing conversion and PLACEHOLDER_EXPR as above.  */
+      placeholder_ptr = 0;
+      while (((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR)
+             && (TYPE_MODE (TREE_TYPE (t))
+                 == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0)))))
+            || TREE_CODE (t) == NON_LVALUE_EXPR
+            || TREE_CODE (t) == PLACEHOLDER_EXPR
+            || (handled_component_p (t) && ! can_address_p (t)))
+       {
+         /* Give the language a chance to do something with this tree
+            before we go inside it.  */
+         if ((set = lang_get_alias_set (t)) != -1)
+           return set;
+
+         if (TREE_CODE (t) == PLACEHOLDER_EXPR)
+           t = find_placeholder (t, &placeholder_ptr);
+         else
+           t = TREE_OPERAND (t, 0);
+       }
+
+      /* Give the language another chance to do something.  */
+      if ((set = lang_get_alias_set (t)) != -1)
        return set;
 
+      /* If we've already determined the alias set for a decl, just return
+        it.  This is necessary for C++ anonymous unions, whose component
+        variables don't look like union members (boo!).  */
+      if (TREE_CODE (t) == VAR_DECL
+         && DECL_RTL_SET_P (t) && GET_CODE (DECL_RTL (t)) == MEM)
+       return MEM_ALIAS_SET (DECL_RTL (t));
+
       /* Now all we care about is the type.  */
       t = TREE_TYPE (t);
     }
@@ -539,16 +576,12 @@ get_alias_set (t)
   /* Variant qualifiers don't affect the alias set, so get the main
      variant. If this is a type with a known alias set, return it.  */
   t = TYPE_MAIN_VARIANT (t);
-  if (TYPE_P (t) && TYPE_ALIAS_SET_KNOWN_P (t))
+  if (TYPE_ALIAS_SET_KNOWN_P (t))
     return TYPE_ALIAS_SET (t);
 
   /* See if the language has special handling for this type.  */
   if ((set = lang_get_alias_set (t)) != -1)
-    {
-      /* If the alias set is now known, we are done.  */
-      if (TYPE_ALIAS_SET_KNOWN_P (t))
-       return TYPE_ALIAS_SET (t);
-    }
+    return set;
 
   /* There are no objects of FUNCTION_TYPE, so there's no point in
      using up an alias set for them.  (There are, of course, pointers
@@ -599,6 +632,11 @@ record_alias_subset (superset, subset)
   alias_set_entry superset_entry;
   alias_set_entry subset_entry;
 
+  /* It is possible in complex type situations for both sets to be the same,
+     in which case we can ignore this operation.  */
+  if (superset == subset)
+    return;
+
   if (superset == 0)
     abort ();
 
@@ -711,7 +749,7 @@ get_frame_alias_set ()
 
 static rtx
 find_base_value (src)
-     register rtx src;
+     rtx src;
 {
   unsigned int regno;
   switch (GET_CODE (src))
@@ -843,7 +881,7 @@ record_set (dest, set, data)
      rtx dest, set;
      void *data ATTRIBUTE_UNUSED;
 {
-  register unsigned regno;
+  unsigned regno;
   rtx src;
 
   if (GET_CODE (dest) != REG)
@@ -954,6 +992,21 @@ record_base_value (regno, val, invariant)
   reg_base_value[regno] = find_base_value (val);
 }
 
+/* Clear alias info for a register.  This is used if an RTL transformation
+   changes the value of a register.  This is used in flow by AUTO_INC_DEC
+   optimizations.  We don't need to clear reg_base_value, since flow only
+   changes the offset.  */
+
+void
+clear_reg_alias_info (reg)
+     rtx reg;
+{
+  unsigned int regno = REGNO (reg);
+
+  if (regno < reg_known_value_size && regno >= FIRST_PSEUDO_REGISTER)
+    reg_known_value[regno] = reg;
+}
+
 /* Returns a canonical version of X, from the point of view alias
    analysis.  (For example, if X is a MEM whose address is a register,
    and the register has a known value (say a SYMBOL_REF), then a MEM
@@ -1002,10 +1055,10 @@ static int
 rtx_equal_for_memref_p (x, y)
      rtx x, y;
 {
-  register int i;
-  register int j;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i;
+  int j;
+  enum rtx_code code;
+  const char *fmt;
 
   if (x == 0 && y == 0)
     return 1;
@@ -1131,9 +1184,9 @@ static rtx
 find_symbolic_term (x)
      rtx x;
 {
-  register int i;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i;
+  enum rtx_code code;
+  const char *fmt;
 
   code = GET_CODE (x);
   if (code == SYMBOL_REF || code == LABEL_REF)
@@ -1160,7 +1213,7 @@ find_symbolic_term (x)
 
 static rtx
 find_base_term (x)
-     register rtx x;
+     rtx x;
 {
   cselib_val *val;
   struct elt_loc_list *l;
@@ -1434,7 +1487,7 @@ addr_side_effect_eval (addr, size, n_refs)
 
 static int
 memrefs_conflict_p (xsize, x, ysize, y, c)
-     register rtx x, y;
+     rtx x, y;
      int xsize, ysize;
      HOST_WIDE_INT c;
 {
@@ -1719,7 +1772,7 @@ true_dependence (mem, mem_mode, x, varies)
      rtx x;
      int (*varies) PARAMS ((rtx, int));
 {
-  register rtx x_addr, mem_addr;
+  rtx x_addr, mem_addr;
   rtx base;
 
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
@@ -1792,7 +1845,7 @@ canon_true_dependence (mem, mem_mode, mem_addr, x, varies)
      enum machine_mode mem_mode;
      int (*varies) PARAMS ((rtx, int));
 {
-  register rtx x_addr;
+  rtx x_addr;
 
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
     return 1;
@@ -1911,8 +1964,8 @@ anti_dependence (mem, x)
 
 int
 output_dependence (mem, x)
-     register rtx mem;
-     register rtx x;
+     rtx mem;
+     rtx x;
 {
   return write_dependence_p (mem, x, /*writep=*/1);
 }
@@ -1925,7 +1978,7 @@ nonlocal_mentioned_p (x)
      rtx x;
 {
   rtx base;
-  register RTX_CODE code;
+  RTX_CODE code;
   int regno;
 
   code = GET_CODE (x);
@@ -1934,7 +1987,7 @@ nonlocal_mentioned_p (x)
     {
       /* Constant functions can be constant if they don't use
          scratch memory used to mark function w/o side effects.  */
-      if (code == CALL_INSN && CONST_CALL_P (x))
+      if (code == CALL_INSN && CONST_OR_PURE_CALL_P (x))
         {
          x = CALL_INSN_FUNCTION_USAGE (x);
          if (x == 0)
@@ -2029,8 +2082,8 @@ nonlocal_mentioned_p (x)
   /* Recursively scan the operands of this expression.  */
 
   {
-    register const char *fmt = GET_RTX_FORMAT (code);
-    register int i;
+    const char *fmt = GET_RTX_FORMAT (code);
+    int i;
     
     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
       {
@@ -2041,7 +2094,7 @@ nonlocal_mentioned_p (x)
          }
        else if (fmt[i] == 'E')
          {
-           register int j;
+           int j;
            for (j = 0; j < XVECLEN (x, i); j++)
              if (nonlocal_mentioned_p (XVECEXP (x, i, j)))
                return 1;
@@ -2098,7 +2151,7 @@ static HARD_REG_SET argument_registers;
 void
 init_alias_once ()
 {
-  register int i;
+  int i;
 
 #ifndef OUTGOING_REGNO
 #define OUTGOING_REGNO(N) N
@@ -2122,9 +2175,9 @@ init_alias_analysis ()
 {
   int maxreg = max_reg_num ();
   int changed, pass;
-  register int i;
-  register unsigned int ui;
-  register rtx insn;
+  int i;
+  unsigned int ui;
+  rtx insn;
 
   reg_known_value_size = maxreg;