On Thu, 23 Feb 2023, Jakub Jelinek wrote:

> On Thu, Feb 23, 2023 at 01:54:27PM +0100, Richard Biener wrote:
> > The following avoids default-initializing auto_vec storage for
> > non-POD T since that's not what the allocated storage fallback
> > will do and it's also not expected for existing cases like
> > 
> >   auto_vec<std::pair<unsigned, unsigned>, 64> elts;
> > 
> > which exist to optimize the allocation.
> > 
> > Bootstrapped and tested on x86_64-unknown-linux-gnu.
> > 
> > It saves around 1kB of text size for cc1.
> > 
> > OK for trunk?
> > 
> > Thanks,
> > Richard.
> > 
> >     * vec.h (auto_vec<T, N>): Turn m_data storage into
> >     uninitialized unsigned char.
> 
> Given that we actually never reference the m_data array anywhere,
> it is just to reserve space, I think even the alignas(T) there is
> useless.  The point is that m_auto has as data members:
>   vec_prefix m_vecpfx;
>   T m_vecdata[1];
> and we rely on it (admittedly -fstrict-flex-arrays{,=2,=3} or
> -fsanitize=bound-sstrict incompatible) being treated as
> flexible array member flowing into the m_data storage after it.

Doesn't the array otherwise eventually overlap with tail padding
in m_auto?  Or does an array of T never produce tail padding?

> Though, this shows we still have work to do.  Because
> 1) T m_vecdata[1]; still has element type T in m_auto and
>    so is actually constructed/destructed uselessly

True.

> 2) the non-POD support is certainly incomplete; we have
>    vec_default_construct and vec_copy_construct and use that
>    for say grow_cleared etc. or vector copies, but don't have
>    anything that would invoke the destructors and don't invoke
>    vec_copy_construct (aka placement new) when we just push
>    stuff into the vector; so, I bet what we do is invalid
>    and kind of works for non-PODs which have assignment operator
>    which overwrites everything, doesn't use anything from the
>    overwritten object and has the same overall effect
>    as copy constructor, and only support trivial dtors
> For full non-POD support, I bet we'd need to vec_copy_construct (..., 1)
> on quick_push rather than invoke operator= there, we'd need
> to destruct stuff on pop/truncate etc., and quick_grow would need
> to be effectively the same as quick_grow_cleared for non-PODs.
> As for 1), if even m_vecdata was
>   alignas(T) unsigned char m_vecdata[sizeof (T)];
> we'll need casts in various spots and it will printing vectors
> by hand in gdb when the .gdbinit printers don't work properly.

Yes, I'm not proposing to fix non-POD support.  I want to make
as-if-POD stuff like std::pair to work like it was intended.

> Oh, and perhaps we should start marking such spots in GCC with
> strict_flex_array attribute to make it clear where we rely on the
> non-strict behavior.

I think we never access the array directly as array, do we?

Richard.

Reply via email to