Skip to content

Commit f85a06d

Browse files
winner245sivan-shani
authored andcommitted
[libc++] Simplify __bitset::__init (llvm#121357)
This PR simplifies `__bitset::__init` into a more compact and readable form, which avoids redundant computations of a `size_t` value and eliminates the overhead of a local array.
1 parent f0714f8 commit f85a06d

File tree

2 files changed

+18
-17
lines changed

2 files changed

+18
-17
lines changed

libcxx/include/bitset

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -273,26 +273,16 @@ inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset() _NOEXCEPT
273273

274274
template <size_t _N_words, size_t _Size>
275275
void __bitset<_N_words, _Size>::__init(unsigned long long __v, false_type) _NOEXCEPT {
276-
__storage_type __t[sizeof(unsigned long long) / sizeof(__storage_type)];
277-
size_t __sz = _Size;
278-
for (size_t __i = 0; __i < sizeof(__t) / sizeof(__t[0]); ++__i, __v >>= __bits_per_word, __sz -= __bits_per_word)
279-
if (__sz < __bits_per_word)
280-
__t[__i] = static_cast<__storage_type>(__v) & (1ULL << __sz) - 1;
281-
else
282-
__t[__i] = static_cast<__storage_type>(__v);
283-
284-
std::copy(__t, __t + sizeof(__t) / sizeof(__t[0]), __first_);
285-
std::fill(
286-
__first_ + sizeof(__t) / sizeof(__t[0]), __first_ + sizeof(__first_) / sizeof(__first_[0]), __storage_type(0));
276+
const size_t __n_words = std::min((sizeof(unsigned long long) - 1) / sizeof(__storage_type) + 1, _N_words);
277+
for (size_t __i = 0; __i < __n_words; ++__i, __v >>= __bits_per_word)
278+
__first_[__i] = static_cast<__storage_type>(__v);
279+
std::fill(__first_ + __n_words, __first_ + _N_words, __storage_type(0));
287280
}
288281

289282
template <size_t _N_words, size_t _Size>
290283
inline _LIBCPP_HIDE_FROM_ABI void __bitset<_N_words, _Size>::__init(unsigned long long __v, true_type) _NOEXCEPT {
291284
__first_[0] = __v;
292-
if (_Size < __bits_per_word)
293-
__first_[0] &= (1ULL << _Size) - 1;
294-
295-
std::fill(__first_ + 1, __first_ + sizeof(__first_) / sizeof(__first_[0]), __storage_type(0));
285+
std::fill(__first_ + 1, __first_ + _N_words, __storage_type(0));
296286
}
297287

298288
# endif // _LIBCPP_CXX03_LANG
@@ -314,7 +304,7 @@ inline _LIBCPP_CONSTEXPR __bitset<_N_words, _Size>::__bitset(unsigned long long
314304
# endif
315305
{
316306
# ifdef _LIBCPP_CXX03_LANG
317-
__init(__v, integral_constant<bool, sizeof(unsigned long long) == sizeof(__storage_type)>());
307+
__init(__v, integral_constant<bool, sizeof(unsigned long long) <= sizeof(__storage_type)>());
318308
# endif
319309
}
320310

@@ -658,7 +648,8 @@ public:
658648

659649
// 23.3.5.1 constructors:
660650
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bitset() _NOEXCEPT {}
661-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bitset(unsigned long long __v) _NOEXCEPT : __base(__v) {}
651+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bitset(unsigned long long __v) _NOEXCEPT
652+
: __base(sizeof(unsigned long long) * CHAR_BIT <= _Size ? __v : __v & ((1ULL << _Size) - 1)) {}
662653
template <class _CharT, __enable_if_t<_IsCharLikeType<_CharT>::value, int> = 0>
663654
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit bitset(
664655
const _CharT* __str,

libcxx/test/benchmarks/bitset.bench.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,14 @@ BENCHMARK(BM_BitsetToString<262144>)->Arg(50)->Name("BM_BitsetToString<262144>/U
103103
BENCHMARK(BM_BitsetToString<524288>)->Arg(50)->Name("BM_BitsetToString<524288>/Uniform (50%)");
104104
BENCHMARK(BM_BitsetToString<1048576>)->Arg(50)->Name("BM_BitsetToString<1048576>/Uniform (50%)"); // 1 << 20
105105

106+
static void BM_ctor_ull(benchmark::State& state) {
107+
unsigned long long val = (1ULL << state.range(0)) - 1;
108+
for (auto _ : state) {
109+
std::bitset<128> b(val);
110+
benchmark::DoNotOptimize(b);
111+
}
112+
}
113+
114+
BENCHMARK(BM_ctor_ull)->DenseRange(1, 63);
115+
106116
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)