On Fri, 17 Aug 2012, Richard Guenther wrote: > > 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" ;)
It turns out the C++ frontend is again the only user. It gets used for DECL_PRIMARY_TEMPLATE. Now, the C++ fronend indeed seems to want to associate information with the template argument vector itself, not the template. As the patch removing TREE_CAHIN is in some sense not an improvement (C++ specific bits remain in the generic tree structure, blocking from the VEC size being moved to spare bits in tree_base), the DECL_PRIMARY_TEMPLATE usage shows that using a TREE_VEC to represent the template argument is the issue. We cannot simply derive from TREE_VEC because it relies on storage allocated at its tail, so instead a C++ specific tree node mimicking a TREE_VEC but sporting extra fields, including ones for the number of non-defaulted args and for DECL_PRIMARY_TEMPLATE would be the way to go. That node would derive from tree_base. This should be pretty straight-forward to do, but I'll push it back for now due to lack of time. So consider this patch withdrawn. You'll instead see me trying to move the length field into tree_base. Richard. > 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 ---- > -- Richard Guenther <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend