Patchwork C++ PATCH for variadic pack expansion memory use

login
register
mail settings
Submitter Jason Merrill
Date Oct. 3, 2011, 4:32 a.m.
Message ID <4E893AC9.1020407@redhat.com>
Download mbox | patch
Permalink /patch/117402/
State New
Headers show

Comments

Jason Merrill - Oct. 3, 2011, 4:32 a.m.
Someone sent me a variadic templates testcase that was using an 
unreasonable amount of memory; -fmem-report showed that half of the 
garbage was from ARGUMENT_PACK_SELECT nodes.  There's no reason why we 
should allocate a new node for each pack on each iteration of the 
expansion; we can just allocate them for the first node and then update 
the index as we go along.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 13dd4a100ef26121960b3fd1552c6c96c4309838
Author: Jason Merrill <jason@redhat.com>
Date:   Sun Oct 2 23:06:40 2011 -0400

    	* pt.c (tsubst_pack_expansion): Re-use ARGUMENT_PACK_SELECTs.
    	Change unsubstituted_packs to bool.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 015ee37..051c89a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9102,7 +9102,8 @@  tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
 		       tree in_decl)
 {
   tree pattern;
-  tree pack, packs = NULL_TREE, unsubstituted_packs = NULL_TREE;
+  tree pack, packs = NULL_TREE;
+  bool unsubstituted_packs = false;
   int i, len = -1;
   tree result;
   htab_t saved_local_specializations = NULL;
@@ -9203,10 +9204,11 @@  tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
           TREE_TYPE (packs) = orig_arg;
         }
       else
-        /* We can't substitute for this parameter pack.  */
-        unsubstituted_packs = tree_cons (TREE_PURPOSE (pack),
-                                         TREE_VALUE (pack),
-                                         unsubstituted_packs);
+	{
+	  /* We can't substitute for this parameter pack.  */
+	  unsubstituted_packs = true;
+	  break;
+	}
     }
 
   /* We cannot expand this expansion expression, because we don't have
@@ -9252,33 +9254,38 @@  tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
       for (pack = packs; pack; pack = TREE_CHAIN (pack))
         {
           tree parm = TREE_PURPOSE (pack);
+	  tree arg;
 
+	  /* Select the Ith argument from the pack.  */
           if (TREE_CODE (parm) == PARM_DECL)
             {
-	      /* Select the Ith argument from the pack.  */
-	      tree arg = make_node (ARGUMENT_PACK_SELECT);
-	      ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
-	      ARGUMENT_PACK_SELECT_INDEX (arg) = i;
-              mark_used (parm);
-              register_local_specialization (arg, parm);
+	      if (i == 0)
+		{
+		  arg = make_node (ARGUMENT_PACK_SELECT);
+		  ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
+		  mark_used (parm);
+		  register_local_specialization (arg, parm);
+		}
+	      else
+		arg = retrieve_local_specialization (parm);
             }
           else
             {
-              tree value = parm;
               int idx, level;
               template_parm_level_and_index (parm, &level, &idx);
-              
-	      if (i < len) 
+
+	      if (i == 0)
 		{
-		  /* Select the Ith argument from the pack. */
-		  value = make_node (ARGUMENT_PACK_SELECT);
-		  ARGUMENT_PACK_SELECT_FROM_PACK (value) = TREE_VALUE (pack);
-		  ARGUMENT_PACK_SELECT_INDEX (value) = i;
+		  arg = make_node (ARGUMENT_PACK_SELECT);
+		  ARGUMENT_PACK_SELECT_FROM_PACK (arg) = TREE_VALUE (pack);
+		  /* Update the corresponding argument.  */
+		  TMPL_ARG (args, level, idx) = arg;
 		}
-
-              /* Update the corresponding argument.  */
-              TMPL_ARG (args, level, idx) = value;
+	      else
+		/* Re-use the ARGUMENT_PACK_SELECT.  */
+		arg = TMPL_ARG (args, level, idx);
             }
+	  ARGUMENT_PACK_SELECT_INDEX (arg) = i;
         }
 
       /* Substitute into the PATTERN with the altered arguments.  */