[libcxx-commits] [libcxx] [libc++][ranges] optimize the performance of `ranges::starts_with` (PR #84570)
Xiaoyang Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Mar 8 13:48:19 PST 2024
https://github.com/xiaoyang-sde created https://github.com/llvm/llvm-project/pull/84570
## Abstract
This pull request optimizes the performance of `ranges::starts_with`.
>From 3a384218365b175e8884a91125efe4e07f9e500a Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Fri, 8 Mar 2024 13:43:39 -0800
Subject: [PATCH 1/2] [libc++][ranges] detect size mismatch in
'ranges::starts_with'
---
.../include/__algorithm/ranges_starts_with.h | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/libcxx/include/__algorithm/ranges_starts_with.h b/libcxx/include/__algorithm/ranges_starts_with.h
index 90e184aa9bccc2..b39e1657a855ea 100644
--- a/libcxx/include/__algorithm/ranges_starts_with.h
+++ b/libcxx/include/__algorithm/ranges_starts_with.h
@@ -15,6 +15,7 @@
#include <__functional/identity.h>
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
+#include <__iterator/distance.h>
#include <__iterator/indirectly_comparable.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
@@ -50,6 +51,17 @@ struct __fn {
_Pred __pred = {},
_Proj1 __proj1 = {},
_Proj2 __proj2 = {}) const {
+ if constexpr (sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2>) {
+ auto __n1 = ranges::distance(__first1, __last1);
+ auto __n2 = ranges::distance(__first2, __last2);
+ if (__n2 == 0) {
+ return true;
+ }
+ if (__n2 > __n1) {
+ return false;
+ }
+ }
+
return __mismatch::__fn::__go(
std::move(__first1),
std::move(__last1),
@@ -69,6 +81,17 @@ struct __fn {
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
+ if constexpr (sized_range<_Range1> && sized_range<_Range2>) {
+ auto __n1 = ranges::size(__range1);
+ auto __n2 = ranges::size(__range2);
+ if (__n2 == 0) {
+ return true;
+ }
+ if (__n2 > __n1) {
+ return false;
+ }
+ }
+
return __mismatch::__fn::__go(
ranges::begin(__range1),
ranges::end(__range1),
>From 5f8773ea9dcedb1a7fbaf02fd7b145834c1b3cf3 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Fri, 8 Mar 2024 13:44:51 -0800
Subject: [PATCH 2/2] [libc++][ranges] change the 'operator()' of
'ranges::starts_with' to 'static'
---
libcxx/include/__algorithm/ranges_starts_with.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/__algorithm/ranges_starts_with.h b/libcxx/include/__algorithm/ranges_starts_with.h
index b39e1657a855ea..93409d5b109137 100644
--- a/libcxx/include/__algorithm/ranges_starts_with.h
+++ b/libcxx/include/__algorithm/ranges_starts_with.h
@@ -43,14 +43,14 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
- _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()(
_Iter1 __first1,
_Sent1 __last1,
_Iter2 __first2,
_Sent2 __last2,
_Pred __pred = {},
_Proj1 __proj1 = {},
- _Proj2 __proj2 = {}) const {
+ _Proj2 __proj2 = {}) {
if constexpr (sized_sentinel_for<_Sent1, _Iter1> && sized_sentinel_for<_Sent2, _Iter2>) {
auto __n1 = ranges::distance(__first1, __last1);
auto __n2 = ranges::distance(__first2, __last2);
@@ -79,8 +79,8 @@ struct __fn {
class _Proj1 = identity,
class _Proj2 = identity>
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
- _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(
- _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const {
+ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool
+ operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) {
if constexpr (sized_range<_Range1> && sized_range<_Range2>) {
auto __n1 = ranges::size(__range1);
auto __n2 = ranges::size(__range2);
More information about the libcxx-commits
mailing list