[PATCH 2/3] libstdc++: Optimize __uninitialized_default using memset

2024-06-27 Thread Maciej Cencora
Hi,

not sure whether I've missed some conditional that would exclude this case,
but your change seems to incorrectly handle trivial types that have a
non-zero bit pattern of value-initialized object, e.g. pointer to member.

Regards,
Maciej Cencora


Re: [PATCH 2/3] libstdc++: Optimize __uninitialized_default using memset

2024-06-27 Thread Maciej Cencora
You could include some of the bigger classes by checking whether the class
type is bit_cast-able to std::array of bytes, and that bitcasted output is
equal to value-initialized array.

Regards,
Maciej

czw., 27 cze 2024 o 14:50 Jonathan Wakely  napisał(a):

> On Thu, 27 Jun 2024 at 13:49, Jonathan Wakely  wrote:
> >
> > On Thu, 27 Jun 2024 at 13:40, Maciej Cencora wrote:
> > >
> > > Hi,
> > >
> > > not sure whether I've missed some conditional that would exclude this
> case, but your change seems to incorrectly handle trivial types that have a
> non-zero bit pattern of value-initialized object, e.g. pointer to member.
> >
> > Good point. I started working on this optimization after last week's
> > https://gcc.gnu.org/r15-1550-g139d65d1f5a60a where is_trivial is
> > appropriate, because valarray only supports numeric types, not
> > pointers to members.
> >
> > But the uninitialized memory algos don't have that restriction, so
> > need to be more careful.
> >
> > I think memset is OK for arithmetic types, enums, pointers, nullptr_t,
> > and trivial classes ... except when those trivial classes contain
> > pointers to members. Which we can't tell.
> >
> > So maybe we can only do it for is_trivial && ((is_scalar and not
> > is_member_pointer) or (is_class and is_empty)).
>
> I suppose any trivial class type smaller than sizeof(int T::*) would
> be OK, because it can't hold a member pointer if it's smaller than
> one.
>
>


Re: [PATCH 2/3] libstdc++: Optimize __uninitialized_default using memset

2024-06-27 Thread Maciej Cencora
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.

Regards,
Maciej Cencora

czw., 27 cze 2024 o 14:57 Maciej Cencora  napisał(a):

> You could include some of the bigger classes by checking whether the class
> type is bit_cast-able to std::array of bytes, and that bitcasted output is
> equal to value-initialized array.
>
> Regards,
> Maciej
>
> czw., 27 cze 2024 o 14:50 Jonathan Wakely  napisał(a):
>
>> On Thu, 27 Jun 2024 at 13:49, Jonathan Wakely  wrote:
>> >
>> > On Thu, 27 Jun 2024 at 13:40, Maciej Cencora wrote:
>> > >
>> > > Hi,
>> > >
>> > > not sure whether I've missed some conditional that would exclude this
>> case, but your change seems to incorrectly handle trivial types that have a
>> non-zero bit pattern of value-initialized object, e.g. pointer to member.
>> >
>> > Good point. I started working on this optimization after last week's
>> > https://gcc.gnu.org/r15-1550-g139d65d1f5a60a where is_trivial is
>> > appropriate, because valarray only supports numeric types, not
>> > pointers to members.
>> >
>> > But the uninitialized memory algos don't have that restriction, so
>> > need to be more careful.
>> >
>> > I think memset is OK for arithmetic types, enums, pointers, nullptr_t,
>> > and trivial classes ... except when those trivial classes contain
>> > pointers to members. Which we can't tell.
>> >
>> > So maybe we can only do it for is_trivial && ((is_scalar and not
>> > is_member_pointer) or (is_class and is_empty)).
>>
>> I suppose any trivial class type smaller than sizeof(int T::*) would
>> be OK, because it can't hold a member pointer if it's smaller than
>> one.
>>
>>


Re: [PATCH 2/3] libstdc++: Optimize __uninitialized_default using memset

2024-06-27 Thread Maciej Cencora
But constexpr-ness of bit_cast has additional limitations and e.g.
providing an union as _Tp would be a hard-error. So we have two options:
 - before bitcasting check if type can be bitcast-ed at compile-time,
 - change the 'if constexpr' to regular 'if'.

If we go with the second solution then we will include classes with
pointers, and unions.
Additionally we could also include types with padding by passing
zero-initialized object (like a class-scope static constexpr or global)
into bit_cast... but then such a variable would be ODR-used and most-likely
won't be optimized out.

I guess the best option would be to introduce in C++ language a new
compiler-backed type trait like:
std::zero_initialized_object_has_all_zeros_object_representation.

Regards,
Maciej

pt., 28 cze 2024 o 00:25 Jonathan Wakely  napisał(a):

> On Thu, 27 Jun 2024 at 14:27, Maciej Cencora  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_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);
>
>


Re: [WIP RFC] libstdc++: add module std

2024-10-18 Thread Maciej Cencora
Hi,

Thanks for working on this!

> stdc++.h also doesn't include the eternally deprecated .  There
are some other deprecated facilities that I notice are included: 
and float_denorm_style, at least.  It would be nice for L{E,}WG to clarify
whether module std is intended to include interfaces that were deprecated in
C++23, since ancient code isn't going to be relying on module std.

Per P2465r3 Standard Library Modules std and std.compat:
Are deprecated features provided by the Standard Library modules?
Yes. This is implied by the normative wording.

While doing some light testing, one thing that immediately popped up
is that we need to export __normal_iterator related operators from
__gnu_cxx namespace.
Otherwise it is impossible to even use std::vector in range-based for loops.

But I think a better solution (than exporting such impl details) is to
make these operators hidden friends.


Another thing - P2465r3 mentions only lerp, byte and related ops as
special w.r.t skipping export from global namespace in std.compat, but
for some reason Microsoft's impl treats 3-arg hypot as special as
well.


Regards,
Maciej Cencora


RE: [PATCH 2/2] libstdc++: Implement for C++26 (P3370R1)

2024-12-03 Thread Maciej Cencora
Hi,

two issues:
1) #include  is missing in std.compat.cc.in

2) does the updated std.compat module actually work? When I experimented
with implementing the std module in gcc, I couldn't #include standard
headers, after they were imported via std module (since GMF merging isn't
implemented yet), i.e. following doesn't work:

import std;
#include 

And that's exactly the scenario we have right now with your #include
 added to std.compat.cc.in ( transitively includes
 and  transitively includes  and )

Regards,
Maciej


RE: [PATCH v2] libstdc++: Implement C++26 features (P2546R5)

2025-04-11 Thread Maciej Cencora
Hi,

unless I missed it, updates of std and std.compat modules are missing.

Regards,
Maciej


Re: [PATCH] c++, libstdc++: Implement C++26 P2830R10 - Constexpr Type Ordering

2025-06-25 Thread Maciej Cencora
Hi,

update of std module is missing.

Regards,
Maciej


[committed] libstdc++: Fix uses of non-reserved names in headers

2023-02-16 Thread Maciej Cencora via Gcc-patches
Hi,

instead of uglyfing all the libstdc++ code wouldn't it be simpler to
just ignore all non-reserved macro expansions (+ some special ones
like assert) inside system headers on compiler level?

Regards,
Maciej


Re: [committed] libstdc++: Simplify variant access functions

2021-10-15 Thread Maciej Cencora via Gcc-patches
Hi,

variant getter can be implemented in C++17 without using "recursive"
calls, but by generating a list of member pointers and applying them
with fold expression. Here's an example:

https://godbolt.org/z/3vcKjWjPG

Regards,
Maciej


[PATCH] tree: Fix up tree_code_{length,type}

2023-01-27 Thread Maciej Cencora via Gcc-patches
Hi,

you can emulate C++17 inline variables in C++11 with either of the two ways:

1) via a template helper
template 
struct Helper
{
static constexpr unsigned value[4] = {1, 2, 3, 4};
};

template 
constexpr unsigned Helper::value[4];

static constexpr auto& arr = Helper<>::value;

2) extern constexpr + weak attribute
[[gnu::weak]] extern constexpr unsigned arr[] = {1, 2, 3, 4};

Regards,
Maciej