Skip to content
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

[libc++][C++26] P2562R1: constexpr Stable Sorting #110320

Merged
merged 38 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
2366f3c
constexpr stable_sort
PaulXiCao Sep 27, 2024
0ea964a
tests
PaulXiCao Sep 27, 2024
2a42516
update algorithm synopsis
PaulXiCao Sep 27, 2024
7cf77e7
update docs
PaulXiCao Sep 27, 2024
05a13a7
paper status: partial
PaulXiCao Oct 2, 2024
e5b51d9
remove include of internal header
PaulXiCao Oct 4, 2024
2ae4f9f
replace _LIBCPP_CONSTEXPR_SINCE_CXX26 by TEST_CONSTEXPR_CXX26
PaulXiCao Oct 4, 2024
bf47937
documentation: use proper function declaration
PaulXiCao Oct 4, 2024
5081abd
workaround for gcc bug with placement new
PaulXiCao Oct 5, 2024
9b139d3
workaround for gcc bug with placement new: fix lambda capturing
PaulXiCao Oct 6, 2024
7dbd004
workaround for gcc bug with placement new: v3
PaulXiCao Oct 6, 2024
363eb7c
workaround for gcc bug with placement new: v4
PaulXiCao Oct 6, 2024
1131098
workaround for gcc bug with placement new: v5 (test)
PaulXiCao Oct 11, 2024
2aada1a
workaround for gcc bug with placement new: v6
PaulXiCao Oct 12, 2024
8f16d4f
workaround for gcc bug with placement new: v7
PaulXiCao Oct 13, 2024
2f90ac3
test: use TEST_STD_VER
PaulXiCao Oct 13, 2024
c91a11a
increase constexpr-steps as unstable abi tests cause more evaluation …
PaulXiCao Oct 18, 2024
47afcf1
simplify testing (possible b.c. increase of constexpr-steps)
PaulXiCao Oct 18, 2024
61cc660
refactor tests: do not extract tests into separate functions
PaulXiCao Nov 9, 2024
648f126
tests: match previous formatting
PaulXiCao Nov 9, 2024
d24a714
disable large test at compiletime
PaulXiCao Nov 9, 2024
61a5556
use construct_at for placement new gcc workaround
PaulXiCao Nov 9, 2024
58ab844
tests: fix static asserts
PaulXiCao Nov 9, 2024
e9ec615
test: gcc hits constexpr operation limit
PaulXiCao Nov 10, 2024
87b5629
add missing CONSTEXPR26 macros
PaulXiCao Nov 22, 2024
a7eb8c6
simplify/fix placement new macro
PaulXiCao Nov 22, 2024
50e5099
formatting
PaulXiCao Nov 23, 2024
af79957
make use of std::__construct_at
PaulXiCao Dec 13, 2024
f26f238
cleanup: undo unnecessary temp variable
PaulXiCao Dec 13, 2024
96c36b2
test: use macro TEST_IS_CONSTANT_EVALUATED
PaulXiCao Dec 13, 2024
032d66a
test: return bool from test()
PaulXiCao Dec 13, 2024
18e8581
increase constexpr-steps for gcc
PaulXiCao Dec 20, 2024
888097c
Merge branch 'main' into constexpr_stable_sort_v2
ldionne Jan 13, 2025
88dc8c8
Fix tests for stable_sort with predicate too
ldionne Jan 13, 2025
6c10833
Fix module issue
ldionne Jan 13, 2025
d5130b5
Try bumping constexpr ops limit on GCC
ldionne Jan 13, 2025
d1d4653
Bump GCC constexpr limit
ldionne Jan 13, 2025
e2b1607
Adjust constexpr steps
ldionne Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cPapers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"`P2497R0 <https://wg21.link/P2497R0>`__","Testing for success or failure of ``<charconv>`` functions","2023-06 (Varna)","|Complete|","18",""
"`P2592R3 <https://wg21.link/P2592R3>`__","Hashing support for ``std::chrono`` value classes","2023-06 (Varna)","","",""
"`P2587R3 <https://wg21.link/P2587R3>`__","``to_string`` or not ``to_string``","2023-06 (Varna)","","",""
"`P2562R1 <https://wg21.link/P2562R1>`__","``constexpr`` Stable Sorting","2023-06 (Varna)","","",""
"`P2562R1 <https://wg21.link/P2562R1>`__","``constexpr`` Stable Sorting","2023-06 (Varna)","|Partial|","20.0",""
"`P2545R4 <https://wg21.link/P2545R4>`__","Read-Copy Update (RCU)","2023-06 (Varna)","","",""
"`P2530R3 <https://wg21.link/P2530R3>`__","Hazard Pointers for C++26","2023-06 (Varna)","","",""
"`P2538R1 <https://wg21.link/P2538R1>`__","ADL-proof ``std::projected``","2023-06 (Varna)","|Complete|","18",""
Expand Down
14 changes: 7 additions & 7 deletions libcxx/include/__algorithm/inplace_merge.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,17 @@ class __invert // invert the sense of a comparison
_Predicate __p_;

public:
_LIBCPP_HIDE_FROM_ABI __invert() {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __invert() {}

_LIBCPP_HIDE_FROM_ABI explicit __invert(_Predicate __p) : __p_(__p) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __invert(_Predicate __p) : __p_(__p) {}

template <class _T1>
_LIBCPP_HIDE_FROM_ABI bool operator()(const _T1& __x) {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _T1& __x) {
return !__p_(__x);
}

template <class _T1, class _T2>
_LIBCPP_HIDE_FROM_ABI bool operator()(const _T1& __x, const _T2& __y) {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator()(const _T1& __x, const _T2& __y) {
return __p_(__y, __x);
}
};
Expand All @@ -66,7 +66,7 @@ template <class _AlgPolicy,
class _InputIterator2,
class _Sent2,
class _OutputIterator>
_LIBCPP_HIDE_FROM_ABI void __half_inplace_merge(
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __half_inplace_merge(
_InputIterator1 __first1,
_Sent1 __last1,
_InputIterator2 __first2,
Expand All @@ -91,7 +91,7 @@ _LIBCPP_HIDE_FROM_ABI void __half_inplace_merge(
}

template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
_LIBCPP_HIDE_FROM_ABI void __buffered_inplace_merge(
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __buffered_inplace_merge(
_BidirectionalIterator __first,
_BidirectionalIterator __middle,
_BidirectionalIterator __last,
Expand Down Expand Up @@ -122,7 +122,7 @@ _LIBCPP_HIDE_FROM_ABI void __buffered_inplace_merge(
}

template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
void __inplace_merge(
_LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge(
_BidirectionalIterator __first,
_BidirectionalIterator __middle,
_BidirectionalIterator __last,
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__algorithm/sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last,
// Sort the iterator range [__first, __last) using the comparator __comp using
// the insertion sort algorithm.
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
_LIBCPP_HIDE_FROM_ABI void
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
__insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;

Expand Down
76 changes: 40 additions & 36 deletions libcxx/include/__algorithm/stable_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <__cstddef/ptrdiff_t.h>
#include <__debug_utils/strict_weak_ordering_check.h>
#include <__iterator/iterator_traits.h>
#include <__memory/construct_at.h>
#include <__memory/destruct_n.h>
#include <__memory/unique_ptr.h>
#include <__memory/unique_temporary_buffer.h>
Expand All @@ -41,7 +42,7 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD

template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
_LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __insertion_sort_move(
_BidirectionalIterator __first1,
_BidirectionalIterator __last1,
typename iterator_traits<_BidirectionalIterator>::value_type* __first2,
Expand All @@ -53,19 +54,19 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
__destruct_n __d(0);
unique_ptr<value_type, __destruct_n&> __h(__first2, __d);
value_type* __last2 = __first2;
::new ((void*)__last2) value_type(_Ops::__iter_move(__first1));
std::__construct_at(__last2, _Ops::__iter_move(__first1));
__d.template __incr<value_type>();
for (++__last2; ++__first1 != __last1; ++__last2) {
value_type* __j2 = __last2;
value_type* __i2 = __j2;
if (__comp(*__first1, *--__i2)) {
::new ((void*)__j2) value_type(std::move(*__i2));
std::__construct_at(__j2, std::move(*__i2));
__d.template __incr<value_type>();
for (--__j2; __i2 != __first2 && __comp(*__first1, *--__i2); --__j2)
*__j2 = std::move(*__i2);
*__j2 = _Ops::__iter_move(__first1);
} else {
::new ((void*)__j2) value_type(_Ops::__iter_move(__first1));
std::__construct_at(__j2, _Ops::__iter_move(__first1));
__d.template __incr<value_type>();
}
}
Expand All @@ -74,7 +75,7 @@ _LIBCPP_HIDE_FROM_ABI void __insertion_sort_move(
}

template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2>
_LIBCPP_HIDE_FROM_ABI void __merge_move_construct(
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_construct(
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
Expand All @@ -89,30 +90,30 @@ _LIBCPP_HIDE_FROM_ABI void __merge_move_construct(
for (; true; ++__result) {
if (__first1 == __last1) {
for (; __first2 != __last2; ++__first2, (void)++__result, __d.template __incr<value_type>())
::new ((void*)__result) value_type(_Ops::__iter_move(__first2));
std::__construct_at(__result, _Ops::__iter_move(__first2));
__h.release();
return;
}
if (__first2 == __last2) {
for (; __first1 != __last1; ++__first1, (void)++__result, __d.template __incr<value_type>())
::new ((void*)__result) value_type(_Ops::__iter_move(__first1));
std::__construct_at(__result, _Ops::__iter_move(__first1));
__h.release();
return;
}
if (__comp(*__first2, *__first1)) {
::new ((void*)__result) value_type(_Ops::__iter_move(__first2));
std::__construct_at(__result, _Ops::__iter_move(__first2));
__d.template __incr<value_type>();
++__first2;
} else {
::new ((void*)__result) value_type(_Ops::__iter_move(__first1));
std::__construct_at(__result, _Ops::__iter_move(__first1));
__d.template __incr<value_type>();
++__first1;
}
}
}

template <class _AlgPolicy, class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
_LIBCPP_HIDE_FROM_ABI void __merge_move_assign(
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __merge_move_assign(
PaulXiCao marked this conversation as resolved.
Show resolved Hide resolved
_InputIterator1 __first1,
_InputIterator1 __last1,
_InputIterator2 __first2,
Expand Down Expand Up @@ -140,41 +141,43 @@ _LIBCPP_HIDE_FROM_ABI void __merge_move_assign(
}

template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
void __stable_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
ptrdiff_t __buff_size);
_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(
_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
ptrdiff_t __buff_size);

template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
void __stable_sort_move(_RandomAccessIterator __first1,
_RandomAccessIterator __last1,
_Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
typename iterator_traits<_RandomAccessIterator>::value_type* __first2) {
_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort_move(
_RandomAccessIterator __first1,
_RandomAccessIterator __last1,
_Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
typename iterator_traits<_RandomAccessIterator>::value_type* __first2) {
using _Ops = _IterOps<_AlgPolicy>;

typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
switch (__len) {
case 0:
return;
case 1:
::new ((void*)__first2) value_type(_Ops::__iter_move(__first1));
std::__construct_at(__first2, _Ops::__iter_move(__first1));
return;
case 2:
__destruct_n __d(0);
unique_ptr<value_type, __destruct_n&> __h2(__first2, __d);
if (__comp(*--__last1, *__first1)) {
::new ((void*)__first2) value_type(_Ops::__iter_move(__last1));
std::__construct_at(__first2, _Ops::__iter_move(__last1));
__d.template __incr<value_type>();
++__first2;
::new ((void*)__first2) value_type(_Ops::__iter_move(__first1));
std::__construct_at(__first2, _Ops::__iter_move(__first1));
} else {
::new ((void*)__first2) value_type(_Ops::__iter_move(__first1));
std::__construct_at(__first2, _Ops::__iter_move(__first1));
__d.template __incr<value_type>();
++__first2;
::new ((void*)__first2) value_type(_Ops::__iter_move(__last1));
std::__construct_at(__first2, _Ops::__iter_move(__last1));
}
__h2.release();
return;
Expand Down Expand Up @@ -218,12 +221,13 @@ _LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_max_bound() {
#endif // _LIBCPP_STD_VER >= 17

template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
void __stable_sort(_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
ptrdiff_t __buff_size) {
_LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(
_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __len,
typename iterator_traits<_RandomAccessIterator>::value_type* __buff,
ptrdiff_t __buff_size) {
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
switch (__len) {
Expand Down Expand Up @@ -279,7 +283,7 @@ void __stable_sort(_RandomAccessIterator __first,
}

template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI void
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
__stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare& __comp) {
using value_type = typename iterator_traits<_RandomAccessIterator>::value_type;
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
Expand All @@ -298,18 +302,18 @@ __stable_sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last,
}

template <class _RandomAccessIterator, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI void
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
std::__stable_sort_impl<_ClassicAlgPolicy>(std::move(__first), std::move(__last), __comp);
}

template <class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
std::stable_sort(__first, __last, __less<>());
}

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___ALGORITHM_STABLE_SORT_H
20 changes: 10 additions & 10 deletions libcxx/include/__memory/destruct_n.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,35 @@ struct __destruct_n {
size_t __size_;

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI void __process(_Tp* __p, false_type) _NOEXCEPT {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __process(_Tp* __p, false_type) _NOEXCEPT {
for (size_t __i = 0; __i < __size_; ++__i, ++__p)
__p->~_Tp();
}

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI void __process(_Tp*, true_type) _NOEXCEPT {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __process(_Tp*, true_type) _NOEXCEPT {}

_LIBCPP_HIDE_FROM_ABI void __incr(false_type) _NOEXCEPT { ++__size_; }
_LIBCPP_HIDE_FROM_ABI void __incr(true_type) _NOEXCEPT {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __incr(false_type) _NOEXCEPT { ++__size_; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __incr(true_type) _NOEXCEPT {}

_LIBCPP_HIDE_FROM_ABI void __set(size_t __s, false_type) _NOEXCEPT { __size_ = __s; }
_LIBCPP_HIDE_FROM_ABI void __set(size_t, true_type) _NOEXCEPT {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set(size_t __s, false_type) _NOEXCEPT { __size_ = __s; }
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set(size_t, true_type) _NOEXCEPT {}

public:
_LIBCPP_HIDE_FROM_ABI explicit __destruct_n(size_t __s) _NOEXCEPT : __size_(__s) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __destruct_n(size_t __s) _NOEXCEPT : __size_(__s) {}

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI void __incr() _NOEXCEPT {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __incr() _NOEXCEPT {
__incr(integral_constant<bool, is_trivially_destructible<_Tp>::value>());
}

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI void __set(size_t __s, _Tp*) _NOEXCEPT {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set(size_t __s, _Tp*) _NOEXCEPT {
__set(__s, integral_constant<bool, is_trivially_destructible<_Tp>::value>());
}

template <class _Tp>
_LIBCPP_HIDE_FROM_ABI void operator()(_Tp* __p) _NOEXCEPT {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator()(_Tp* __p) _NOEXCEPT {
__process(__p, integral_constant<bool, is_trivially_destructible<_Tp>::value>());
}
};
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -1530,11 +1530,11 @@ template <class RandomAccessIterator, class Compare>
sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);

template <class RandomAccessIterator>
void
constexpr void // constexpr in C++26
stable_sort(RandomAccessIterator first, RandomAccessIterator last);

template <class RandomAccessIterator, class Compare>
void
constexpr void // constexpr in C++26
stable_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);

template <class RandomAccessIterator>
Expand Down
5 changes: 4 additions & 1 deletion libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,10 @@ module std [system] {
module sort_heap { header "__algorithm/sort_heap.h" }
module sort { header "__algorithm/sort.h" }
module stable_partition { header "__algorithm/stable_partition.h" }
module stable_sort { header "__algorithm/stable_sort.h" }
module stable_sort {
header "__algorithm/stable_sort.h"
export std.memory.unique_temporary_buffer // TODO: Workaround for https://github.com/llvm/llvm-project/issues/120108
}
module swap_ranges { header "__algorithm/swap_ranges.h" }
module three_way_comp_ref_type { header "__algorithm/three_way_comp_ref_type.h" }
module transform { header "__algorithm/transform.h" }
Expand Down
Loading
Loading