Enable nonoverallping_component_refs even after the base pointers are equivalent

Richard Biener rguenther@suse.de
Wed Jul 3 12:40:00 GMT 2019


On Tue, 2 Jul 2019, Jan Hubicka wrote:

> Hi,
> this patch adds the shortcut for must aliases discussed earlier and enables
> access path even if bases are proved to be equivalent - it could still do
> useful job for arrays etc.
> 
> tramp3d stats go from:
> 
> Alias oracle query stats:
>   refs_may_alias_p: 4421560 disambiguations, 4781790 queries
>   ref_maybe_used_by_call_p: 6790 disambiguations, 4447962 queries
>   call_may_clobber_ref_p: 883 disambiguations, 883 queries
>   nonoverlapping_component_refs_p: 0 disambiguations, 9272 queries
>   nonoverlapping_component_refs_since_match_p: 31 disambiguations, 39391 queries
>   aliasing_component_refs_p: 918 disambiguations, 30889 queries
>   TBAA oracle: 1924468 disambiguations 3851145 queries
>                774336 are in alias set 0
>                714019 queries asked about the same object
>                0 queries asked about the same alias set
>                0 access volatile
>                282546 are dependent in the DAG
>                155776 are aritificially in conflict with void *
> 
> to
> 
> Alias oracle query stats:
>   refs_may_alias_p: 4421611 disambiguations, 4781828 queries
>   ref_maybe_used_by_call_p: 6790 disambiguations, 4448013 queries
>   call_may_clobber_ref_p: 883 disambiguations, 883 queries
>   nonoverlapping_component_refs_p: 0 disambiguations, 8964 queries
>   nonoverlapping_component_refs_since_match_p: 66 disambiguations, 18470 queries
>   aliasing_component_refs_p: 918 disambiguations, 30371 queries
>   TBAA oracle: 1924492 disambiguations 3849967 queries
>                774336 are in alias set 0
>                714095 queries asked about the same object
>                0 queries asked about the same alias set
>                0 access volatile
>                281268 are dependent in the DAG
>                155776 are aritificially in conflict with void *
> 
> PTA query stats:
>   pt_solution_includes: 906632 disambiguations, 1214744 queries
>   pt_solutions_intersect: 121330 disambiguations, 553172 queries
> 
> So twice as many nonoverlapping_component_refs_since_match_p disambiguations,
> half of querries.
> 
> We can miss some of disambiguations where addresses are same but types
> are different, but I think those are not useful - this is the case where
> memory type was dynamically changed.  If we walk with TBAA enabled and
> see the prevoius use, we got kind of lost anyway and propagating even
> older values seems to have no use.
> 
> Note that i tried to implement ranges_must_overlap_p predicate which could
> save us from more tests but got lost in polyints and I think it is not worth
> the effort since these cases are quite borderline.
> 
> Similar test would make sense in aliasing_component_refs_p but I think
> it may make more sense to reorder the tests there. Right now we do:
> 
>   get_ref_base_and_extent (match2, &offadj, &sztmp, &msztmp, &reverse);
>   offset2 -= offadj;
>   get_ref_base_and_extent (match1, &offadj, &sztmp, &msztmp, &reverse);
>   offset1 -= offadj;
>   if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2))
> 
> First I think that one get_ref_base_and_extent is always redundant since either
> match1 or match2 is base so we could pass it down.
> 
> However it seems to me that perhaps doing
> nonoverlapping_component_refs_since_match_p would be cheaper and one can do the
> range check only after this one returns -1 saving quite many
> get_ref_base_and_extent calls.

Yeah, that sounds worthwhile (this function is the worst offender
compile-time wise)

> Bootstrapped/regtested x86_64-linux, OK?
> 
> Honza
> 
> Index: testsuite/gcc.dg/tree-ssa/alias-access-path-3.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/alias-access-path-3.c	(nonexistent)
> +++ testsuite/gcc.dg/tree-ssa/alias-access-path-3.c	(working copy)
> @@ -0,0 +1,22 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-fre1" } */
> +struct a {int v1;
> +	  int v2;};
> +struct b {struct a a[0];};
> +
> +int
> +test (struct b *bptr1, struct b *bptr2, int i, int j)
> +{
> +  bptr1->a[i].v1=123;
> +  bptr2->a[j].v2=1;
> +  return bptr1->a[i].v1;
> +}
> +int
> +test2 (struct b *bptr1, struct b *bptr2, int i, int j)
> +{
> +  bptr1->a[i].v1=123;
> +  bptr2->a[j].v1=1;
> +  return bptr1->a[i].v1;
> +}
> +/* test should be optimized, while test2 should not.  */
> +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre1"} } */
> Index: testsuite/gcc.dg/tree-ssa/alias-access-path-8.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/alias-access-path-8.c	(nonexistent)
> +++ testsuite/gcc.dg/tree-ssa/alias-access-path-8.c	(working copy)
> @@ -0,0 +1,21 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-fre3" } */
> +struct a {
> +  int val;
> +};
> +struct b {
> +  struct a a[10],a2[10];
> +};
> +struct c {
> +  struct b b[10];
> +} *cptr,*cptr2;
> +
> +
> +int
> +test (int i, int j, int k, int l)
> +{
> +  cptr->b[i].a[j].val=123;
> +  cptr2->b[k].a2[l].val=2;
> +  return cptr->b[i].a[j].val;
> +}
> +/* { dg-final { scan-tree-dump-times "return 123" 1 "fre3"} } */

Why does this only happen in fre3?!

Otherwise OK.

Thanks,
Richard.

> Index: tree-ssa-alias.c
> ===================================================================
> --- tree-ssa-alias.c	(revision 272927)
> +++ tree-ssa-alias.c	(working copy)
> @@ -1452,8 +1452,10 @@ nonoverlapping_component_refs_p (const_t
>  static bool
>  decl_refs_may_alias_p (tree ref1, tree base1,
>  		       poly_int64 offset1, poly_int64 max_size1,
> +		       poly_int64 size1,
>  		       tree ref2, tree base2,
> -		       poly_int64 offset2, poly_int64 max_size2)
> +		       poly_int64 offset2, poly_int64 max_size2,
> +		       poly_int64 size2)
>  {
>    gcc_checking_assert (DECL_P (base1) && DECL_P (base2));
>  
> @@ -1466,6 +1468,10 @@ decl_refs_may_alias_p (tree ref1, tree b
>    if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2))
>      return false;
>  
> +  /* If there is must alias, there is no use disambiguating further.  */
> +  if (known_eq (size1, max_size1) && known_eq (size2, max_size2))
> +    return true;
> +
>    /* For components with variable position, the above test isn't sufficient,
>       so we disambiguate component references manually.  */
>    if (ref1 && ref2
> @@ -1487,10 +1493,12 @@ decl_refs_may_alias_p (tree ref1, tree b
>  static bool
>  indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
>  			       poly_int64 offset1, poly_int64 max_size1,
> +			       poly_int64 size1,
>  			       alias_set_type ref1_alias_set,
>  			       alias_set_type base1_alias_set,
>  			       tree ref2 ATTRIBUTE_UNUSED, tree base2,
>  			       poly_int64 offset2, poly_int64 max_size2,
> +			       poly_int64 size2,
>  			       alias_set_type ref2_alias_set,
>  			       alias_set_type base2_alias_set, bool tbaa_p)
>  {
> @@ -1598,7 +1606,19 @@ indirect_ref_may_alias_decl_p (tree ref1
>        && (TREE_CODE (TREE_TYPE (base1)) != ARRAY_TYPE
>  	  || (TYPE_SIZE (TREE_TYPE (base1))
>  	      && TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) == INTEGER_CST)))
> -    return ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2);
> +    {
> +      if (!ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2))
> +	return false;
> +      if (!ref1 || !ref2
> +	  /* If there is must alias, there is no use disambiguating further.  */
> +	  || (known_eq (size1, max_size1) && known_eq (size2, max_size2)))
> +	return true;
> +      int res = nonoverlapping_component_refs_since_match_p (base1, ref1,
> +							     base2, ref2);
> +      if (res == -1)
> +	return !nonoverlapping_component_refs_p (ref1, ref2);
> +      return !res;
> +    }
>  
>    /* Do access-path based disambiguation.  */
>    if (ref1 && ref2
> @@ -1623,10 +1643,12 @@ indirect_ref_may_alias_decl_p (tree ref1
>  static bool
>  indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
>  			   poly_int64 offset1, poly_int64 max_size1,
> +			   poly_int64 size1,
>  			   alias_set_type ref1_alias_set,
>  			   alias_set_type base1_alias_set,
>  			   tree ref2 ATTRIBUTE_UNUSED, tree base2,
>  			   poly_int64 offset2, poly_int64 max_size2,
> +			   poly_int64 size2,
>  			   alias_set_type ref2_alias_set,
>  			   alias_set_type base2_alias_set, bool tbaa_p)
>  {
> @@ -1671,6 +1693,9 @@ indirect_refs_may_alias_p (tree ref1 ATT
>        if (!ranges_maybe_overlap_p (offset1 + moff1, max_size1,
>  				   offset2 + moff2, max_size2))
>  	return false;
> +      /* If there is must alias, there is no use disambiguating further.  */
> +      if (known_eq (size1, max_size1) && known_eq (size2, max_size2))
> +	return true;
>        if (ref1 && ref2)
>  	{
>  	  int res = nonoverlapping_component_refs_since_match_p (NULL, ref1,
> @@ -1717,7 +1742,18 @@ indirect_refs_may_alias_p (tree ref1 ATT
>           can overlap by an exact multiple of their element size.
>           See gcc.dg/torture/alias-2.c.  */
>        && TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE)
> -    return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
> +    {
> +      if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2))
> +	return false;
> +      if (!ref1 || !ref2
> +	  || (known_eq (size1, max_size1) && known_eq (size2, max_size2)))
> +	return true;
> +      int res = nonoverlapping_component_refs_since_match_p (base1, ref1,
> +							     base2, ref2);
> +      if (res == -1)
> +	return !nonoverlapping_component_refs_p (ref1, ref2);
> +      return !res;
> +    }
>  
>    /* Do access-path based disambiguation.  */
>    if (ref1 && ref2
> @@ -1802,7 +1838,9 @@ refs_may_alias_p_2 (ao_ref *ref1, ao_ref
>    var2_p = DECL_P (base2);
>    if (var1_p && var2_p)
>      return decl_refs_may_alias_p (ref1->ref, base1, offset1, max_size1,
> -				  ref2->ref, base2, offset2, max_size2);
> +				  ref1->size,
> +				  ref2->ref, base2, offset2, max_size2,
> +				  ref2->size);
>  
>    /* Handle restrict based accesses.
>       ???  ao_ref_base strips inner MEM_REF [&decl], recover from that
> @@ -1870,21 +1908,21 @@ refs_may_alias_p_2 (ao_ref *ref1, ao_ref
>    /* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators.  */
>    if (var1_p && ind2_p)
>      return indirect_ref_may_alias_decl_p (ref2->ref, base2,
> -					  offset2, max_size2,
> +					  offset2, max_size2, ref2->size,
>  					  ao_ref_alias_set (ref2),
>  					  ao_ref_base_alias_set (ref2),
>  					  ref1->ref, base1,
> -					  offset1, max_size1,
> +					  offset1, max_size1, ref1->size,
>  					  ao_ref_alias_set (ref1),
>  					  ao_ref_base_alias_set (ref1),
>  					  tbaa_p);
>    else if (ind1_p && ind2_p)
>      return indirect_refs_may_alias_p (ref1->ref, base1,
> -				      offset1, max_size1,
> +				      offset1, max_size1, ref1->size,
>  				      ao_ref_alias_set (ref1),
>  				      ao_ref_base_alias_set (ref1),
>  				      ref2->ref, base2,
> -				      offset2, max_size2,
> +				      offset2, max_size2, ref2->size,
>  				      ao_ref_alias_set (ref2),
>  				      ao_ref_base_alias_set (ref2),
>  				      tbaa_p);
> 



More information about the Gcc-patches mailing list