Hi, this patch simplifies function types. For GCC it cuts number of type duplicates to half (to about 500 duplicates). I need to analyze the remaining ones, but i think they are mostly caused by mixing up complete/incomplete enums and arrays of pointers that should be last necessary changes to avoid duplicated ODR types at the GCC bootstrap.
We are now down from 650MB to 450MB of ltrans files since my last report https://gcc.gnu.org/ml/gcc-patches/2018-10/msg02034.html phase opt and generate : 39.37 ( 78%) 0.87 ( 13%) 40.27 ( 70%) 411110 kB ( 29%) phase stream in : 10.34 ( 20%) 0.40 ( 6%) 10.74 ( 19%) 980729 kB ( 70%) ipa function summary : 0.20 ( 0%) 0.05 ( 1%) 0.24 ( 0%) 67974 kB ( 5%) ipa cp : 0.85 ( 2%) 0.05 ( 1%) 0.93 ( 2%) 126839 kB ( 9%) ipa inlining heuristics : 30.71 ( 61%) 0.08 ( 1%) 30.81 ( 53%) 119761 kB ( 9%) lto stream inflate : 2.41 ( 5%) 0.20 ( 3%) 2.51 ( 4%) 0 kB ( 0%) ipa lto gimple in : 1.21 ( 2%) 0.50 ( 8%) 1.65 ( 3%) 201610 kB ( 14%) ipa lto gimple out : 0.04 ( 0%) 0.03 ( 0%) 0.07 ( 0%) 0 kB ( 0%) whopr partitioning : 1.31 ( 3%) 0.01 ( 0%) 1.32 ( 2%) 5338 kB ( 0%) ipa icf : 2.93 ( 6%) 0.07 ( 1%) 3.04 ( 5%) 12830 kB ( 1%) TOTAL : 50.54 6.60 57.72 1393898 kB Thus even relatively small improvements in type merging still translate to large improvements in overal ltrans stream size, because types keeps dupicating everything else. lto-bootstrapped/regtested x86_64-linux before some last minute change. Re-testing, OK if it passes? Honza * tree.c (free_lang_data_in_type): Add fld parameter; simplify return and parameter types of function and method types. (free_lang_data_in_cgraph): Update. Index: tree.c =================================================================== --- tree.c (revision 265848) +++ tree.c (working copy) @@ -5261,7 +5261,7 @@ free_lang_data_in_binfo (tree binfo) /* Reset all language specific information still present in TYPE. */ static void -free_lang_data_in_type (tree type) +free_lang_data_in_type (tree type, struct free_lang_data_d *fld) { gcc_assert (TYPE_P (type)); @@ -5280,6 +5280,7 @@ free_lang_data_in_type (tree type) if (TREE_CODE (type) == FUNCTION_TYPE) { + TREE_TYPE (type) = fld_simplified_type (TREE_TYPE (type), fld); /* Remove the const and volatile qualifiers from arguments. The C++ front end removes them, but the C front end does not, leading to false ODR violation errors when merging two @@ -5287,6 +5288,7 @@ free_lang_data_in_type (tree type) different front ends. */ for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p)) { + TREE_VALUE (p) = fld_simplified_type (TREE_VALUE (p), fld); tree arg_type = TREE_VALUE (p); if (TYPE_READONLY (arg_type) || TYPE_VOLATILE (arg_type)) @@ -5295,16 +5297,22 @@ free_lang_data_in_type (tree type) & ~TYPE_QUAL_CONST & ~TYPE_QUAL_VOLATILE; TREE_VALUE (p) = build_qualified_type (arg_type, quals); - free_lang_data_in_type (TREE_VALUE (p)); + free_lang_data_in_type (TREE_VALUE (p), fld); } /* C++ FE uses TREE_PURPOSE to store initial values. */ TREE_PURPOSE (p) = NULL; } } else if (TREE_CODE (type) == METHOD_TYPE) - for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p)) - /* C++ FE uses TREE_PURPOSE to store initial values. */ - TREE_PURPOSE (p) = NULL; + { + TREE_TYPE (type) = fld_simplified_type (TREE_TYPE (type), fld); + for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p)) + { + /* C++ FE uses TREE_PURPOSE to store initial values. */ + TREE_VALUE (p) = fld_simplified_type (TREE_VALUE (p), fld); + TREE_PURPOSE (p) = NULL; + } + } else if (RECORD_OR_UNION_TYPE_P (type)) { /* Remove members that are not FIELD_DECLs from the field list @@ -5985,7 +5994,7 @@ free_lang_data_in_cgraph (void) /* Traverse every type found freeing its language data. */ FOR_EACH_VEC_ELT (fld.types, i, t) - free_lang_data_in_type (t); + free_lang_data_in_type (t, &fld); if (flag_checking) { FOR_EACH_VEC_ELT (fld.types, i, t)