[libcxx-commits] [libcxx] [libc++] Optimize string operator[] for known large inputs (PR #69500)
Ilya Tocar via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Oct 20 14:20:02 PDT 2023
https://github.com/TocarIP updated https://github.com/llvm/llvm-project/pull/69500
>From 90bfa6e5b222fbfeca8f6ec43b2a184f7defe0d4 Mon Sep 17 00:00:00 2001
From: Ilya Tokar <tokarip at google.com>
Date: Fri, 6 Oct 2023 16:08:04 -0400
Subject: [PATCH] [libc++] Optimize string operator[] for known large inputs
If we know that index is larger than SSO size, we know that we
can't be in SSO case, and should access the pointer. This removes
extra check from operator[] for inputs known at compile time to be
larger than SSO.
---
libcxx/include/string | 6 ++++++
.../basic.string/string.access/index.pass.cpp | 21 +++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/libcxx/include/string b/libcxx/include/string
index 91935162f02383a..cf9f0c847eb43af 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1198,11 +1198,17 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds");
+ if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) {
+ return *(__get_long_pointer() + __pos);
+ }
return *(data() + __pos);
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __pos) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds");
+ if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) {
+ return *(__get_long_pointer() + __pos);
+ }
return *(__get_pointer() + __pos);
}
diff --git a/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp b/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
index a270dd579667b1d..8ba8bf0c8b096bb 100644
--- a/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.access/index.pass.cpp
@@ -34,10 +34,31 @@ TEST_CONSTEXPR_CXX20 void test_string() {
assert(s2[0] == '\0');
}
+// Same, but for the string that doesn't fit into SSO.
+template <class S>
+TEST_CONSTEXPR_CXX20 void test_string_long() {
+ S s("0123456789012345678901234567890123456789");
+ const S& cs = s;
+ ASSERT_SAME_TYPE(decltype(s[0]), typename S::reference);
+ ASSERT_SAME_TYPE(decltype(cs[0]), typename S::const_reference);
+ LIBCPP_ASSERT_NOEXCEPT(s[0]);
+ LIBCPP_ASSERT_NOEXCEPT(cs[0]);
+ for (typename S::size_type i = 0; i < cs.size(); ++i) {
+ assert(s[i] == static_cast<char>('0' + (i % 10)));
+ assert(cs[i] == s[i]);
+ }
+ assert(s[33] == static_cast<char>('0' + (33 % 10)));
+ assert(cs[34] == s[34]);
+ assert(cs[cs.size()] == '\0');
+ const S s2 = S();
+ assert(s2[0] == '\0');
+}
+
TEST_CONSTEXPR_CXX20 bool test() {
test_string<std::string>();
#if TEST_STD_VER >= 11
test_string<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
+ test_string_long<std::basic_string<char, std::char_traits<char>, min_allocator<char>>>();
#endif
return true;
More information about the libcxx-commits
mailing list