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 <[email protected]>
SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany;
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG Nürnberg)