I've been looking at -fmem-report for a testcase from someone on the committee, and found a couple of low-hanging fruits.
The first patch doesn't change any allocation, just makes it so -fmem-report can see who's calling cxx_make_type. The second patch avoids creating a vector (which we then never freed) every time we push_to_top_level for doing template instantiation. This alone improved peak memory use by 30%. The third patch avoids redundantly creating level-lowered versions of TEMPLATE_TYPE_PARM, as we had already been doing for non-type parameters. This improved peak memory use by another 20%. Unfortunately, these don't affect the 80290 testcase significantly. Tested x86_64-pc-linux-gnu, applying to trunk.
commit 472c58fd2b3620b8461c59af58af056e53793d85 Author: Jason Merrill <ja...@redhat.com> Date: Wed Jun 20 15:01:26 2018 -0400 Let -fmem-report see callers of cxx_make_type. * lex.c (cxx_make_type): Add MEM_STAT_DECL. (make_class_type): Likewise. (cxx_make_type_hook): New. * cp-objcp-common.h (LANG_HOOKS_MAKE_TYPE): Use cxx_make_type_hook. diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 18ccc5bb6cf..6f08253f70f 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -34,6 +34,7 @@ extern tree cp_unit_size_without_reusable_padding (tree); extern tree cp_get_global_decls (); extern tree cp_pushdecl (tree); extern void cp_register_dumps (gcc::dump_manager *); +extern tree cxx_make_type_hook (tree_code); /* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c, @@ -126,7 +127,7 @@ extern void cp_register_dumps (gcc::dump_manager *); #define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN cp_type_quals #undef LANG_HOOKS_MAKE_TYPE -#define LANG_HOOKS_MAKE_TYPE cxx_make_type +#define LANG_HOOKS_MAKE_TYPE cxx_make_type_hook #undef LANG_HOOKS_TYPE_FOR_MODE #define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode #undef LANG_HOOKS_TYPE_FOR_SIZE diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ee9242f9313..0994377e5d7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6495,8 +6495,8 @@ extern void retrofit_lang_decl (tree); extern void fit_decomposition_lang_decl (tree, tree); extern tree copy_decl (tree CXX_MEM_STAT_INFO); extern tree copy_type (tree CXX_MEM_STAT_INFO); -extern tree cxx_make_type (enum tree_code); -extern tree make_class_type (enum tree_code); +extern tree cxx_make_type (enum tree_code CXX_MEM_STAT_INFO); +extern tree make_class_type (enum tree_code CXX_MEM_STAT_INFO); extern const char *get_identifier_kind_name (tree); extern void set_identifier_kind (tree, cp_identifier_kind); extern bool cxx_init (void); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index c47ae1dd5a1..bd5d507e97b 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -852,9 +852,9 @@ maybe_add_lang_type_raw (tree t) } tree -cxx_make_type (enum tree_code code) +cxx_make_type (enum tree_code code MEM_STAT_DECL) { - tree t = make_node (code); + tree t = make_node (code PASS_MEM_STAT); if (maybe_add_lang_type_raw (t)) { @@ -868,10 +868,18 @@ cxx_make_type (enum tree_code code) return t; } +/* A wrapper without the memory stats for LANG_HOOKS_MAKE_TYPE. */ + tree -make_class_type (enum tree_code code) +cxx_make_type_hook (enum tree_code code) { - tree t = cxx_make_type (code); + return cxx_make_type (code); +} + +tree +make_class_type (enum tree_code code MEM_STAT_DECL) +{ + tree t = cxx_make_type (code PASS_MEM_STAT); SET_CLASS_TYPE_P (t, 1); return t; }
commit 0fb3fe86c4e32f8f72976d78f8af5b5229868129 Author: Jason Merrill <ja...@redhat.com> Date: Wed Jun 20 12:05:34 2018 -0400 Reduce garbage from push_to_top_level. * name-lookup.c (do_push_to_top_level): Don't allocate current_lang_base. (do_pop_from_top_level): Release current_lang_base. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index ec001016d3e..a30c37428ad 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -6852,7 +6852,7 @@ do_push_to_top_level (void) scope_chain = s; current_function_decl = NULL_TREE; - vec_alloc (current_lang_base, 10); + current_lang_base = NULL; current_lang_name = lang_name_cplusplus; current_namespace = global_namespace; push_class_stack (); @@ -6872,7 +6872,7 @@ do_pop_from_top_level (void) invalidate_class_lookup_cache (); pop_class_stack (); - current_lang_base = 0; + release_tree_vector (current_lang_base); scope_chain = s->prev; FOR_EACH_VEC_SAFE_ELT (s->old_bindings, i, saved)
commit 93ca12c981968b5d545f1428d7b6d47557f207f7 Author: Jason Merrill <ja...@redhat.com> Date: Wed Jun 20 12:36:29 2018 -0400 * pt.c (tsubst) [TEMPLATE_TYPE_PARM]: Use TEMPLATE_PARM_DESCENDANTS. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c5433dc46ae..69e9479302e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -14472,6 +14472,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) && !PLACEHOLDER_TYPE_CONSTRAINTS (r)) /* Break infinite recursion when substituting the constraints of a constrained placeholder. */; + else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM + && !PLACEHOLDER_TYPE_CONSTRAINTS (t) + && !CLASS_PLACEHOLDER_TEMPLATE (t) + && (arg = TEMPLATE_TYPE_PARM_INDEX (t), + r = TEMPLATE_PARM_DESCENDANTS (arg)) + && (TEMPLATE_PARM_LEVEL (r) + == TEMPLATE_PARM_LEVEL (arg) - levels)) + /* Cache the simple case of lowering a type parameter. */ + r = TREE_TYPE (r); else { r = copy_type (t);