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)

Reply via email to