OSDN Git Service

In ChangeLog:
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index 53de65f..84fbdc9 100644 (file)
@@ -35,6 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "cselib.h"
 #include "splay-tree.h"
 #include "ggc.h"
+#include "langhooks.h"
 
 /* The alias sets assigned to MEMs assist the back-end in determining
    which MEMs can alias which other MEMs.  In general, two MEMs in
@@ -95,11 +96,10 @@ static rtx find_base_term           PARAMS ((rtx));
 static int base_alias_check            PARAMS ((rtx, rtx, enum machine_mode,
                                                 enum machine_mode));
 static int handled_component_p         PARAMS ((tree));
-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)));
@@ -342,7 +342,7 @@ objects_must_conflict_p (t1, t2)
 /* T is an expression with pointer type.  Find the DECL on which this
    expression is based.  (For example, in `a[i]' this would be `a'.)
    If there is no such DECL, or a unique decl cannot be determined,
-   NULL_TREE is retured.  */
+   NULL_TREE is returned.  */
 
 static tree
 find_base_decl (t)
@@ -426,7 +426,7 @@ handled_component_p (t)
 /* Return 1 if all the nested component references handled by
    get_inner_reference in T are such that we can address the object in T.  */
 
-static int
+int
 can_address_p (t)
      tree t;
 {
@@ -438,13 +438,18 @@ can_address_p (t)
   else if (TREE_CODE (t) == BIT_FIELD_REF)
     return 0;
 
+  /* Fields are addressable unless they are marked as nonaddressable or
+     the containing type has alias set 0.  */
   else if (TREE_CODE (t) == COMPONENT_REF
           && ! DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1))
+          && get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) != 0
           && can_address_p (TREE_OPERAND (t, 0)))
     return 1;
 
+  /* Likewise for arrays.  */
   else if ((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
           && ! TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0)))
+          && get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) != 0
           && can_address_p (TREE_OPERAND (t, 0)))
     return 1;
 
@@ -458,7 +463,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
@@ -473,63 +477,95 @@ get_alias_set (t)
      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.  Also replace PLACEHOLDER_EXPRs and pick up the outermost
-     object that we could have a pointer to.  */
+     aren't types.  */
   if (! TYPE_P (t))
     {
-      /* Remove any NOPs and see what any PLACEHOLD_EXPRs will expand to.  */
-      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;
+      tree inner = t;
+      tree placeholder_ptr = 0;
+
+      /* Remove any nops, then give the language a chance to do
+        something with this tree before we look at it.  */
+      STRIP_NOPS (t);
+      set = (*lang_hooks.get_alias_set) (t);
+      if (set != -1)
+       return set;
 
-         if (TREE_CODE (t) == PLACEHOLDER_EXPR)
-           t = find_placeholder (t, 0);
+      /* First see if the actual object referenced is an INDIRECT_REF from a
+        restrict-qualified pointer or a "void *".  Replace
+        PLACEHOLDER_EXPRs.  */
+      while (TREE_CODE (inner) == PLACEHOLDER_EXPR
+            || handled_component_p (inner))
+       {
+         if (TREE_CODE (inner) == PLACEHOLDER_EXPR)
+           inner = find_placeholder (inner, &placeholder_ptr);
          else
-           t = TREE_OPERAND (t, 0);
-       }
+           inner = TREE_OPERAND (inner, 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;
+         STRIP_NOPS (inner);
+       }
 
       /* Check for accesses through restrict-qualified pointers.  */
-      if (TREE_CODE (t) == INDIRECT_REF)
+      if (TREE_CODE (inner) == INDIRECT_REF)
        {
-         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;
        }
 
-      /* If we've already determined the alias set for this decl, just
-        return it.  This is necessary for C++ anonymous unions, whose
-        component variables don't look like union members (boo!).  */
+      /* 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) == PLACEHOLDER_EXPR
+            || (handled_component_p (t) && ! can_address_p (t)))
+       {
+         if (TREE_CODE (t) == PLACEHOLDER_EXPR)
+           t = find_placeholder (t, &placeholder_ptr);
+         else
+           t = TREE_OPERAND (t, 0);
+
+         STRIP_NOPS (t);
+       }
+
+      /* 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));
 
-      /* Give the language another chance to do something special.  */
-      if (orig_t != t
-         && (set = lang_get_alias_set (t)) != -1)
-       return set;
-
       /* Now all we care about is the type.  */
       t = TREE_TYPE (t);
     }
@@ -537,16 +573,13 @@ 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);
-    }
+  set = (*lang_hooks.get_alias_set) (t);
+  if (set != -1)
+    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
@@ -1221,7 +1254,7 @@ find_base_term (x)
        rtx tmp1 = XEXP (x, 0);
        rtx tmp2 = XEXP (x, 1);
 
-       /* This is a litle bit tricky since we have to determine which of
+       /* This is a little bit tricky since we have to determine which of
           the two operands represents the real base address.  Otherwise this
           routine may return the index register instead of the base register.
 
@@ -1784,7 +1817,7 @@ true_dependence (mem, mem_mode, x, varies)
   if (aliases_everything_p (x))
     return 1;
 
-  /* We cannot use aliases_everyting_p to test MEM, since we must look
+  /* We cannot use aliases_everything_p to test MEM, since we must look
      at MEM_MODE, rather than GET_MODE (MEM).  */
   if (mem_mode == QImode || GET_CODE (mem_addr) == AND)
     return 1;
@@ -1799,7 +1832,7 @@ true_dependence (mem, mem_mode, x, varies)
 }
 
 /* Canonical true dependence: X is read after store in MEM takes place.
-   Variant of true_dependece which assumes MEM has already been 
+   Variant of true_dependence which assumes MEM has already been 
    canonicalized (hence we no longer do that here).  
    The mem_addr argument has been added, since true_dependence computed 
    this value prior to canonicalizing.  */
@@ -1841,7 +1874,7 @@ canon_true_dependence (mem, mem_mode, mem_addr, x, varies)
   if (aliases_everything_p (x))
     return 1;
 
-  /* We cannot use aliases_everyting_p to test MEM, since we must look
+  /* We cannot use aliases_everything_p to test MEM, since we must look
      at MEM_MODE, rather than GET_MODE (MEM).  */
   if (mem_mode == QImode || GET_CODE (mem_addr) == AND)
     return 1;
@@ -2199,7 +2232,7 @@ init_alias_analysis ()
         start counting from zero each iteration of the loop.  */
       unique_id = 0;
 
-      /* We're at the start of the funtion each iteration through the
+      /* We're at the start of the function each iteration through the
         loop, so we're copying arguments.  */
       copying_arguments = 1;
 
@@ -2241,7 +2274,7 @@ init_alias_analysis ()
              rtx note, set;
 
 #if defined (HAVE_prologue) || defined (HAVE_epilogue)
-             /* The prologue/epilouge insns are not threaded onto the
+             /* The prologue/epilogue insns are not threaded onto the
                 insn chain until after reload has completed.  Thus,
                 there is no sense wasting time checking if INSN is in
                 the prologue/epilogue until after reload has completed.  */