Hi,
this is cleaner version of the patch.  During weekend I did some tests with
firefox, libreoffice and gcc builds and it seems to work well. For firefox
it reaches almost linear scalability of the ltrans files (they are 1.9GB,
after increasing number of partitions to 128 they grow to 2GB that looks
quite acceptable. Resulting .s and libxul binary are actually bigger than
that when debug info is enabled).

So if that works in other cases, I will increas lto-partitions and probably
declare it good enough for this stage1 and will try to move to other things.

Concerning two things we have discussed, I am keeping recursion to
free_lang_data_in_type for now as reordering seems just temporary solution
until we do more freeing from both types and decl (eventually I want to free
subtypes of function types that also brings a lot of context. On Firefox that
acount another 5% of stream data volume).

One option would be to change the walking order for this stage1 and worry
about it next stage1.  Other option would be to simply push the newly created
types to the fld queues.

I also did not share fld_type_variant_equal_p with check_base_type since
that one checks also context that we do not want to do. Probably could be
cleaned up incrementally - I wonder why Objective-C needs it.

I looked into enabling free_lang_data by default.  My main problem there is
what to do with late langhooks, say one for variably_modified_type_p.
I suppose we could just declare middle-end self contained wrt analyzing
IL and try to disable them one by one after free lang data was run?

What we however want to do about late warnings? Do we have some idea how
many are those and what kind of % modifiers needs to be printed correctly?
Say late warning wants to print a type, how we are going to do that?

Boostrapped/regtested x86_64-linux.

Honza
        * tree.c (free_lang_data_in_type): Forward declare.
        (fld_type_variant_equal_p): New function.
        (fld_type_variant): New function
        (fld_incomplete_types): New hash.
        (fld_incomplete_type_of): New function
        (fld_simplfied-type): New function.
        (free_lang_data_in_decl): New.
Index: tree.c
===================================================================
--- tree.c      (revision 265573)
+++ tree.c      (working copy)
@@ -265,6 +265,8 @@
 static void print_debug_expr_statistics (void);
 static void print_value_expr_statistics (void);
 
+static void free_lang_data_in_type (tree type);
+
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 
@@ -5038,6 +5041,115 @@
     SET_EXPR_LOCATION (t, loc);
 }
 
+/* Do same comparsion as check_qualified_type skipping lang part of type
+   and be more permissive about type names: we only care that names are
+   same (for diagnostics) and that ODR names are the same.  */
+
+static bool
+fld_type_variant_equal_p (tree t, tree v)
+{
+  if (TYPE_QUALS (t) != TYPE_QUALS (v)
+      || TYPE_NAME (t) != TYPE_NAME (v)
+      || TYPE_ALIGN (t) != TYPE_ALIGN (v)
+      || !attribute_list_equal (TYPE_ATTRIBUTES (t),
+                               TYPE_ATTRIBUTES (v)))
+    return false;
+
+  return true;
+}
+
+/* Find variant of FIRST that match T and create new one if necessary.  */
+
+static tree
+fld_type_variant (tree first, tree t)
+{
+  if (first == TYPE_MAIN_VARIANT (t))
+    return t;
+  for (tree v = first; v; v = TYPE_NEXT_VARIANT (v))
+    if (fld_type_variant_equal_p (t, v))
+      return v;
+  tree v = build_variant_type_copy (first);
+  TYPE_READONLY (v) = TYPE_READONLY (t);
+  TYPE_VOLATILE (v) = TYPE_VOLATILE (t);
+  TYPE_ATOMIC (v) = TYPE_ATOMIC (t);
+  TYPE_RESTRICT (v) = TYPE_RESTRICT (t);
+  TYPE_ADDR_SPACE (v) = TYPE_ADDR_SPACE (t);
+  TYPE_NAME (v) = TYPE_NAME (t);
+  TYPE_ATTRIBUTES (v) = TYPE_ATTRIBUTES (t);
+  return v;
+}
+
+/* Map complete types to incomplete types.  */
+
+static hash_map<tree, tree> *fld_incomplete_types;
+
+/* For T being aggregate type try to turn it into a incomplete variant.
+   Return T if no simplification is possible.  */
+
+static tree
+fld_incomplete_type_of (tree t)
+{
+  if (!t)
+    return NULL;
+  if (POINTER_TYPE_P (t))
+    {
+      tree t2 = fld_incomplete_type_of (TREE_TYPE (t));
+      if (t2 != TREE_TYPE (t))
+       {
+         tree first;
+         if (TREE_CODE (t) == POINTER_TYPE)
+           first = build_pointer_type_for_mode (t2, TYPE_MODE (t),
+                                               TYPE_REF_CAN_ALIAS_ALL (t));
+         else
+           first = build_reference_type_for_mode (t2, TYPE_MODE (t),
+                                               TYPE_REF_CAN_ALIAS_ALL (t));
+         return fld_type_variant (first, t);
+       }
+      return t;
+    }
+  if (!RECORD_OR_UNION_TYPE_P (t) || !COMPLETE_TYPE_P (t))
+    return t;
+  if (TYPE_MAIN_VARIANT (t) == t)
+    {
+      bool existed;
+      tree &copy
+        = fld_incomplete_types->get_or_insert (t, &existed);
+
+      if (!existed)
+       {
+         copy = build_distinct_type_copy (t);
+
+         /* It is possible type was not seen by free_lang_data yet.  */
+         free_lang_data_in_type (copy);
+         TYPE_SIZE (copy) = NULL;
+         SET_TYPE_MODE (copy, VOIDmode);
+         SET_TYPE_ALIGN (copy, BITS_PER_UNIT);
+         TYPE_SIZE_UNIT (copy) = NULL;
+         if (AGGREGATE_TYPE_P (t))
+           {
+             TYPE_FIELDS (copy) = NULL;
+             TYPE_BINFO (copy) = NULL;
+           }
+         else
+           TYPE_VALUES (copy) = NULL;
+       }
+      return copy;
+   }
+  return (fld_type_variant
+           (fld_incomplete_type_of (TYPE_MAIN_VARIANT (t)), t));
+}
+
+/* Simplify type T for scenarios where we do not need complete pointer
+   types.  */
+
+static tree
+fld_simplified_type (tree t)
+{
+  if (t && POINTER_TYPE_P (t))
+    return fld_incomplete_type_of (t);
+  return t;
+}
+
 /* Reset the expression *EXPR_P, a size or position.
 
    ??? We could reset all non-constant sizes or positions.  But it's cheap
@@ -5354,9 +5470,12 @@
       DECL_VISIBILITY_SPECIFIED (decl) = 0;
       DECL_INITIAL (decl) = NULL_TREE;
       DECL_ORIGINAL_TYPE (decl) = NULL_TREE;
     }
   else if (TREE_CODE (decl) == FIELD_DECL)
-    DECL_INITIAL (decl) = NULL_TREE;
+    {
+      TREE_TYPE (decl) = fld_simplified_type (TREE_TYPE (decl));
+      DECL_INITIAL (decl) = NULL_TREE;
+    }
   else if (TREE_CODE (decl) == TRANSLATION_UNIT_DECL
            && DECL_INITIAL (decl)
            && TREE_CODE (DECL_INITIAL (decl)) == BLOCK)
@@ -5866,6 +5989,8 @@
       || (!flag_generate_lto && !flag_generate_offload))
     return 0;
 
+  fld_incomplete_types = new hash_map<tree, tree>;
+
   /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one.  */
   if (vec_safe_is_empty (all_translation_units))
     build_translation_unit_decl (NULL_TREE);

Reply via email to