Skip to content

Conversation

@philnik777
Copy link
Contributor

This allows propagating optimizations to different algorithms by just optimizing the lowest one. This is especially relevant now that we start optimizing how we're iterating through ranges (e.g. the segmented iterator optimizations) and adding assumptions so the compier can better leverage semantics guaranteed by the standard (e.g. __builtin_assume_dereferenceable).

@philnik777 philnik777 changed the title [libc++] Forward std::all_of and std::none_of to std::all_of [libc++] Forward std::all_of and std::none_of to std::any_of Nov 12, 2025
@ldionne ldionne marked this pull request as ready for review November 12, 2025 16:21
@ldionne ldionne requested a review from a team as a code owner November 12, 2025 16:21
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Nov 12, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 12, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

This allows propagating optimizations to different algorithms by just optimizing the lowest one. This is especially relevant now that we start optimizing how we're iterating through ranges (e.g. the segmented iterator optimizations) and adding assumptions so the compier can better leverage semantics guaranteed by the standard (e.g. __builtin_assume_dereferenceable).


Full diff: https://github.com/llvm/llvm-project/pull/167670.diff

2 Files Affected:

  • (modified) libcxx/include/__algorithm/all_of.h (+5-5)
  • (modified) libcxx/include/__algorithm/none_of.h (+2-4)
diff --git a/libcxx/include/__algorithm/all_of.h b/libcxx/include/__algorithm/all_of.h
index 6acc117fc47bc..bed6fdb073f80 100644
--- a/libcxx/include/__algorithm/all_of.h
+++ b/libcxx/include/__algorithm/all_of.h
@@ -10,9 +10,11 @@
 #ifndef _LIBCPP___ALGORITHM_ALL_OF_H
 #define _LIBCPP___ALGORITHM_ALL_OF_H
 
+#include <__algorithm/any_of.h>
 #include <__config>
 #include <__functional/identity.h>
 #include <__type_traits/invoke.h>
+#include <__utility/move.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -23,11 +25,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _Iter, class _Sent, class _Proj, class _Pred>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
 __all_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
-  for (; __first != __last; ++__first) {
-    if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
-      return false;
-  }
-  return true;
+  using _Ref          = decltype(std::__invoke(__proj, *__first));
+  auto __wrapped_pred = [&__pred](_Ref __arg) { return !std::__invoke(__pred, std::forward<_Ref>(__arg)); };
+  return !std::__any_of(std::move(__first), std::move(__last), __wrapped_pred, __proj);
 }
 
 template <class _InputIterator, class _Predicate>
diff --git a/libcxx/include/__algorithm/none_of.h b/libcxx/include/__algorithm/none_of.h
index e6bd197622292..0ccdb4e0b0ec0 100644
--- a/libcxx/include/__algorithm/none_of.h
+++ b/libcxx/include/__algorithm/none_of.h
@@ -10,6 +10,7 @@
 #ifndef _LIBCPP___ALGORITHM_NONE_OF_H
 #define _LIBCPP___ALGORITHM_NONE_OF_H
 
+#include <__algorithm/any_of.h>
 #include <__config>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -21,10 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _InputIterator, class _Predicate>
 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
 none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
-  for (; __first != __last; ++__first)
-    if (__pred(*__first))
-      return false;
-  return true;
+  return !std::any_of(__first, __last, __pred);
 }
 
 _LIBCPP_END_NAMESPACE_STD

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense, have a few comments.

}
return true;
using _Ref = decltype(std::__invoke(__proj, *__first));
auto __wrapped_pred = [&__pred](_Ref __arg) { return !std::__invoke(__pred, std::forward<_Ref>(__arg)); };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there is any benefit to spell _Ref out, rather than just taking a forwarding reference? is the bahaviour same if the _Ref is a PR value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there is: the compiler doesn't crash. (See #145881)

@github-actions
Copy link

github-actions bot commented Nov 17, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777 philnik777 force-pushed the forward_all_none_of branch 2 times, most recently from 92250df to 622f157 Compare November 18, 2025 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants