Hi,
this patch fixes another problem where we manage to produce a variant of
variadic array that has different TYPE_SIZE (but an equivalent expression).
This happens because remap_type_1 blindly copies all expressions referred by
variadic type while for variants it may just reuse ones it earlier copied when
producing a copy of the main variant.

Bootstrapped/regtested x86_64-linux, lto-bootstrapped and tested on Firefox
build with the main variant checking patch in, comitted.

Honza

        * tree-inline.c (remap_type_1): Do not duplicate fields
        that are shared in between type and its main variant.
Index: tree-inline.c
===================================================================
--- tree-inline.c       (revision 212098)
+++ tree-inline.c       (working copy)
@@ -451,6 +451,8 @@ remap_type_1 (tree type, copy_body_data
   TYPE_POINTER_TO (new_tree) = NULL;
   TYPE_REFERENCE_TO (new_tree) = NULL;
 
+  /* Copy all types that may contain references to local variables; be sure to
+     preserve sharing in between type and its main variant when possible.  */
   switch (TREE_CODE (new_tree))
     {
     case INTEGER_TYPE:
@@ -458,40 +460,72 @@ remap_type_1 (tree type, copy_body_data
     case FIXED_POINT_TYPE:
     case ENUMERAL_TYPE:
     case BOOLEAN_TYPE:
-      t = TYPE_MIN_VALUE (new_tree);
-      if (t && TREE_CODE (t) != INTEGER_CST)
-        walk_tree (&TYPE_MIN_VALUE (new_tree), copy_tree_body_r, id, NULL);
-
-      t = TYPE_MAX_VALUE (new_tree);
-      if (t && TREE_CODE (t) != INTEGER_CST)
-        walk_tree (&TYPE_MAX_VALUE (new_tree), copy_tree_body_r, id, NULL);
+      if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
+       {
+         gcc_checking_assert (TYPE_MIN_VALUE (type) == TYPE_MIN_VALUE 
(TYPE_MAIN_VARIANT (type)));
+         gcc_checking_assert (TYPE_MAX_VALUE (type) == TYPE_MAX_VALUE 
(TYPE_MAIN_VARIANT (type)));
+
+         TYPE_MIN_VALUE (new_tree) = TYPE_MIN_VALUE (TYPE_MAIN_VARIANT 
(new_tree));
+         TYPE_MAX_VALUE (new_tree) = TYPE_MAX_VALUE (TYPE_MAIN_VARIANT 
(new_tree));
+       }
+      else
+       {
+         t = TYPE_MIN_VALUE (new_tree);
+         if (t && TREE_CODE (t) != INTEGER_CST)
+           walk_tree (&TYPE_MIN_VALUE (new_tree), copy_tree_body_r, id, NULL);
+
+         t = TYPE_MAX_VALUE (new_tree);
+         if (t && TREE_CODE (t) != INTEGER_CST)
+           walk_tree (&TYPE_MAX_VALUE (new_tree), copy_tree_body_r, id, NULL);
+       }
       return new_tree;
 
     case FUNCTION_TYPE:
-      TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
-      walk_tree (&TYPE_ARG_TYPES (new_tree), copy_tree_body_r, id, NULL);
+      if (TYPE_MAIN_VARIANT (new_tree) != new_tree
+         && TREE_TYPE (type) == TREE_TYPE (TYPE_MAIN_VARIANT (type)))
+       TREE_TYPE (new_tree) = TREE_TYPE (TYPE_MAIN_VARIANT (new_tree));
+      else
+        TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
+      if (TYPE_MAIN_VARIANT (new_tree) != new_tree
+         && TYPE_ARG_TYPES (type) == TYPE_ARG_TYPES (TYPE_MAIN_VARIANT (type)))
+       TYPE_ARG_TYPES (new_tree) = TYPE_ARG_TYPES (TYPE_MAIN_VARIANT 
(new_tree));
+      else
+        walk_tree (&TYPE_ARG_TYPES (new_tree), copy_tree_body_r, id, NULL);
       return new_tree;
 
     case ARRAY_TYPE:
-      TREE_TYPE (new_tree) = remap_type (TREE_TYPE (new_tree), id);
-      TYPE_DOMAIN (new_tree) = remap_type (TYPE_DOMAIN (new_tree), id);
+      if (TYPE_MAIN_VARIANT (new_tree) != new_tree
+         && TREE_TYPE (type) == TREE_TYPE (TYPE_MAIN_VARIANT (type)))
+       TREE_TYPE (new_tree) = TREE_TYPE (TYPE_MAIN_VARIANT (new_tree));
+
+      if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
+       {
+         gcc_checking_assert (TYPE_DOMAIN (type) == TYPE_DOMAIN 
(TYPE_MAIN_VARIANT (type)));
+         TYPE_DOMAIN (new_tree) = TYPE_DOMAIN (TYPE_MAIN_VARIANT (new_tree));
+       }
+      else
+       TYPE_DOMAIN (new_tree) = remap_type (TYPE_DOMAIN (new_tree), id);
       break;
 
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      {
-       tree f, nf = NULL;
-
-       for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f))
-         {
-           t = remap_decl (f, id);
-           DECL_CONTEXT (t) = new_tree;
-           DECL_CHAIN (t) = nf;
-           nf = t;
-         }
-       TYPE_FIELDS (new_tree) = nreverse (nf);
-      }
+      if (TYPE_MAIN_VARIANT (type) != type
+         && TYPE_FIELDS (type) == TYPE_FIELDS (TYPE_MAIN_VARIANT (type)))
+       TYPE_FIELDS (new_tree) = TYPE_FIELDS (TYPE_MAIN_VARIANT (new_tree));
+      else
+       {
+         tree f, nf = NULL;
+
+         for (f = TYPE_FIELDS (new_tree); f ; f = DECL_CHAIN (f))
+           {
+             t = remap_decl (f, id);
+             DECL_CONTEXT (t) = new_tree;
+             DECL_CHAIN (t) = nf;
+             nf = t;
+           }
+         TYPE_FIELDS (new_tree) = nreverse (nf);
+       }
       break;
 
     case OFFSET_TYPE:
@@ -500,8 +534,20 @@ remap_type_1 (tree type, copy_body_data
       gcc_unreachable ();
     }
 
-  walk_tree (&TYPE_SIZE (new_tree), copy_tree_body_r, id, NULL);
-  walk_tree (&TYPE_SIZE_UNIT (new_tree), copy_tree_body_r, id, NULL);
+  /* All variants of type share the same size, so use the already remaped 
data.  */
+  if (TYPE_MAIN_VARIANT (new_tree) != new_tree)
+    {
+      gcc_checking_assert (TYPE_SIZE (type) == TYPE_SIZE (TYPE_MAIN_VARIANT 
(type)));
+      gcc_checking_assert (TYPE_SIZE_UNIT (type) == TYPE_SIZE_UNIT 
(TYPE_MAIN_VARIANT (type)));
+
+      TYPE_SIZE (new_tree) = TYPE_SIZE (TYPE_MAIN_VARIANT (new_tree));
+      TYPE_SIZE_UNIT (new_tree) = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT 
(new_tree));
+    }
+  else
+    {
+      walk_tree (&TYPE_SIZE (new_tree), copy_tree_body_r, id, NULL);
+      walk_tree (&TYPE_SIZE_UNIT (new_tree), copy_tree_body_r, id, NULL);
+    }
 
   return new_tree;
 }

Reply via email to