On Thu, Oct 24, 2024 at 8:16 AM Andrew Pinski <pins...@gmail.com> wrote:
>
> On Wed, Oct 23, 2024 at 12:28 AM Andrew Pinski <pins...@gmail.com> wrote:
> >
> > On Tue, Oct 22, 2024 at 11:49 PM Richard Biener
> > <richard.guent...@gmail.com> wrote:
> > >
> > > On Tue, Oct 22, 2024 at 5:31 PM Andrew Pinski <quic_apin...@quicinc.com> 
> > > wrote:
> > > >
> > > > This adds quick_emplace_push and safe_emplace_push to vec.
> > > > These are like std::vector's emplace_back so you don't need an extra
> > > > copy of the struct around.
> > > >
> > > > Since we require C++11 and also support partial non-PODs for vec, these 
> > > > functions
> > > > can be added.
> > > >
> > > > I will be using them to cleanup some code and even improving how some 
> > > > places
> > > > use vec.
> > > >
> > > > Bootstrapped and tested on x86_64-linux-gnu.
> > > >
> > > > gcc/ChangeLog:
> > > >
> > > >         * vec.h (vec<T,vl_embed>::quick_emplace_push): New function.
> > > >         (vec<T,vl_ptr>::quick_emplace_push): New function.
> > > >         (vec<T,vl_ptr>::safe_emplace_push): New function.
> > > >         * vec.cc (test_init): Add test for safe_emplace_push.
> > > >         (test_quick_emplace_push): New function.
> > > >         (test_safe_emplace_push): New function.
> > > >         (vec_cc_tests): Call test_quick_emplace_push and
> > > >         test_safe_emplace_push.
> > > >
> > > > Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> > > > ---
> > > >  gcc/vec.cc | 41 +++++++++++++++++++++++++++++++++++++++++
> > > >  gcc/vec.h  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> > > >  2 files changed, 87 insertions(+)
> > > >
> > > > diff --git a/gcc/vec.cc b/gcc/vec.cc
> > > > index ba963b96c6a..cd7cd3c156b 100644
> > > > --- a/gcc/vec.cc
> > > > +++ b/gcc/vec.cc
> > > > @@ -304,6 +304,10 @@ test_init ()
> > > >
> > > >      ASSERT_EQ (2, v1.length ());
> > > >      ASSERT_EQ (2, v2.length ());
> > > > +    v2.safe_emplace_push (1);
> > > > +
> > > > +    ASSERT_EQ (3, v1.length ());
> > > > +    ASSERT_EQ (3, v2.length ());
> > > >      v1.release ();
> > > >    }
> > > >  }
> > > > @@ -327,6 +331,25 @@ test_quick_push ()
> > > >    ASSERT_EQ (7, v[2]);
> > > >  }
> > > >
> > > > +/* Verify that vec::quick_emplace_push works correctly.  */
> > > > +
> > > > +static void
> > > > +test_quick_emplace_push ()
> > > > +{
> > > > +  auto_vec <std::pair<int,int>> v;
> > > > +  ASSERT_EQ (0, v.length ());
> > > > +  v.reserve (3);
> > > > +  ASSERT_EQ (0, v.length ());
> > > > +  ASSERT_TRUE (v.space (3));
> > > > +  v.quick_emplace_push (5, 5);
> > > > +  v.quick_emplace_push (6, 6);
> > > > +  v.quick_emplace_push (7, 7);
> > > > +  ASSERT_EQ (3, v.length ());
> > > > +  ASSERT_EQ (std::make_pair(5,5), v[0]);
> > > > +  ASSERT_EQ (std::make_pair(6,6), v[1]);
> > > > +  ASSERT_EQ (std::make_pair(7,7), v[2]);
> > > > +}
> > > > +
> > > >  /* Verify that vec::safe_push works correctly.  */
> > > >
> > > >  static void
> > > > @@ -343,6 +366,22 @@ test_safe_push ()
> > > >    ASSERT_EQ (7, v[2]);
> > > >  }
> > > >
> > > > +/* Verify that vec::safe_emplace_push works correctly.  */
> > > > +
> > > > +static void
> > > > +test_safe_emplace_push ()
> > > > +{
> > > > +  auto_vec <std::pair<int,int>> v;
> > > > +  ASSERT_EQ (0, v.length ());
> > > > +  v.safe_emplace_push (5, 5);
> > > > +  v.safe_emplace_push (6, 6);
> > > > +  v.safe_emplace_push (7, 7);
> > > > +  ASSERT_EQ (3, v.length ());
> > > > +  ASSERT_EQ (std::make_pair(5,5), v[0]);
> > > > +  ASSERT_EQ (std::make_pair(6,6), v[1]);
> > > > +  ASSERT_EQ (std::make_pair(7,7), v[2]);
> > > > +}
> > > > +
> > > >  /* Verify that vec::truncate works correctly.  */
> > > >
> > > >  static void
> > > > @@ -591,7 +630,9 @@ vec_cc_tests ()
> > > >  {
> > > >    test_init ();
> > > >    test_quick_push ();
> > > > +  test_quick_emplace_push ();
> > > >    test_safe_push ();
> > > > +  test_safe_emplace_push ();
> > > >    test_truncate ();
> > > >    test_safe_grow_cleared ();
> > > >    test_pop ();
> > > > diff --git a/gcc/vec.h b/gcc/vec.h
> > > > index b13c4716428..8277d156f05 100644
> > > > --- a/gcc/vec.h
> > > > +++ b/gcc/vec.h
> > > > @@ -619,6 +619,8 @@ public:
> > > >    void splice (const vec &);
> > > >    void splice (const vec *src);
> > > >    T *quick_push (const T &);
> > > > +  template <typename ...Args>
> > > > +  T *quick_emplace_push (Args&&... args);
> > > >    using pop_ret_type
> > > >      = typename std::conditional <std::is_trivially_destructible 
> > > > <T>::value,
> > > >                                  T &, void>::type;
> > > > @@ -1044,6 +1046,21 @@ vec<T, A, vl_embed>::quick_push (const T &obj)
> > > >    return slot;
> > > >  }
> > > >
> > > > +/* Push T(ARGS) (a new element) onto the end of the vector.  There 
> > > > must be
> > > > +   sufficient space in the vector.  Return a pointer to the slot
> > > > +   where T(ARGS) was inserted.  */
> > > > +
> > > > +template<typename T, typename A>
> > > > +template<typename ...Args>
> > > > +inline T *
> > > > +vec<T, A, vl_embed>::quick_emplace_push (Args&&... args)
> > > > +{
> > > > +  gcc_checking_assert (space (1));
> > > > +  T *slot = &address ()[m_vecpfx.m_num++];
> > > > +  ::new (static_cast<void*>(slot)) T (std::forward<Args>(args)...);
> > > > +  return slot;
> > > > +}
> > > > +
> > > >
> > > >  /* Pop and return a reference to the last element off the end of the
> > > >     vector.  If T has non-trivial destructor, this method just pops
> > > > @@ -1612,7 +1629,11 @@ public:
> > > >    void splice (const vec &);
> > > >    void safe_splice (const vec & CXX_MEM_STAT_INFO);
> > > >    T *quick_push (const T &);
> > > > +  template <typename ...Args>
> > > > +  T *quick_emplace_push (Args&&... args);
> > > >    T *safe_push (const T &CXX_MEM_STAT_INFO);
> > > > +  template <typename ...Args>
> > > > +  T *safe_emplace_push (Args&&... args CXX_MEM_STAT_INFO);
> > > >    using pop_ret_type
> > > >      = typename std::conditional <std::is_trivially_destructible 
> > > > <T>::value,
> > > >                                  T &, void>::type;
> > > > @@ -2070,6 +2091,18 @@ vec<T, va_heap, vl_ptr>::quick_push (const T 
> > > > &obj)
> > > >    return m_vec->quick_push (obj);
> > > >  }
> > > >
> > > > +/* Push OBJ (a new element) onto the end of the vector.  There must be
> > > > +   sufficient space in the vector.  Return a pointer to the slot
> > > > +   where OBJ was inserted.  */
> > > > +
> > > > +template<typename T>
> > > > +template <typename ...Args>
> > > > +inline T *
> > > > +vec<T, va_heap, vl_ptr>::quick_emplace_push (Args&& ... args)
> > > > +{
> > > > +  return m_vec->quick_emplace_push (std::forward<Args>(args)...);
> > > > +}
> > > > +
> > > >
> > > >  /* Push a new element OBJ onto the end of this vector.  Reallocates
> > > >     the embedded vector, if needed.  Return a pointer to the slot where
> > > > @@ -2083,6 +2116,19 @@ vec<T, va_heap, vl_ptr>::safe_push (const T &obj 
> > > > MEM_STAT_DECL)
> > > >    return quick_push (obj);
> > > >  }
> > > >
> > > > +/* Push a new element T(ARGS) onto the end of this vector.  Reallocates
> > > > +   the embedded vector, if needed.  Return a pointer to the slot where
> > > > +   OBJ was inserted.  */
> > > > +
> > > > +template<typename T>
> > > > +template <typename ...Args>
> > > > +inline T *
> > > > +vec<T, va_heap, vl_ptr>::safe_emplace_push (Args&&... args 
> > > > MEM_STAT_DECL)
> > >
> > > Did you check this works with --enable-gather-detailed-mem-stats?
> >
> > Whoops, let me test that. It might be the case it needs to be in the
> > front because of the way variadic templates work.
>
> So the answer is No, it does not work.  In recent years has these
> stats been useful?

I've been using it extensively recently, so yes - definitely.

> I know it is useful to know how much a pass
> allocates to make sure it does not go off to the weeds but recording
> where the allocation in the pass have recently helped?

Yes!

> Rather I am asking should we just forebode recording them for
> safe_emplace_push since there is no way for variadic templates and
> default arguments to work together.

Then do not use variadic templates?  Can't we use std::initializer_list or so?

> Though we could just declare there are at max 3 arguments to a
> constructor and not do variadic templates. We can add more if needed
> but I think having one for 0, 1, 2, and 3 arguments will be enough for
> most constructors (pair is 2; I have an usage that has 0 arguments
> that I am working on).
>
> So the 3 options forward I see are:
> * drop the patch and just keep what is happening today
> * Don't pass the stats
> * Have a fixed number of arguments for safe_emplace_push (0, 1, 2, and
> 3) and have a variable number still for quick_emplace_push (since
> there is no allocation done).
>
> I prefer the last one but the middle one is ok too.

I prefer the last or the first, definitely not the second.

Alternatively have a variant where the locator needs to be explicitly
sepecified as earlier arg, like

vec.safe_emplace_push (PASS_STAT 3, 4, 5);

?

> Thanks,
> Andrew Pinski
>
>
>
>
> >
> > Thanks,
> > Andrew
> >
> > >
> > > > +{
> > > > +  reserve (1, false PASS_MEM_STAT);
> > > > +  return quick_emplace_push (std::forward<Args>(args)...);
> > > > +}
> > > > +
> > > >
> > > >  /* Pop and return a reference to the last element off the end of the
> > > >     vector.  If T has non-trivial destructor, this method just pops
> > > > --
> > > > 2.43.0
> > > >

Reply via email to