On Mon, 10 Jun 2019, Jan Hubicka wrote:
> Hi,
> this is kind of minimal patch to handle pointers in access paths.
> I do not include logic for arrays nor attempt to deal better with incomparable
> pointers (such as pointers to two different incomplete record types).
>
> A lazy way would be to simply compare alias sets, but I want to handle more
> because our rules for globbing pointers are not transitive. For example void *
> is equivalent to pointer to any incomplete type. But we can still say that
> pointer to record is different from pointer to function which helps in
> practice
> since propagating pointers to functions is rather important.
>
> Alias sets of pointer to record and pointer to function are both same as void
> *
> because we have no way to distinguish multiple pointers of same kind and we
> special case only void * alias set. Here we can work bit better without much
> of extra hassle and we also catch most of cases (since most accesses are to
> types w/o pointers which we disambiguate this way).
>
> Number of disambiguations on tramp3d via access path grows from 1000 to
>
> Alias oracle query stats:
> refs_may_alias_p: 3025065 disambiguations, 3321073 queries
> ref_maybe_used_by_call_p: 7118 disambiguations, 3050683 queries
> call_may_clobber_ref_p: 817 disambiguations, 817 queries
> aliasing_component_ref_p: 8703 disambiguations, 24495 queries
> TBAA oracle: 1429175 disambiguations 2934191 queries
> 552425 are in alias set 0
> 573848 queries asked about the same object
> 0 queries asked about the same alias set
> 0 access volatile
> 257310 are dependent in the DAG
> 121433 are aritificially in conflict with void *
>
> So about 8x more.
>
> lto-bootstrapped/regtested x86_64 with all languages, OK?
So the important thing is that during matching the paths
aptr->a and *bptr we return false for
same_type_for_tbaa (int *, struct a *), correct? But if
we can do that then the alias sets should not conflict in
the first place and we shouldn't need any path-based disambiguation
here.
So to me this is the wrong place to fix.
Richard.
> * gcc.dg/lto/alias-access-path-3_0.c: New testcase.
> * tree-ssa-alias.c (same_type_for_tbaa): Look into pointed-to types
> to test structural equivalence of pointer types.
>
> Index: testsuite/gcc.dg/lto/alias-access-path-3_0.c
> ===================================================================
> --- testsuite/gcc.dg/lto/alias-access-path-3_0.c (nonexistent)
> +++ testsuite/gcc.dg/lto/alias-access-path-3_0.c (working copy)
> @@ -0,0 +1,37 @@
> +/* { dg-lto-do run } */
> +/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */
> +#include <stdlib.h>
> +
> +/* We should disambiguate
> + int *
> + and
> + struct a *
> + despite the fact they get same alias set because struct a is incomplete.
> */
> +
> +typedef int (*fnptr) ();
> +
> +__attribute__ ((used))
> +struct
> +{
> + int *a;
> +} a, *aptr = &a;
> +
> +struct a **bptr;
> +
> +static void
> +inline_me_late (int argc)
> +{
> + if (argc == -1)
> + *bptr = (void *)(size_t)1;
> +}
> +
> +int
> +main (int argc)
> +{
> + typeof (aptr) aptr2 = aptr;
> + aptr2->a = 0;
> + inline_me_late (argc);
> + if (!__builtin_constant_p (aptr2->a == 0))
> + __builtin_abort ();
> + return 0;
> +}
> Index: tree-ssa-alias.c
> ===================================================================
> --- tree-ssa-alias.c (revision 272037)
> +++ tree-ssa-alias.c (working copy)
> @@ -791,10 +791,39 @@ same_type_for_tbaa (tree type1, tree typ
> if (type1 == type2)
> return 1;
>
> + /* For LTO we do not define canonical types of pointers. Look into
> + corresponding pointed-to-types. To speed non-LTO checks,
> + do not bother to do that if canonical types are defined though. */
> + while (POINTER_TYPE_P (type1) && POINTER_TYPE_P (type2)
> + && (TYPE_STRUCTURAL_EQUALITY_P (type1)
> + || TYPE_STRUCTURAL_EQUALITY_P (type2)))
> + {
> + type1 = TREE_TYPE (type1);
> + type2 = TREE_TYPE (type2);
> + /* As an extension, we consider void pointer TBAA compatible with all
> + other pointer types. This is especially importnat in LTO where
> + non-C languages may want to bind to C pointers via void *. */
> + if (VOID_TYPE_P (type1) || VOID_TYPE_P (type2))
> + return 1;
> + }
> +
> /* If we would have to do structural comparison bail out. */
> if (TYPE_STRUCTURAL_EQUALITY_P (type1)
> || TYPE_STRUCTURAL_EQUALITY_P (type2))
> - return -1;
> + {
> + /* If type1 and type2 are diferent kinds, return 0.
> + This is important espcially when we hit incomplete types or
> + function/method types after walking pointed-to types above.
> +
> + ??? As a special case we want to consider ARRAY_TYPE possibly
> + same as its base type to solve some issues with Fortran frontend. */
> + if (TREE_CODE (type1) != ARRAY_TYPE
> + && TREE_CODE (type2) != ARRAY_TYPE
> + && tree_code_for_canonical_type_merging (TREE_CODE (type1))
> + != tree_code_for_canonical_type_merging (TREE_CODE (type2)))
> + return 0;
> + return -1;
> + }
>
> /* Compare the canonical types. */
> if (TYPE_CANONICAL (type1) == TYPE_CANONICAL (type2))
>
--
Richard Biener <[email protected]>
SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany;
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG Nürnberg)