On Wed, 26 Feb 2020, Jan Hubicka wrote:

> Hi,
> This patch solves problem caused by the disagreement between FRE and access
> path orracle.
> 
> FRE is checking stores for equivalence based on their address, value and
> base+ref alias sets.  Because ref alias set is not always the alias set of
> innermost type, but it may be one of refs in the access path (as decided by
> component_uses_parent_alias_set_from) it means that we can not really rely on
> the remaining part of access path to be meaningful in any way except for
> offset+size computation.
> 
> The patch makes alias (which is used by FRE to validate transform) and
> tree-ssa-alias to share same logic for ending the access path relevant for
> TBAA. tree-ssa-alias previously ended access paths on VIEW_CONVERT_EXPR and
> BIT_FIELD_REF so it is not hard to wire in common predicate.  However it led 
> to
> additional issues (I tried to read the code quite carefully for possible extra
> fun, so I hope I found it all):
> 
>   1) alias_component_refs_walk compares base and reference sizes to see
>      if one access path may continue by another.  This check can be confused
>      by an union containing structure with zero sized array.  In this case we
>      no longer see the refernece to zero sized array and think that ref size
>      is 0.
> 
>      In an access path there can be at most one (valid) trailing/zero sized
>      array access, so the sizes in the access path are decreasing with the
>      this exception. This is already handled by the logic, however the access
>      is not expected to happen past the end of TBAA segment.  I suppose this
>      was kind of latent problem before because one can think of access path
>      doing traling array past VIEW_CONVERT_EXPR, but since in C code we don't
>      VCE and in non-C we don't do trailing arrays, we did not hit the problem.
> 
>      I fixed this by tracking if the trailing array references appearing after
>      the end of TBAA access path and mostly punt in the second case (because 
> we
>      need to support kind of all type puning here). I do not think we can 
> assume
>      much of sanity here, in particular, we no longer know there is only one
>      because FRE may mix things up.
> 
>      An exception is the walk that looks for occurence of basetype of path1
>      within TBAA relevant part of path2.  Here we realy care about TBAA
>      relevant parts of paths and thus do not need to give up.
> 
>      I broke out the logic into ends_tbaa_access_path_p to avoid duplication 
> and
>      to let me stick some detailed comments. This became much more complex
>      than I originally imagined (still it is useful to make oracle both faster
>      and more precise).
> 
>      Note that logic in aliasing_component_refs_walk is safe since it works
>      on TBAA relevant segments of paths only.
>   2) nonoverlapping_refs_since_match_p is using TBAA only in the corner case
>      that the paths got out of sync and re-synchronize of types of same size
>      are found.  I thus extended it to whole paths (not only TBAA relevant
>      parts) and track if the TBAA part can be used by counting of number of
>      TBAA relevant res on the stack.
> 
>      I have noticed that in one case we call nonoverlapping_refs_since_match_p
>      before checking for view converting MEM_REFs and in others we check
>      after.  I think we want to just disable TBAA part if view convert
>      is in there but still disambiguate.  I will do this incrementaly.
>   3) nonoverlapping_component_refs_p uses TBAA so it needs to punt on
>      end of TBAA path. It deals with no sizes and thus there is not the issue
>      as in 1).
> 
> I am also attaching one (most probably) valid C++ testcase (by Mark Williams)
> where we incorrectly disambiguated while the code is valid by the common
> initial sequence rule.  This happens to be fixed by same patch. Here one 
> access
> goes through union and follows by access path trhough one filed, while other
> access path start by different field of the union with common initial 
> sequence.
> This made aliasing_component_refs_p to not find the overlapping type (because
> there is none) and disambiguate.  Now we cut the first access path by the 
> union
> reference and this makes us to find the path continuation in
> alias_component_refs_walk.
> 
> If FRE is ever made more careful about access paths past the fist union
> reference (I think that would be good idea since unions are quite common in 
> C++
> and we throw away quite useful info) then we will need to teach access path
> oracle about the common initial sequence rule (which, as Mark pointed out, is
> part of both C and C++ standards).
> 
> Only argument that can possibly invalidate this testcase is that I do not see
> that stadnard is clear about the situation where one access path contains the
> union but other starts after the union.
> 
> Clearly if both start after the union reference we are right to disambiguate
> (since there is no union unvolved).  If both starts before union then there is
> common initial sequence and by standard it is defined. This case works on 
> current
> trunk because aliasing_component_refs_p resorts to base+offset after finding
> the match. But even that is more or less an accident I would say.
> 
> I had to xfail three testcases.  While alias-access-path ones are
> artificial and odd, 20030807-7 is derived from gcc and shows that we
> give up on disambiguations of: tree is typedef to union  tree_node, so
> this patch disables useful references through tree pointers.
> 
> I am still planning to collect some data on the effect of this change to
> TBAA (running LTO bootstrap now), but unless we want to reorganize FRE,
> I do not think there is better solution.
> 
> Bootstrapped/regtested x86_64-linux, OK?

OK and thanks for the elaborate write-up and comments in the code ;)

Thanks,
Richard.

> gcc/ChangeLog:
> 
> 2020-02-26  Jan Hubicka  <hubi...@ucw.cz>
> 
>       PR middle-end/92152
>       * alias.c (ends_tbaa_access_path_p): Break out from ...
>       (component_uses_parent_alias_set_from): ... here.
>       * alias.h (ends_tbaa_access_path_p): Declare.
>       * tree-ssa-alias.c (access_path_may_continue_p): Break out from ...;
>       handle trailing arrays past end of tbaa access path.
>       (aliasing_component_refs_p): ... here; likewise.
>       (nonoverlapping_refs_since_match_p): Track TBAA segment of the access
>       path; disambiguate also past end of it.
>       (nonoverlapping_component_refs_p): Use only TBAA segment of the access
>       path.
> 
> gcc/testsuite/ChangeLog:
> 
> 2020-02-26  Jan Hubicka  <hubi...@ucw.cz>
> 
>       * gcc.dg/tree-ssa/alias-access-path-12.c: New testcase.
>       * g++.dg/torture/pr92152.C: New testcase.
>       * gcc.dg/torture/pr92152.c: New testcase.
>       * gcc.dg/tree-ssa/20030807-7.c: xfail.
>       * gcc.dg/tree-ssa/alias-access-path-4.c: xfail one case.
>       * gcc.dg/tree-ssa/alias-access-path-5.c: xfail one case.
> 
> 
> diff --git a/gcc/alias.c b/gcc/alias.c
> index 3794f9b6a9e..fe75e22cdb5 100644
> --- a/gcc/alias.c
> +++ b/gcc/alias.c
> @@ -587,6 +587,49 @@ objects_must_conflict_p (tree t1, tree t2)
>    return alias_sets_must_conflict_p (set1, set2);
>  }
>  
> +/* Return true if T is an end of the access path which can be used
> +   by type based alias oracle.  */
> +
> +bool
> +ends_tbaa_access_path_p (const_tree t)
> +{
> +  switch (TREE_CODE (t))
> +    {
> +    case COMPONENT_REF:
> +      if (DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1)))
> +     return true;
> +      /* Permit type-punning when accessing a union, provided the access
> +      is directly through the union.  For example, this code does not
> +      permit taking the address of a union member and then storing
> +      through it.  Even the type-punning allowed here is a GCC
> +      extension, albeit a common and useful one; the C standard says
> +      that such accesses have implementation-defined behavior.  */
> +      else if (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
> +     return true;
> +      break;
> +
> +    case ARRAY_REF:
> +    case ARRAY_RANGE_REF:
> +      if (TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0))))
> +     return true;
> +      break;
> +
> +    case REALPART_EXPR:
> +    case IMAGPART_EXPR:
> +      break;
> +
> +    case BIT_FIELD_REF:
> +    case VIEW_CONVERT_EXPR:
> +      /* Bitfields and casts are never addressable.  */
> +      return true;
> +      break;
> +
> +    default:
> +      gcc_unreachable ();
> +    }
> +  return false;
> +}
> +
>  /* Return the outermost parent of component present in the chain of
>     component references handled by get_inner_reference in T with the
>     following property:
> @@ -601,40 +644,8 @@ component_uses_parent_alias_set_from (const_tree t)
>  
>    while (handled_component_p (t))
>      {
> -      switch (TREE_CODE (t))
> -     {
> -     case COMPONENT_REF:
> -       if (DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1)))
> -         found = t;
> -       /* Permit type-punning when accessing a union, provided the access
> -          is directly through the union.  For example, this code does not
> -          permit taking the address of a union member and then storing
> -          through it.  Even the type-punning allowed here is a GCC
> -          extension, albeit a common and useful one; the C standard says
> -          that such accesses have implementation-defined behavior.  */
> -       else if (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
> -         found = t;
> -       break;
> -
> -     case ARRAY_REF:
> -     case ARRAY_RANGE_REF:
> -       if (TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0))))
> -         found = t;
> -       break;
> -
> -     case REALPART_EXPR:
> -     case IMAGPART_EXPR:
> -       break;
> -
> -     case BIT_FIELD_REF:
> -     case VIEW_CONVERT_EXPR:
> -       /* Bitfields and casts are never addressable.  */
> -       found = t;
> -       break;
> -
> -     default:
> -       gcc_unreachable ();
> -     }
> +      if (ends_tbaa_access_path_p (t))
> +     found = t;
>  
>        t = TREE_OPERAND (t, 0);
>      }
> diff --git a/gcc/alias.h b/gcc/alias.h
> index 0fdf0095f2c..781b040fec1 100644
> --- a/gcc/alias.h
> +++ b/gcc/alias.h
> @@ -26,6 +26,7 @@ extern alias_set_type get_deref_alias_set (tree);
>  extern alias_set_type get_varargs_alias_set (void);
>  extern alias_set_type get_frame_alias_set (void);
>  extern tree component_uses_parent_alias_set_from (const_tree);
> +extern bool ends_tbaa_access_path_p (const_tree);
>  extern bool alias_set_subset_of (alias_set_type, alias_set_type);
>  extern void record_alias_subset (alias_set_type, alias_set_type);
>  extern void record_component_aliases (tree);
> diff --git a/gcc/testsuite/g++.dg/torture/pr92152.C 
> b/gcc/testsuite/g++.dg/torture/pr92152.C
> new file mode 100644
> index 00000000000..1aff9b735be
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/torture/pr92152.C
> @@ -0,0 +1,74 @@
> +/* { dg-do run } */
> +using size_t = unsigned long;
> +using uint64_t = unsigned long;
> +
> +namespace HPHP {
> +
> +inline void bitvec_set(uint64_t* bits, size_t index) {
> +  bits[index / 64] |= 1ull << (index % 64);
> +}
> +
> +namespace jit {
> +///////////////////////////////////////////////////////////////////////////////
> +
> +struct VregSet {
> +  struct Block;
> +
> +  VregSet() : blocks{} { blocks.data[1] = 1LL << 0x30; };
> +
> +  VregSet(const VregSet& o)
> +    : blocks{o.blocks}
> +  {
> +  }
> +
> +  bool any() const {
> +    if (!isExtended()) return blocks.any();
> +    return true;
> +  }
> +  void removePhys() {
> +    auto const b = !isExtended() ? &blocks : extended.blocks;
> +    b->data[0] = 0;
> +    b->data[1] = 0;
> +  }
> +  static constexpr size_t kBitsPerBlock = 256;
> +  bool isExtended() const {
> +    return extended.data[1] & (1ULL << (kExtendedBit % 64));
> +  }
> +
> +  static constexpr size_t kExtendedBit = 127;
> +
> +  struct Block {
> +    bool any() const {
> +      return data[0] | data[1];
> +    }
> +    uint64_t data[2];
> +  };
> +  struct Extended {
> +    uint64_t data[2];
> +    Block* blocks;
> +  };
> +
> +  union {
> +    Block blocks{};
> +    Extended extended;
> +  };
> +};
> +
> +//////////////////////////////////////////////////////////////////////
> +
> +
> +__attribute__((noinline))
> +bool test(VregSet&& c) {
> +  auto copy = c;
> +  copy.removePhys();
> +  return copy.any();
> +}
> +///////////////////////////////////////////////////////////////////////////////
> +}}
> +///////////////////////////////////////////////////////////////////////////////
> +
> +int main() {
> +  if (HPHP::jit::test(HPHP::jit::VregSet{}))
> +    __builtin_abort ();
> +  return 0;
> +} 
> diff --git a/gcc/testsuite/gcc.dg/torture/pr92152.c 
> b/gcc/testsuite/gcc.dg/torture/pr92152.c
> new file mode 100644
> index 00000000000..a4f883956d4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr92152.c
> @@ -0,0 +1,23 @@
> +/* { dg-do run } */
> +union U
> +{
> +  long long i;
> +  long f;
> +} v;
> +     
> +long
> +foo (long *f)
> +{
> +  *f = 1;
> +  v.i = 0;
> +  v.f = 0;
> +  return *f;
> +}
> +     
> +int
> +main ()
> +{
> +  if (foo (&v.f) != 0)
> +    __builtin_abort ();
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c
> index 0dda180d43a..ca06f712890 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c
> @@ -34,4 +34,4 @@ simplify_condition (cond_p)
>  }
>  
>  /* There should be exactly one IF conditional.  */
> -/* { dg-final { scan-tree-dump-times "if " 1 "vrp1" } } */
> +/* { dg-final { scan-tree-dump-times "if " 1 "vrp1" { xfail *-*-* } } } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-12.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-12.c
> new file mode 100644
> index 00000000000..738f45503a5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-12.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fno-strict-aliasing -fdump-tree-optimized" } */
> +
> +struct S
> +{
> +  int i;
> +  int j;
> +};
> +union U
> +{
> +  struct S a[10];
> +};
> +int
> +foo (union U *u, int n, int i, int j)
> +{
> +  u->a[i].i = 123;
> +  u->a[j].j = j;
> +  return u->a[i].i;
> +}
> +/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c
> index 641ef89cbb8..2883fd37f31 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c
> @@ -20,5 +20,5 @@ test2 (struct b *bptr1, union c *cptr, int i, int j)
>    cptr->b.a[j].v1=1;
>    return bptr1->a[i].v1;
>  }
> -/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
> +/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"  { xfail 
> *-*-* } } } */
>  /* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c
> index 412f99e7c55..c58d478e0eb 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c
> @@ -21,5 +21,5 @@ test2 (struct b *bptr1, union c *cptr, int i, int j)
>    cptr->b.a[j].v1=1;
>    return bptr1->a[i].v1;
>  }
> -/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
> +/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"  { xfail 
> *-*-* } } } */
>  /* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */
> diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
> index 7554e209efa..2e8290f35d5 100644
> --- a/gcc/tree-ssa-alias.c
> +++ b/gcc/tree-ssa-alias.c
> @@ -995,6 +995,51 @@ aliasing_component_refs_walk (tree ref1, tree type1, 
> tree base1,
>    return -1;
>  }
>  
> +/* Consider access path1 base1....ref1 and access path2 base2...ref2.
> +   Return true if they can be composed to single access path
> +   base1...ref1...base2...ref2.
> +
> +   REF_TYPE1 if type of REF1.  END_STRUCT_PAST_END1 is true if there is
> +   a trailing array access after REF1 in the non-TBAA part of the access.
> +   REF1_ALIAS_SET is the alias set of REF1.
> +
> +   BASE_TYPE2 is type of base2.  END_STRUCT_REF2 is non-NULL if there is
> +   a traling array access in the TBAA part of access path2.
> +   BASE2_ALIAS_SET is the alias set of base2.  */
> +
> +bool
> +access_path_may_continue_p (tree ref_type1, bool end_struct_past_end1,
> +                         alias_set_type ref1_alias_set,
> +                         tree base_type2, tree end_struct_ref2,
> +                         alias_set_type base2_alias_set)
> +{
> +  /* Access path can not continue past types with no components.  */
> +  if (!type_has_components_p (ref_type1))
> +    return false;
> +
> +  /* If first access path ends by too small type to hold base of
> +     the second access path, typically paths can not continue.
> +
> +     Punt if end_struct_past_end1 is true.  We want to support arbitrary
> +     type puning past first COMPONENT_REF to union because redundant store
> +     elimination depends on this, see PR92152.  For this reason we can not
> +     check size of the reference because types may partially overlap.  */
> +  if (!end_struct_past_end1)
> +    {
> +      if (compare_type_sizes (ref_type1, base_type2) < 0)
> +     return false;
> +      /* If the path2 contains trailing array access we can strenghten the 
> check
> +      to verify that also the size of element of the trailing array fits.
> +      In fact we could check for offset + type_size, but we do not track
> +      offsets and this is quite side case.  */
> +      if (end_struct_ref2
> +       && compare_type_sizes (ref_type1, TREE_TYPE (end_struct_ref2)) < 0)
> +     return false;
> +    }
> +  return (base2_alias_set == ref1_alias_set
> +       || alias_set_subset_of (base2_alias_set, ref1_alias_set));
> +}
> +
>  /* Determine if the two component references REF1 and REF2 which are
>     based on access types TYPE1 and TYPE2 and of which at least one is based
>     on an indirect reference may alias.  
> @@ -1021,8 +1066,30 @@ aliasing_component_refs_p (tree ref1,
>    tree type1, type2;
>    bool maybe_match = false;
>    tree end_struct_ref1 = NULL, end_struct_ref2 = NULL;
> +  bool end_struct_past_end1 = false;
> +  bool end_struct_past_end2 = false;
> +
> +  /* Choose bases and base types to search for.
> +     The access path is as follows:
> +       base....end_of_tbaa_ref...actual_ref
> +     At one place in the access path may be a reference to zero sized or
> +     trailing array.
> +
> +     We generally discard the segment after end_of_tbaa_ref however
> +     we need to be careful in case it contains zero sized or traling array.
> +     These may happen after refernce to union and in this case we need to
> +     not disambiguate type puning scenarios.
> +
> +     We set:
> +     base1 to point to base
> +
> +     ref1 to point to end_of_tbaa_ref
>  
> -  /* Choose bases and base types to search for.  */
> +     end_struct_ref1 to point the trailing reference (if it exists
> +     in range base....end_of_tbaa_ref
> +
> +     end_struct_past_end1 is true if this traling refernece occurs in
> +     end_of_tbaa_ref...actual_ref.  */
>    base1 = ref1;
>    while (handled_component_p (base1))
>      {
> @@ -1042,9 +1109,15 @@ aliasing_component_refs_p (tree ref1,
>         gcc_checking_assert (!end_struct_ref1);
>            end_struct_ref1 = base1;
>       }
> -      if (TREE_CODE (base1) == VIEW_CONVERT_EXPR
> -       || TREE_CODE (base1) == BIT_FIELD_REF)
> -     ref1 = TREE_OPERAND (base1, 0);
> +      if (ends_tbaa_access_path_p (base1))
> +     {
> +       ref1 = TREE_OPERAND (base1, 0);
> +       if (end_struct_ref1)
> +         {
> +           end_struct_past_end1 = true;
> +           end_struct_ref1 = NULL;
> +         }
> +     }
>        base1 = TREE_OPERAND (base1, 0);
>      }
>    type1 = TREE_TYPE (base1);
> @@ -1056,9 +1129,15 @@ aliasing_component_refs_p (tree ref1,
>         gcc_checking_assert (!end_struct_ref2);
>         end_struct_ref2 = base2;
>       }
> -      if (TREE_CODE (base2) == VIEW_CONVERT_EXPR
> -       || TREE_CODE (base2) == BIT_FIELD_REF)
> -     ref2 = TREE_OPERAND (base2, 0);
> +      if (ends_tbaa_access_path_p (base2))
> +     {
> +       ref2 = TREE_OPERAND (base2, 0);
> +       if (end_struct_ref2)
> +         {
> +           end_struct_past_end2 = true;
> +           end_struct_ref2 = NULL;
> +         }
> +     }
>        base2 = TREE_OPERAND (base2, 0);
>      }
>    type2 = TREE_TYPE (base2);
> @@ -1070,7 +1149,8 @@ aliasing_component_refs_p (tree ref1,
>  
>    /* If type2 is big enough to contain type1 walk its access path.
>       We also need to care of arrays at the end of structs that may extend
> -     beyond the end of structure.  */
> +     beyond the end of structure.  If this occurs in the TBAA part of the
> +     access path, we need to consider the increased type as well.  */
>    if (cmp_outer >= 0
>        || (end_struct_ref2
>         && compare_type_sizes (TREE_TYPE (end_struct_ref2), type1) >= 0))
> @@ -1113,31 +1193,14 @@ aliasing_component_refs_p (tree ref1,
>        return false;
>      }
>  
> -  /* If we have two type access paths B1.path1 and B2.path2 they may
> -     only alias if either B1 is in B2.path2 or B2 is in B1.path1.
> -     But we can still have a path that goes B1.path1...B2.path2 with
> -     a part that we do not see.  So we can only disambiguate now
> -     if there is no B2 in the tail of path1 and no B1 on the
> -     tail of path2.  */
> -  if (compare_type_sizes (TREE_TYPE (ref2), type1) >= 0
> -      && (!end_struct_ref1
> -       || compare_type_sizes (TREE_TYPE (ref2),
> -                              TREE_TYPE (end_struct_ref1)) >= 0)
> -      && type_has_components_p (TREE_TYPE (ref2))
> -      && (base1_alias_set == ref2_alias_set
> -          || alias_set_subset_of (base1_alias_set, ref2_alias_set)))
> -    {
> -      ++alias_stats.aliasing_component_refs_p_may_alias;
> -      return true;
> -    }
> -  /* If this is ptr vs. decl then we know there is no ptr ... decl path.  */
> -  if (compare_type_sizes (TREE_TYPE (ref1), type2) >= 0
> -      && (!end_struct_ref2
> -       || compare_type_sizes (TREE_TYPE (ref1),
> -                              TREE_TYPE (end_struct_ref2)) >= 0)
> -      && type_has_components_p (TREE_TYPE (ref1))
> -      && (base2_alias_set == ref1_alias_set
> -       || alias_set_subset_of (base2_alias_set, ref1_alias_set)))
> +  if (access_path_may_continue_p (TREE_TYPE (ref1), end_struct_past_end1,
> +                               ref1_alias_set,
> +                               type2, end_struct_ref2,
> +                               base2_alias_set)
> +      || access_path_may_continue_p (TREE_TYPE (ref2), end_struct_past_end2,
> +                                  ref2_alias_set,
> +                                  type1, end_struct_ref1,
> +                                  base1_alias_set))
>      {
>        ++alias_stats.aliasing_component_refs_p_may_alias;
>        return true;
> @@ -1348,6 +1411,7 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>                                  tree match2, tree ref2,
>                                  bool partial_overlap)
>  {
> +  int ntbaa1 = 0, ntbaa2 = 0;
>    /* Early return if there are no references to match, we do not need
>       to walk the access paths.
>  
> @@ -1365,25 +1429,33 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>    /* Create the stack of handled components for REF1.  */
>    while (handled_component_p (ref1) && ref1 != match1)
>      {
> -      if (TREE_CODE (ref1) == VIEW_CONVERT_EXPR
> -       || TREE_CODE (ref1) == BIT_FIELD_REF)
> -     component_refs1.truncate (0);
> +      /* We use TBAA only to re-synchronize after mismatched refs.  So we
> +      do not need to truncate access path after TBAA part ends.  */
> +      if (ends_tbaa_access_path_p (ref1))
> +     ntbaa1 = 0;
>        else
> -        component_refs1.safe_push (ref1);
> +     ntbaa1++;
> +      component_refs1.safe_push (ref1);
>        ref1 = TREE_OPERAND (ref1, 0);
>      }
>  
>    /* Create the stack of handled components for REF2.  */
>    while (handled_component_p (ref2) && ref2 != match2)
>      {
> -      if (TREE_CODE (ref2) == VIEW_CONVERT_EXPR
> -       || TREE_CODE (ref2) == BIT_FIELD_REF)
> -     component_refs2.truncate (0);
> +      if (ends_tbaa_access_path_p (ref2))
> +     ntbaa2 = 0;
>        else
> -        component_refs2.safe_push (ref2);
> +     ntbaa2++;
> +      component_refs2.safe_push (ref2);
>        ref2 = TREE_OPERAND (ref2, 0);
>      }
>  
> +  if (!flag_strict_aliasing)
> +    {
> +      ntbaa1 = 0;
> +      ntbaa2 = 0;
> +    }
> +
>    bool mem_ref1 = TREE_CODE (ref1) == MEM_REF && ref1 != match1;
>    bool mem_ref2 = TREE_CODE (ref2) == MEM_REF && ref2 != match2;
>  
> @@ -1444,6 +1516,7 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>         for (; narray_refs1 > narray_refs2; narray_refs1--)
>           {
>             ref1 = component_refs1.pop ();
> +           ntbaa1--;
>  
>             /* If index is non-zero we need to check whether the reference
>                does not break the main invariant that bases are either
> @@ -1471,6 +1544,7 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>         for (; narray_refs2 > narray_refs1; narray_refs2--)
>           {
>             ref2 = component_refs2.pop ();
> +           ntbaa2--;
>             if (!operand_equal_p (TREE_OPERAND (ref2, 1),
>                                   cheap_array_ref_low_bound (ref2), 0))
>               return 0;
> @@ -1480,6 +1554,8 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>           {
>             int cmp = nonoverlapping_array_refs_p (component_refs1.pop (),
>                                                    component_refs2.pop ());
> +           ntbaa1--;
> +           ntbaa2--;
>             if (cmp == 1 && !partial_overlap)
>               {
>                 ++alias_stats
> @@ -1494,7 +1570,7 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>                    from type based alias analysis if we reach referneces to
>                    same sizes.  We do not attempt to match array sizes, so
>                    just finish array walking and look for component refs.  */
> -               if (!flag_strict_aliasing)
> +               if (ntbaa1 < 0 || ntbaa2 < 0)
>                   {
>                     ++alias_stats.nonoverlapping_refs_since_match_p_may_alias;
>                     return -1;
> @@ -1503,6 +1579,8 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>                   {
>                     component_refs1.pop ();
>                     component_refs2.pop ();
> +                   ntbaa1--;
> +                   ntbaa2--;
>                   }
>                 break;
>               }
> @@ -1520,10 +1598,11 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>             return 0;
>           }
>         ref1 = component_refs1.pop ();
> +       ntbaa1--;
>         if (TREE_CODE (ref1) != COMPONENT_REF)
>           {
>             seen_unmatched_ref_p = true;
> -           if (!flag_strict_aliasing)
> +           if (ntbaa1 < 0 || ntbaa2 < 0)
>               {
>                 ++alias_stats.nonoverlapping_refs_since_match_p_may_alias;
>                 return -1;
> @@ -1541,9 +1620,10 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>             return 0;
>           }
>         ref2 = component_refs2.pop ();
> +       ntbaa2--;
>         if (TREE_CODE (ref2) != COMPONENT_REF)
>           {
> -           if (!flag_strict_aliasing)
> +           if (ntbaa1 < 0 || ntbaa2 < 0)
>               {
>                 ++alias_stats.nonoverlapping_refs_since_match_p_may_alias;
>                 return -1;
> @@ -1569,11 +1649,9 @@ nonoverlapping_refs_since_match_p (tree match1, tree 
> ref1,
>  
>        partial_overlap = false;
>  
> -      gcc_checking_assert (!seen_unmatched_ref_p || flag_strict_aliasing);
> -
>        /* If we skipped array refs on type of different sizes, we can
>        no longer be sure that there are not partial overlaps.  */
> -      if (seen_unmatched_ref_p
> +      if (seen_unmatched_ref_p && ntbaa1 >= 0 && ntbaa2 >= 0
>         && !operand_equal_p (TYPE_SIZE (type1), TYPE_SIZE (type2), 0))
>       {
>         ++alias_stats
> @@ -1663,8 +1741,7 @@ nonoverlapping_component_refs_p (const_tree x, 
> const_tree y)
>         if (TREE_CODE (type) == RECORD_TYPE)
>           fieldsx.safe_push (field);
>       }
> -      else if (TREE_CODE (x) == VIEW_CONVERT_EXPR
> -            || TREE_CODE (x) == BIT_FIELD_REF)
> +      else if (ends_tbaa_access_path_p (x))
>       fieldsx.truncate (0);
>        x = TREE_OPERAND (x, 0);
>      }
> @@ -1680,8 +1757,7 @@ nonoverlapping_component_refs_p (const_tree x, 
> const_tree y)
>         if (TREE_CODE (type) == RECORD_TYPE)
>           fieldsy.safe_push (TREE_OPERAND (y, 1));
>       }
> -      else if (TREE_CODE (y) == VIEW_CONVERT_EXPR
> -            || TREE_CODE (y) == BIT_FIELD_REF)
> +      else if (ends_tbaa_access_path_p (y))
>       fieldsy.truncate (0);
>        y = TREE_OPERAND (y, 0);
>      }
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to