OSDN Git Service

* config/i386/i386.md (*cmpfp_<mode>): Enable for optimize_size.
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index cdbb94d..06ad867 100644 (file)
@@ -1,13 +1,13 @@
 /* Alias analysis for GNU C
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+   2007 Free Software Foundation, Inc.
    Contributed by John Carr (jfc@mit.edu).
 
 This file is part of GCC.
 
 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
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ 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 GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -46,10 +45,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "varray.h"
 #include "tree-pass.h"
 #include "ipa-type-escape.h"
+#include "df.h"
 
 /* The aliasing API provided here solves related but different problems:
 
-   Say there exists (in c) 
+   Say there exists (in c)
 
    struct X {
      struct Y y1;
@@ -87,7 +87,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    this may be too conservative for some C++ types.
 
    The pass ipa-type-escape does this analysis for the types whose
-   instances do not escape across the compilation boundary.  
+   instances do not escape across the compilation boundary.
 
    Historically in GCC, these two problems were combined and a single
    data structure was used to represent the solution to these
@@ -109,11 +109,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    `double'.  (However, a store to an `int' cannot alias a `double'
    and vice versa.)  We indicate this via a tree structure that looks
    like:
-           struct S
-            /   \
+          struct S
+           /   \
           /     \
-         |/_     _\|
-         int    double
+        |/_     _\|
+        int    double
 
    (The arrows are directed and point downwards.)
     In this situation we say the alias set for `struct S' is the
@@ -131,7 +131,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 struct alias_set_entry GTY(())
 {
   /* The alias set number, as stored in MEM_ALIAS_SET.  */
-  HOST_WIDE_INT alias_set;
+  alias_set_type alias_set;
+
+  /* Nonzero if would have a child of zero: this effectively makes this
+     alias set the same as alias set zero.  */
+  int has_zero_child;
 
   /* The children of the alias set.  These are not just the immediate
      children, but, in fact, all descendants.  So, if we have:
@@ -141,35 +145,29 @@ struct alias_set_entry GTY(())
      continuing our example above, the children here will be all of
      `int', `double', `float', and `struct S'.  */
   splay_tree GTY((param1_is (int), param2_is (int))) children;
-
-  /* Nonzero if would have a child of zero: this effectively makes this
-     alias set the same as alias set zero.  */
-  int has_zero_child;
 };
 typedef struct alias_set_entry *alias_set_entry;
 
-static int rtx_equal_for_memref_p (rtx, rtx);
-static rtx find_symbolic_term (rtx);
+static int rtx_equal_for_memref_p (const_rtx, const_rtx);
 static int memrefs_conflict_p (int, rtx, int, rtx, HOST_WIDE_INT);
-static void record_set (rtx, rtx, void *);
+static void record_set (rtx, const_rtx, void *);
 static int base_alias_check (rtx, rtx, enum machine_mode,
                             enum machine_mode);
 static rtx find_base_value (rtx);
-static int mems_in_disjoint_alias_sets_p (rtx, rtx);
+static int mems_in_disjoint_alias_sets_p (const_rtx, const_rtx);
 static int insert_subset_children (splay_tree_node, void*);
 static tree find_base_decl (tree);
-static alias_set_entry get_alias_set_entry (HOST_WIDE_INT);
-static rtx fixed_scalar_and_varying_struct_p (rtx, rtx, rtx, rtx,
-                                             int (*) (rtx, int));
-static int aliases_everything_p (rtx);
-static bool nonoverlapping_component_refs_p (tree, tree);
+static alias_set_entry get_alias_set_entry (alias_set_type);
+static const_rtx fixed_scalar_and_varying_struct_p (const_rtx, const_rtx, rtx, rtx,
+                                                   bool (*) (const_rtx, bool));
+static int aliases_everything_p (const_rtx);
+static bool nonoverlapping_component_refs_p (const_tree, const_tree);
 static tree decl_for_component_ref (tree);
 static rtx adjust_offset_for_component_ref (tree, rtx);
-static int nonoverlapping_memrefs_p (rtx, rtx);
-static int write_dependence_p (rtx, rtx, int);
+static int write_dependence_p (const_rtx, const_rtx, int);
 
-static void memory_modified_1 (rtx, rtx, void *);
-static void record_alias_subset (HOST_WIDE_INT, HOST_WIDE_INT);
+static void memory_modified_1 (rtx, const_rtx, void *);
+static void record_alias_subset (alias_set_type, alias_set_type);
 
 /* Set up all info needed to perform alias analysis on memory references.  */
 
@@ -206,32 +204,21 @@ static void record_alias_subset (HOST_WIDE_INT, HOST_WIDE_INT);
    current function performs nonlocal memory memory references for the
    purposes of marking the function as a constant function.  */
 
-static GTY(()) varray_type reg_base_value;
+static GTY(()) VEC(rtx,gc) *reg_base_value;
 static rtx *new_reg_base_value;
 
 /* We preserve the copy of old array around to avoid amount of garbage
    produced.  About 8% of garbage produced were attributed to this
    array.  */
-static GTY((deletable)) varray_type old_reg_base_value;
+static GTY((deletable)) VEC(rtx,gc) *old_reg_base_value;
 
 /* Static hunks of RTL used by the aliasing code; these are initialized
    once per function to avoid unnecessary RTL allocations.  */
 static GTY (()) rtx static_reg_base_value[FIRST_PSEUDO_REGISTER];
 
-#define REG_BASE_VALUE(X) \
-  (reg_base_value && REGNO (X) < VARRAY_SIZE (reg_base_value) \
-   ? VARRAY_RTX (reg_base_value, REGNO (X)) : 0)
-
-/* Vector of known invariant relationships between registers.  Set in
-   loop unrolling.  Indexed by register number, if nonzero the value
-   is an expression describing this register in terms of another.
-
-   The length of this array is REG_BASE_VALUE_SIZE.
-
-   Because this array contains only pseudo registers it has no effect
-   after reload.  */
-static GTY((length("alias_invariant_size"))) rtx *alias_invariant;
-static GTY(()) unsigned int alias_invariant_size;
+#define REG_BASE_VALUE(X)                              \
+  (REGNO (X) < VEC_length (rtx, reg_base_value)                \
+   ? VEC_index (rtx, reg_base_value, REGNO (X)) : 0)
 
 /* Vector indexed by N giving the initial (unchanging) value known for
    pseudo-register N.  This array is initialized in init_alias_analysis,
@@ -259,23 +246,26 @@ static bool *reg_known_equiv_p;
    NOTE_INSN_FUNCTION_BEG note.  */
 static bool copying_arguments;
 
+DEF_VEC_P(alias_set_entry);
+DEF_VEC_ALLOC_P(alias_set_entry,gc);
+
 /* The splay-tree used to store the various alias set entries.  */
-static GTY ((param_is (struct alias_set_entry))) varray_type alias_sets;
+static GTY (()) VEC(alias_set_entry,gc) *alias_sets;
 \f
 /* Returns a pointer to the alias set entry for ALIAS_SET, if there is
    such an entry, or NULL otherwise.  */
 
 static inline alias_set_entry
-get_alias_set_entry (HOST_WIDE_INT alias_set)
+get_alias_set_entry (alias_set_type alias_set)
 {
-  return (alias_set_entry)VARRAY_GENERIC_PTR (alias_sets, alias_set);
+  return VEC_index (alias_set_entry, alias_sets, alias_set);
 }
 
 /* Returns nonzero if the alias sets for MEM1 and MEM2 are such that
    the two MEMs cannot alias each other.  */
 
 static inline int
-mems_in_disjoint_alias_sets_p (rtx mem1, rtx mem2)
+mems_in_disjoint_alias_sets_p (const_rtx mem1, const_rtx mem2)
 {
 /* Perform a basic sanity check.  Namely, that there are no alias sets
    if we're not using strict aliasing.  This helps to catch bugs
@@ -301,18 +291,36 @@ insert_subset_children (splay_tree_node node, void *data)
   return 0;
 }
 
+/* Return true if the first alias set is a subset of the second.  */
+
+bool
+alias_set_subset_of (alias_set_type set1, alias_set_type set2)
+{
+  alias_set_entry ase;
+
+  /* Everything is a subset of the "aliases everything" set.  */
+  if (set2 == 0)
+    return true;
+
+  /* Otherwise, check if set1 is a subset of set2.  */
+  ase = get_alias_set_entry (set2);
+  if (ase != 0
+      && ((ase->has_zero_child && set1 == 0)
+         || splay_tree_lookup (ase->children,
+                               (splay_tree_key) set1)))
+    return true;
+  return false;
+}
+
 /* Return 1 if the two specified alias sets may conflict.  */
 
 int
-alias_sets_conflict_p (HOST_WIDE_INT set1, HOST_WIDE_INT set2)
+alias_sets_conflict_p (alias_set_type set1, alias_set_type set2)
 {
   alias_set_entry ase;
 
-  /* If have no alias set information for one of the operands, we have
-     to assume it can alias anything.  */
-  if (set1 == 0 || set2 == 0
-      /* If the two alias sets are the same, they may alias.  */
-      || set1 == set2)
+  /* The easy case.  */
+  if (alias_sets_must_conflict_p (set1, set2))
     return 1;
 
   /* See if the first alias set is a subset of the second.  */
@@ -332,15 +340,14 @@ alias_sets_conflict_p (HOST_WIDE_INT set1, HOST_WIDE_INT set2)
     return 1;
 
   /* The two alias sets are distinct and neither one is the
-     child of the other.  Therefore, they cannot alias.  */
+     child of the other.  Therefore, they cannot conflict.  */
   return 0;
 }
 
-/* Return 1 if the two specified alias sets might conflict, or if any subtype
-   of these alias sets might conflict.  */
+/* Return 1 if the two specified alias sets will always conflict.  */
 
 int
-alias_sets_might_conflict_p (HOST_WIDE_INT set1, HOST_WIDE_INT set2)
+alias_sets_must_conflict_p (alias_set_type set1, alias_set_type set2)
 {
   if (set1 == 0 || set2 == 0 || set1 == set2)
     return 1;
@@ -348,7 +355,6 @@ alias_sets_might_conflict_p (HOST_WIDE_INT set1, HOST_WIDE_INT set2)
   return 0;
 }
 
-\f
 /* Return 1 if any MEM object of type T1 will always conflict (using the
    dependency routines in this file) with any MEM object of type T2.
    This is used when allocating temporary storage.  If T1 and/or T2 are
@@ -357,7 +363,7 @@ alias_sets_might_conflict_p (HOST_WIDE_INT set1, HOST_WIDE_INT set2)
 int
 objects_must_conflict_p (tree t1, tree t2)
 {
-  HOST_WIDE_INT set1, set2;
+  alias_set_type set1, set2;
 
   /* If neither has a type specified, we don't know if they'll conflict
      because we may be using them to store objects of various types, for
@@ -374,12 +380,11 @@ objects_must_conflict_p (tree t1, tree t2)
   set1 = t1 ? get_alias_set (t1) : 0;
   set2 = t2 ? get_alias_set (t2) : 0;
 
-  /* Otherwise they conflict if they have no alias set or the same. We
-     can't simply use alias_sets_conflict_p here, because we must make
-     sure that every subtype of t1 will conflict with every subtype of
+  /* We can't use alias_sets_conflict_p because we must make sure
+     that every subtype of t1 will conflict with every subtype of
      t2 for which a pair of subobjects of these respective subtypes
      overlaps on the stack.  */
-  return set1 == 0 || set2 == 0 || set1 == set2;
+  return alias_sets_must_conflict_p (set1, set2);
 }
 \f
 /* T is an expression with pointer type.  Find the DECL on which this
@@ -395,9 +400,14 @@ find_base_decl (tree t)
   if (t == 0 || t == error_mark_node || ! POINTER_TYPE_P (TREE_TYPE (t)))
     return 0;
 
-  /* If this is a declaration, return it.  */
+  /* If this is a declaration, return it.  If T is based on a restrict
+     qualified decl, return that decl.  */
   if (DECL_P (t))
-    return t;
+    {
+      if (TREE_CODE (t) == VAR_DECL && DECL_BASED_ON_RESTRICT_P (t))
+       t = DECL_GET_RESTRICT_BASE (t);
+      return t;
+    }
 
   /* Handle general expressions.  It would be nice to deal with
      COMPONENT_REFs here.  If we could tell that `a' and `b' were the
@@ -436,7 +446,7 @@ find_base_decl (tree t)
    assignable alias sets.  */
 
 bool
-component_uses_parent_alias_set (tree t)
+component_uses_parent_alias_set (const_tree t)
 {
   while (1)
     {
@@ -475,10 +485,10 @@ component_uses_parent_alias_set (tree t)
 /* Return the alias set for T, which may be either a type or an
    expression.  Call language-specific routine for help, if needed.  */
 
-HOST_WIDE_INT
+alias_set_type
 get_alias_set (tree t)
 {
-  HOST_WIDE_INT set;
+  alias_set_type set;
 
   /* If we're not doing any alias analysis, just assume everything
      aliases everything else.  Also return 0 if this or its type is
@@ -515,7 +525,12 @@ get_alias_set (tree t)
       /* Check for accesses through restrict-qualified pointers.  */
       if (INDIRECT_REF_P (inner))
        {
-         tree decl = find_base_decl (TREE_OPERAND (inner, 0));
+         tree decl;
+
+         if (TREE_CODE (TREE_OPERAND (inner, 0)) == SSA_NAME)
+           decl = SSA_NAME_VAR (TREE_OPERAND (inner, 0));
+         else
+           decl = find_base_decl (TREE_OPERAND (inner, 0));
 
          if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
            {
@@ -531,7 +546,7 @@ get_alias_set (tree t)
                     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
+                 alias_set_type pointed_to_alias_set
                    = get_alias_set (pointed_to_type);
 
                  if (pointed_to_alias_set == 0)
@@ -594,6 +609,18 @@ get_alias_set (tree t)
   if (TYPE_ALIAS_SET_KNOWN_P (t))
     return TYPE_ALIAS_SET (t);
 
+  /* We don't want to set TYPE_ALIAS_SET for incomplete types.  */
+  if (!COMPLETE_TYPE_P (t))
+    {
+      /* For arrays with unknown size the conservative answer is the
+        alias set of the element type.  */
+      if (TREE_CODE (t) == ARRAY_TYPE)
+       return get_alias_set (TREE_TYPE (t));
+
+      /* But return zero as a conservative answer for incomplete types.  */
+      return 0;
+    }
+
   /* See if the language has special handling for this type.  */
   set = lang_hooks.get_alias_set (t);
   if (set != -1)
@@ -602,7 +629,8 @@ get_alias_set (tree t)
   /* 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
      and references to functions, but that's different.)  */
-  else if (TREE_CODE (t) == FUNCTION_TYPE)
+  else if (TREE_CODE (t) == FUNCTION_TYPE
+          || TREE_CODE (t) == METHOD_TYPE)
     set = 0;
 
   /* Unless the language specifies otherwise, let vector types alias
@@ -628,18 +656,15 @@ get_alias_set (tree t)
 
 /* Return a brand-new alias set.  */
 
-static GTY(()) HOST_WIDE_INT last_alias_set;
-
-HOST_WIDE_INT
+alias_set_type
 new_alias_set (void)
 {
   if (flag_strict_aliasing)
     {
-      if (!alias_sets)
-       VARRAY_GENERIC_PTR_INIT (alias_sets, 10, "alias sets");
-      else
-       VARRAY_GROW (alias_sets, last_alias_set + 2);
-      return ++last_alias_set;
+      if (alias_sets == 0)
+       VEC_safe_push (alias_set_entry, gc, alias_sets, 0);
+      VEC_safe_push (alias_set_entry, gc, alias_sets, 0);
+      return VEC_length (alias_set_entry, alias_sets) - 1;
     }
   else
     return 0;
@@ -659,7 +684,7 @@ new_alias_set (void)
    subset of alias set zero.  */
 
 static void
-record_alias_subset (HOST_WIDE_INT superset, HOST_WIDE_INT subset)
+record_alias_subset (alias_set_type superset, alias_set_type subset)
 {
   alias_set_entry superset_entry;
   alias_set_entry subset_entry;
@@ -681,7 +706,7 @@ record_alias_subset (HOST_WIDE_INT superset, HOST_WIDE_INT subset)
       superset_entry->children
        = splay_tree_new_ggc (splay_tree_compare_ints);
       superset_entry->has_zero_child = 0;
-      VARRAY_GENERIC_PTR (alias_sets, superset) = superset_entry;
+      VEC_replace (alias_set_entry, alias_sets, superset, superset_entry);
     }
 
   if (subset == 0)
@@ -708,14 +733,13 @@ record_alias_subset (HOST_WIDE_INT superset, HOST_WIDE_INT subset)
 
 /* Record that component types of TYPE, if any, are part of that type for
    aliasing purposes.  For record types, we only record component types
-   for fields that are marked addressable.  For array types, we always
-   record the component types, so the front end should not call this
-   function if the individual component aren't addressable.  */
+   for fields that are not marked non-addressable.  For array types, we
+   only record the component type if it is not marked non-aliased.  */
 
 void
 record_component_aliases (tree type)
 {
-  HOST_WIDE_INT superset = get_alias_set (type);
+  alias_set_type superset = get_alias_set (type);
   tree field;
 
   if (superset == 0)
@@ -724,7 +748,7 @@ record_component_aliases (tree type)
   switch (TREE_CODE (type))
     {
     case ARRAY_TYPE:
-      if (! TYPE_NONALIASED_COMPONENT (type))
+      if (!TYPE_NONALIASED_COMPONENT (type))
        record_alias_subset (superset, get_alias_set (TREE_TYPE (type)));
       break;
 
@@ -736,14 +760,14 @@ record_component_aliases (tree type)
        {
          int i;
          tree binfo, base_binfo;
-         
+
          for (binfo = TYPE_BINFO (type), i = 0;
               BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
            record_alias_subset (superset,
                                 get_alias_set (BINFO_TYPE (base_binfo)));
        }
       for (field = TYPE_FIELDS (type); field != 0; field = TREE_CHAIN (field))
-       if (TREE_CODE (field) == FIELD_DECL && ! DECL_NONADDRESSABLE_P (field))
+       if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
          record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
       break;
 
@@ -759,9 +783,9 @@ record_component_aliases (tree type)
 /* Allocate an alias set for use in storing and reading from the varargs
    spill area.  */
 
-static GTY(()) HOST_WIDE_INT varargs_set = -1;
+static GTY(()) alias_set_type varargs_set = -1;
 
-HOST_WIDE_INT
+alias_set_type
 get_varargs_alias_set (void)
 {
 #if 1
@@ -781,9 +805,9 @@ get_varargs_alias_set (void)
 /* Likewise, but used for the fixed portions of the frame, e.g., register
    save areas.  */
 
-static GTY(()) HOST_WIDE_INT frame_set = -1;
+static GTY(()) alias_set_type frame_set = -1;
 
-HOST_WIDE_INT
+alias_set_type
 get_frame_alias_set (void)
 {
   if (frame_set == -1)
@@ -821,16 +845,16 @@ find_base_value (rtx src)
         The test above is not sufficient because the scheduler may move
         a copy out of an arg reg past the NOTE_INSN_FUNCTION_BEGIN.  */
       if ((regno >= FIRST_PSEUDO_REGISTER || fixed_regs[regno])
-         && regno < VARRAY_SIZE (reg_base_value))
+         && regno < VEC_length (rtx, reg_base_value))
        {
          /* If we're inside init_alias_analysis, use new_reg_base_value
             to reduce the number of relaxation iterations.  */
          if (new_reg_base_value && new_reg_base_value[regno]
-             && REG_N_SETS (regno) == 1)
+             && DF_REG_DEF_COUNT (regno) == 1)
            return new_reg_base_value[regno];
 
-         if (VARRAY_RTX (reg_base_value, regno))
-           return VARRAY_RTX (reg_base_value, regno);
+         if (VEC_index (rtx, reg_base_value, regno))
+           return VEC_index (rtx, reg_base_value, regno);
        }
 
       return 0;
@@ -963,7 +987,7 @@ static char *reg_seen;
 static int unique_id;
 
 static void
-record_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
+record_set (rtx dest, const_rtx set, void *data ATTRIBUTE_UNUSED)
 {
   unsigned regno;
   rtx src;
@@ -974,7 +998,7 @@ record_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
 
   regno = REGNO (dest);
 
-  gcc_assert (regno < VARRAY_SIZE (reg_base_value));
+  gcc_assert (regno < VEC_length (rtx, reg_base_value));
 
   /* If this spans multiple hard registers, then we must indicate that every
      register has an unusable value.  */
@@ -1029,7 +1053,7 @@ record_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
      If neither case holds, reject the original base value as invalid.
      Note that the following situation is not detected:
 
-         extern int x, y;  int *p = &x; p += (&y-&x);
+        extern int x, y;  int *p = &x; p += (&y-&x);
 
      ANSI C does not allow computing the difference of addresses
      of distinct top level objects.  */
@@ -1074,55 +1098,9 @@ record_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
   reg_seen[regno] = 1;
 }
 
-/* Called from loop optimization when a new pseudo-register is
-   created.  It indicates that REGNO is being set to VAL.  f INVARIANT
-   is true then this value also describes an invariant relationship
-   which can be used to deduce that two registers with unknown values
-   are different.  */
-
-void
-record_base_value (unsigned int regno, rtx val, int invariant)
-{
-  if (invariant && alias_invariant && regno < alias_invariant_size)
-    alias_invariant[regno] = val;
-
-  if (regno >= VARRAY_SIZE (reg_base_value))
-    VARRAY_GROW (reg_base_value, max_reg_num ());
-
-  if (REG_P (val))
-    {
-      VARRAY_RTX (reg_base_value, regno)
-        = REG_BASE_VALUE (val);
-      return;
-    }
-  VARRAY_RTX (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 (rtx reg)
-{
-  unsigned int regno = REGNO (reg);
-
-  if (regno >= FIRST_PSEUDO_REGISTER)
-    {
-      regno -= FIRST_PSEUDO_REGISTER;
-      if (regno < reg_known_value_size)
-       {
-         reg_known_value[regno] = reg;
-         reg_known_equiv_p[regno] = false;
-       }
-    }
-}
-
 /* If a value is known for REGNO, return it.  */
 
-rtx 
+rtx
 get_reg_known_value (unsigned int regno)
 {
   if (regno >= FIRST_PSEUDO_REGISTER)
@@ -1223,7 +1201,7 @@ canon_rtx (rtx x)
    different numbers are, in fact, equivalent.  */
 
 static int
-rtx_equal_for_memref_p (rtx x, rtx y)
+rtx_equal_for_memref_p (const_rtx x, const_rtx y)
 {
   int i;
   int j;
@@ -1264,6 +1242,7 @@ rtx_equal_for_memref_p (rtx x, rtx y)
     case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_FIXED:
       /* There's no need to compare the contents of CONST_DOUBLEs or
         CONST_INTs because pointer equality is a good enough
         comparison for these nodes.  */
@@ -1356,39 +1335,6 @@ rtx_equal_for_memref_p (rtx x, rtx y)
   return 1;
 }
 
-/* Given an rtx X, find a SYMBOL_REF or LABEL_REF within
-   X and return it, or return 0 if none found.  */
-
-static rtx
-find_symbolic_term (rtx x)
-{
-  int i;
-  enum rtx_code code;
-  const char *fmt;
-
-  code = GET_CODE (x);
-  if (code == SYMBOL_REF || code == LABEL_REF)
-    return x;
-  if (OBJECT_P (x))
-    return 0;
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      rtx t;
-
-      if (fmt[i] == 'e')
-       {
-         t = find_symbolic_term (XEXP (x, i));
-         if (t != 0)
-           return t;
-       }
-      else if (fmt[i] == 'E')
-       break;
-    }
-  return 0;
-}
-
 rtx
 find_base_term (rtx x)
 {
@@ -1651,7 +1597,7 @@ addr_side_effect_eval (rtx addr, int size, int n_refs)
 
   if (offset)
     addr = gen_rtx_PLUS (GET_MODE (addr), XEXP (addr, 0),
-                        GEN_INT (offset));
+                        GEN_INT (offset));
   else
     addr = XEXP (addr, 0);
   addr = canon_rtx (addr);
@@ -1787,25 +1733,6 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
          return memrefs_conflict_p (xsize, x0, ysize, y0, c);
        }
 
-      case REG:
-       /* Are these registers known not to be equal?  */
-       if (alias_invariant)
-         {
-           unsigned int r_x = REGNO (x), r_y = REGNO (y);
-           rtx i_x, i_y;       /* invariant relationships of X and Y */
-
-           i_x = r_x >= alias_invariant_size ? 0 : alias_invariant[r_x];
-           i_y = r_y >= alias_invariant_size ? 0 : alias_invariant[r_y];
-
-           if (i_x == 0 && i_y == 0)
-             break;
-
-           if (! memrefs_conflict_p (xsize, i_x ? i_x : x,
-                                     ysize, i_y ? i_y : y, c))
-             return 0;
-         }
-       break;
-
       default:
        break;
       }
@@ -1886,7 +1813,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
    only be a dependence here if both reads are volatile.  */
 
 int
-read_dependence (rtx mem, rtx x)
+read_dependence (const_rtx mem, const_rtx x)
 {
   return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem);
 }
@@ -1899,21 +1826,23 @@ read_dependence (rtx mem, rtx x)
    nonzero whenever variation is possible.
    MEM1_ADDR and MEM2_ADDR are the addresses of MEM1 and MEM2.  */
 
-static rtx
-fixed_scalar_and_varying_struct_p (rtx mem1, rtx mem2, rtx mem1_addr,
+static const_rtx
+fixed_scalar_and_varying_struct_p (const_rtx mem1, const_rtx mem2, rtx mem1_addr,
                                   rtx mem2_addr,
-                                  int (*varies_p) (rtx, int))
+                                  bool (*varies_p) (const_rtx, bool))
 {
   if (! flag_strict_aliasing)
     return NULL_RTX;
 
-  if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
+  if (MEM_ALIAS_SET (mem2)
+      && MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
       && !varies_p (mem1_addr, 1) && varies_p (mem2_addr, 1))
     /* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
        varying address.  */
     return mem1;
 
-  if (MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
+  if (MEM_ALIAS_SET (mem1)
+      && MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
       && varies_p (mem1_addr, 1) && !varies_p (mem2_addr, 1))
     /* MEM2 is a scalar at a fixed address; MEM1 is a struct at a
        varying address.  */
@@ -1926,7 +1855,7 @@ fixed_scalar_and_varying_struct_p (rtx mem1, rtx mem2, rtx mem1_addr,
    indicates that it might well alias *anything*.  */
 
 static int
-aliases_everything_p (rtx mem)
+aliases_everything_p (const_rtx mem)
 {
   if (GET_CODE (XEXP (mem, 0)) == AND)
     /* If the address is an AND, it's very hard to know at what it is
@@ -1940,9 +1869,9 @@ aliases_everything_p (rtx mem)
    overlap for any pair of objects.  */
 
 static bool
-nonoverlapping_component_refs_p (tree x, tree y)
+nonoverlapping_component_refs_p (const_tree x, const_tree y)
 {
-  tree fieldx, fieldy, typex, typey, orig_y;
+  const_tree fieldx, fieldy, typex, typey, orig_y;
 
   do
     {
@@ -1952,13 +1881,13 @@ nonoverlapping_component_refs_p (tree x, tree y)
       do
        {
          fieldx = TREE_OPERAND (x, 1);
-         typex = DECL_FIELD_CONTEXT (fieldx);
+         typex = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldx));
 
          y = orig_y;
          do
            {
              fieldy = TREE_OPERAND (y, 1);
-             typey = DECL_FIELD_CONTEXT (fieldy);
+             typey = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldy));
 
              if (typex == typey)
                goto found;
@@ -1971,7 +1900,7 @@ nonoverlapping_component_refs_p (tree x, tree y)
        }
       while (x && TREE_CODE (x) == COMPONENT_REF);
       /* Never found a common type.  */
-      return true;
+      return false;
 
     found:
       /* If we're left with accessing different fields of a structure,
@@ -2039,8 +1968,8 @@ adjust_offset_for_component_ref (tree x, rtx offset)
 /* Return nonzero if we can determine the exprs corresponding to memrefs
    X and Y and they do not overlap.  */
 
-static int
-nonoverlapping_memrefs_p (rtx x, rtx y)
+int
+nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
 {
   tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
   rtx rtlx, rtly;
@@ -2051,14 +1980,14 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
   /* Unless both have exprs, we can't tell anything.  */
   if (exprx == 0 || expry == 0)
     return 0;
-  
+
   /* If both are field references, we may be able to determine something.  */
   if (TREE_CODE (exprx) == COMPONENT_REF
       && TREE_CODE (expry) == COMPONENT_REF
       && nonoverlapping_component_refs_p (exprx, expry))
     return 1;
 
-  
+
   /* If the field reference test failed, look at the DECLs involved.  */
   moffsetx = MEM_OFFSET (x);
   if (TREE_CODE (exprx) == COMPONENT_REF)
@@ -2070,7 +1999,7 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
         tree fieldcontext = DECL_FIELD_CONTEXT (field);
         if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
                                                       TREE_TYPE (field)))
-          return 1;     
+          return 1;
        }
       {
        tree t = decl_for_component_ref (exprx);
@@ -2098,7 +2027,7 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
         tree fieldcontext = DECL_FIELD_CONTEXT (field);
         if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
                                                       TREE_TYPE (field)))
-          return 1;     
+          return 1;
        }
       {
        tree t = decl_for_component_ref (expry);
@@ -2189,8 +2118,8 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
 /* True dependence: X is read after store in MEM takes place.  */
 
 int
-true_dependence (rtx mem, enum machine_mode mem_mode, rtx x,
-                int (*varies) (rtx, int))
+true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x,
+                bool (*varies) (const_rtx, bool))
 {
   rtx x_addr, mem_addr;
   rtx base;
@@ -2199,11 +2128,14 @@ true_dependence (rtx mem, enum machine_mode mem_mode, rtx x,
     return 1;
 
   /* (mem:BLK (scratch)) is a special mechanism to conflict with everything.
-     This is used in epilogue deallocation functions.  */
+     This is used in epilogue deallocation functions, and in cselib.  */
   if (GET_MODE (x) == BLKmode && GET_CODE (XEXP (x, 0)) == SCRATCH)
     return 1;
   if (GET_MODE (mem) == BLKmode && GET_CODE (XEXP (mem, 0)) == SCRATCH)
     return 1;
+  if (MEM_ALIAS_SET (x) == ALIAS_SET_MEMORY_BARRIER
+      || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
+    return 1;
 
   if (DIFFERENT_ALIAS_SETS_P (x, mem))
     return 0;
@@ -2263,8 +2195,8 @@ true_dependence (rtx mem, enum machine_mode mem_mode, rtx x,
    this value prior to canonicalizing.  */
 
 int
-canon_true_dependence (rtx mem, enum machine_mode mem_mode, rtx mem_addr,
-                      rtx x, int (*varies) (rtx, int))
+canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
+                      const_rtx x, bool (*varies) (const_rtx, bool))
 {
   rtx x_addr;
 
@@ -2277,6 +2209,9 @@ canon_true_dependence (rtx mem, enum machine_mode mem_mode, rtx mem_addr,
     return 1;
   if (GET_MODE (mem) == BLKmode && GET_CODE (XEXP (mem, 0)) == SCRATCH)
     return 1;
+  if (MEM_ALIAS_SET (x) == ALIAS_SET_MEMORY_BARRIER
+      || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
+    return 1;
 
   if (DIFFERENT_ALIAS_SETS_P (x, mem))
     return 0;
@@ -2321,10 +2256,10 @@ canon_true_dependence (rtx mem, enum machine_mode mem_mode, rtx mem_addr,
    (or, if WRITEP is nonzero, a write to) MEM.  */
 
 static int
-write_dependence_p (rtx mem, rtx x, int writep)
+write_dependence_p (const_rtx mem, const_rtx x, int writep)
 {
   rtx x_addr, mem_addr;
-  rtx fixed_scalar;
+  const_rtx fixed_scalar;
   rtx base;
 
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
@@ -2336,6 +2271,9 @@ write_dependence_p (rtx mem, rtx x, int writep)
     return 1;
   if (GET_MODE (mem) == BLKmode && GET_CODE (XEXP (mem, 0)) == SCRATCH)
     return 1;
+  if (MEM_ALIAS_SET (x) == ALIAS_SET_MEMORY_BARRIER
+      || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
+    return 1;
 
   if (DIFFERENT_ALIAS_SETS_P (x, mem))
     return 0;
@@ -2381,7 +2319,7 @@ write_dependence_p (rtx mem, rtx x, int writep)
 /* Anti dependence: X is written after read in MEM takes place.  */
 
 int
-anti_dependence (rtx mem, rtx x)
+anti_dependence (const_rtx mem, const_rtx x)
 {
   return write_dependence_p (mem, x, /*writep=*/0);
 }
@@ -2389,17 +2327,19 @@ anti_dependence (rtx mem, rtx x)
 /* Output dependence: X is written after store in MEM takes place.  */
 
 int
-output_dependence (rtx mem, rtx x)
+output_dependence (const_rtx mem, const_rtx x)
 {
   return write_dependence_p (mem, x, /*writep=*/1);
 }
 \f
 
 void
-init_alias_once (void)
+init_alias_target (void)
 {
   int i;
 
+  memset (static_reg_base_value, 0, sizeof static_reg_base_value);
+
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     /* Check whether this register can hold an incoming pointer
        argument.  FUNCTION_ARG_REGNO_P tests outgoing register
@@ -2425,11 +2365,11 @@ init_alias_once (void)
    to be memory reference.  */
 static bool memory_modified;
 static void
-memory_modified_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
+memory_modified_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
 {
   if (MEM_P (x))
     {
-      if (anti_dependence (x, (rtx)data) || output_dependence (x, (rtx)data))
+      if (anti_dependence (x, (const_rtx)data) || output_dependence (x, (const_rtx)data))
        memory_modified = true;
     }
 }
@@ -2438,12 +2378,12 @@ memory_modified_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
 /* Return true when INSN possibly modify memory contents of MEM
    (i.e. address can be modified).  */
 bool
-memory_modified_in_insn_p (rtx mem, rtx insn)
+memory_modified_in_insn_p (const_rtx mem, const_rtx insn)
 {
   if (!INSN_P (insn))
     return false;
   memory_modified = false;
-  note_stores (PATTERN (insn), memory_modified_1, mem);
+  note_stores (PATTERN (insn), memory_modified_1, CONST_CAST_RTX(mem));
   return memory_modified;
 }
 
@@ -2465,27 +2405,17 @@ init_alias_analysis (void)
   reg_known_value = ggc_calloc (reg_known_value_size, sizeof (rtx));
   reg_known_equiv_p = xcalloc (reg_known_value_size, sizeof (bool));
 
-  /* Overallocate reg_base_value to allow some growth during loop
-     optimization.  Loop unrolling can create a large number of
-     registers.  */
+  /* If we have memory allocated from the previous run, use it.  */
   if (old_reg_base_value)
-    {
-      reg_base_value = old_reg_base_value;
-      /* If varray gets large zeroing cost may get important.  */
-      if (VARRAY_SIZE (reg_base_value) > 256
-          && VARRAY_SIZE (reg_base_value) > 4 * maxreg)
-       VARRAY_GROW (reg_base_value, maxreg);
-      VARRAY_CLEAR (reg_base_value);
-      if (VARRAY_SIZE (reg_base_value) < maxreg)
-       VARRAY_GROW (reg_base_value, maxreg);
-    }
-  else
-    {
-      VARRAY_RTX_INIT (reg_base_value, maxreg, "reg_base_value");
-    }
+    reg_base_value = old_reg_base_value;
+
+  if (reg_base_value)
+    VEC_truncate (rtx, reg_base_value, 0);
 
-  new_reg_base_value = xmalloc (maxreg * sizeof (rtx));
-  reg_seen = xmalloc (maxreg);
+  VEC_safe_grow_cleared (rtx, gc, reg_base_value, maxreg);
+
+  new_reg_base_value = XNEWVEC (rtx, maxreg);
+  reg_seen = XNEWVEC (char, maxreg);
 
   /* The basic idea is that each pass through this loop will use the
      "constant" information from the previous pass to propagate alias
@@ -2496,7 +2426,7 @@ init_alias_analysis (void)
      the optimization level or flag_expensive_optimizations.
 
      We could propagate more information in the first pass by making use
-     of REG_N_SETS to determine immediately that the alias information
+     of DF_REG_DEF_COUNT to determine immediately that the alias information
      for a pseudo is "constant".
 
      A program with an uninitialized variable can cause an infinite loop
@@ -2555,8 +2485,8 @@ init_alias_analysis (void)
 #endif
 
              /* If this insn has a noalias note, process it,  Otherwise,
-                scan for sets.  A simple set will have no side effects
-                which could change the base value of any other register.  */
+                scan for sets.  A simple set will have no side effects
+                which could change the base value of any other register.  */
 
              if (GET_CODE (PATTERN (insn)) == SET
                  && REG_NOTES (insn) != 0
@@ -2575,10 +2505,12 @@ init_alias_analysis (void)
                  rtx src = SET_SRC (set);
                  rtx t;
 
-                 if (REG_NOTES (insn) != 0
-                     && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
-                          && REG_N_SETS (regno) == 1)
-                         || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
+                 note = find_reg_equal_equiv_note (insn);
+                 if (note && REG_NOTE_KIND (note) == REG_EQUAL
+                     && DF_REG_DEF_COUNT (regno) != 1)
+                   note = NULL_RTX;
+
+                 if (note != NULL_RTX
                      && GET_CODE (XEXP (note, 0)) != EXPR_LIST
                      && ! rtx_varies_p (XEXP (note, 0), 1)
                      && ! reg_overlap_mentioned_p (SET_DEST (set),
@@ -2588,7 +2520,7 @@ init_alias_analysis (void)
                      set_reg_known_equiv_p (regno,
                        REG_NOTE_KIND (note) == REG_EQUIV);
                    }
-                 else if (REG_N_SETS (regno) == 1
+                 else if (DF_REG_DEF_COUNT (regno) == 1
                           && GET_CODE (src) == PLUS
                           && REG_P (XEXP (src, 0))
                           && (t = get_reg_known_value (REGNO (XEXP (src, 0))))
@@ -2598,7 +2530,7 @@ init_alias_analysis (void)
                      set_reg_known_value (regno, t);
                      set_reg_known_equiv_p (regno, 0);
                    }
-                 else if (REG_N_SETS (regno) == 1
+                 else if (DF_REG_DEF_COUNT (regno) == 1
                           && ! rtx_varies_p (src, 1))
                    {
                      set_reg_known_value (regno, src);
@@ -2607,21 +2539,21 @@ init_alias_analysis (void)
                }
            }
          else if (NOTE_P (insn)
-                  && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+                  && NOTE_KIND (insn) == NOTE_INSN_FUNCTION_BEG)
            copying_arguments = false;
        }
 
       /* Now propagate values from new_reg_base_value to reg_base_value.  */
-      gcc_assert (maxreg == (unsigned int) max_reg_num());
-      
+      gcc_assert (maxreg == (unsigned int) max_reg_num ());
+
       for (ui = 0; ui < maxreg; ui++)
        {
          if (new_reg_base_value[ui]
-             && new_reg_base_value[ui] != VARRAY_RTX (reg_base_value, ui)
+             && new_reg_base_value[ui] != VEC_index (rtx, reg_base_value, ui)
              && ! rtx_equal_p (new_reg_base_value[ui],
-                               VARRAY_RTX (reg_base_value, ui)))
+                               VEC_index (rtx, reg_base_value, ui)))
            {
-             VARRAY_RTX (reg_base_value, ui) = new_reg_base_value[ui];
+             VEC_replace (rtx, reg_base_value, ui, new_reg_base_value[ui]);
              changed = 1;
            }
        }
@@ -2633,38 +2565,6 @@ init_alias_analysis (void)
     if (reg_known_value[i] == 0)
       reg_known_value[i] = regno_reg_rtx[i + FIRST_PSEUDO_REGISTER];
 
-  /* Simplify the reg_base_value array so that no register refers to
-     another register, except to special registers indirectly through
-     ADDRESS expressions.
-
-     In theory this loop can take as long as O(registers^2), but unless
-     there are very long dependency chains it will run in close to linear
-     time.
-
-     This loop may not be needed any longer now that the main loop does
-     a better job at propagating alias information.  */
-  pass = 0;
-  do
-    {
-      changed = 0;
-      pass++;
-      for (ui = 0; ui < maxreg; ui++)
-       {
-         rtx base = VARRAY_RTX (reg_base_value, ui);
-         if (base && REG_P (base))
-           {
-             unsigned int base_regno = REGNO (base);
-             if (base_regno == ui)             /* register set from itself */
-               VARRAY_RTX (reg_base_value, ui) = 0;
-             else
-               VARRAY_RTX (reg_base_value, ui)
-                 = VARRAY_RTX (reg_base_value, base_regno);
-             changed = 1;
-           }
-       }
-    }
-  while (changed && pass < MAX_ALIAS_LOOP_PASSES);
-
   /* Clean up.  */
   free (new_reg_base_value);
   new_reg_base_value = 0;
@@ -2682,42 +2582,6 @@ end_alias_analysis (void)
   reg_known_value_size = 0;
   free (reg_known_equiv_p);
   reg_known_equiv_p = 0;
-  if (alias_invariant)
-    {
-      ggc_free (alias_invariant);
-      alias_invariant = 0;
-      alias_invariant_size = 0;
-    }
 }
-\f
-/* Do control and data flow analysis; write some of the results to the
-   dump file.  */
-static void
-rest_of_handle_cfg (void)
-{
-  if (dump_file)
-    dump_flow_info (dump_file);
-  if (optimize)
-    cleanup_cfg (CLEANUP_EXPENSIVE
-                 | (flag_thread_jumps ? CLEANUP_THREADING : 0));
-}
-
-struct tree_opt_pass pass_cfg =
-{
-  "cfg",                                /* name */
-  NULL,                                        /* gate */   
-  rest_of_handle_cfg,                   /* execute */       
-  NULL,                                 /* sub */
-  NULL,                                 /* next */
-  0,                                    /* static_pass_number */
-  TV_FLOW,                              /* tv_id */
-  0,                                    /* properties_required */
-  0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
-  0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
-  'f'                                   /* letter */
-};
-
 
 #include "gt-alias.h"