Hi, while looking at the cases disambiguated by access path and not by alias simple alias set lookup I noticed that there are number of accesses to pointers of different type which we consider as possible equivalent.
For example struct a *a; struct b *b; is currently considered aliasing with LTO if one of the structures is incomplete. For C++ sources we could fix this by looking up the complete variant via ODR type hash. Note that this is also safe WRT subset construction for aggregates because we glob all pointers to void * with LTO prior calling get_alias_set (so currently any two structures containing pointer conflict with each other). This quite simple patch saves about 5% of void * globbing when compiling cc1plus with LTO. Stats change from: Alias oracle query stats: refs_may_alias_p: 39482421 disambiguations, 47760976 queries ref_maybe_used_by_call_p: 58817 disambiguations, 40085376 queries call_may_clobber_ref_p: 5579 disambiguations, 8373 queries aliasing_component_ref_p: 99652 disambiguations, 285661 queries TBAA oracle: 11408132 disambiguations 35099843 queries 14285452 are in alias set 0 5370901 queries asked about the same object 147 queries asked about the same alias set 0 access volatile 1721512 are dependent in the DAG 2313699 are aritificially in conflict with void * PTA query stats: pt_solution_includes: 474714 disambiguations, 7173966 queries pt_solutions_intersect: 390271 disambiguations, 7304940 queries To: Alias oracle query stats: refs_may_alias_p: 39461257 disambiguations, 47717872 queries ref_maybe_used_by_call_p: 58819 disambiguations, 40064384 queries call_may_clobber_ref_p: 5579 disambiguations, 8373 queries aliasing_component_ref_p: 91509 disambiguations, 277156 queries TBAA oracle: 11436147 disambiguations 34996771 queries 14283553 are in alias set 0 5389241 queries asked about the same object 147 queries asked about the same alias set 0 access volatile 1694396 are dependent in the DAG 2193287 are aritificially in conflict with void * PTA query stats: pt_solution_includes: 474052 disambiguations, 7165766 queries pt_solutions_intersect: 389420 disambiguations, 7268793 queries Bootstrapped/regtested x86_64-linux, comitted. Honza * alias.c: Include ipa-utils.h. (get_alias_set): Try to complete ODR type via ODR type hash lookup. * ipa-devirt.c (prevailing_odr_type): New. * ipa-utils.h (previaling_odr_type): Declare. * g++.dg/lto/alias-1_0.C: New testcase. * g++.dg/lto/alias-1_1.C: New testcase. Index: alias.c =================================================================== --- alias.c (revision 271836) +++ alias.c (working copy) @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. #include "cfganal.h" #include "rtl-iter.h" #include "cgraph.h" +#include "ipa-utils.h" /* The aliasing API provided here solves related but different problems: @@ -1008,6 +1009,14 @@ get_alias_set (tree t) } p = TYPE_MAIN_VARIANT (p); + /* In LTO for C++ programs we can turn in complete types to complete + using ODR name lookup. */ + if (in_lto_p && TYPE_STRUCTURAL_EQUALITY_P (p) && odr_type_p (p)) + { + p = prevailing_odr_type (p); + gcc_checking_assert (TYPE_MAIN_VARIANT (p) == p); + } + /* Make void * compatible with char * and also void **. Programs are commonly violating TBAA by this. Index: ipa-devirt.c =================================================================== --- ipa-devirt.c (revision 271836) +++ ipa-devirt.c (working copy) @@ -2170,6 +2170,20 @@ get_odr_type (tree type, bool insert) return val; } +/* Return type that in ODR type hash prevailed TYPE. Be careful and punt + on ODR violations. */ + +tree +prevailing_odr_type (tree type) +{ + odr_type t = get_odr_type (type, false); + if (!t || t->odr_violated) + return type; + return t->type; +} + +/* Return true if we reported some ODR violation on TYPE. */ + bool odr_type_violation_reported_p (tree type) { Index: ipa-utils.h =================================================================== --- ipa-utils.h (revision 271836) +++ ipa-utils.h (working copy) @@ -92,6 +92,7 @@ void warn_types_mismatch (tree t1, tree bool odr_or_derived_type_p (const_tree t); bool odr_types_equivalent_p (tree type1, tree type2); bool odr_type_violation_reported_p (tree type); +tree prevailing_odr_type (tree type); /* Return vector containing possible targets of polymorphic call E. If COMPLETEP is non-NULL, store true if the list is complete. Index: testsuite/g++.dg/lto/alias-1_0.C =================================================================== --- testsuite/g++.dg/lto/alias-1_0.C (nonexistent) +++ testsuite/g++.dg/lto/alias-1_0.C (working copy) @@ -0,0 +1,31 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options { { -O2 -flto } } } */ + +/* With LTO we consider all pointers to incomplete types to be possibly + aliasing. This makes *bptr to alias with aptr. + However with C++ ODR rule we can turn incomplete pointers to complete + dragging in info from alias-1_1.C. */ + +#include <string.h> + +typedef int (*fnptr) (); + +__attribute__ ((used)) +struct a *aptr; + +__attribute__ ((used)) +struct b **bptr = (struct b**)&aptr; +extern void init (); +extern void inline_me_late (int); + + +int +main (int argc, char **argv) +{ + init (); + aptr = 0; + inline_me_late (argc); + if (!__builtin_constant_p (aptr == 0)) + __builtin_abort (); + return (size_t)aptr; +} Index: testsuite/g++.dg/lto/alias-1_1.C =================================================================== --- testsuite/g++.dg/lto/alias-1_1.C (nonexistent) +++ testsuite/g++.dg/lto/alias-1_1.C (working copy) @@ -0,0 +1,16 @@ +#include <string.h> +struct a {int a;} a; +struct b {short b;} b; +extern struct b **bptr; +void +inline_me_late (int argc) +{ + if (argc == -1) + *bptr = (struct b *)(size_t)1; +} +void +init() +{ + a.a=1; + b.b=2; +}