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 © + = 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);