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 ----

Reply via email to