On Mon, 5 Nov 2018, Jan Hubicka wrote: > Hi, > this patch fixes the miscompare I introduced to spec2006 GCC benchmark > when build with LTO. > The problem is that fld_incomplete_type_of builds new pointer type to > incomplete type rather than complete but it ends up giving wrong type > canonical. > > This patch also improves TBAA with early opts because we do no lose info > by producing incomplete variants. > Note that build_pointer_type may return existing type and in that case I > overwrite TYPE_CANONICAL of it, but I believe it should be harmless > because all pointers to a given type should have canonicals constructed > same way. > > lto-bootstrapped/regtested x86_64-linux. > > Honza > * gcc.dg/lto/tbaa-1.c: New testcase. > * tree.c (fld_incomplete_type_of): Copy TYPE_CANONICAL while creating > pointer 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 265766) > +++ tree.c (working copy) > @@ -5146,6 +5146,7 @@ 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)); > + TYPE_CANONICAL (first) = TYPE_CANONICAL (TYPE_MAIN_VARIANT (t));
Hmm, this _should_ be a no-op. Can you, before that line, add gcc_assert (TYPE_CANONICAL (t2) != t2 && TYPE_CANONICAL (t2) == TYPE_CANONICAL (TREE_TYPE (t))); ? That is, the incomplete variant should share TYPE_CANONICAL with the pointed-to type and be _not_ the canonical leader (otherwise all other pointer types are bogus). > add_tree_to_fld_list (first, fld); > return fld_type_variant (first, t, fld); > } > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)