diff mbox series

c++, v2: Introduce append_ctor_to_tree_vector

Message ID Z4/k55PwyqJ3niTX@tucnak
State New
Headers show
Series c++, v2: Introduce append_ctor_to_tree_vector | expand

Commit Message

Jakub Jelinek Jan. 21, 2025, 6:18 p.m. UTC
On Tue, Jan 21, 2025 at 05:35:02PM +0100, Jakub Jelinek wrote:
> On Tue, Jan 21, 2025 at 05:15:17PM +0100, Jakub Jelinek wrote:
> > On Tue, Jan 21, 2025 at 11:06:35AM -0500, Jason Merrill wrote:
> > > > --- gcc/c-family/c-common.cc.jj	2025-01-20 18:00:35.667875671 +0100
> > > > +++ gcc/c-family/c-common.cc	2025-01-21 09:29:23.955582581 +0100
> > > > @@ -9010,33 +9010,46 @@ make_tree_vector_from_list (tree list)
> > > >     return ret;
> > > >   }
> > > > -/* Get a new tree vector of the values of a CONSTRUCTOR.  */
> > > > +/* Append to a tree vector the values of a CONSTRUCTOR.
> > > > +   nelts should be at least CONSTRUCTOR_NELTS (ctor) and v
> > > > +   should be initialized with make_tree_vector (); followed by
> > > > +   vec_safe_reserve (v, nelts); or equivalently vec_alloc (v, nelts);
> > > > +   optionally followed by pushes of other elements (up to
> > > > +   nelts - CONSTRUCTOR_NELTS (ctor)).  */
> > > 
> > > How about using v->allocated () instead of passing in nelts?
> > 
> > That is not necessarily the same.
> > Both vec_safe_reserve (v, nelts) and vec_alloc (v, nelts); actually
> > use exact=false, so they can allocate something larger (doesn't hurt
> > e.g. if RAW_DATA_CST is small enough and fits), but if it used v->allocated
> > (), it could overallocate from the overallocated size.
> > So, e.g. even if nelts + RAW_DATA_LENGTH (x) - 1 <= v->allocated () - v->length ()
> > and thus we could just use a vector without reallocating,
> > v->allocated () + RAW_DATA_LENGTH (x) - 1 could be too much.
> 
> On the other side, if one uses v = vec_alloc (v, nelts) then v->allocated ()
> is guaranteed to be MAX (4, nelts) and if one uses v = make_tree_vector ();
> vec_safe_reserve (v, nelts); then v->allocated () will be I think at most
> MAX (24, nelts).
> So perhaps not that big deal (at least if the function inside of it uses
> unsigned nelts = v->allocated (); and then uses nelts rather than
> v->allocated () in the loop.  Unless some new caller of the function uses
> a vector reallocated more times.

So, if you prefer that, here is the variant patch, so far lightly tested -
GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-g++ RUNTESTFLAGS="dg.exp='embed* pr118532.C explicit20.C class-deduction-aggr16.C'"
can do full bootstrap/regtest tonight.

2025-01-21  Jakub Jelinek  <jakub@redhat.com>

gcc/c-family/
	* c-common.h (append_ctor_to_tree_vector): Declare.
	* c-common.cc (append_ctor_to_tree_vector): New function.
	(make_tree_vector_from_ctor): Use it.
gcc/cp/
	* call.cc (add_list_candidates): Use append_ctor_to_tree_vector.



	Jakub
diff mbox series

Patch

--- gcc/c-family/c-common.h.jj	2025-01-17 11:29:33.139696380 +0100
+++ gcc/c-family/c-common.h	2025-01-21 09:30:09.520947570 +0100
@@ -1190,6 +1190,8 @@  extern vec<tree, va_gc> *make_tree_vecto
 extern void release_tree_vector (vec<tree, va_gc> *);
 extern vec<tree, va_gc> *make_tree_vector_single (tree);
 extern vec<tree, va_gc> *make_tree_vector_from_list (tree);
+extern vec<tree, va_gc> *append_ctor_to_tree_vector (vec<tree, va_gc> *,
+						     tree);
 extern vec<tree, va_gc> *make_tree_vector_from_ctor (tree);
 extern vec<tree, va_gc> *make_tree_vector_copy (const vec<tree, va_gc> *);
 
--- gcc/c-family/c-common.cc.jj	2025-01-20 18:00:35.667875671 +0100
+++ gcc/c-family/c-common.cc	2025-01-21 09:29:23.955582581 +0100
@@ -9010,33 +9010,45 @@  make_tree_vector_from_list (tree list)
   return ret;
 }
 
-/* Get a new tree vector of the values of a CONSTRUCTOR.  */
+/* Append to a tree vector the values of a CONSTRUCTOR.
+   v should be initialized with make_tree_vector (); followed by
+   vec_safe_reserve (v, nelts); or equivalently vec_alloc (v, nelts);
+   optionally followed by pushes of other elements (up to
+   nelts - CONSTRUCTOR_NELTS (ctor)).  */
 
 vec<tree, va_gc> *
-make_tree_vector_from_ctor (tree ctor)
+append_ctor_to_tree_vector (vec<tree, va_gc> *v, tree ctor)
 {
-  vec<tree,va_gc> *ret = make_tree_vector ();
-  unsigned nelts = CONSTRUCTOR_NELTS (ctor);
-  vec_safe_reserve (ret, CONSTRUCTOR_NELTS (ctor));
+  unsigned nelts = v->allocated ();
   for (unsigned i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i)
     if (TREE_CODE (CONSTRUCTOR_ELT (ctor, i)->value) == RAW_DATA_CST)
       {
 	tree raw_data = CONSTRUCTOR_ELT (ctor, i)->value;
 	nelts += RAW_DATA_LENGTH (raw_data) - 1;
-	vec_safe_reserve (ret, nelts - ret->length ());
+	vec_safe_reserve (v, nelts - v->length ());
 	if (TYPE_PRECISION (TREE_TYPE (raw_data)) > CHAR_BIT
 	    || TYPE_UNSIGNED (TREE_TYPE (raw_data)))
 	  for (unsigned j = 0; j < (unsigned) RAW_DATA_LENGTH (raw_data); ++j)
-	    ret->quick_push (build_int_cst (TREE_TYPE (raw_data),
-					    RAW_DATA_UCHAR_ELT (raw_data, j)));
+	    v->quick_push (build_int_cst (TREE_TYPE (raw_data),
+					  RAW_DATA_UCHAR_ELT (raw_data, j)));
 	else
 	  for (unsigned j = 0; j < (unsigned) RAW_DATA_LENGTH (raw_data); ++j)
-	    ret->quick_push (build_int_cst (TREE_TYPE (raw_data),
-					    RAW_DATA_SCHAR_ELT (raw_data, j)));
+	    v->quick_push (build_int_cst (TREE_TYPE (raw_data),
+					  RAW_DATA_SCHAR_ELT (raw_data, j)));
       }
     else
-      ret->quick_push (CONSTRUCTOR_ELT (ctor, i)->value);
-  return ret;
+      v->quick_push (CONSTRUCTOR_ELT (ctor, i)->value);
+  return v;
+}
+
+/* Get a new tree vector of the values of a CONSTRUCTOR.  */
+
+vec<tree, va_gc> *
+make_tree_vector_from_ctor (tree ctor)
+{
+  vec<tree,va_gc> *ret = make_tree_vector ();
+  vec_safe_reserve (ret, CONSTRUCTOR_NELTS (ctor));
+  return append_ctor_to_tree_vector (ret, ctor);
 }
 
 /* Get a new tree vector which is a copy of an existing one.  */
--- gcc/cp/call.cc.jj	2025-01-21 09:11:58.214113697 +0100
+++ gcc/cp/call.cc	2025-01-21 19:13:01.568407526 +0100
@@ -4258,30 +4258,10 @@  add_list_candidates (tree fns, tree firs
 
   /* Expand the CONSTRUCTOR into a new argument vec.  */
   vec<tree, va_gc> *new_args;
-  unsigned nelts = nart + CONSTRUCTOR_NELTS (init_list);
-  vec_alloc (new_args, nelts);
+  vec_alloc (new_args, nart + CONSTRUCTOR_NELTS (init_list));
   for (unsigned i = 0; i < nart; ++i)
     new_args->quick_push ((*args)[i]);
-  for (unsigned i = 0; i < CONSTRUCTOR_NELTS (init_list); ++i)
-    if (TREE_CODE (CONSTRUCTOR_ELT (init_list, i)->value) == RAW_DATA_CST)
-      {
-	tree raw_data = CONSTRUCTOR_ELT (init_list, i)->value;
-	nelts += RAW_DATA_LENGTH (raw_data) - 1;
-	vec_safe_reserve (new_args, nelts - new_args->length ());
-	if (TYPE_PRECISION (TREE_TYPE (raw_data)) > CHAR_BIT
-	    || TYPE_UNSIGNED (TREE_TYPE (raw_data)))
-	  for (unsigned j = 0; j < (unsigned) RAW_DATA_LENGTH (raw_data); ++j)
-	    new_args->quick_push (build_int_cst (TREE_TYPE (raw_data),
-						 RAW_DATA_UCHAR_ELT (raw_data,
-								     j)));
-	else
-	  for (unsigned j = 0; j < (unsigned) RAW_DATA_LENGTH (raw_data); ++j)
-	    new_args->quick_push (build_int_cst (TREE_TYPE (raw_data),
-						 RAW_DATA_SCHAR_ELT (raw_data,
-								     j)));
-      }
-    else
-      new_args->quick_push (CONSTRUCTOR_ELT (init_list, i)->value);
+  new_args = append_ctor_to_tree_vector (new_args, init_list);
 
   /* We aren't looking for list-ctors anymore.  */
   flags &= ~LOOKUP_LIST_ONLY;