Hi,
this patch fixes profiledbootstrap failure with LTO enabled.
What happens is that alias_ptr_types_compatible_p relies on the
fact that alias sets are not refined from WPA to ltrans time:

    /* This function originally abstracts from simply comparing
       get_deref_alias_set so that we are sure this still computes
       the same result after LTO type merging is applied.
       When in LTO type merging is done we can actually do this compare.
    */
  if (in_lto_p)
    return get_deref_alias_set (t1) == get_deref_alias_set (t2);
  else
    return (TYPE_MAIN_VARIANT (TREE_TYPE (t1))
            == TYPE_MAIN_VARIANT (TREE_TYPE (t2)));

This conditional is confused - it pesimizes code with -fno-lto
for no good reason. I will fix that separately: we now have
lto_streaming_expected_p so I think it should read

 if (!lto_stremaing_expected_p () || flag_wpa)
   use alias sets
 else
   use main varaiants as conservative estimate.

(so if we ever get idea to ICF during incremental link or deduplicate in
early passes, things will work safely).  I will send separate patch on
this.


Not refining alias sets from WPA to ltrans time is a good invariant to
maintain and the canonical type hash behaves this way.  However I broke
this with the ODR logic.

Normally we define canonical types for C++ ODR types according to their
type names.  However to make ODR types compatible with C types we check
if structurally equivalent C type exists and if so, we ignore ODR
names giving up on the precision.

This however is not stable between WPA and ltrans since at ltrans the
type merging does not see as many types as WPA does.  To make this
consistent the patch makes WPA ODR_TYPE_P == 0 for ODR types that
conflicted with non-ODR type.

I had to drop one sanity check in ipa-utils.h (that I think is not very
important - I added it while introducing CXX_ODR_P machinery) and also
it now may happen that we query odr_based_tbaa_p before registering
first ODR type so we do not want to ICE here.
ODR type registration happens early to produce ODR violation warings.
Those are not done at ltrans, so dropping the registration is safe. The
type will still be added while computing the type inheritance graph if
needed for devirtualization (and late devirtualization is not very
useful anyway since it won't enable inlining).

Bootstrapped, regtested x86_64-linux, OK?
I think this should go to release branches after some soaking in
mainline too, even if we don't have direct reproducers.

Note that Martin implemented type checker to sanity check that alias
sets are never getting refined from compile to WPa and from WPA to
ltrans.  I recovered the patch and will play with it more.
I think we should eventually establish this (if alias sets are refined
from copmile time to WPA it is either wrong code issue or frontend alias
sets are not as good as they should be), but of course there are fun
issues.  My plan is to see if I can identify some wrong code bugs and
leave rest for early next stage1.

        PR bootstrap/97857
        * ipa-devirt.c (odr_based_tbaa_p): Do not ICE when
        odr_hash is not initialized.
        * ipa-utils.h (type_with_linkage_p): Do not sanity check
        CXX_ODR_P.
        * lto-common.c (gimple_register_canonical_type_1): Only
        register types with TYPE_CXX_ODR_P flag; sanity check that no
        conflict happens at ltrans time.
        * tree-streamer-out.c (pack_ts_type_common_value_fields): Set
        CXX_ODR_P according to the canonical type.
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 067ed5ba073..6e6df0b2af5 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -2032,6 +2032,8 @@ odr_based_tbaa_p (const_tree type)
 {
   if (!RECORD_OR_UNION_TYPE_P (type))
     return false;
+  if (!odr_hash)
+    return false;
   odr_type t = get_odr_type (const_cast <tree> (type), false);
   if (!t || !t->tbaa_enabled)
     return false;
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index 880e527c590..91571d8e82a 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -211,8 +211,6 @@ type_with_linkage_p (const_tree t)
   if (!TYPE_CONTEXT (t))
     return false;
 
-  gcc_checking_assert (TREE_CODE (t) == ENUMERAL_TYPE || TYPE_CXX_ODR_P (t));
-
   return true;
 }
 
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index 6944c469f89..0a3033c3695 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -415,8 +415,8 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
      that we can use to lookup structurally equivalent non-ODR type.
      In case we decide to treat type as unique ODR type we recompute hash based
      on name and let TBAA machinery know about our decision.  */
-  if (RECORD_OR_UNION_TYPE_P (t)
-      && odr_type_p (t) && !odr_type_violation_reported_p (t))
+  if (RECORD_OR_UNION_TYPE_P (t) && odr_type_p (t)
+      && TYPE_CXX_ODR_P (t) && !odr_type_violation_reported_p (t))
     {
       /* Anonymous namespace types never conflict with non-C++ types.  */
       if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
@@ -434,6 +434,7 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
       if (slot && !TYPE_CXX_ODR_P (*(tree *)slot))
        {
          tree nonodr = *(tree *)slot;
+         gcc_checking_assert (!flag_ltrans);
          if (symtab->dump_file)
            {
              fprintf (symtab->dump_file,
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index d7a451cfef4..9383cc4b903 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -343,7 +343,11 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, 
tree expr)
     {
       bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
       bp_pack_value (bp, TYPE_FINAL_P (expr), 1);
-      bp_pack_value (bp, TYPE_CXX_ODR_P (expr), 1);
+      /* alias_ptr_types_compatible_p relies on fact that during LTO
+         types do not get refined from WPA time to ltrans.  */
+      bp_pack_value (bp, flag_wpa && TYPE_CANONICAL (expr)
+                        ? TYPE_CXX_ODR_P (TYPE_CANONICAL (expr))
+                        : TYPE_CXX_ODR_P (expr), 1);
     }
   else if (TREE_CODE (expr) == ARRAY_TYPE)
     bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);

Reply via email to