Hi, while looking into the earlier bug I noticed that type_hash_canon is used to avoid producing type duplicates. The type is however created, then looked up in the cache and if it exists it is never used. The function takes care to remove the code found memory stats but never actually free it. I suppose it is artifact of conversion from obstack to ggc. We produce a lot of type duplicates this way that is not very cool.
It always bit bothered me that unify_scc does not update the statistics so this patch introduces free_node that can be used to free given tree node. Bootstrapped/regtested x86_64-linux, OK? * tree.c (free_node): New function. (type_hash_canon): Use it. * tree.h (free_node): Declare. * lto.c (unify_scc): Use free_node. Index: tree.c =================================================================== --- tree.c (revision 230718) +++ tree.c (working copy) @@ -1103,6 +1103,27 @@ make_node_stat (enum tree_code code MEM_ return t; } + +/* Free tree node. */ + +void +free_node (tree node) +{ + enum tree_code code = TREE_CODE (node); + if (GATHER_STATISTICS) + { + tree_code_counts[(int) TREE_CODE (node)]--; + tree_node_counts[(int) t_kind]--; + tree_node_sizes[(int) t_kind] -= tree_code_size (TREE_CODE (node)); + } + if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) + vec_free (CONSTRUCTOR_ELTS (node)); + else if (code == BLOCK) + vec_free (BLOCK_NONLOCALIZED_VARS (node)); + else if (code == TREE_BINFO) + vec_free (BINFO_BASE_ACCESSES (node)); + ggc_free (node); +} /* Return a new node with the same contents as NODE except that its TREE_CHAIN, if it has one, is zero and it has a fresh uid. */ @@ -7100,12 +7123,7 @@ type_hash_canon (unsigned int hashcode, { tree t1 = ((type_hash *) *loc)->type; gcc_assert (TYPE_MAIN_VARIANT (t1) == t1); - if (GATHER_STATISTICS) - { - tree_code_counts[(int) TREE_CODE (type)]--; - tree_node_counts[(int) t_kind]--; - tree_node_sizes[(int) t_kind] -= sizeof (struct tree_type_non_common); - } + free_node (type); return t1; } else Index: tree.h =================================================================== --- tree.h (revision 230718) +++ tree.h (working copy) @@ -3763,6 +3763,10 @@ extern int allocate_decl_uid (void); extern tree make_node_stat (enum tree_code MEM_STAT_DECL); #define make_node(t) make_node_stat (t MEM_STAT_INFO) +/* Free tree node. */ + +extern void free_node (tree); + /* Make a copy of a node, with all the same contents. */ extern tree copy_node_stat (tree MEM_STAT_DECL); Index: lto/lto.c =================================================================== --- lto/lto.c (revision 230718) +++ lto/lto.c (working copy) @@ -1623,13 +1622,9 @@ unify_scc (struct data_in *data_in, unsi data_in->location_cache.revert_location_cache (); for (unsigned i = 0; i < len; ++i) { - enum tree_code code; if (TYPE_P (scc->entries[i])) num_merged_types++; - code = TREE_CODE (scc->entries[i]); - if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) - vec_free (CONSTRUCTOR_ELTS (scc->entries[i])); - ggc_free (scc->entries[i]); + free_node (scc->entries[i]); } break;