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));
          add_tree_to_fld_list (first, fld);
          return fld_type_variant (first, t, fld);
        }

Reply via email to