Skip to content

Commit 8f0500b

Browse files
philnik777Priyanshu3820
authored andcommitted
[libc++] Forward std::all_of and std::none_of to std::any_of (llvm#167670)
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`).
1 parent 390703f commit 8f0500b

File tree

3 files changed

+151
-9
lines changed

3 files changed

+151
-9
lines changed

libcxx/include/__algorithm/all_of.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,28 @@
1010
#ifndef _LIBCPP___ALGORITHM_ALL_OF_H
1111
#define _LIBCPP___ALGORITHM_ALL_OF_H
1212

13+
#include <__algorithm/any_of.h>
1314
#include <__config>
1415
#include <__functional/identity.h>
1516
#include <__type_traits/invoke.h>
17+
#include <__utility/forward.h>
18+
#include <__utility/move.h>
1619

1720
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1821
# pragma GCC system_header
1922
#endif
2023

24+
_LIBCPP_PUSH_MACROS
25+
#include <__undef_macros>
26+
2127
_LIBCPP_BEGIN_NAMESPACE_STD
2228

2329
template <class _Iter, class _Sent, class _Proj, class _Pred>
2430
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
2531
__all_of(_Iter __first, _Sent __last, _Pred& __pred, _Proj& __proj) {
26-
for (; __first != __last; ++__first) {
27-
if (!std::__invoke(__pred, std::__invoke(__proj, *__first)))
28-
return false;
29-
}
30-
return true;
32+
using _Ref = decltype(std::__invoke(__proj, *__first));
33+
auto __negated_pred = [&__pred](_Ref __arg) -> bool { return !std::__invoke(__pred, std::forward<_Ref>(__arg)); };
34+
return !std::__any_of(std::move(__first), std::move(__last), __negated_pred, __proj);
3135
}
3236

3337
template <class _InputIterator, class _Predicate>
@@ -39,4 +43,6 @@ all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
3943

4044
_LIBCPP_END_NAMESPACE_STD
4145

46+
_LIBCPP_POP_MACROS
47+
4248
#endif // _LIBCPP___ALGORITHM_ALL_OF_H

libcxx/include/__algorithm/none_of.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
#ifndef _LIBCPP___ALGORITHM_NONE_OF_H
1111
#define _LIBCPP___ALGORITHM_NONE_OF_H
1212

13+
#include <__algorithm/any_of.h>
1314
#include <__config>
15+
#include <__functional/identity.h>
1416

1517
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1618
# pragma GCC system_header
@@ -21,10 +23,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2123
template <class _InputIterator, class _Predicate>
2224
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
2325
none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) {
24-
for (; __first != __last; ++__first)
25-
if (__pred(*__first))
26-
return false;
27-
return true;
26+
__identity __proj;
27+
return !std::__any_of(__first, __last, __pred, __proj);
2828
}
2929

3030
_LIBCPP_END_NAMESPACE_STD
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// <algorithm>
12+
//
13+
// Algorithms that take predicates should support predicates that return a non-boolean value as long as the
14+
// returned type is implicitly convertible to bool.
15+
16+
#include <algorithm>
17+
18+
#include <initializer_list>
19+
20+
#include "boolean_testable.h"
21+
22+
using Value = StrictComparable<int>;
23+
using Iterator = StrictBooleanIterator<Value*>;
24+
auto pred1 = StrictUnaryPredicate;
25+
auto pred2 = StrictBinaryPredicate;
26+
27+
void f(Iterator it, Iterator out, std::size_t n, Value const& val, std::initializer_list<Value> ilist) {
28+
(void)std::any_of(it, it, pred1);
29+
(void)std::all_of(it, it, pred1);
30+
(void)std::none_of(it, it, pred1);
31+
(void)std::find_if(it, it, pred1);
32+
(void)std::find_if_not(it, it, pred1);
33+
(void)std::find_first_of(it, it, it, it);
34+
(void)std::find_first_of(it, it, it, it, pred2);
35+
(void)std::adjacent_find(it, it);
36+
(void)std::adjacent_find(it, it, pred2);
37+
(void)std::mismatch(it, it, it, it);
38+
(void)std::mismatch(it, it, it, it, pred2);
39+
(void)std::mismatch(it, it, it);
40+
(void)std::mismatch(it, it, it);
41+
(void)std::mismatch(it, it, it, pred2);
42+
(void)std::equal(it, it, it, it);
43+
(void)std::equal(it, it, it, it, pred2);
44+
(void)std::equal(it, it, it);
45+
(void)std::equal(it, it, it, pred2);
46+
(void)std::lexicographical_compare(it, it, it, it);
47+
(void)std::lexicographical_compare(it, it, it, it, pred2);
48+
(void)std::partition_point(it, it, pred1);
49+
(void)std::lower_bound(it, it, val);
50+
(void)std::lower_bound(it, it, val, pred2);
51+
(void)std::upper_bound(it, it, val);
52+
(void)std::upper_bound(it, it, val, pred2);
53+
(void)std::equal_range(it, it, val);
54+
(void)std::equal_range(it, it, val, pred2);
55+
(void)std::binary_search(it, it, val);
56+
(void)std::binary_search(it, it, val, pred2);
57+
(void)std::min(val, val);
58+
(void)std::min(val, val, pred2);
59+
(void)std::min(ilist);
60+
(void)std::min(ilist, pred2);
61+
(void)std::max(val, val);
62+
(void)std::max(val, val, pred2);
63+
(void)std::max(ilist);
64+
(void)std::max(ilist, pred2);
65+
(void)std::minmax(val, val);
66+
(void)std::minmax(val, val, pred2);
67+
(void)std::minmax(ilist);
68+
(void)std::minmax(ilist, pred2);
69+
(void)std::min_element(it, it);
70+
(void)std::min_element(it, it, pred2);
71+
(void)std::max_element(it, it);
72+
(void)std::max_element(it, it, pred2);
73+
(void)std::minmax_element(it, it);
74+
(void)std::minmax_element(it, it, pred2);
75+
(void)std::count_if(it, it, pred1);
76+
(void)std::search(it, it, it, it);
77+
(void)std::search(it, it, it, it, pred2);
78+
(void)std::search_n(it, it, n, val);
79+
(void)std::search_n(it, it, n, val, pred2);
80+
(void)std::is_partitioned(it, it, pred1);
81+
(void)std::is_sorted(it, it);
82+
(void)std::is_sorted(it, it, pred2);
83+
(void)std::is_sorted_until(it, it);
84+
(void)std::is_sorted_until(it, it, pred2);
85+
(void)std::is_heap(it, it);
86+
(void)std::is_heap(it, it, pred2);
87+
(void)std::is_heap_until(it, it);
88+
(void)std::is_heap_until(it, it, pred2);
89+
(void)std::clamp(val, val, val);
90+
(void)std::clamp(val, val, val, pred2);
91+
(void)std::is_permutation(it, it, it, it);
92+
(void)std::is_permutation(it, it, it, it, pred2);
93+
(void)std::copy_if(it, it, out, pred1);
94+
(void)std::remove_copy_if(it, it, out, pred1);
95+
(void)std::remove_copy(it, it, out, val);
96+
(void)std::replace(it, it, val, val);
97+
(void)std::replace_if(it, it, pred1, val);
98+
(void)std::replace_copy_if(it, it, out, pred1, val);
99+
(void)std::replace_copy(it, it, out, val, val);
100+
(void)std::unique_copy(it, it, out, pred2);
101+
(void)std::partition_copy(it, it, out, out, pred1);
102+
(void)std::partial_sort_copy(it, it, it, it, pred2);
103+
(void)std::merge(it, it, it, it, out);
104+
(void)std::merge(it, it, it, it, out, pred2);
105+
(void)std::set_difference(it, it, it, it, out, pred2);
106+
(void)std::set_intersection(it, it, it, it, out, pred2);
107+
(void)std::set_symmetric_difference(it, it, it, it, out, pred2);
108+
(void)std::set_union(it, it, it, it, out, pred2);
109+
(void)std::remove_if(it, it, pred1);
110+
(void)std::remove(it, it, val);
111+
(void)std::unique(it, it, pred2);
112+
(void)std::partition(it, it, pred1);
113+
(void)std::stable_partition(it, it, pred1);
114+
(void)std::sort(it, it);
115+
(void)std::sort(it, it, pred2);
116+
(void)std::stable_sort(it, it);
117+
(void)std::stable_sort(it, it, pred2);
118+
(void)std::partial_sort(it, it, it);
119+
(void)std::partial_sort(it, it, it, pred2);
120+
(void)std::nth_element(it, it, it);
121+
(void)std::nth_element(it, it, it, pred2);
122+
(void)std::inplace_merge(it, it, it);
123+
(void)std::inplace_merge(it, it, it, pred2);
124+
(void)std::make_heap(it, it);
125+
(void)std::make_heap(it, it, pred2);
126+
(void)std::push_heap(it, it);
127+
(void)std::push_heap(it, it, pred2);
128+
(void)std::pop_heap(it, it);
129+
(void)std::pop_heap(it, it, pred2);
130+
(void)std::sort_heap(it, it);
131+
(void)std::sort_heap(it, it, pred2);
132+
(void)std::prev_permutation(it, it);
133+
(void)std::prev_permutation(it, it, pred2);
134+
(void)std::next_permutation(it, it);
135+
(void)std::next_permutation(it, it, pred2);
136+
}

0 commit comments

Comments
 (0)