- 
                Notifications
    
You must be signed in to change notification settings  - Fork 15.1k
 
[libc++] Refactor bitset::{any, all} #128445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
30e237c    to
    097854d      
    Compare
  
    097854d    to
    509e87c      
    Compare
  
    | 
          
 @llvm/pr-subscribers-libcxx Author: Peng Liu (winner245) ChangesThe  Full diff: https://github.com/llvm/llvm-project/pull/128445.diff 1 Files Affected: 
 diff --git a/libcxx/include/bitset b/libcxx/include/bitset
index f905b6f274e3f..8d0a5ec67a748 100644
--- a/libcxx/include/bitset
+++ b/libcxx/include/bitset
@@ -224,8 +224,12 @@ protected:
     return to_ullong(integral_constant < bool, _Size< sizeof(unsigned long long) * CHAR_BIT>());
   }
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT;
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT;
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT {
+    return std::find(__make_iter(0), __make_iter(_Size), false) == __make_iter(_Size);
+  }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT {
+    return std::find(__make_iter(0), __make_iter(_Size), true) != __make_iter(_Size);
+  }
   _LIBCPP_HIDE_FROM_ABI size_t __hash_code() const _NOEXCEPT;
 
 private:
@@ -388,40 +392,6 @@ __bitset<_N_words, _Size>::to_ullong(true_type, true_type) const {
   return __r;
 }
 
-template <size_t _N_words, size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool __bitset<_N_words, _Size>::all() const _NOEXCEPT {
-  // do middle whole words
-  size_t __n                  = _Size;
-  __const_storage_pointer __p = __first_;
-  for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
-    if (~*__p)
-      return false;
-  // do last partial word
-  if (__n > 0) {
-    __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
-    if (~*__p & __m)
-      return false;
-  }
-  return true;
-}
-
-template <size_t _N_words, size_t _Size>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool __bitset<_N_words, _Size>::any() const _NOEXCEPT {
-  // do middle whole words
-  size_t __n                  = _Size;
-  __const_storage_pointer __p = __first_;
-  for (; __n >= __bits_per_word; ++__p, __n -= __bits_per_word)
-    if (*__p)
-      return true;
-  // do last partial word
-  if (__n > 0) {
-    __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
-    if (*__p & __m)
-      return true;
-  }
-  return false;
-}
-
 template <size_t _N_words, size_t _Size>
 inline size_t __bitset<_N_words, _Size>::__hash_code() const _NOEXCEPT {
   size_t __h = 0;
@@ -713,8 +683,8 @@ public:
   _LIBCPP_HIDE_FROM_ABI bool operator!=(const bitset& __rhs) const _NOEXCEPT;
 #  endif
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool test(size_t __pos) const;
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT;
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT;
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool all() const _NOEXCEPT { return __base::all(); }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool any() const _NOEXCEPT { return __base::any(); }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool none() const _NOEXCEPT { return !any(); }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator<<(size_t __pos) const _NOEXCEPT;
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset operator>>(size_t __pos) const _NOEXCEPT;
@@ -901,16 +871,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool bitset<_Size>::test(siz
   return (*this)[__pos];
 }
 
-template <size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool bitset<_Size>::all() const _NOEXCEPT {
-  return __base::all();
-}
-
-template <size_t _Size>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool bitset<_Size>::any() const _NOEXCEPT {
-  return __base::any();
-}
-
 template <size_t _Size>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bitset<_Size>
 bitset<_Size>::operator<<(size_t __pos) const _NOEXCEPT {
 | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but can you please confirm that the codegen is the same?
| 
           In terms of codegen (https://godbolt.org/z/cdEbbTTnY at -O2), I found that the previous implementation generates more efficient assembly as it directly checks the underlying storage. In contrast, my proposed implementation introduces function calls to   | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Requesting changes since this degrades codegen.
669261f    to
    28fb22d      
    Compare
  
    | 
           The new refactoring yields exactly the same code in terms of codegen, as verified on https://godbolt.org/z/xx8hb4sPM.  | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the refactoring! I have a minor suggestion but LGTM otherwise.
| _LIBCPP_HIDE_FROM_ABI size_t __hash_code() const _NOEXCEPT; | ||
| 
               | 
          ||
| private: | ||
| struct __bit_not { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't block this patch on it, however it might be nice to consider a follow-up refactoring.
We have a __bit_not in valarray here: https://github.com/llvm/llvm-project/blob/main/libcxx/include/valarray#L491
We could provide a single __bit_not in https://github.com/llvm/llvm-project/blob/main/libcxx/include/__functional/operations.h#L220 and use it from both valarray and bitset.
28fb22d    to
    018d34e      
    Compare
  
    | 
          
 ✅ With the latest revision this PR passed the C/C++ code formatter.  | 
    
018d34e    to
    255b057      
    Compare
  
    255b057    to
    f26d014      
    Compare
  
    
This patch refactors the
all()andany()methods inbitsetto eliminate redundant code while preserving the performance. Code generation remains unchanged, as verified on Compiler Explorer.