Index: tree-ssa-alias.c
===================================================================
--- tree-ssa-alias.c	(revision 272283)
+++ tree-ssa-alias.c	(working copy)
@@ -100,6 +100,8 @@ static struct {
   unsigned HOST_WIDE_INT call_may_clobber_ref_p_no_alias;
   unsigned HOST_WIDE_INT aliasing_component_refs_p_may_alias;
   unsigned HOST_WIDE_INT aliasing_component_refs_p_no_alias;
+  unsigned HOST_WIDE_INT nonoverlapping_component_refs_p_may_alias;
+  unsigned HOST_WIDE_INT nonoverlapping_component_refs_p_no_alias;
 } alias_stats;
 
 void
@@ -124,7 +126,13 @@ dump_alias_stats (FILE *s)
 	   alias_stats.call_may_clobber_ref_p_no_alias,
 	   alias_stats.call_may_clobber_ref_p_no_alias
 	   + alias_stats.call_may_clobber_ref_p_may_alias);
-  fprintf (s, "  aliasing_component_ref_p: "
+  fprintf (s, "  nonoverlapping_component_refs_p: "
+	   HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+	   HOST_WIDE_INT_PRINT_DEC" queries\n",
+	   alias_stats.nonoverlapping_component_refs_p_no_alias,
+	   alias_stats.nonoverlapping_component_refs_p_no_alias
+	   + alias_stats.nonoverlapping_component_refs_p_may_alias);
+  fprintf (s, "  aliasing_component_refs_p: "
 	   HOST_WIDE_INT_PRINT_DEC" disambiguations, "
 	   HOST_WIDE_INT_PRINT_DEC" queries\n",
 	   alias_stats.aliasing_component_refs_p_no_alias,
@@ -1029,106 +1037,6 @@ aliasing_component_refs_p (tree ref1,
   return false;
 }
 
-/* Return true if we can determine that component references REF1 and REF2,
-   that are within a common DECL, cannot overlap.  */
-
-static bool
-nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
-{
-  auto_vec<tree, 16> component_refs1;
-  auto_vec<tree, 16> component_refs2;
-
-  /* Create the stack of handled components for REF1.  */
-  while (handled_component_p (ref1))
-    {
-      component_refs1.safe_push (ref1);
-      ref1 = TREE_OPERAND (ref1, 0);
-    }
-  if (TREE_CODE (ref1) == MEM_REF)
-    {
-      if (!integer_zerop (TREE_OPERAND (ref1, 1)))
-	return false;
-      ref1 = TREE_OPERAND (TREE_OPERAND (ref1, 0), 0);
-    }
-
-  /* Create the stack of handled components for REF2.  */
-  while (handled_component_p (ref2))
-    {
-      component_refs2.safe_push (ref2);
-      ref2 = TREE_OPERAND (ref2, 0);
-    }
-  if (TREE_CODE (ref2) == MEM_REF)
-    {
-      if (!integer_zerop (TREE_OPERAND (ref2, 1)))
-	return false;
-      ref2 = TREE_OPERAND (TREE_OPERAND (ref2, 0), 0);
-    }
-
-  /* Bases must be either same or uncomparable.  */
-  gcc_checking_assert (ref1 == ref2
-		       || (DECL_P (ref1) && DECL_P (ref2)
-			   && compare_base_decls (ref1, ref2) != 0));
-
-  /* Pop the stacks in parallel and examine the COMPONENT_REFs of the same
-     rank.  This is sufficient because we start from the same DECL and you
-     cannot reference several fields at a time with COMPONENT_REFs (unlike
-     with ARRAY_RANGE_REFs for arrays) so you always need the same number
-     of them to access a sub-component, unless you're in a union, in which
-     case the return value will precisely be false.  */
-  while (true)
-    {
-      do
-	{
-	  if (component_refs1.is_empty ())
-	    return false;
-	  ref1 = component_refs1.pop ();
-	}
-      while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref1, 0))));
-
-      do
-	{
-	  if (component_refs2.is_empty ())
-	     return false;
-	  ref2 = component_refs2.pop ();
-	}
-      while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref2, 0))));
-
-      /* Beware of BIT_FIELD_REF.  */
-      if (TREE_CODE (ref1) != COMPONENT_REF
-	  || TREE_CODE (ref2) != COMPONENT_REF)
-	return false;
-
-      tree field1 = TREE_OPERAND (ref1, 1);
-      tree field2 = TREE_OPERAND (ref2, 1);
-
-      /* ??? We cannot simply use the type of operand #0 of the refs here
-	 as the Fortran compiler smuggles type punning into COMPONENT_REFs
-	 for common blocks instead of using unions like everyone else.  */
-      tree type1 = DECL_CONTEXT (field1);
-      tree type2 = DECL_CONTEXT (field2);
-
-      /* We cannot disambiguate fields in a union or qualified union.  */
-      if (type1 != type2 || TREE_CODE (type1) != RECORD_TYPE)
-	 return false;
-
-      if (field1 != field2)
-	{
-	  /* A field and its representative need to be considered the
-	     same.  */
-	  if (DECL_BIT_FIELD_REPRESENTATIVE (field1) == field2
-	      || DECL_BIT_FIELD_REPRESENTATIVE (field2) == field1)
-	    return false;
-	  /* Different fields of the same record type cannot overlap.
-	     ??? Bitfields can overlap at RTL level so punt on them.  */
-	  if (DECL_BIT_FIELD (field1) && DECL_BIT_FIELD (field2))
-	    return false;
-	  return true;
-	}
-    }
-
-  return false;
-}
-
 /* qsort compare function to sort FIELD_DECLs after their
    DECL_FIELD_CONTEXT TYPE_UID.  */
 
@@ -1154,40 +1062,66 @@ nonoverlapping_component_refs_p (const_t
 {
   if (!flag_strict_aliasing
       || !x || !y
-      || TREE_CODE (x) != COMPONENT_REF
-      || TREE_CODE (y) != COMPONENT_REF)
-    return false;
+      || !handled_component_p (x)
+      || !handled_component_p (y))
+    {
+      ++alias_stats.nonoverlapping_component_refs_p_may_alias;
+      return false;
+    }
 
   auto_vec<const_tree, 16> fieldsx;
-  while (TREE_CODE (x) == COMPONENT_REF)
+  while (handled_component_p (x))
     {
-      tree field = TREE_OPERAND (x, 1);
-      tree type = DECL_FIELD_CONTEXT (field);
-      if (TREE_CODE (type) == RECORD_TYPE)
-	fieldsx.safe_push (field);
+      if (TREE_CODE (x) == COMPONENT_REF)
+	{
+	  tree field = TREE_OPERAND (x, 1);
+	  tree type = DECL_FIELD_CONTEXT (field);
+	  if (TREE_CODE (type) == RECORD_TYPE)
+	    fieldsx.safe_push (field);
+	}
       x = TREE_OPERAND (x, 0);
     }
   if (fieldsx.length () == 0)
-    return false;
+    {
+      ++alias_stats.nonoverlapping_component_refs_p_may_alias;
+      return false;
+    }
   auto_vec<const_tree, 16> fieldsy;
-  while (TREE_CODE (y) == COMPONENT_REF)
+  while (handled_component_p (y))
     {
-      tree field = TREE_OPERAND (y, 1);
-      tree type = DECL_FIELD_CONTEXT (field);
-      if (TREE_CODE (type) == RECORD_TYPE)
-	fieldsy.safe_push (TREE_OPERAND (y, 1));
+      if (TREE_CODE (y) == COMPONENT_REF)
+	{
+	  tree field = TREE_OPERAND (y, 1);
+	  tree type = DECL_FIELD_CONTEXT (field);
+	  if (TREE_CODE (type) == RECORD_TYPE)
+	    fieldsy.safe_push (TREE_OPERAND (y, 1));
+	}
       y = TREE_OPERAND (y, 0);
     }
   if (fieldsy.length () == 0)
-    return false;
+    {
+      ++alias_stats.nonoverlapping_component_refs_p_may_alias;
+      return false;
+    }
 
   /* Most common case first.  */
   if (fieldsx.length () == 1
       && fieldsy.length () == 1)
-    return ((DECL_FIELD_CONTEXT (fieldsx[0])
-	     == DECL_FIELD_CONTEXT (fieldsy[0]))
-	    && fieldsx[0] != fieldsy[0]
-	    && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0])));
+    {
+      if ((DECL_FIELD_CONTEXT (fieldsx[0])
+	   == DECL_FIELD_CONTEXT (fieldsy[0]))
+	  && fieldsx[0] != fieldsy[0]
+	  && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0])))
+	{
+	   ++alias_stats.nonoverlapping_component_refs_p_no_alias;
+	   return true;
+	}
+      else
+	{
+	   ++alias_stats.nonoverlapping_component_refs_p_may_alias;
+	   return false;
+	}
+    }
 
   if (fieldsx.length () == 2)
     {
@@ -1215,19 +1149,26 @@ nonoverlapping_component_refs_p (const_t
       if (typex == typey)
 	{
 	  /* We're left with accessing different fields of a structure,
-	     no possible overlap.  */
+	     no possible overlap.
+	     If we can not disambiguate, do not give up and try to continue:
+	     it is possible that there are multiple matching types on the
+	     access patch and each of them may result in disambiguation.  */
 	  if (fieldx != fieldy)
 	    {
 	      /* A field and its representative need to be considered the
 		 same.  */
 	      if (DECL_BIT_FIELD_REPRESENTATIVE (fieldx) == fieldy
 		  || DECL_BIT_FIELD_REPRESENTATIVE (fieldy) == fieldx)
-		return false;
+		;
 	      /* Different fields of the same record type cannot overlap.
 		 ??? Bitfields can overlap at RTL level so punt on them.  */
-	      if (DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy))
-		return false;
-	      return true;
+	      else if (DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy))
+		;
+	      else
+		{
+		  ++alias_stats.nonoverlapping_component_refs_p_no_alias;
+		  return true;
+		}
 	    }
 	}
       if (TYPE_UID (typex) < TYPE_UID (typey))
@@ -1245,10 +1186,11 @@ nonoverlapping_component_refs_p (const_t
     }
   while (1);
 
+  ++alias_stats.nonoverlapping_component_refs_p_may_alias;
   return false;
 }
 
 
 /* Return true if two memory references based on the variables BASE1
    and BASE2 constrained to [OFFSET1, OFFSET1 + MAX_SIZE1) and
    [OFFSET2, OFFSET2 + MAX_SIZE2) may alias.  REF1 and REF2
@@ -1271,11 +1212,41 @@ decl_refs_may_alias_p (tree ref1, tree b
   if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2))
     return false;
 
+  /* Access path oracle below needs to know both references.  */
+  if (!ref1 || !ref2)
+    return true;
+
+  /* If the decl is accessed via a MEM_REF, reconstruct the base
+     we can use for TBAA.  */
+  tree dbase1 = ref1;
+
+  while (handled_component_p (dbase1))
+    dbase1 = TREE_OPERAND (dbase1, 0);
+  if (TREE_CODE (dbase1) == MEM_REF
+      || TREE_CODE (dbase1) == TARGET_MEM_REF)
+    {
+      tree ptrtype1 = TREE_TYPE (TREE_OPERAND (dbase1, 1));
+      /* If first reference is view-converted, give up now.  */
+      if (same_type_for_tbaa (TREE_TYPE (dbase1), TREE_TYPE (ptrtype1)) != 1)
+	return true;
+    }
+
+  tree dbase2 = ref2;
+
+  while (handled_component_p (dbase2))
+    dbase2 = TREE_OPERAND (dbase2, 0);
+  if (TREE_CODE (dbase2) == MEM_REF
+      || TREE_CODE (dbase2) == TARGET_MEM_REF)
+    {
+      tree ptrtype2 = TREE_TYPE (TREE_OPERAND (dbase2, 1));
+      /* If second reference is view-converted, give up now.  */
+      if (same_type_for_tbaa (TREE_TYPE (dbase2), TREE_TYPE (ptrtype2)) != 1)
+	return true;
+    }
+
   /* For components with variable position, the above test isn't sufficient,
      so we disambiguate component references manually.  */
-  if (ref1 && ref2
-      && handled_component_p (ref1) && handled_component_p (ref2)
-      && nonoverlapping_component_refs_of_decl_p (ref1, ref2))
+  if (nonoverlapping_component_refs_p (ref1, ref2))
     return false;
 
   return true;     
