Conditionally on is_constant_evaluated() being false, bitset::reset delegate to __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT)) and uses a loop otherwise. In contrast, bitset::set unconditionally has a raw loop. Can't bitset::set also not similarly use __builtin_memset(_M_w, 0xFF, _Nw * sizeof(_WordT)); when is_constant_evaluated() is false?
Yup, I don't see why not.
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:e7ae13a858f36031b8fd3aa07362752ff2b19b2e commit r14-9002-ge7ae13a858f36031b8fd3aa07362752ff2b19b2e Author: Jonathan Wakely <jwakely@redhat.com> Date: Thu Feb 8 15:46:08 2024 +0000 libstdc++: Use memset to optimize std::bitset::set() [PR113807] As pointed out in the PR we already do this for reset(). libstdc++-v3/ChangeLog: PR libstdc++/113807 * include/std/bitset (bitset::set()): Use memset instead of a loop over the individual words.
Nice that this is changed now. I noticed a similar optimization could be done for bitset::operator== (more accurately: the helper _M_is_equal) where there is an opportunity to use memcmp, with a similar dance for consteval contexts. MSVC STL also does this.
I'm surprised the compiler can't optimize _M_do_set() and operator== already, but it looks like it doesn't recognize the trivial loops.
For unsigned int a[1024]; void foo (void) { for (int i = 0; i < 1024; ++i) a[i] = 0; } void bar (void) { for (int i = 0; i < 1024; ++i) a[i] = -1; } it certainly can.
It can also for an effective memset to a non-constant, but it has to be uniform, thus 'char'.
Hmm, yes, the code for bitset<N>::set() is actually similar to what we get for foo() in comment 5. The new version with memset does produce different (vectorized?) code though. For operator== the current code is quite branchy, and looks better with memcmp to me (but I don't really know what I'm talking about).
For bitset::operator==, I wonder why (at last in C++20 and later mode) it is not defaulted? For bitset::set and bitset::operator==, I also wonder why the manual loop vs memset/memcmp consteval logic is not delegated to a call of std::fill_n or std::equal, respectively? Then std::bitset is better proofed against future changes in the tradeoffs between manual loops, unrolled loops or library calls, no?
(In reply to rhalbersma from comment #8) > For bitset::operator==, I wonder why (at last in C++20 and later mode) it is > not defaulted? Because nobody bothered to change working code. > For bitset::set and bitset::operator==, I also wonder why the manual loop vs > memset/memcmp consteval logic is not delegated to a call of std::fill_n or > std::equal, respectively? Those aren't constexpr in C++14, but bitset is. If we delegated to those algos we'd still need a constexpr-in-C++14 manual loop.
GCC 14.1 is being released, retargeting bugs to GCC 14.2.