Skip to content

Commit 1b0553c

Browse files
authored
[libc++] Use _BitInt and __builtin_popcountg in bitset::count() (#160679)
This has multiple benefits: 1) The compiler has to do way less work to figure out things fold into a simple `popcount`, improving compile times quite a bit 2) The compiler inlines better, since the compile doesn't have to do complicated optimizations to get to the same point. Looking at the pipeline, it seems that without this, LLVM has to go all the way to GVN to get to the same code as there is after the first InstCombine pass with this change. Currently this applies only to `bitset`s with at most 64 bits, but that is by far the most common case.
1 parent 1685a6a commit 1b0553c

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

libcxx/include/bitset

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,16 @@ bitset<_Size>::to_string(char __zero, char __one) const {
867867

868868
template <size_t _Size>
869869
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 size_t bitset<_Size>::count() const _NOEXCEPT {
870-
return static_cast<size_t>(std::count(__base::__make_iter(0), __base::__make_iter(_Size), true));
870+
# if defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(_LIBCPP_CXX03_LANG)
871+
if constexpr (_Size == 0) {
872+
return 0;
873+
} else if constexpr (_Size <= __base::__bits_per_word) {
874+
return __builtin_popcountg(static_cast<unsigned _BitInt(_Size)>(__base::__first_));
875+
} else
876+
# endif
877+
{
878+
return static_cast<size_t>(std::count(__base::__make_iter(0), __base::__make_iter(_Size), true));
879+
}
871880
}
872881

873882
template <size_t _Size>

0 commit comments

Comments
 (0)