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? * 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))