On Thu, 18 Jul 2019, Jan Hubicka wrote:

> Hi,
> this patch adjusts LTO tree merging to treat anonymous namespace types
> as local to a given TU, so just like !TREE_PUBLIC decls they are not
> merged (this is unify_scc change). This makes them to get different
> canonical types and act as independent types for TBAA.
> 
> I also modified canonical type calculation to never consider anonymous
> namespace types as interoperable with structurally equivalent types
> declared in non-C++ translation units.
> 
> Both these changes are tested by the testcase (first change makes set1
> and set2 independent and second chnage makes set1&set2 independent of
> set3).
> 
> lto-bootstrapped/regtested x86_64-linux

OK.  I wonder if we can/should carve off some bits to note
type_with_linkage_p and type_in_anonymous_namespace_p in the tree
itself?  At least in type_common there's plenty of bits left.
Not sure how expensive / reliable (non-C++?) those tests otherwise are.

Thanks,
Richard.

> Honza
> 
>       * lto-common.c (gimple_register_canonical_type_1): Do not look for
>       non-ODR conflicts of types in anonymous namespaces.
>       (unify_scc): Do not merge anonymous namespace types.
>       * g++.dg/lto/alias-5_0.C: New testcase.
>       * g++.dg/lto/alias-5_1.C: New.
>       * g++.dg/lto/alias-5_2.c: New.
> Index: lto/lto-common.c
> ===================================================================
> --- lto/lto-common.c  (revision 273551)
> +++ lto/lto-common.c  (working copy)
> @@ -418,13 +418,19 @@ gimple_register_canonical_type_1 (tree t
>    if (RECORD_OR_UNION_TYPE_P (t)
>        && odr_type_p (t) && !odr_type_violation_reported_p (t))
>      {
> -      /* Here we rely on fact that all non-ODR types was inserted into
> -      canonical type hash and thus we can safely detect conflicts between
> -      ODR types and interoperable non-ODR types.  */
> -      gcc_checking_assert (type_streaming_finished
> -                        && TYPE_MAIN_VARIANT (t) == t);
> -      slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash,
> -                                    NO_INSERT);
> +      /* Anonymous namespace types never conflict with non-C++ types.  */
> +      if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
> +     slot = NULL;
> +      else
> +     {
> +       /* Here we rely on fact that all non-ODR types was inserted into
> +          canonical type hash and thus we can safely detect conflicts between
> +          ODR types and interoperable non-ODR types.  */
> +       gcc_checking_assert (type_streaming_finished
> +                            && TYPE_MAIN_VARIANT (t) == t);
> +       slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash,
> +                                        NO_INSERT);
> +     }
>        if (slot && !TYPE_CXX_ODR_P (*(tree *)slot))
>       {
>         tree nonodr = *(tree *)slot;
> @@ -1640,11 +1646,14 @@ unify_scc (class data_in *data_in, unsig
>        tree t = streamer_tree_cache_get_tree (cache, from + i);
>        scc->entries[i] = t;
>        /* Do not merge SCCs with local entities inside them.  Also do
> -      not merge TRANSLATION_UNIT_DECLs.  */
> +      not merge TRANSLATION_UNIT_DECLs and anonymous namespace types.  */
>        if (TREE_CODE (t) == TRANSLATION_UNIT_DECL
>         || (VAR_OR_FUNCTION_DECL_P (t)
>             && !(TREE_PUBLIC (t) || DECL_EXTERNAL (t)))
> -       || TREE_CODE (t) == LABEL_DECL)
> +       || TREE_CODE (t) == LABEL_DECL
> +       || (TYPE_P (t)
> +           && type_with_linkage_p (TYPE_MAIN_VARIANT (t))
> +           && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t))))
>       {
>         /* Avoid doing any work for these cases and do not worry to
>            record the SCCs for further merging.  */
> Index: testsuite/g++.dg/lto/alias-5_0.C
> ===================================================================
> --- testsuite/g++.dg/lto/alias-5_0.C  (nonexistent)
> +++ testsuite/g++.dg/lto/alias-5_0.C  (working copy)
> @@ -0,0 +1,35 @@
> +/* { dg-lto-do run } */
> +/* { dg-lto-options { { -O3 -flto } } } */
> +/* This testcase tests that anonymous namespaces in different TUs are treated
> +   as different types by LTO TBAA and that they never alias with structurally
> +   same C types.  */
> +namespace {
> +  __attribute__((used))
> +  struct a {int a;} *p,**ptr=&p;
> +};
> +void
> +set1()
> +{
> +  *ptr=0;
> +}
> +void
> +get1()
> +{
> +  if (!__builtin_constant_p (*ptr==0))
> +    __builtin_abort ();
> +}
> +extern void set2();
> +extern "C" void set3();
> +int n = 1;
> +int
> +main()
> +{
> +  for (int i = 0; i < n; i++)
> +    {
> +      set1();
> +      set2();
> +      set3();
> +      get1();
> +    }
> +  return 0;
> +}
> Index: testsuite/g++.dg/lto/alias-5_1.C
> ===================================================================
> --- testsuite/g++.dg/lto/alias-5_1.C  (nonexistent)
> +++ testsuite/g++.dg/lto/alias-5_1.C  (working copy)
> @@ -0,0 +1,9 @@
> +namespace {
> +  __attribute__((used))
> +  struct a {int a;} *p,**ptr=&p,q;
> +};
> +void
> +set2()
> +{
> +  *ptr=&q;
> +}
> Index: testsuite/g++.dg/lto/alias-5_2.c
> ===================================================================
> --- testsuite/g++.dg/lto/alias-5_2.c  (nonexistent)
> +++ testsuite/g++.dg/lto/alias-5_2.c  (working copy)
> @@ -0,0 +1,7 @@
> +  __attribute__((used))
> +  struct a {int a;} *p,**ptr=&p,q;
> +void
> +set3()
> +{
> +  *ptr=&q;
> +}
> 

-- 
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