2011-05-20 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 20 May 2011 09:35:03 +0000 (09:35 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 20 May 2011 09:35:03 +0000 (09:35 +0000)
* gimple.c (gimple_register_type_1): Do not fiddle with
main-variant or pointer-to chains.  Delay all fixup to
uniquify_nodes.

lto/
* lto.c (lto_ft_common): Remove pointer-to chain teardown.
(lto_ft_type): Move main-variant and pointer-to chain building ...
(uniquify_nodes): ... here.  Compute TYPE_CANONICAL also here,
in a separate final loop.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@173938 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gimple.c
gcc/lto/ChangeLog
gcc/lto/lto.c

index 0cdc8a5..b89b3f9 100644 (file)
@@ -1,3 +1,9 @@
+2011-05-20  Richard Guenther  <rguenther@suse.de>
+
+       * gimple.c (gimple_register_type_1): Do not fiddle with
+       main-variant or pointer-to chains.  Delay all fixup to
+       uniquify_nodes.
+
 2011-05-19  Quentin Neill  <quentin.neill@amd.com>
 
        * config/i386/sse.md (fma4_fmsubadd): Use <ssemodesuffix>.
index e30c7ad..5b03e15 100644 (file)
@@ -4476,7 +4476,6 @@ gimple_register_type_1 (tree t, bool registering_mv)
 {
   void **slot;
   gimple_type_leader_entry *leader;
-  tree mv_leader;
 
   /* If we registered this type before return the cached result.  */
   leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE];
@@ -4495,91 +4494,23 @@ gimple_register_type_1 (tree t, bool registering_mv)
      case we do not care for the main variant leader.  */
   if (!registering_mv
       && TYPE_MAIN_VARIANT (t) != t)
-    mv_leader = gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true);
-  else
-    mv_leader = t;
+    gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true);
 
+  /* See if we already have an equivalent type registered.  */
   slot = htab_find_slot (gimple_types, t, INSERT);
   if (*slot
       && *(tree *)slot != t)
     {
       tree new_type = (tree) *((tree *) slot);
-
-      /* Do not merge types with different addressability.  */
-      gcc_assert (TREE_ADDRESSABLE (t) == TREE_ADDRESSABLE (new_type));
-
-      /* If t is not its main variant then make t unreachable from its
-        main variant list.  Otherwise we'd queue up a lot of duplicates
-        there.  */
-      if (t != TYPE_MAIN_VARIANT (t))
-       {
-         tree tem = TYPE_MAIN_VARIANT (t);
-         while (tem && TYPE_NEXT_VARIANT (tem) != t)
-           tem = TYPE_NEXT_VARIANT (tem);
-         if (tem)
-           TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
-         TYPE_NEXT_VARIANT (t) = NULL_TREE;
-       }
-
-      /* If we are a pointer then remove us from the pointer-to or
-        reference-to chain.  Otherwise we'd queue up a lot of duplicates
-        there.  */
-      if (TREE_CODE (t) == POINTER_TYPE)
-       {
-         if (TYPE_POINTER_TO (TREE_TYPE (t)) == t)
-           TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t);
-         else
-           {
-             tree tem = TYPE_POINTER_TO (TREE_TYPE (t));
-             while (tem && TYPE_NEXT_PTR_TO (tem) != t)
-               tem = TYPE_NEXT_PTR_TO (tem);
-             if (tem)
-               TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t);
-           }
-         TYPE_NEXT_PTR_TO (t) = NULL_TREE;
-       }
-      else if (TREE_CODE (t) == REFERENCE_TYPE)
-       {
-         if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t)
-           TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t);
-         else
-           {
-             tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t));
-             while (tem && TYPE_NEXT_REF_TO (tem) != t)
-               tem = TYPE_NEXT_REF_TO (tem);
-             if (tem)
-               TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t);
-           }
-         TYPE_NEXT_REF_TO (t) = NULL_TREE;
-       }
-
       leader->type = t;
       leader->leader = new_type;
-      t = new_type;
-    }
-  else
-    {
-      leader->type = t;
-      leader->leader = t;
-      /* We're the type leader.  Make our TYPE_MAIN_VARIANT valid.  */
-      if (TYPE_MAIN_VARIANT (t) != t
-         && TYPE_MAIN_VARIANT (t) != mv_leader)
-       {
-         /* Remove us from our main variant list as we are not the variant
-            leader and the variant leader will change.  */
-         tree tem = TYPE_MAIN_VARIANT (t);
-         while (tem && TYPE_NEXT_VARIANT (tem) != t)
-           tem = TYPE_NEXT_VARIANT (tem);
-         if (tem)
-           TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
-         TYPE_NEXT_VARIANT (t) = NULL_TREE;
-         /* Adjust our main variant.  Linking us into its variant list
-            will happen at fixup time.  */
-         TYPE_MAIN_VARIANT (t) = mv_leader;
-       }
-      *slot = (void *) t;
+      return new_type;
     }
 
+  /* If not, insert it to the cache and the hash.  */
+  leader->type = t;
+  leader->leader = t;
+  *slot = (void *) t;
   return t;
 }
 
index 79e0146..893997a 100644 (file)
@@ -1,3 +1,10 @@
+2011-05-20  Richard Guenther  <rguenther@suse.de>
+
+       * lto.c (lto_ft_common): Remove pointer-to chain teardown.
+       (lto_ft_type): Move main-variant and pointer-to chain building ...
+       (uniquify_nodes): ... here.  Compute TYPE_CANONICAL also here,
+       in a separate final loop.
+
 2011-05-19  Richard Guenther  <rguenther@suse.de>
 
        * lto.c (uniquify_nodes): First register all types before
index 67e080f..d64ba18 100644 (file)
@@ -259,45 +259,9 @@ static void lto_fixup_types (tree);
 static void
 lto_ft_common (tree t)
 {
-  /* The following re-creates the TYPE_REFERENCE_TO and TYPE_POINTER_TO
-     lists.  We do not stream TYPE_REFERENCE_TO, TYPE_POINTER_TO or
-     TYPE_NEXT_PTR_TO and TYPE_NEXT_REF_TO.
-     First remove us from any pointer list we are on.  */
-  if (TREE_CODE (t) == POINTER_TYPE)
-    {
-      if (TYPE_POINTER_TO (TREE_TYPE (t)) == t)
-       TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t);
-      else
-       {
-         tree tem = TYPE_POINTER_TO (TREE_TYPE (t));
-         while (tem && TYPE_NEXT_PTR_TO (tem) != t)
-           tem = TYPE_NEXT_PTR_TO (tem);
-         if (tem)
-           TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t);
-       }
-      TYPE_NEXT_PTR_TO (t) = NULL_TREE;
-    }
-  else if (TREE_CODE (t) == REFERENCE_TYPE)
-    {
-      if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t)
-       TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t);
-      else
-       {
-         tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t));
-         while (tem && TYPE_NEXT_REF_TO (tem) != t)
-           tem = TYPE_NEXT_REF_TO (tem);
-         if (tem)
-           TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t);
-       }
-      TYPE_NEXT_REF_TO (t) = NULL_TREE;
-    }
-
   /* Fixup our type.  */
   LTO_FIXUP_TREE (TREE_TYPE (t));
 
-  /* Second put us on the list of pointers of the new pointed-to type
-     if we are a main variant.  This is done in lto_ft_type after
-     fixing up our main variant.  */
   LTO_FIXUP_TREE (TREE_CHAIN (t));
 }
 
@@ -374,8 +338,6 @@ lto_ft_field_decl (tree t)
 static void
 lto_ft_type (tree t)
 {
-  tree tem, mv;
-
   lto_ft_common (t);
   LTO_FIXUP_TREE (TYPE_CACHED_VALUES (t));
   LTO_FIXUP_TREE (TYPE_SIZE (t));
@@ -392,67 +354,6 @@ lto_ft_type (tree t)
   LTO_FIXUP_TREE (t->type_non_common.binfo);
 
   LTO_FIXUP_TREE (TYPE_CONTEXT (t));
-
-  /* Compute the canonical type of t and fix that up.  From this point
-     there are no longer any types with TYPE_STRUCTURAL_EQUALITY_P
-     and its type-based alias problems.  */
-  if (!TYPE_CANONICAL (t))
-    {
-      TYPE_CANONICAL (t) = gimple_register_canonical_type (t);
-      LTO_FIXUP_TREE (TYPE_CANONICAL (t));
-    }
-
-  /* The following re-creates proper variant lists while fixing up
-     the variant leaders.  We do not stream TYPE_NEXT_VARIANT so the
-     variant list state before fixup is broken.  */
-
-  /* Remove us from our main variant list if we are not the variant leader.  */
-  if (TYPE_MAIN_VARIANT (t) != t)
-    {
-      tem = TYPE_MAIN_VARIANT (t);
-      while (tem && TYPE_NEXT_VARIANT (tem) != t)
-       tem = TYPE_NEXT_VARIANT (tem);
-      if (tem)
-       TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
-      TYPE_NEXT_VARIANT (t) = NULL_TREE;
-    }
-
-  /* Query our new main variant.  */
-  mv = gimple_register_type (TYPE_MAIN_VARIANT (t));
-
-  /* If we were the variant leader and we get replaced ourselves drop
-     all variants from our list.  */
-  if (TYPE_MAIN_VARIANT (t) == t
-      && mv != t)
-    {
-      tem = t;
-      while (tem)
-       {
-         tree tem2 = TYPE_NEXT_VARIANT (tem);
-         TYPE_NEXT_VARIANT (tem) = NULL_TREE;
-         tem = tem2;
-       }
-    }
-
-  /* Finally adjust our main variant and fix it up.  */
-  TYPE_MAIN_VARIANT (t) = mv;
-  LTO_FIXUP_TREE (TYPE_MAIN_VARIANT (t));
-
-  /* As the second step of reconstructing the pointer chains put us
-     on the list of pointers of the new pointed-to type
-     if we are a main variant.  See lto_ft_common for the first step.  */
-  if (TREE_CODE (t) == POINTER_TYPE
-      && TYPE_MAIN_VARIANT (t) == t)
-    {
-      TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t));
-      TYPE_POINTER_TO (TREE_TYPE (t)) = t;
-    }
-  else if (TREE_CODE (t) == REFERENCE_TYPE
-          && TYPE_MAIN_VARIANT (t) == t)
-    {
-      TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t));
-      TYPE_REFERENCE_TO (TREE_TYPE (t)) = t;
-    }
 }
 
 /* Fix up fields of a BINFO T.  */
@@ -608,19 +509,21 @@ uniquify_nodes (struct data_in *data_in, unsigned from)
 
   /* Go backwards because childs streamed for the first time come
      as part of their parents, and hence are created after them.  */
+
+  /* First register all types in the cache.
+     This makes sure to have the original structure in the type cycles
+     when registering them and computing hashes.  */
   for (i = len; i-- > from;)
     {
       tree t = VEC_index (tree, cache->nodes, i);
-      if (!t)
+      if (!t
+         || !TYPE_P (t))
        continue;
 
-      /* Now try to find a canonical variant of T itself.  */
-      if (TYPE_P (t))
-       gimple_register_type (t);
+      gimple_register_type (t);
     }
 
-  /* Go backwards because childs streamed for the first time come
-     as part of their parents, and hence are created after them.  */
+  /* Second fixup all trees in the new cache entries.  */
   for (i = len; i-- > from;)
     {
       tree t = VEC_index (tree, cache->nodes, i);
@@ -631,43 +534,103 @@ uniquify_nodes (struct data_in *data_in, unsigned from)
       /* First fixup the fields of T.  */
       lto_fixup_types (t);
 
+      if (!TYPE_P (t))
+       continue;
+
       /* Now try to find a canonical variant of T itself.  */
-      if (TYPE_P (t))
+      t = gimple_register_type (t);
+
+      if (t == oldt)
        {
-         t = gimple_register_type (t);
-         if (t == oldt
-             && TYPE_MAIN_VARIANT (t) != t)
+         /* The following re-creates proper variant lists while fixing up
+            the variant leaders.  We do not stream TYPE_NEXT_VARIANT so the
+            variant list state before fixup is broken.  */
+         tree tem, mv;
+
+         /* Remove us from our main variant list if we are not the
+            variant leader.  */
+         if (TYPE_MAIN_VARIANT (t) != t)
            {
-             /* If this is its own type, link it into the variant chain.  */
-             TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t));
-             TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)) = t;
+             tem = TYPE_MAIN_VARIANT (t);
+             while (tem && TYPE_NEXT_VARIANT (tem) != t)
+               tem = TYPE_NEXT_VARIANT (tem);
+             if (tem)
+               TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
+             TYPE_NEXT_VARIANT (t) = NULL_TREE;
            }
-       }
-      if (t != oldt)
-       {
-         if (RECORD_OR_UNION_TYPE_P (t))
+
+         /* Query our new main variant.  */
+         mv = gimple_register_type (TYPE_MAIN_VARIANT (t));
+
+         /* If we were the variant leader and we get replaced ourselves drop
+            all variants from our list.  */
+         if (TYPE_MAIN_VARIANT (t) == t
+             && mv != t)
            {
-             tree f1, f2;
-             if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt))
-               for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt);
-                    f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
-                 {
-                   unsigned ix;
-                   gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2));
-                   if (!lto_streamer_cache_lookup (cache, f2, &ix))
-                     gcc_unreachable ();
-                   /* If we're going to replace an element which we'd
-                      still visit in the next iterations, we wouldn't
-                      handle it, so do it here.  We do have to handle it
-                      even though the field_decl itself will be removed,
-                      as it could refer to e.g. integer_cst which we
-                      wouldn't reach via any other way, hence they
-                      (and their type) would stay uncollected.  */
-                   if (ix < i)
-                     lto_fixup_types (f2);
-                   lto_streamer_cache_insert_at (cache, f1, ix);
-                 }
+             tem = t;
+             while (tem)
+               {
+                 tree tem2 = TYPE_NEXT_VARIANT (tem);
+                 TYPE_NEXT_VARIANT (tem) = NULL_TREE;
+                 tem = tem2;
+               }
+           }
+
+         /* If we are not our own variant leader link us into our new leaders
+            variant list.  */
+         if (mv != t)
+           {
+             TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (mv);
+             TYPE_NEXT_VARIANT (mv) = t;
+           }
+
+         /* Finally adjust our main variant and fix it up.  */
+         TYPE_MAIN_VARIANT (t) = mv;
+
+         /* The following reconstructs the pointer chains
+            of the new pointed-to type if we are a main variant.  We do
+            not stream those so they are broken before fixup.  */
+         if (TREE_CODE (t) == POINTER_TYPE
+             && TYPE_MAIN_VARIANT (t) == t)
+           {
+             TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t));
+             TYPE_POINTER_TO (TREE_TYPE (t)) = t;
+           }
+         else if (TREE_CODE (t) == REFERENCE_TYPE
+                  && TYPE_MAIN_VARIANT (t) == t)
+           {
+             TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t));
+             TYPE_REFERENCE_TO (TREE_TYPE (t)) = t;
            }
+       }
+
+      else if (RECORD_OR_UNION_TYPE_P (t))
+       {
+         tree f1, f2;
+         if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt))
+           for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt);
+                f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+             {
+               unsigned ix;
+               gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2));
+               if (!lto_streamer_cache_lookup (cache, f2, &ix))
+                 gcc_unreachable ();
+               /* If we're going to replace an element which we'd
+                  still visit in the next iterations, we wouldn't
+                  handle it, so do it here.  We do have to handle it
+                  even though the field_decl itself will be removed,
+                  as it could refer to e.g. integer_cst which we
+                  wouldn't reach via any other way, hence they
+                  (and their type) would stay uncollected.  */
+               /* ???  We should rather make sure to replace all
+                  references to f2 with f1.  That means handling
+                  COMPONENT_REFs and CONSTRUCTOR elements in
+                  lto_fixup_types and special-case the field-decl
+                  operand handling.  */
+               if (ix < i)
+                 lto_fixup_types (f2);
+               lto_streamer_cache_insert_at (cache, f1, ix);
+             }
 
          /* If we found a tree that is equal to oldt replace it in the
             cache, so that further users (in the various LTO sections)
@@ -675,6 +638,22 @@ uniquify_nodes (struct data_in *data_in, unsigned from)
          lto_streamer_cache_insert_at (cache, t, i);
        }
     }
+
+  /* Finally compute the canonical type of t.  From this point
+     there are no longer any types with TYPE_STRUCTURAL_EQUALITY_P
+     and its type-based alias problems.  This step requires the
+     TYPE_POINTER_TO lists being present, so make sure it is done
+     last.  */
+  for (i = len; i-- > from;)
+    {
+      tree t = VEC_index (tree, cache->nodes, i);
+      if (!t
+         || !TYPE_P (t))
+       continue;
+
+      if (!TYPE_CANONICAL (t))
+       TYPE_CANONICAL (t) = gimple_register_canonical_type (t);
+    }
 }
 
 /* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.