Introduce LABEL_REF_LABEL
[platform/upstream/gcc.git] / gcc / alias.c
index c9870ec..a098cb7 100644 (file)
@@ -1,5 +1,5 @@
 /* Alias analysis for GNU C
-   Copyright (C) 1997-2013 Free Software Foundation, Inc.
+   Copyright (C) 1997-2014 Free Software Foundation, Inc.
    Contributed by John Carr (jfc@mit.edu).
 
 This file is part of GCC.
@@ -24,27 +24,30 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "varasm.h"
+#include "expr.h"
 #include "tm_p.h"
 #include "function.h"
 #include "alias.h"
 #include "emit-rtl.h"
 #include "regs.h"
 #include "hard-reg-set.h"
-#include "basic-block.h"
 #include "flags.h"
 #include "diagnostic-core.h"
 #include "cselib.h"
 #include "splay-tree.h"
-#include "ggc.h"
 #include "langhooks.h"
 #include "timevar.h"
 #include "dumpfile.h"
 #include "target.h"
-#include "cgraph.h"
 #include "df.h"
 #include "tree-ssa-alias.h"
-#include "pointer-set.h"
-#include "tree-flow.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "rtl-iter.h"
 
 /* The aliasing API provided here solves related but different problems:
 
@@ -154,9 +157,10 @@ static rtx find_base_value (rtx);
 static int mems_in_disjoint_alias_sets_p (const_rtx, const_rtx);
 static int insert_subset_children (splay_tree_node, void*);
 static alias_set_entry get_alias_set_entry (alias_set_type);
-static bool nonoverlapping_component_refs_p (const_rtx, const_rtx);
 static tree decl_for_component_ref (tree);
-static int write_dependence_p (const_rtx, const_rtx, int);
+static int write_dependence_p (const_rtx,
+                              const_rtx, enum machine_mode, rtx,
+                              bool, bool, bool);
 
 static void memory_modified_1 (rtx, const_rtx, void *);
 
@@ -298,10 +302,9 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
       && ! is_global_var (base)
       && cfun->gimple_df->decls_to_pointers != NULL)
     {
-      void *namep;
-      namep = pointer_map_contains (cfun->gimple_df->decls_to_pointers, base);
+      tree *namep = cfun->gimple_df->decls_to_pointers->get (base);
       if (namep)
-       ref->base = build_simple_mem_ref (*(tree *)namep);
+       ref->base = build_simple_mem_ref (*namep);
     }
 
   ref->ref_alias_set = MEM_ALIAS_SET (mem);
@@ -336,9 +339,10 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
   if (MEM_EXPR (mem) != get_spill_slot_decl (false)
       && (ref->offset < 0
          || (DECL_P (ref->base)
-             && (!host_integerp (DECL_SIZE (ref->base), 1)
-                 || (TREE_INT_CST_LOW (DECL_SIZE ((ref->base)))
-                     < (unsigned HOST_WIDE_INT)(ref->offset + ref->size))))))
+             && (DECL_SIZE (ref->base) == NULL_TREE
+                 || TREE_CODE (DECL_SIZE (ref->base)) != INTEGER_CST
+                 || wi::ltu_p (wi::to_offset (DECL_SIZE (ref->base)),
+                               ref->offset + ref->size)))))
     return false;
 
   return true;
@@ -498,51 +502,70 @@ objects_must_conflict_p (tree t1, tree t2)
   return alias_sets_must_conflict_p (set1, set2);
 }
 \f
-/* Return true if all nested component references handled by
-   get_inner_reference in T are such that we should use the alias set
-   provided by the object at the heart of T.
-
-   This is true for non-addressable components (which don't have their
-   own alias set), as well as components of objects in alias set zero.
-   This later point is a special case wherein we wish to override the
-   alias set used by the component, but we don't have per-FIELD_DECL
-   assignable alias sets.  */
-
-bool
-component_uses_parent_alias_set (const_tree t)
+/* Return the outermost parent of component present in the chain of
+   component references handled by get_inner_reference in T with the
+   following property:
+     - the component is non-addressable, or
+     - the parent has alias set zero,
+   or NULL_TREE if no such parent exists.  In the former cases, the alias
+   set of this parent is the alias set that must be used for T itself.  */
+
+tree
+component_uses_parent_alias_set_from (const_tree t)
 {
-  while (1)
-    {
-      /* If we're at the end, it vacuously uses its own alias set.  */
-      if (!handled_component_p (t))
-       return false;
+  const_tree found = NULL_TREE;
 
+  while (handled_component_p (t))
+    {
       switch (TREE_CODE (t))
        {
        case COMPONENT_REF:
          if (DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1)))
-           return true;
+           found = t;
          break;
 
        case ARRAY_REF:
        case ARRAY_RANGE_REF:
          if (TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0))))
-           return true;
+           found = t;
          break;
 
        case REALPART_EXPR:
        case IMAGPART_EXPR:
          break;
 
-       default:
+       case BIT_FIELD_REF:
+       case VIEW_CONVERT_EXPR:
          /* Bitfields and casts are never addressable.  */
-         return true;
+         found = t;
+         break;
+
+       default:
+         gcc_unreachable ();
        }
 
+      if (get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) == 0)
+       found = t;
+
       t = TREE_OPERAND (t, 0);
-      if (get_alias_set (TREE_TYPE (t)) == 0)
-       return true;
     }
+  if (found)
+    return TREE_OPERAND (found, 0);
+
+  return NULL_TREE;
+}
+
+
+/* Return whether the pointer-type T effective for aliasing may
+   access everything and thus the reference has to be assigned
+   alias-set zero.  */
+
+static bool
+ref_all_alias_ptr_type_p (const_tree t)
+{
+  return (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE
+         || TYPE_REF_CAN_ALIAS_ALL (t));
 }
 
 /* Return the alias set for the memory pointed to by T, which may be
@@ -552,11 +575,6 @@ component_uses_parent_alias_set (const_tree t)
 static alias_set_type
 get_deref_alias_set_1 (tree t)
 {
-  /* If we're not doing any alias analysis, just assume everything
-     aliases everything else.  */
-  if (!flag_strict_aliasing)
-    return 0;
-
   /* All we care about is the type.  */
   if (! TYPE_P (t))
     t = TREE_TYPE (t);
@@ -564,8 +582,7 @@ get_deref_alias_set_1 (tree t)
   /* If we have an INDIRECT_REF via a void pointer, we don't
      know anything about what that might alias.  Likewise if the
      pointer is marked that way.  */
-  if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE
-      || TYPE_REF_CAN_ALIAS_ALL (t))
+  if (ref_all_alias_ptr_type_p (t))
     return 0;
 
   return -1;
@@ -577,6 +594,11 @@ get_deref_alias_set_1 (tree t)
 alias_set_type
 get_deref_alias_set (tree t)
 {
+  /* If we're not doing any alias analysis, just assume everything
+     aliases everything else.  */
+  if (!flag_strict_aliasing)
+    return 0;
+
   alias_set_type set = get_deref_alias_set_1 (t);
 
   /* Fall back to the alias-set of the pointed-to type.  */
@@ -590,6 +612,98 @@ get_deref_alias_set (tree t)
   return set;
 }
 
+/* Return the pointer-type relevant for TBAA purposes from the
+   memory reference tree *T or NULL_TREE in which case *T is
+   adjusted to point to the outermost component reference that
+   can be used for assigning an alias set.  */
+static tree
+reference_alias_ptr_type_1 (tree *t)
+{
+  tree inner;
+
+  /* Get the base object of the reference.  */
+  inner = *t;
+  while (handled_component_p (inner))
+    {
+      /* If there is a VIEW_CONVERT_EXPR in the chain we cannot use
+        the type of any component references that wrap it to
+        determine the alias-set.  */
+      if (TREE_CODE (inner) == VIEW_CONVERT_EXPR)
+       *t = TREE_OPERAND (inner, 0);
+      inner = TREE_OPERAND (inner, 0);
+    }
+
+  /* Handle pointer dereferences here, they can override the
+     alias-set.  */
+  if (INDIRECT_REF_P (inner)
+      && ref_all_alias_ptr_type_p (TREE_TYPE (TREE_OPERAND (inner, 0))))
+    return TREE_TYPE (TREE_OPERAND (inner, 0));
+  else if (TREE_CODE (inner) == TARGET_MEM_REF)
+    return TREE_TYPE (TMR_OFFSET (inner));
+  else if (TREE_CODE (inner) == MEM_REF
+          && ref_all_alias_ptr_type_p (TREE_TYPE (TREE_OPERAND (inner, 1))))
+    return TREE_TYPE (TREE_OPERAND (inner, 1));
+
+  /* If the innermost reference is a MEM_REF that has a
+     conversion embedded treat it like a VIEW_CONVERT_EXPR above,
+     using the memory access type for determining the alias-set.  */
+  if (TREE_CODE (inner) == MEM_REF
+      && (TYPE_MAIN_VARIANT (TREE_TYPE (inner))
+         != TYPE_MAIN_VARIANT
+              (TREE_TYPE (TREE_TYPE (TREE_OPERAND (inner, 1))))))
+    return TREE_TYPE (TREE_OPERAND (inner, 1));
+
+  /* Otherwise, pick up the outermost object that we could have
+     a pointer to.  */
+  tree tem = component_uses_parent_alias_set_from (*t);
+  if (tem)
+    *t = tem;
+
+  return NULL_TREE;
+}
+
+/* Return the pointer-type relevant for TBAA purposes from the
+   gimple memory reference tree T.  This is the type to be used for
+   the offset operand of MEM_REF or TARGET_MEM_REF replacements of T
+   and guarantees that get_alias_set will return the same alias
+   set for T and the replacement.  */
+
+tree
+reference_alias_ptr_type (tree t)
+{
+  tree ptype = reference_alias_ptr_type_1 (&t);
+  /* If there is a given pointer type for aliasing purposes, return it.  */
+  if (ptype != NULL_TREE)
+    return ptype;
+
+  /* Otherwise build one from the outermost component reference we
+     may use.  */
+  if (TREE_CODE (t) == MEM_REF
+      || TREE_CODE (t) == TARGET_MEM_REF)
+    return TREE_TYPE (TREE_OPERAND (t, 1));
+  else
+    return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (t)));
+}
+
+/* Return whether the pointer-types T1 and T2 used to determine
+   two alias sets of two references will yield the same answer
+   from get_deref_alias_set.  */
+
+bool
+alias_ptr_types_compatible_p (tree t1, tree t2)
+{
+  if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+    return true;
+
+  if (ref_all_alias_ptr_type_p (t1)
+      || ref_all_alias_ptr_type_p (t2))
+    return false;
+
+  return (TYPE_MAIN_VARIANT (TREE_TYPE (t1))
+         == TYPE_MAIN_VARIANT (TREE_TYPE (t2)));
+}
+
 /* Return the alias set for T, which may be either a type or an
    expression.  Call language-specific routine for help, if needed.  */
 
@@ -613,8 +727,6 @@ get_alias_set (tree t)
      aren't types.  */
   if (! TYPE_P (t))
     {
-      tree inner;
-
       /* Give the language a chance to do something with this tree
         before we look at it.  */
       STRIP_NOPS (t);
@@ -622,51 +734,11 @@ get_alias_set (tree t)
       if (set != -1)
        return set;
 
-      /* Get the base object of the reference.  */
-      inner = t;
-      while (handled_component_p (inner))
-       {
-         /* If there is a VIEW_CONVERT_EXPR in the chain we cannot use
-            the type of any component references that wrap it to
-            determine the alias-set.  */
-         if (TREE_CODE (inner) == VIEW_CONVERT_EXPR)
-           t = TREE_OPERAND (inner, 0);
-         inner = TREE_OPERAND (inner, 0);
-       }
-
-      /* Handle pointer dereferences here, they can override the
-        alias-set.  */
-      if (INDIRECT_REF_P (inner))
-       {
-         set = get_deref_alias_set_1 (TREE_OPERAND (inner, 0));
-         if (set != -1)
-           return set;
-       }
-      else if (TREE_CODE (inner) == TARGET_MEM_REF)
-       return get_deref_alias_set (TMR_OFFSET (inner));
-      else if (TREE_CODE (inner) == MEM_REF)
-       {
-         set = get_deref_alias_set_1 (TREE_OPERAND (inner, 1));
-         if (set != -1)
-           return set;
-       }
-
-      /* If the innermost reference is a MEM_REF that has a
-        conversion embedded treat it like a VIEW_CONVERT_EXPR above,
-        using the memory access type for determining the alias-set.  */
-     if (TREE_CODE (inner) == MEM_REF
-        && TYPE_MAIN_VARIANT (TREE_TYPE (inner))
-           != TYPE_MAIN_VARIANT
-              (TREE_TYPE (TREE_TYPE (TREE_OPERAND (inner, 1)))))
-       return get_deref_alias_set (TREE_OPERAND (inner, 1));
-
-      /* Otherwise, pick up the outermost object that we could have a pointer
-        to, processing conversions as above.  */
-      while (component_uses_parent_alias_set (t))
-       {
-         t = TREE_OPERAND (t, 0);
-         STRIP_NOPS (t);
-       }
+      /* Get the alias pointer-type to use or the outermost object
+         that we could have a pointer to.  */
+      tree ptype = reference_alias_ptr_type_1 (&t);
+      if (ptype != NULL)
+       return get_deref_alias_set (ptype);
 
       /* If we've already determined the alias set for a decl, just return
         it.  This is necessary for C++ anonymous unions, whose component
@@ -871,7 +943,7 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
     {
       /* Create an entry for the SUPERSET, so that we have a place to
         attach the SUBSET.  */
-      superset_entry = ggc_alloc_cleared_alias_set_entry_d ();
+      superset_entry = ggc_cleared_alloc<alias_set_entry_d> ();
       superset_entry->alias_set = superset;
       superset_entry->children
        = splay_tree_new_ggc (splay_tree_compare_ints,
@@ -922,17 +994,6 @@ record_component_aliases (tree type)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      /* Recursively record aliases for the base classes, if there are any.  */
-      if (TYPE_BINFO (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 = DECL_CHAIN (field))
        if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field))
          record_alias_subset (superset, get_alias_set (TREE_TYPE (field)));
@@ -1460,7 +1521,7 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y)
       return REGNO (x) == REGNO (y);
 
     case LABEL_REF:
-      return XEXP (x, 0) == XEXP (y, 0);
+      return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
 
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
@@ -1471,9 +1532,7 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y)
 
     case VALUE:
     CASE_CONST_UNIQUE:
-      /* 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.  */
+      /* Pointer equality guarantees equality for these nodes.  */
       return 0;
 
     default:
@@ -1687,16 +1746,16 @@ find_base_term (rtx x)
           term is from a pointer or is a named object or a special address
           (like an argument or stack reference), then use it for the
           base term.  */
-       tmp1 = find_base_term (tmp1);
-       if (tmp1 != NULL_RTX
+       rtx base = find_base_term (tmp1);
+       if (base != NULL_RTX
            && ((REG_P (tmp1) && REG_POINTER (tmp1))
-                || known_base_value_p (tmp1)))
-         return tmp1;
-       tmp2 = find_base_term (tmp2);
-       if (tmp2 != NULL_RTX
+                || known_base_value_p (base)))
+         return base;
+       base = find_base_term (tmp2);
+       if (base != NULL_RTX
            && ((REG_P (tmp2) && REG_POINTER (tmp2))
-                || known_base_value_p (tmp2)))
-         return tmp2;
+                || known_base_value_p (base)))
+         return base;
 
        /* We could not determine which of the two operands was the
           base register and which was the index.  So we can determine
@@ -1793,27 +1852,18 @@ base_alias_check (rtx x, rtx x_base, rtx y, rtx y_base,
   return 1;
 }
 
-/* Callback for for_each_rtx, that returns 1 upon encountering a VALUE
-   whose UID is greater than the int uid that D points to.  */
-
-static int
-refs_newer_value_cb (rtx *x, void *d)
-{
-  if (GET_CODE (*x) == VALUE && CSELIB_VAL_PTR (*x)->uid > *(int *)d)
-    return 1;
-
-  return 0;
-}
-
 /* Return TRUE if EXPR refers to a VALUE whose uid is greater than
    that of V.  */
 
 static bool
-refs_newer_value_p (rtx expr, rtx v)
+refs_newer_value_p (const_rtx expr, rtx v)
 {
   int minuid = CSELIB_VAL_PTR (v)->uid;
-
-  return for_each_rtx (&expr, refs_newer_value_cb, &minuid);
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, expr, NONCONST)
+    if (GET_CODE (*iter) == VALUE && CSELIB_VAL_PTR (*iter)->uid > minuid)
+      return true;
+  return false;
 }
 
 /* Convert the address X into something we can use.  This is done by returning
@@ -1893,7 +1943,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_mode (offset, GET_MODE (addr)));
   else
     addr = XEXP (addr, 0);
   addr = canon_rtx (addr);
@@ -2186,68 +2236,6 @@ read_dependence (const_rtx mem, const_rtx x)
   return false;
 }
 
-/* Return true if we can determine that the fields referenced cannot
-   overlap for any pair of objects.  */
-
-static bool
-nonoverlapping_component_refs_p (const_rtx rtlx, const_rtx rtly)
-{
-  const_tree x = MEM_EXPR (rtlx), y = MEM_EXPR (rtly);
-  const_tree fieldx, fieldy, typex, typey, orig_y;
-
-  if (!flag_strict_aliasing
-      || !x || !y
-      || TREE_CODE (x) != COMPONENT_REF
-      || TREE_CODE (y) != COMPONENT_REF)
-    return false;
-
-  do
-    {
-      /* The comparison has to be done at a common type, since we don't
-        know how the inheritance hierarchy works.  */
-      orig_y = y;
-      do
-       {
-         fieldx = TREE_OPERAND (x, 1);
-         typex = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldx));
-
-         y = orig_y;
-         do
-           {
-             fieldy = TREE_OPERAND (y, 1);
-             typey = TYPE_MAIN_VARIANT (DECL_FIELD_CONTEXT (fieldy));
-
-             if (typex == typey)
-               goto found;
-
-             y = TREE_OPERAND (y, 0);
-           }
-         while (y && TREE_CODE (y) == COMPONENT_REF);
-
-         x = TREE_OPERAND (x, 0);
-       }
-      while (x && TREE_CODE (x) == COMPONENT_REF);
-      /* Never found a common type.  */
-      return false;
-
-    found:
-      /* If we're left with accessing different fields of a structure, then no
-        possible overlap, unless they are both bitfields.  */
-      if (TREE_CODE (typex) == RECORD_TYPE && fieldx != fieldy)
-       return !(DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy));
-
-      /* The comparison on the current field failed.  If we're accessing
-        a very nested structure, look at the next outer level.  */
-      x = TREE_OPERAND (x, 0);
-      y = TREE_OPERAND (y, 0);
-    }
-  while (x && y
-        && TREE_CODE (x) == COMPONENT_REF
-        && TREE_CODE (y) == COMPONENT_REF);
-
-  return false;
-}
-
 /* Look at the bottom of the COMPONENT_REF list for a DECL, and return it.  */
 
 static tree
@@ -2276,15 +2264,22 @@ adjust_offset_for_component_ref (tree x, bool *known_p,
     {
       tree xoffset = component_ref_field_offset (x);
       tree field = TREE_OPERAND (x, 1);
+      if (TREE_CODE (xoffset) != INTEGER_CST)
+       {
+         *known_p = false;
+         return;
+       }
 
-      if (! host_integerp (xoffset, 1))
+      offset_int woffset
+       = (wi::to_offset (xoffset)
+          + wi::lrshift (wi::to_offset (DECL_FIELD_BIT_OFFSET (field)),
+                         LOG2_BITS_PER_UNIT));
+      if (!wi::fits_uhwi_p (woffset))
        {
          *known_p = false;
          return;
        }
-      *offset += (tree_low_cst (xoffset, 1)
-                 + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
-                    / BITS_PER_UNIT));
+      *offset += woffset.to_uhwi ();
 
       x = TREE_OPERAND (x, 0);
     }
@@ -2523,9 +2518,6 @@ true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
   if (nonoverlapping_memrefs_p (mem, x, false))
     return 0;
 
-  if (nonoverlapping_component_refs_p (mem, x))
-    return 0;
-
   return rtx_refs_may_alias_p (x, mem, true);
 }
 
@@ -2553,15 +2545,24 @@ canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
 }
 
 /* Returns nonzero if a write to X might alias a previous read from
-   (or, if WRITEP is nonzero, a write to) MEM.  */
+   (or, if WRITEP is true, a write to) MEM.
+   If X_CANONCALIZED is true, then X_ADDR is the canonicalized address of X,
+   and X_MODE the mode for that access.
+   If MEM_CANONICALIZED is true, MEM is canonicalized.  */
 
 static int
-write_dependence_p (const_rtx mem, const_rtx x, int writep)
+write_dependence_p (const_rtx mem,
+                   const_rtx x, enum machine_mode x_mode, rtx x_addr,
+                   bool mem_canonicalized, bool x_canonicalized, bool writep)
 {
-  rtx x_addr, mem_addr;
+  rtx mem_addr;
   rtx base;
   int ret;
 
+  gcc_checking_assert (x_canonicalized
+                      ? (x_addr != NULL_RTX && x_mode != VOIDmode)
+                      : (x_addr == NULL_RTX && x_mode == VOIDmode));
+
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
     return 1;
 
@@ -2585,17 +2586,21 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
   if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x))
     return 1;
 
-  x_addr = XEXP (x, 0);
   mem_addr = XEXP (mem, 0);
-  if (!((GET_CODE (x_addr) == VALUE
-        && GET_CODE (mem_addr) != VALUE
-        && reg_mentioned_p (x_addr, mem_addr))
-       || (GET_CODE (x_addr) != VALUE
-           && GET_CODE (mem_addr) == VALUE
-           && reg_mentioned_p (mem_addr, x_addr))))
+  if (!x_addr)
     {
-      x_addr = get_addr (x_addr);
-      mem_addr = get_addr (mem_addr);
+      x_addr = XEXP (x, 0);
+      if (!((GET_CODE (x_addr) == VALUE
+            && GET_CODE (mem_addr) != VALUE
+            && reg_mentioned_p (x_addr, mem_addr))
+           || (GET_CODE (x_addr) != VALUE
+               && GET_CODE (mem_addr) == VALUE
+               && reg_mentioned_p (mem_addr, x_addr))))
+       {
+         x_addr = get_addr (x_addr);
+         if (!mem_canonicalized)
+           mem_addr = get_addr (mem_addr);
+       }
     }
 
   base = find_base_term (mem_addr);
@@ -2611,11 +2616,16 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
                          GET_MODE (mem)))
     return 0;
 
-  x_addr = canon_rtx (x_addr);
-  mem_addr = canon_rtx (mem_addr);
+  if (!x_canonicalized)
+    {
+      x_addr = canon_rtx (x_addr);
+      x_mode = GET_MODE (x);
+    }
+  if (!mem_canonicalized)
+    mem_addr = canon_rtx (mem_addr);
 
   if ((ret = memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
-                                SIZE_FOR_MODE (x), x_addr, 0)) != -1)
+                                GET_MODE_SIZE (x_mode), x_addr, 0)) != -1)
     return ret;
 
   if (nonoverlapping_memrefs_p (x, mem, false))
@@ -2629,7 +2639,23 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
 int
 anti_dependence (const_rtx mem, const_rtx x)
 {
-  return write_dependence_p (mem, x, /*writep=*/0);
+  return write_dependence_p (mem, x, VOIDmode, NULL_RTX,
+                            /*mem_canonicalized=*/false,
+                            /*x_canonicalized*/false, /*writep=*/false);
+}
+
+/* Likewise, but we already have a canonicalized MEM, and X_ADDR for X.
+   Also, consider X in X_MODE (which might be from an enclosing
+   STRICT_LOW_PART / ZERO_EXTRACT).
+   If MEM_CANONICALIZED is true, MEM is canonicalized.  */
+
+int
+canon_anti_dependence (const_rtx mem, bool mem_canonicalized,
+                      const_rtx x, enum machine_mode x_mode, rtx x_addr)
+{
+  return write_dependence_p (mem, x, x_mode, x_addr,
+                            mem_canonicalized, /*x_canonicalized=*/true,
+                            /*writep=*/false);
 }
 
 /* Output dependence: X is written after store in MEM takes place.  */
@@ -2637,7 +2663,9 @@ anti_dependence (const_rtx mem, const_rtx x)
 int
 output_dependence (const_rtx mem, const_rtx x)
 {
-  return write_dependence_p (mem, x, /*writep=*/1);
+  return write_dependence_p (mem, x, VOIDmode, NULL_RTX,
+                            /*mem_canonicalized=*/false,
+                            /*x_canonicalized*/false, /*writep=*/true);
 }
 \f
 
@@ -2802,7 +2830,8 @@ init_alias_analysis (void)
   int changed, pass;
   int i;
   unsigned int ui;
-  rtx insn, val;
+  rtx_insn *insn;
+  rtx val;
   int rpo_cnt;
   int *rpo;
 
@@ -2846,7 +2875,7 @@ init_alias_analysis (void)
      The state of the arrays for the set chain in question does not matter
      since the program has undefined behavior.  */
 
-  rpo = XNEWVEC (int, n_basic_blocks);
+  rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
   rpo_cnt = pre_and_rev_post_order_compute (NULL, rpo, false);
 
   pass = 0;
@@ -2869,21 +2898,18 @@ init_alias_analysis (void)
       /* Wipe the reg_seen array clean.  */
       bitmap_clear (reg_seen);
 
-      /* Mark all hard registers which may contain an address.
-        The stack, frame and argument pointers may contain an address.
-        An argument register which can hold a Pmode value may contain
-        an address even if it is not in BASE_REGS.
-
-        The address expression is VOIDmode for an argument and
-        Pmode for other registers.  */
-
-      memcpy (new_reg_base_value, static_reg_base_value,
-             FIRST_PSEUDO_REGISTER * sizeof (rtx));
+      /* Initialize the alias information for this pass.  */
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (static_reg_base_value[i])
+         {
+           new_reg_base_value[i] = static_reg_base_value[i];
+           bitmap_set_bit (reg_seen, i);
+         }
 
       /* Walk the insns adding values to the new_reg_base_value array.  */
       for (i = 0; i < rpo_cnt; i++)
        {
-         basic_block bb = BASIC_BLOCK (rpo[i]);
+         basic_block bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);
          FOR_BB_INSNS (bb, insn)
            {
              if (NONDEBUG_INSN_P (insn))