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 <[email protected]>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB
21284 (AG Nuernberg)