[libcxx-commits] [libcxx] [libc++] Optimize std::lexicographical_compare_three_way (PR #230336)
Advit Arora via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Oct 13 05:08:59 PDT 2026
https://github.com/advitrocks9 updated https://github.com/llvm/llvm-project/pull/230336
>From 2298d76b6ae2146eb7216af402be159a5f04b1c7 Mon Sep 17 00:00:00 2001
From: Advit Arora <advitarora2 at gmail.com>
Date: Thu, 8 Oct 2026 17:22:20 -0700
Subject: [PATCH 1/3] [libc++] Optimize std::lexicographical_compare_three_way
`std::lexicographical_compare_three_way` compares one element at a time, even with the default comparator on integers.
With `std::compare_three_way` on a type whose `==` compares bytes, the first unequal element is the first one whose bytes differ. So this finds it with `std::mismatch`, which is vectorized, or with `memcmp` for unsigned bytes, and calls the comparator once there. `lexicographical_compare` has done the same since #65279.
The fast path only applies to contiguous ranges compared with `std::compare_three_way` on trivially equality comparable types. Floating point, custom comparators and debug hardening keep the old loop. `compare_three_way` gets a `__desugars_to` tag for this, which is safe because `three_way_comparable_with` requires `a <=> b == 0` to match `a == b`.
```
ns, before -> after n=1 n=16 n=1024 n=65536
unsigned char 0.68 -> 2.46 5.26 -> 2.39 229 -> 10.3 14293 -> 942
signed char 0.69 -> 2.29 5.50 -> 1.84 236 -> 22.6 14826 -> 1447
int 0.67 -> 2.02 5.49 -> 2.72 238 -> 103 16807 -> 6438
```
Measured with the in-tree benchmark, clang -O3, Ryzen 9 5950X. One-element ranges are about 1.5 ns slower, the same tradeoff as the two-way version.
Container `operator<=>` uses a different comparator, so `vector<int> <=> vector<int>` isn't covered yet. I'll do that separately.
Fixes #129325
Assisted-by: Claude Code
---
libcxx/docs/ReleaseNotes/24.rst | 3 +
.../lexicographical_compare_three_way.h | 36 +++++++++-
libcxx/include/__compare/compare_three_way.h | 4 ++
libcxx/include/__type_traits/desugars_to.h | 3 +
...exicographical_compare_three_way.bench.cpp | 12 +++-
...lexicographical_compare_three_way.pass.cpp | 68 +++++++++++++++++++
6 files changed, 122 insertions(+), 4 deletions(-)
diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index 04f02ab66a773c..d6d0a92619a5f4 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -62,6 +62,9 @@ Improvements and New Features
-----------------------------
- ``basic_filebuf`` now supports files larger than 2GB on 32-bit AIX and 32-bit glibc targets.
+- ``std::lexicographical_compare_three_way`` has been optimized for contiguous ranges of integers and other trivially
+ equality comparable types, resulting in a performance improvement of up to 22x for ``unsigned char`` and 2.5x for
+ ``int``.
Deprecations and Removals
-------------------------
diff --git a/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/libcxx/include/__algorithm/lexicographical_compare_three_way.h
index 5be95c4d513471..46abf705b0710c 100644
--- a/libcxx/include/__algorithm/lexicographical_compare_three_way.h
+++ b/libcxx/include/__algorithm/lexicographical_compare_three_way.h
@@ -10,14 +10,22 @@
#define _LIBCPP___ALGORITHM_LEXICOGRAPHICAL_COMPARE_THREE_WAY_H
#include <__algorithm/min.h>
+#include <__algorithm/mismatch.h>
#include <__algorithm/three_way_comp_ref_type.h>
+#include <__algorithm/unwrap_iter.h>
#include <__compare/compare_three_way.h>
#include <__compare/ordering.h>
#include <__concepts/arithmetic.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__string/constexpr_c_functions.h>
#include <__type_traits/common_type.h>
+#include <__type_traits/desugars_to.h>
+#include <__type_traits/enable_if.h>
#include <__type_traits/is_constructible.h>
+#include <__type_traits/is_equality_comparable.h>
+#include <__type_traits/is_trivially_lexicographically_comparable.h>
+#include <__type_traits/is_volatile.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -62,6 +70,28 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_fast_pa
return __len1 <=> __len2;
}
+template <class _Tp,
+ class _Cmp,
+ __enable_if_t<__desugars_to_v<__compare_three_way_tag, _Cmp, _Tp, _Tp> && !is_volatile<_Tp>::value &&
+ __is_trivially_equality_comparable_v<_Tp, _Tp>,
+ int> = 0>
+_LIBCPP_HIDE_FROM_ABI constexpr auto
+__lexicographical_compare_three_way_fast_path(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Cmp& __comp)
+ -> decltype(__comp(*__first1, *__first2)) {
+ auto __len1 = __last1 - __first1;
+ auto __len2 = __last2 - __first2;
+ if constexpr (__is_trivially_lexicographically_comparable_v<_Tp, _Tp>) {
+ auto __res = std::__constexpr_memcmp(__first1, __first2, __element_count(std::min(__len1, __len2)));
+ if (__res != 0)
+ return __res <=> 0;
+ } else {
+ auto __res = std::mismatch(__first1, __last1, __first2, __last2);
+ if (__res.first != __last1 && __res.second != __last2)
+ return __comp(*__res.first, *__res.second);
+ }
+ return __len1 <=> __len2;
+}
+
// Unoptimized implementation which compares the iterators against the end in every loop iteration
template <class _InputIterator1, class _InputIterator2, class _Cmp>
_LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_slow_path(
@@ -101,7 +131,11 @@ template <class _InputIterator1, class _InputIterator2, class _Cmp>
if constexpr (__has_random_access_iterator_category<_InputIterator1>::value &&
__has_random_access_iterator_category<_InputIterator2>::value) {
return std::__lexicographical_compare_three_way_fast_path(
- std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __wrapped_comp_ref);
+ std::__unwrap_iter(__first1),
+ std::__unwrap_iter(__last1),
+ std::__unwrap_iter(__first2),
+ std::__unwrap_iter(__last2),
+ __wrapped_comp_ref);
} else {
// Unoptimized implementation which compares the iterators against the end in every loop iteration
return std::__lexicographical_compare_three_way_slow_path(
diff --git a/libcxx/include/__compare/compare_three_way.h b/libcxx/include/__compare/compare_three_way.h
index 6999000e9dceae..a0c4278629fcda 100644
--- a/libcxx/include/__compare/compare_three_way.h
+++ b/libcxx/include/__compare/compare_three_way.h
@@ -12,6 +12,7 @@
#include <__compare/three_way_comparable.h>
#include <__config>
+#include <__type_traits/desugars_to.h>
#include <__utility/forward.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -33,6 +34,9 @@ struct compare_three_way {
using is_transparent = void;
};
+template <class _Tp, class _Up>
+inline const bool __desugars_to_v<__compare_three_way_tag, compare_three_way, _Tp, _Up> = true;
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP_STD_VER >= 20
diff --git a/libcxx/include/__type_traits/desugars_to.h b/libcxx/include/__type_traits/desugars_to.h
index 029b3c6336837c..65744d1742b3a9 100644
--- a/libcxx/include/__type_traits/desugars_to.h
+++ b/libcxx/include/__type_traits/desugars_to.h
@@ -40,6 +40,9 @@ struct __greater_tag {};
// additional semantic requirements on that operation.
struct __totally_ordered_less_tag {};
+// syntactically, the operation is equivalent to calling `a <=> b`, and `a <=> b == 0` is equivalent to `a == b`
+struct __compare_three_way_tag {};
+
// This class template is used to determine whether an operation "desugars"
// (or boils down) to a given canonical operation.
//
diff --git a/libcxx/test/benchmarks/algorithms/lexicographical_compare_three_way.bench.cpp b/libcxx/test/benchmarks/algorithms/lexicographical_compare_three_way.bench.cpp
index 75105c4fc1fd1a..36572ce527ed54 100644
--- a/libcxx/test/benchmarks/algorithms/lexicographical_compare_three_way.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/lexicographical_compare_three_way.bench.cpp
@@ -9,6 +9,8 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
#include <algorithm>
+#include <iterator>
+#include <vector>
#include "benchmark/benchmark.h"
#include "test_iterators.h"
@@ -17,12 +19,12 @@
template <class IteratorT>
static TEST_ALIGN_BENCHMARK void BM_lexicographical_compare_three_way(benchmark::State& state) {
auto size = state.range(0);
- std::vector<int> v1;
+ std::vector<std::iter_value_t<IteratorT>> v1;
v1.resize(size);
// v2 is identical except for the last value.
// This means, that `lexicographical_compare_three_way` actually has to
// compare the complete vector and cannot bail out early.
- std::vector<int> v2 = v1;
+ auto v2 = v1;
v2.back() += 1;
auto b1 = IteratorT{v1.data()};
auto e1 = IteratorT{v1.data() + v1.size()};
@@ -36,10 +38,14 @@ static TEST_ALIGN_BENCHMARK void BM_lexicographical_compare_three_way(benchmark:
// Type alias to make sure the `*` does not appear in the benchmark name.
// A `*` would confuse the Python test runner running this google benchmark.
-using IntPtr = int*;
+using IntPtr = int*;
+using UnsignedCharPtr = unsigned char*;
+using SignedCharPtr = signed char*;
// `lexicographical_compare_three_way` has a fast path for random access iterators.
BENCHMARK(BM_lexicographical_compare_three_way<IntPtr>)->RangeMultiplier(4)->Range(1, 1 << 20);
+BENCHMARK(BM_lexicographical_compare_three_way<UnsignedCharPtr>)->RangeMultiplier(4)->Range(1, 1 << 20);
+BENCHMARK(BM_lexicographical_compare_three_way<SignedCharPtr>)->RangeMultiplier(4)->Range(1, 1 << 20);
BENCHMARK(BM_lexicographical_compare_three_way<random_access_iterator<IntPtr>>)->RangeMultiplier(4)->Range(1, 1 << 20);
BENCHMARK(BM_lexicographical_compare_three_way<cpp17_input_iterator<IntPtr>>)->RangeMultiplier(4)->Range(1, 1 << 20);
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
index d7cd49987689db..739e56f2176d2c 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
@@ -19,6 +19,8 @@
#include <cassert>
#include <compare>
#include <concepts>
+#include <cstddef>
+#include <limits>
#include <vector>
#include "test_macros.h"
@@ -108,6 +110,71 @@ constexpr void test_comparison_categories() {
std::partial_ordering::unordered);
}
+struct DefaultedOrder {
+ int i;
+ constexpr auto operator<=>(const DefaultedOrder&) const = default;
+};
+
+struct ReversedWeakOrder {
+ int i;
+ constexpr std::weak_ordering operator<=>(const ReversedWeakOrder& other) const { return other.i <=> i; }
+ constexpr bool operator==(const ReversedWeakOrder&) const = default;
+};
+
+template <class T, class Order>
+constexpr void test_long_range(T lhs, T rhs, Order expected) {
+ std::array<T, 300> a{};
+ std::array<T, 300> b{};
+ a[257] = lhs;
+ b[257] = rhs;
+ test_lexicographical_compare<const T*, const T*>(a, b, expected);
+ test_lexicographical_compare<const T*, const T*>(a, std::array<T, 257>{}, std::strong_ordering::greater);
+}
+
+constexpr void test_element_types() {
+ using SChar = signed char;
+ using UChar = unsigned char;
+ test_lexicographical_compare<const SChar*, const SChar*>(
+ std::array<SChar, 2>{0, -1}, std::array<SChar, 2>{0, 1}, std::strong_ordering::less);
+ test_lexicographical_compare<const UChar*, const UChar*>(
+ std::array<UChar, 2>{0, 255}, std::array<UChar, 2>{0, 1}, std::strong_ordering::greater);
+ test_lexicographical_compare<const UChar*, const UChar*>(
+ std::array<UChar, 2>{1, 2}, std::array<UChar, 3>{1, 2, 0}, std::strong_ordering::less);
+ test_lexicographical_compare<const UChar*, const UChar*>(
+ std::array<UChar, 0>{}, std::array<UChar, 0>{}, std::strong_ordering::equal);
+ test_lexicographical_compare<const std::byte*, const std::byte*>(
+ std::array{std::byte{0}, std::byte{255}}, std::array{std::byte{0}, std::byte{1}}, std::strong_ordering::greater);
+ test_lexicographical_compare<const char*, const char*>(
+ std::array{'a', 'b'}, std::array{'a', 'b', 'c'}, std::strong_ordering::less);
+ test_lexicographical_compare<const bool*, const bool*>(
+ std::array{true, false}, std::array{true, true}, std::strong_ordering::less);
+ test_lexicographical_compare<const int*, const int*>(std::array{-1}, std::array{1}, std::strong_ordering::less);
+ test_lexicographical_compare<const int*, const int*>(std::array{256}, std::array{1}, std::strong_ordering::greater);
+ test_lexicographical_compare<const long long*, const long long*>(
+ std::array{1LL, -1LL}, std::array{1LL, 1LL}, std::strong_ordering::less);
+
+ test_lexicographical_compare<const double*, const double*>(
+ std::array{-0.0, 1.0}, std::array{0.0, 2.0}, std::partial_ordering::less);
+ test_lexicographical_compare<const double*, const double*>(
+ std::array{1.0, std::numeric_limits<double>::quiet_NaN()},
+ std::array{1.0, std::numeric_limits<double>::quiet_NaN()},
+ std::partial_ordering::unordered);
+
+ test_lexicographical_compare<const DefaultedOrder*, const DefaultedOrder*>(
+ std::array<DefaultedOrder, 2>{{{1}, {-1}}},
+ std::array<DefaultedOrder, 2>{{{1}, {1}}},
+ std::strong_ordering::less);
+ test_lexicographical_compare<const ReversedWeakOrder*, const ReversedWeakOrder*>(
+ std::array<ReversedWeakOrder, 2>{{{1}, {2}}},
+ std::array<ReversedWeakOrder, 2>{{{1}, {3}}},
+ std::weak_ordering::greater);
+
+ test_long_range<SChar>(1, -1, std::strong_ordering::greater);
+ test_long_range<UChar>(1, 255, std::strong_ordering::less);
+ test_long_range<int>(256, 1, std::strong_ordering::greater);
+ test_long_range<long long>(-1, 1, std::strong_ordering::less);
+}
+
// Check that it works with proxy iterators
constexpr void test_proxy_iterators() {
std::vector<bool> vec(10, true);
@@ -118,6 +185,7 @@ constexpr void test_proxy_iterators() {
constexpr bool test() {
test_iterator_types();
test_comparison_categories();
+ test_element_types();
test_proxy_iterators();
return true;
>From 95f6c5c9106c6ede1cffb26a2caf1640c3dd143f Mon Sep 17 00:00:00 2001
From: Advit Arora <advitarora2 at gmail.com>
Date: Mon, 12 Oct 2026 11:54:24 -0700
Subject: [PATCH 2/3] Use if constexpr instead of SFINAE for the fast path
---
.../lexicographical_compare_three_way.h | 53 +++++++++----------
1 file changed, 24 insertions(+), 29 deletions(-)
diff --git a/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/libcxx/include/__algorithm/lexicographical_compare_three_way.h
index 46abf705b0710c..fbd86ebc98d391 100644
--- a/libcxx/include/__algorithm/lexicographical_compare_three_way.h
+++ b/libcxx/include/__algorithm/lexicographical_compare_three_way.h
@@ -21,11 +21,13 @@
#include <__string/constexpr_c_functions.h>
#include <__type_traits/common_type.h>
#include <__type_traits/desugars_to.h>
-#include <__type_traits/enable_if.h>
#include <__type_traits/is_constructible.h>
#include <__type_traits/is_equality_comparable.h>
+#include <__type_traits/is_pointer.h>
+#include <__type_traits/is_same.h>
#include <__type_traits/is_trivially_lexicographically_comparable.h>
#include <__type_traits/is_volatile.h>
+#include <__type_traits/remove_pointer.h>
#include <__utility/move.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -58,37 +60,30 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_fast_pa
_Len2 __len2 = __last2 - __first2;
_Common __min_len = std::min<_Common>(__len1, __len2);
- for (_Common __i = 0; __i < __min_len; ++__i) {
- auto __c = __comp(*__first1, *__first2);
- if (__c != 0) {
- return __c;
+ using _Tp = remove_pointer_t<_InputIterator1>;
+ if constexpr (is_pointer_v<_InputIterator1> && is_same_v<_InputIterator1, _InputIterator2> &&
+ __desugars_to_v<__compare_three_way_tag, _Cmp, _Tp, _Tp> && !is_volatile_v<_Tp> &&
+ __is_trivially_equality_comparable_v<_Tp, _Tp>) {
+ if constexpr (__is_trivially_lexicographically_comparable_v<_Tp, _Tp>) {
+ auto __res = std::__constexpr_memcmp(__first1, __first2, __element_count(__min_len));
+ if (__res != 0)
+ return __res <=> 0;
+ } else {
+ auto __res = std::mismatch(__first1, __last1, __first2, __last2);
+ if (__res.first != __last1 && __res.second != __last2)
+ return __comp(*__res.first, *__res.second);
}
- ++__first1;
- ++__first2;
- }
-
- return __len1 <=> __len2;
-}
-
-template <class _Tp,
- class _Cmp,
- __enable_if_t<__desugars_to_v<__compare_three_way_tag, _Cmp, _Tp, _Tp> && !is_volatile<_Tp>::value &&
- __is_trivially_equality_comparable_v<_Tp, _Tp>,
- int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__lexicographical_compare_three_way_fast_path(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Cmp& __comp)
- -> decltype(__comp(*__first1, *__first2)) {
- auto __len1 = __last1 - __first1;
- auto __len2 = __last2 - __first2;
- if constexpr (__is_trivially_lexicographically_comparable_v<_Tp, _Tp>) {
- auto __res = std::__constexpr_memcmp(__first1, __first2, __element_count(std::min(__len1, __len2)));
- if (__res != 0)
- return __res <=> 0;
} else {
- auto __res = std::mismatch(__first1, __last1, __first2, __last2);
- if (__res.first != __last1 && __res.second != __last2)
- return __comp(*__res.first, *__res.second);
+ for (_Common __i = 0; __i < __min_len; ++__i) {
+ auto __c = __comp(*__first1, *__first2);
+ if (__c != 0) {
+ return __c;
+ }
+ ++__first1;
+ ++__first2;
+ }
}
+
return __len1 <=> __len2;
}
>From 83385cc7d31a0d18f30d61398663229e6fbcd7e1 Mon Sep 17 00:00:00 2001
From: Advit Arora <advitarora2 at gmail.com>
Date: Tue, 13 Oct 2026 04:48:52 -0700
Subject: [PATCH 3/3] Take the fast path for T* vs const T*
---
.../lexicographical_compare_three_way.h | 16 ++++++++++------
libcxx/include/__string/constexpr_c_functions.h | 2 +-
.../lexicographical_compare_three_way.bench.cpp | 16 +++++-----------
.../lexicographical_compare_three_way.pass.cpp | 1 +
4 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/libcxx/include/__algorithm/lexicographical_compare_three_way.h
index fbd86ebc98d391..183785380b04f4 100644
--- a/libcxx/include/__algorithm/lexicographical_compare_three_way.h
+++ b/libcxx/include/__algorithm/lexicographical_compare_three_way.h
@@ -27,6 +27,7 @@
#include <__type_traits/is_same.h>
#include <__type_traits/is_trivially_lexicographically_comparable.h>
#include <__type_traits/is_volatile.h>
+#include <__type_traits/remove_const.h>
#include <__type_traits/remove_pointer.h>
#include <__utility/move.h>
@@ -60,18 +61,21 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __lexicographical_compare_three_way_fast_pa
_Len2 __len2 = __last2 - __first2;
_Common __min_len = std::min<_Common>(__len1, __len2);
- using _Tp = remove_pointer_t<_InputIterator1>;
- if constexpr (is_pointer_v<_InputIterator1> && is_same_v<_InputIterator1, _InputIterator2> &&
+ using _Tp = remove_const_t<remove_pointer_t<_InputIterator1>>;
+ if constexpr (is_pointer_v<_InputIterator1> && is_pointer_v<_InputIterator2> &&
+ is_same_v<_Tp, remove_const_t<remove_pointer_t<_InputIterator2>>> &&
__desugars_to_v<__compare_three_way_tag, _Cmp, _Tp, _Tp> && !is_volatile_v<_Tp> &&
__is_trivially_equality_comparable_v<_Tp, _Tp>) {
+ const _Tp* __f1 = __first1;
+ const _Tp* __f2 = __first2;
if constexpr (__is_trivially_lexicographically_comparable_v<_Tp, _Tp>) {
- auto __res = std::__constexpr_memcmp(__first1, __first2, __element_count(__min_len));
+ auto __res = std::__constexpr_memcmp(__f1, __f2, __element_count(__min_len));
if (__res != 0)
return __res <=> 0;
} else {
- auto __res = std::mismatch(__first1, __last1, __first2, __last2);
- if (__res.first != __last1 && __res.second != __last2)
- return __comp(*__res.first, *__res.second);
+ auto __res = std::mismatch(__f1, __f1 + __min_len, __f2);
+ if (__res.first != __f1 + __min_len)
+ return *__res.first <=> *__res.second;
}
} else {
for (_Common __i = 0; __i < __min_len; ++__i) {
diff --git a/libcxx/include/__string/constexpr_c_functions.h b/libcxx/include/__string/constexpr_c_functions.h
index 4b05e862b80e31..771968cdd48056 100644
--- a/libcxx/include/__string/constexpr_c_functions.h
+++ b/libcxx/include/__string/constexpr_c_functions.h
@@ -75,7 +75,7 @@ __constexpr_memcmp(const _Tp* __lhs, const _Up* __rhs, __element_count __n) {
if (__libcpp_is_constant_evaluated()) {
#ifdef _LIBCPP_COMPILER_CLANG_BASED
- if (sizeof(_Tp) == 1 && !is_same<_Tp, bool>::value)
+ if (sizeof(_Tp) == 1 && !is_same<_Tp, bool>::value && !__is_std_byte_v<_Tp>)
return __builtin_memcmp(__lhs, __rhs, __count * sizeof(_Tp));
#endif
diff --git a/libcxx/test/benchmarks/algorithms/lexicographical_compare_three_way.bench.cpp b/libcxx/test/benchmarks/algorithms/lexicographical_compare_three_way.bench.cpp
index 36572ce527ed54..4fbb465ce89524 100644
--- a/libcxx/test/benchmarks/algorithms/lexicographical_compare_three_way.bench.cpp
+++ b/libcxx/test/benchmarks/algorithms/lexicographical_compare_three_way.bench.cpp
@@ -36,17 +36,11 @@ static TEST_ALIGN_BENCHMARK void BM_lexicographical_compare_three_way(benchmark:
}
}
-// Type alias to make sure the `*` does not appear in the benchmark name.
-// A `*` would confuse the Python test runner running this google benchmark.
-using IntPtr = int*;
-using UnsignedCharPtr = unsigned char*;
-using SignedCharPtr = signed char*;
-
// `lexicographical_compare_three_way` has a fast path for random access iterators.
-BENCHMARK(BM_lexicographical_compare_three_way<IntPtr>)->RangeMultiplier(4)->Range(1, 1 << 20);
-BENCHMARK(BM_lexicographical_compare_three_way<UnsignedCharPtr>)->RangeMultiplier(4)->Range(1, 1 << 20);
-BENCHMARK(BM_lexicographical_compare_three_way<SignedCharPtr>)->RangeMultiplier(4)->Range(1, 1 << 20);
-BENCHMARK(BM_lexicographical_compare_three_way<random_access_iterator<IntPtr>>)->RangeMultiplier(4)->Range(1, 1 << 20);
-BENCHMARK(BM_lexicographical_compare_three_way<cpp17_input_iterator<IntPtr>>)->RangeMultiplier(4)->Range(1, 1 << 20);
+BENCHMARK(BM_lexicographical_compare_three_way<int*>)->RangeMultiplier(4)->Range(1, 1 << 20);
+BENCHMARK(BM_lexicographical_compare_three_way<unsigned char*>)->RangeMultiplier(4)->Range(1, 1 << 20);
+BENCHMARK(BM_lexicographical_compare_three_way<signed char*>)->RangeMultiplier(4)->Range(1, 1 << 20);
+BENCHMARK(BM_lexicographical_compare_three_way<random_access_iterator<int*>>)->RangeMultiplier(4)->Range(1, 1 << 20);
+BENCHMARK(BM_lexicographical_compare_three_way<cpp17_input_iterator<int*>>)->RangeMultiplier(4)->Range(1, 1 << 20);
BENCHMARK_MAIN();
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
index 739e56f2176d2c..4f48749b0bda33 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
@@ -128,6 +128,7 @@ constexpr void test_long_range(T lhs, T rhs, Order expected) {
a[257] = lhs;
b[257] = rhs;
test_lexicographical_compare<const T*, const T*>(a, b, expected);
+ test_lexicographical_compare<T*, const T*>(a, b, expected);
test_lexicographical_compare<const T*, const T*>(a, std::array<T, 257>{}, std::strong_ordering::greater);
}
More information about the libcxx-commits
mailing list