This gets rid of this field, pushing it into a short int in tree_base (hopefully 2^16 non-defaulted template args are enough ...). The existing code is a bit confusing because of the differences with respect to ENABLE_CHECKING, it has very little testcase coverage as well (a single testcase, g++.dg/template/error39.C), so I am not sure I got the idea correct (especially as ENABLE_CHECKING vs. non-ENABLE_CHECKING looks to introduce subtle differences?).
Anyway, a previous iteration that failed g++.dg/template/error39.C bootstrapped and tested all languages ok, the following version now passes g++.dg/template/error39.C and hopefully bootstrap and regtest as well. We build a _lot_ of TREE_VECs from the C++ frontend, so this 8 byte saving is quite visible. TREE_VEC is the most used TREE_CODE by far on PR54146: ... ssa_name 363597 mem_ref 403966 addr_expr 1203839 tree_list 1205721 tree_vec 2654415 which translates to 109615896 bytes allocated in TREE_VECs (yes, that includes the actual storage, the average size is 41.3 bytes, with this patch TREE_VEC itself shrinks from 40 bytes to 32 bytes which means the average TREE_VEC size is one!). Let's hope removing TREE_TYPE from TREE_VEC is as "easy" ;) Re-bootstrap and regtest running on x86_64-unknown-linux-gnu. Ok for the C++ parts? Thanks, Richard. 2012-08-17 Richard Guenther <rguent...@suse.de> * tree.h (struct tree_base): Put address_space into a union, alongside a new field non_default_template_args_count used by C++ TREE_VECs. (struct tree_vec): Derive from tree_typed instead of tree_common. (TYPE_ADDR_SPACE): Adjust. * tree.c (initialize_tree_contains_struct): Adjust tree type hierarchy. cp/ * cp-tree.h (NON_DEFAULT_TEMPLATE_ARGS_COUNT): Remove. (SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT, GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT): Use non_default_template_args_count in tree_base instead of TREE_CHAIN. * pt.c (expand_template_argument_pack): Adjust. (template_parm_to_arg): Likewise. (current_template_args): Likewise. (coerce_template_parameter_pack): Likewise. (coerce_template_parms): Likewise. (tsubst_template_args): Likewise. (type_unification_real): Likewise. * parser.c (cp_parser_template_argument_list): Likewise. Index: gcc/tree.h =================================================================== *** gcc/tree.h (revision 190469) --- gcc/tree.h (working copy) *************** struct GTY(()) tree_base { *** 453,465 **** unsigned packed_flag : 1; unsigned user_align : 1; unsigned nameless_flag : 1; ! unsigned spare : 12; ! ! /* This field is only used with type nodes; the only reason it is present ! in tree_base instead of tree_type is to save space. The size of the ! field must be large enough to hold addr_space_t values. */ ! unsigned address_space : 8; }; struct GTY(()) tree_typed { --- 453,473 ---- unsigned packed_flag : 1; unsigned user_align : 1; unsigned nameless_flag : 1; + unsigned spare0 : 4; ! /* The following has to be at a 16-bit alignment boundary to be properly ! packed and not make tree_base larger than 64 bits. */ ! union tree_base_spare_bits { ! /* This field is only used with type nodes; the only reason it is present ! in tree_base instead of tree_type is to save space. The size of the ! field must be large enough to hold addr_space_t values. */ ! unsigned char address_space; ! ! /* This field is only used with tree_vec nodes by the C++ frontend; the ! only reason it is present in tree_base instead of tree_vec is to ! save space. */ ! unsigned short non_default_template_args_count; ! } GTY((skip(""))) spare; }; struct GTY(()) tree_typed { *************** struct GTY(()) tree_list { *** 1483,1489 **** #define TREE_VEC_ELT(NODE,I) TREE_VEC_ELT_CHECK (NODE, I) struct GTY(()) tree_vec { ! struct tree_common common; int length; tree GTY ((length ("TREE_VEC_LENGTH ((tree)&%h)"))) a[1]; }; --- 1491,1497 ---- #define TREE_VEC_ELT(NODE,I) TREE_VEC_ELT_CHECK (NODE, I) struct GTY(()) tree_vec { ! struct tree_typed typed; int length; tree GTY ((length ("TREE_VEC_LENGTH ((tree)&%h)"))) a[1]; }; *************** extern enum machine_mode vector_type_mod *** 2182,2188 **** #define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.nameless_flag) /* The address space the type is in. */ ! #define TYPE_ADDR_SPACE(NODE) (TYPE_CHECK (NODE)->base.address_space) /* There is a TYPE_QUAL value for each type qualifier. They can be combined by bitwise-or to form the complete set of qualifiers for a --- 2190,2196 ---- #define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.nameless_flag) /* The address space the type is in. */ ! #define TYPE_ADDR_SPACE(NODE) (TYPE_CHECK (NODE)->base.spare.address_space) /* There is a TYPE_QUAL value for each type qualifier. They can be combined by bitwise-or to form the complete set of qualifiers for a Index: gcc/tree.c =================================================================== *** gcc/tree.c (revision 190469) --- gcc/tree.c (working copy) *************** initialize_tree_contains_struct (void) *** 382,387 **** --- 382,388 ---- case TS_REAL_CST: case TS_FIXED_CST: case TS_VECTOR: + case TS_VEC: case TS_STRING: case TS_COMPLEX: case TS_SSA_NAME: *************** initialize_tree_contains_struct (void) *** 395,401 **** case TS_DECL_MINIMAL: case TS_TYPE_COMMON: case TS_LIST: - case TS_VEC: case TS_BINFO: case TS_OMP_CLAUSE: case TS_OPTIMIZATION: --- 396,401 ---- Index: gcc/cp/pt.c =================================================================== *** gcc/cp/pt.c (revision 190469) --- gcc/cp/pt.c (working copy) *************** expand_template_argument_pack (tree args *** 3301,3307 **** tree result_args = NULL_TREE; int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0; int num_result_args = -1; ! int non_default_args_count = -1; /* First, determine if we need to expand anything, and the number of slots we'll need. */ --- 3301,3307 ---- tree result_args = NULL_TREE; int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0; int num_result_args = -1; ! int non_default_args_count; /* First, determine if we need to expand anything, and the number of slots we'll need. */ *************** expand_template_argument_pack (tree args *** 3331,3339 **** /* Expand arguments. */ result_args = make_tree_vec (num_result_args); ! if (NON_DEFAULT_TEMPLATE_ARGS_COUNT (args)) ! non_default_args_count = ! GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args); for (in_arg = 0; in_arg < nargs; ++in_arg) { tree arg = TREE_VEC_ELT (args, in_arg); --- 3331,3337 ---- /* Expand arguments. */ result_args = make_tree_vec (num_result_args); ! non_default_args_count = GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args); for (in_arg = 0; in_arg < nargs; ++in_arg) { tree arg = TREE_VEC_ELT (args, in_arg); *************** expand_template_argument_pack (tree args *** 3343,3350 **** int i, num_packed = TREE_VEC_LENGTH (packed); for (i = 0; i < num_packed; ++i, ++out_arg) TREE_VEC_ELT (result_args, out_arg) = TREE_VEC_ELT(packed, i); ! if (non_default_args_count > 0) ! non_default_args_count += num_packed; } else { --- 3341,3347 ---- int i, num_packed = TREE_VEC_LENGTH (packed); for (i = 0; i < num_packed; ++i, ++out_arg) TREE_VEC_ELT (result_args, out_arg) = TREE_VEC_ELT(packed, i); ! non_default_args_count += num_packed; } else { *************** expand_template_argument_pack (tree args *** 3352,3359 **** ++out_arg; } } ! if (non_default_args_count >= 0) ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (result_args, non_default_args_count); return result_args; } --- 3349,3355 ---- ++out_arg; } } ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (result_args, non_default_args_count); return result_args; } *************** template_parm_to_arg (tree t) *** 3702,3711 **** /* Turn this argument into a TYPE_ARGUMENT_PACK with a single element, which expands T. */ tree vec = make_tree_vec (1); ! #ifdef ENABLE_CHECKING ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT ! (vec, TREE_VEC_LENGTH (vec)); ! #endif TREE_VEC_ELT (vec, 0) = make_pack_expansion (t); t = cxx_make_type (TYPE_ARGUMENT_PACK); --- 3698,3704 ---- /* Turn this argument into a TYPE_ARGUMENT_PACK with a single element, which expands T. */ tree vec = make_tree_vec (1); ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec)); TREE_VEC_ELT (vec, 0) = make_pack_expansion (t); t = cxx_make_type (TYPE_ARGUMENT_PACK); *************** template_parm_to_arg (tree t) *** 3722,3731 **** with a single element, which expands T. */ tree vec = make_tree_vec (1); tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t)); ! #ifdef ENABLE_CHECKING ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT ! (vec, TREE_VEC_LENGTH (vec)); ! #endif TREE_VEC_ELT (vec, 0) = make_pack_expansion (t); t = make_node (NONTYPE_ARGUMENT_PACK); --- 3715,3721 ---- with a single element, which expands T. */ tree vec = make_tree_vec (1); tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t)); ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec)); TREE_VEC_ELT (vec, 0) = make_pack_expansion (t); t = make_node (NONTYPE_ARGUMENT_PACK); *************** current_template_args (void) *** 3800,3808 **** for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i) TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i)); - #ifdef ENABLE_CHECKING SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a)); - #endif if (length > 1) TREE_VEC_ELT (args, --l) = a; --- 3790,3796 ---- *************** coerce_template_parameter_pack (tree par *** 6410,6419 **** } SET_ARGUMENT_PACK_ARGS (argument_pack, packed_args); - #ifdef ENABLE_CHECKING SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (packed_args, TREE_VEC_LENGTH (packed_args)); - #endif return argument_pack; } --- 6398,6405 ---- *************** coerce_template_parms (tree parms, *** 6457,6462 **** --- 6443,6449 ---- tree new_inner_args; int saved_unevaluated_operand; int saved_inhibit_evaluation_warnings; + bool defaulted_arg_found; /* When used as a boolean value, indicates whether this is a variadic template parameter list. Since it's an int, we can also *************** coerce_template_parms (tree parms, *** 6528,6533 **** --- 6515,6521 ---- c_inhibit_evaluation_warnings = 0; new_inner_args = make_tree_vec (nparms); new_args = add_outermost_template_args (args, new_inner_args); + defaulted_arg_found = false; for (parm_idx = 0, arg_idx = 0; parm_idx < nparms; parm_idx++, arg_idx++) { tree arg; *************** coerce_template_parms (tree parms, *** 6586,6593 **** /* The position of the first default template argument, is also the number of non-defaulted arguments in NEW_INNER_ARGS. Record that. */ ! if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args)) ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args, arg_idx); } else break; --- 6574,6584 ---- /* The position of the first default template argument, is also the number of non-defaulted arguments in NEW_INNER_ARGS. Record that. */ ! if (!defaulted_arg_found) ! { ! defaulted_arg_found = true; ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args, arg_idx); ! } } else break; *************** coerce_template_parms (tree parms, *** 6619,6629 **** if (lost) return error_mark_node; ! #ifdef ENABLE_CHECKING ! if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args)) SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args, TREE_VEC_LENGTH (new_inner_args)); - #endif return new_inner_args; } --- 6610,6618 ---- if (lost) return error_mark_node; ! if (!defaulted_arg_found) SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args, TREE_VEC_LENGTH (new_inner_args)); return new_inner_args; } *************** tsubst_template_args (tree t, tree args, *** 9393,9404 **** It will rather be the nested TREE_VECs that will carry one. In other words, ORIG_T carries a non defaulted argument count only if it doesn't contain any nested TREE_VEC. */ ! if (NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t)) ! { ! int count = GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t); ! count += expanded_len_adjust; ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (t, count); ! } for (i = 0, out = 0; i < len; i++) { if ((PACK_EXPANSION_P (TREE_VEC_ELT (orig_t, i)) --- 9382,9390 ---- It will rather be the nested TREE_VECs that will carry one. In other words, ORIG_T carries a non defaulted argument count only if it doesn't contain any nested TREE_VEC. */ ! int count = GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t); ! count += expanded_len_adjust; ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (t, count); for (i = 0, out = 0; i < len; i++) { if ((PACK_EXPANSION_P (TREE_VEC_ELT (orig_t, i)) *************** type_unification_real (tree tparms, *** 14982,14995 **** const tree *args; unsigned int nargs; unsigned int ia; gcc_assert (TREE_CODE (tparms) == TREE_VEC); gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST); gcc_assert (ntparms > 0); ! /* Reset the number of non-defaulted template arguments contained ! in TARGS. */ ! NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE; again: parms = xparms; --- 14968,14981 ---- const tree *args; unsigned int nargs; unsigned int ia; + bool defaulted_arg_found; gcc_assert (TREE_CODE (tparms) == TREE_VEC); gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST); gcc_assert (ntparms > 0); ! /* Note that we did not yet find a defaulted template argument. */ ! defaulted_arg_found = false; again: parms = xparms; *************** type_unification_real (tree tparms, *** 15140,15147 **** /* The position of the first default template argument, is also the number of non-defaulted arguments in TARGS. Record that. */ ! if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs)) ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i); continue; } } --- 15126,15136 ---- /* The position of the first default template argument, is also the number of non-defaulted arguments in TARGS. Record that. */ ! if (!defaulted_arg_found) ! { ! defaulted_arg_found = true; ! SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i); ! } continue; } } *************** type_unification_real (tree tparms, *** 15170,15179 **** return unify_parameter_deduction_failure (explain_p, tparm); } } ! #ifdef ENABLE_CHECKING ! if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs)) SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs)); - #endif return unify_success (explain_p); } --- 15159,15166 ---- return unify_parameter_deduction_failure (explain_p, tparm); } } ! if (!defaulted_arg_found) SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs)); return unify_success (explain_p); } Index: gcc/cp/cp-tree.h =================================================================== *** gcc/cp/cp-tree.h (revision 190469) --- gcc/cp/cp-tree.h (working copy) *************** extern void decl_shadowed_for_var_insert *** 2661,2681 **** #define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) /* For a given TREE_VEC containing a template argument list, this property contains the number of arguments that are not ! defaulted. */ ! #define NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) TREE_CHAIN (TREE_VEC_CHECK (NODE)) ! /* Below are the setter and getter of the NON_DEFAULT_TEMPLATE_ARGS_COUNT property. */ #define SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE, INT_VALUE) \ ! NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) = build_int_cst (NULL_TREE, INT_VALUE) ! #ifdef ENABLE_CHECKING #define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \ ! int_cst_value (NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE)) ! #else ! #define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \ ! NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE) \ ! ? int_cst_value (NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE)) \ ! : TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (NODE)) ! #endif /* The list of typedefs - used in the template - that need access checking at template instantiation time. */ #define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) \ --- 2661,2673 ---- #define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) /* For a given TREE_VEC containing a template argument list, this property contains the number of arguments that are not ! defaulted. The following are the setter and getter of this property. */ #define SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE, INT_VALUE) \ ! TREE_VEC_CHECK (NODE)->base.spare.non_default_template_args_count \ ! = (INT_VALUE) #define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \ ! ((int) TREE_VEC_CHECK (NODE)->base.spare.non_default_template_args_count) /* The list of typedefs - used in the template - that need access checking at template instantiation time. */ #define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) \ Index: gcc/cp/parser.c =================================================================== *** gcc/cp/parser.c (revision 190469) --- gcc/cp/parser.c (working copy) *************** cp_parser_template_argument_list (cp_par *** 12855,12863 **** parser->non_integral_constant_expression_p = saved_non_ice_p; parser->integral_constant_expression_p = saved_ice_p; parser->in_template_argument_list_p = saved_in_template_argument_list_p; - #ifdef ENABLE_CHECKING SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec)); - #endif return vec; } --- 12855,12861 ----