[PATCH 2/3] libstdc++: Optimize __uninitialized_default using memset
Jonathan Wakely
jwakely@redhat.com
Thu Jun 27 22:25:04 GMT 2024
On Thu, 27 Jun 2024 at 14:27, Maciej Cencora <m.cencora@gmail.com> wrote:
>
> I think going the bit_cast way would be the best because it enables the optimization for many more classes including common wrappers like optional, variant, pair, tuple and std::array.
This isn't tested but seems to work on simple cases. But for large
objects the loop hits the constexpr iteration limit and compilation
fails, so it needs a sizeof(_Tp) < 64 or something.
using _ValueType
= typename iterator_traits<_ForwardIterator>::value_type;
using _Tp = remove_all_extents_t<_ValueType>;
// Need value-init to be equivalent to zero-init.
if constexpr (is_member_pointer<_Tp>::value)
return nullptr;
else if constexpr (!is_scalar<_Tp>::value)
{
using __trivial
= __and_<is_trivial<_ValueType>,
is_trivially_constructible<_ValueType>>;
if constexpr (__trivial::value)
{
struct _Bytes
{
unsigned char __b[sizeof(_Tp)];
#if __cpp_constexpr >= 201304
constexpr bool _M_nonzero() const
{
for (auto __c : __b)
if (__c)
return true;
return false;
}
#else
constexpr bool _M_nonzero(size_t __n = 0) const
{
return __n < sizeof(_Tp)
&& (__b[__n] || _M_nonzero(__n + 1));
}
#endif
};
if constexpr (__builtin_bit_cast(_Bytes, _Tp())._M_nonzero())
return nullptr;
}
}
using _Ptr = decltype(std::__to_address(__first));
// Cannot use memset if _Ptr is cv-qualified.
if constexpr (is_convertible<_Ptr, void*>::value)
return std::__to_address(__first);
More information about the Libstdc++
mailing list