On Tue, 16 Jul 2019, Jan Hubicka wrote: > Hi, > this is the hunk we omitted from the original patch enabling TBAA for > ODR types. Currently record_component_aliases record all pointers as > void *. This is because canonical type merging handles them this way > and thus it may merge for example > > strut a { int *ptr;}; > > and > > struct b { short *ptr;}; > > into one canonical type. The alias set of that canonical type then must > conflict with both int * and short * which we do by globing it to void * > which conflict with everything. > > For ODR types where we do canonical types based on their name we however > assign differnt TYPE_CANONICAL to each of them. Thanks to this we can > make alias set to contain int * or short * respectively. > > > Bootstrapped/regtested x86_64-linux, OK?
OK. Richard. > Honza > * alias.c (record_component_aliases): Do not simplify pointed-to > types of ODR types > * testsuite/g++.dg/lto/alias-4_0.C > Index: alias.c > =================================================================== > --- alias.c (revision 273478) > +++ alias.c (working copy) > @@ -1202,47 +1202,52 @@ record_component_aliases (tree type) > case RECORD_TYPE: > case UNION_TYPE: > case QUAL_UNION_TYPE: > - for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN > (field)) > - if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field)) > - { > - /* LTO type merging does not make any difference between > - component pointer types. We may have > - > - struct foo {int *a;}; > - > - as TYPE_CANONICAL of > - > - struct bar {float *a;}; > - > - Because accesses to int * and float * do not alias, we would get > - false negative when accessing the same memory location by > - float ** and bar *. We thus record the canonical type as: > - > - struct {void *a;}; > - > - void * is special cased and works as a universal pointer type. > - Accesses to it conflicts with accesses to any other pointer > - type. */ > - tree t = TREE_TYPE (field); > - if (in_lto_p) > - { > - /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their > - element type and that type has to be normalized to void *, > - too, in the case it is a pointer. */ > - while (!canonical_type_used_p (t) && !POINTER_TYPE_P (t)) > - { > - gcc_checking_assert (TYPE_STRUCTURAL_EQUALITY_P (t)); > - t = TREE_TYPE (t); > - } > - if (POINTER_TYPE_P (t)) > - t = ptr_type_node; > - else if (flag_checking) > - gcc_checking_assert (get_alias_set (t) > - == get_alias_set (TREE_TYPE (field))); > - } > - > - record_alias_subset (superset, get_alias_set (t)); > - } > + { > + /* LTO non-ODR type merging does not make any difference between > + component pointer types. We may have > + > + struct foo {int *a;}; > + > + as TYPE_CANONICAL of > + > + struct bar {float *a;}; > + > + Because accesses to int * and float * do not alias, we would get > + false negative when accessing the same memory location by > + float ** and bar *. We thus record the canonical type as: > + > + struct {void *a;}; > + > + void * is special cased and works as a universal pointer type. > + Accesses to it conflicts with accesses to any other pointer > + type. */ > + bool void_pointers = in_lto_p > + && (!odr_type_p (type) > + || !odr_based_tbaa_p (type)); > + for (field = TYPE_FIELDS (type); field != 0; field = DECL_CHAIN (field)) > + if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field)) > + { > + tree t = TREE_TYPE (field); > + if (void_pointers) > + { > + /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their > + element type and that type has to be normalized to void *, > + too, in the case it is a pointer. */ > + while (!canonical_type_used_p (t) && !POINTER_TYPE_P (t)) > + { > + gcc_checking_assert (TYPE_STRUCTURAL_EQUALITY_P (t)); > + t = TREE_TYPE (t); > + } > + if (POINTER_TYPE_P (t)) > + t = ptr_type_node; > + else if (flag_checking) > + gcc_checking_assert (get_alias_set (t) > + == get_alias_set (TREE_TYPE (field))); > + } > + > + record_alias_subset (superset, get_alias_set (t)); > + } > + } > break; > > case COMPLEX_TYPE: > > Index: testsuite/g++.dg/lto/alias-4_0.C > =================================================================== > --- testsuite/g++.dg/lto/alias-4_0.C (nonexistent) > +++ testsuite/g++.dg/lto/alias-4_0.C (working copy) > @@ -0,0 +1,31 @@ > +/* { dg-lto-do run } */ > +/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */ > +__attribute__ ((used)) > +short *ptr_init, **ptr=&ptr_init; > + > +__attribute__ ((used)) > +struct a { > + int *aptr; > +} a, *aptr=&a; > + > +void > +write_ptr () > +{ > + *aptr = a; > +} > + > +__attribute__ ((used)) > +void > +test () > +{ > + *ptr = (short int *)0; > + write_ptr (); > + if (!__builtin_constant_p (*ptr == (void *)0)) > + __builtin_abort (); > +} > +int > +main() > +{ > + test (); > + return 0; > +} > -- Richard Biener <rguent...@suse.de> SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG Nürnberg)