Hi, this is updated version of the patch. As discussed on IRC, C++ has two different types of references (rvalue and normal). They have different canonical type, but this does not affect outcome of get_alias_set because it rebuilds the pointer/reference types from scratch.
The effect of this patch is to turn both into one type when pointer is reuilt that should be safe. So I simply relaxed the sanity check that type canonicals needs to be same for pointers. lto-bootstrapped/regtested x86_64-linux, plan to commit it shortly. Honza * gcc.dg/lto/tbaa-1.c: New testcase. * tree.c (fld_type_variant): Copy canonical type. (fld_incomplete_type_of): Check that canonical types looks sane; copy canonical type. (verify_type): Accept when incomplete type has complete canonical type. Index: testsuite/gcc.dg/lto/tbaa-1.c =================================================================== --- testsuite/gcc.dg/lto/tbaa-1.c (nonexistent) +++ testsuite/gcc.dg/lto/tbaa-1.c (working copy) @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -flto -fdump-tree-evrp" } */ +typedef struct rtx_def *rtx; +typedef struct cselib_val_struct +{ + union + { + } u; + struct elt_loc_list *locs; +} +cselib_val; +struct elt_loc_list +{ + struct elt_loc_list *next; + rtx loc; +}; +static int n_useless_values; +unchain_one_elt_loc_list (pl) + struct elt_loc_list **pl; +{ + struct elt_loc_list *l = *pl; + *pl = l->next; +} + +discard_useless_locs (x, info) + void **x; +{ + cselib_val *v = (cselib_val *) * x; + struct elt_loc_list **p = &v->locs; + int had_locs = v->locs != 0; + while (*p) + { + unchain_one_elt_loc_list (p); + p = &(*p)->next; + } + if (had_locs && v->locs == 0) + { + n_useless_values++; + } +} +/* { dg-final { scan-tree-dump-times "n_useless_values" 2 "evrp" } } */ Index: tree.c =================================================================== --- tree.c (revision 265807) +++ tree.c (working copy) @@ -5118,6 +5118,7 @@ fld_type_variant (tree first, tree t, st TYPE_ADDR_SPACE (v) = TYPE_ADDR_SPACE (t); TYPE_NAME (v) = TYPE_NAME (t); TYPE_ATTRIBUTES (v) = TYPE_ATTRIBUTES (t); + TYPE_CANONICAL (v) = TYPE_CANONICAL (t); add_tree_to_fld_list (v, fld); return v; } @@ -5146,6 +5147,8 @@ fld_incomplete_type_of (tree t, struct f else first = build_reference_type_for_mode (t2, TYPE_MODE (t), TYPE_REF_CAN_ALIAS_ALL (t)); + gcc_assert (TYPE_CANONICAL (t2) != t2 + && TYPE_CANONICAL (t2) == TYPE_CANONICAL (TREE_TYPE (t))); add_tree_to_fld_list (first, fld); return fld_type_variant (first, t, fld); } @@ -5169,6 +5174,7 @@ fld_incomplete_type_of (tree t, struct f SET_TYPE_MODE (copy, VOIDmode); SET_TYPE_ALIGN (copy, BITS_PER_UNIT); TYPE_SIZE_UNIT (copy) = NULL; + TYPE_CANONICAL (copy) = TYPE_CANONICAL (t); if (AGGREGATE_TYPE_P (t)) { TYPE_FIELDS (copy) = NULL; @@ -13880,7 +13893,8 @@ verify_type (const_tree t) with variably sized arrays because their sizes possibly gimplified to different variables. */ && !variably_modified_type_p (ct, NULL) - && !gimple_canonical_types_compatible_p (t, ct, false)) + && !gimple_canonical_types_compatible_p (t, ct, false) + && COMPLETE_TYPE_P (t)) { error ("TYPE_CANONICAL is not compatible"); debug_tree (ct);