[libcxx-commits] [libcxx] a769608 - [libc++] Fold __search_substring into _Traits::find in case the second string has length 1 (#160076)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Sep 25 00:29:05 PDT 2025
Author: Nikolas Klauser
Date: 2025-09-25T09:29:01+02:00
New Revision: a769608339ad4fff68081ceb7f388da8b660cfa1
URL: https://github.com/llvm/llvm-project/commit/a769608339ad4fff68081ceb7f388da8b660cfa1
DIFF: https://github.com/llvm/llvm-project/commit/a769608339ad4fff68081ceb7f388da8b660cfa1.diff
LOG: [libc++] Fold __search_substring into _Traits::find in case the second string has length 1 (#160076)
Apple M4:
```
Benchmark Baseline Candidate Difference % Difference
----------------------------------------------------------- ---------- ----------- ------------ --------------
BM_string_literal/1024 16.99 16.79 -0.21 -1.21
BM_string_literal/128 3.44 3.34 -0.10 -2.88
BM_string_literal/16 1.80 1.69 -0.11 -5.93
BM_string_literal/2048 38.44 38.38 -0.07 -0.17
BM_string_literal/256 5.77 5.65 -0.12 -2.02
BM_string_literal/32 2.03 1.92 -0.11 -5.44
BM_string_literal/4096 73.92 73.74 -0.18 -0.25
BM_string_literal/512 9.49 9.41 -0.08 -0.84
BM_string_literal/64 2.59 2.45 -0.14 -5.38
BM_string_literal/8 1.79 1.69 -0.11 -5.90
BM_string_literal/8192 132.09 131.81 -0.28 -0.21
```
Added:
Modified:
libcxx/include/__string/char_traits.h
libcxx/test/benchmarks/containers/string.bench.cpp
libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h
index 86c92477cbfeb..8292750919427 100644
--- a/libcxx/include/__string/char_traits.h
+++ b/libcxx/include/__string/char_traits.h
@@ -369,6 +369,13 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const _CharT* __searc
if (__len1 < __len2)
return __last1;
+ if (__builtin_constant_p(__len2 == 1) && __len2 == 1) {
+ auto __res = _Traits::find(__first1, __len1, *__first2);
+ if (__res == nullptr)
+ return __last1;
+ return __res;
+ }
+
// First element of __first2 is loop invariant.
_CharT __f2 = *__first2;
while (true) {
diff --git a/libcxx/test/benchmarks/containers/string.bench.cpp b/libcxx/test/benchmarks/containers/string.bench.cpp
index 966775d31a8cf..2484ec8fd955f 100644
--- a/libcxx/test/benchmarks/containers/string.bench.cpp
+++ b/libcxx/test/benchmarks/containers/string.bench.cpp
@@ -60,6 +60,45 @@ static void BM_StringFindMatch2(benchmark::State& state) {
}
BENCHMARK(BM_StringFindMatch2)->Range(1, MAX_STRING_LEN / 4);
+static void BM_StringFindStringLiteral(benchmark::State& state) {
+ std::string s;
+
+ for (int i = 0; i < state.range(0); i++)
+ s += 'a';
+
+ s += 'b';
+
+ benchmark::DoNotOptimize(s.data());
+ benchmark::ClobberMemory();
+ size_t pos;
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(pos = s.find("b"));
+ benchmark::ClobberMemory();
+ }
+}
+
+BENCHMARK(BM_StringFindStringLiteral)->RangeMultiplier(2)->Range(8, 8 << 10);
+
+static void BM_StringFindCharLiteral(benchmark::State& state) {
+ std::string s;
+
+ for (int i = 0; i < state.range(0); i++)
+ s += 'a';
+
+ s += 'b';
+
+ benchmark::DoNotOptimize(s.data());
+ benchmark::ClobberMemory();
+ size_t pos;
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(pos = s.find('b'));
+ benchmark::ClobberMemory();
+ }
+}
+BENCHMARK(BM_StringFindCharLiteral)->RangeMultiplier(2)->Range(8, 8 << 10);
+
static void BM_StringCtorDefault(benchmark::State& state) {
for (auto _ : state) {
std::string Default;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
index 60ed469ce991b..4aa4a3f339142 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
@@ -43,14 +43,17 @@ TEST_CONSTEXPR_CXX20 void test0() {
test(S(""), S("abcdeabcde"), 1, S::npos);
test(S(""), S("abcdeabcdeabcdeabcde"), 1, S::npos);
test(S("abcde"), S(""), 0, 0);
+ test(S("abcde"), S("a"), 0, 0);
test(S("abcde"), S("abcde"), 0, 0);
test(S("abcde"), S("abcdeabcde"), 0, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 0, S::npos);
test(S("abcde"), S(""), 1, 1);
+ test(S("abcde"), S("a"), 1, S::npos);
test(S("abcde"), S("abcde"), 1, S::npos);
test(S("abcde"), S("abcdeabcde"), 1, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 1, S::npos);
test(S("abcde"), S(""), 2, 2);
+ test(S("abcde"), S("a"), 2, S::npos);
test(S("abcde"), S("abcde"), 2, S::npos);
test(S("abcde"), S("abcdeabcde"), 2, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 2, S::npos);
@@ -59,58 +62,72 @@ TEST_CONSTEXPR_CXX20 void test0() {
test(S("abcde"), S("abcdeabcde"), 4, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 4, S::npos);
test(S("abcde"), S(""), 5, 5);
+ test(S("abcde"), S("a"), 5, S::npos);
test(S("abcde"), S("abcde"), 5, S::npos);
test(S("abcde"), S("abcdeabcde"), 5, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 5, S::npos);
test(S("abcde"), S(""), 6, S::npos);
+ test(S("abcde"), S("a"), 6, S::npos);
test(S("abcde"), S("abcde"), 6, S::npos);
test(S("abcde"), S("abcdeabcde"), 6, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 6, S::npos);
test(S("abcdeabcde"), S(""), 0, 0);
+ test(S("abcdeabcde"), S("a"), 0, 0);
test(S("abcdeabcde"), S("abcde"), 0, 0);
test(S("abcdeabcde"), S("abcdeabcde"), 0, 0);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 0, S::npos);
test(S("abcdeabcde"), S(""), 1, 1);
+ test(S("abcdeabcde"), S("a"), 1, 5);
test(S("abcdeabcde"), S("abcde"), 1, 5);
test(S("abcdeabcde"), S("abcdeabcde"), 1, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 1, S::npos);
test(S("abcdeabcde"), S(""), 5, 5);
+ test(S("abcdeabcde"), S("a"), 5, 5);
test(S("abcdeabcde"), S("abcde"), 5, 5);
test(S("abcdeabcde"), S("abcdeabcde"), 5, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 5, S::npos);
test(S("abcdeabcde"), S(""), 9, 9);
+ test(S("abcdeabcde"), S("a"), 9, S::npos);
test(S("abcdeabcde"), S("abcde"), 9, S::npos);
test(S("abcdeabcde"), S("abcdeabcde"), 9, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 9, S::npos);
test(S("abcdeabcde"), S(""), 10, 10);
+ test(S("abcdeabcde"), S("a"), 10, S::npos);
test(S("abcdeabcde"), S("abcde"), 10, S::npos);
test(S("abcdeabcde"), S("abcdeabcde"), 10, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 10, S::npos);
test(S("abcdeabcde"), S(""), 11, S::npos);
+ test(S("abcdeabcde"), S("a"), 11, S::npos);
test(S("abcdeabcde"), S("abcde"), 11, S::npos);
test(S("abcdeabcde"), S("abcdeabcde"), 11, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 11, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 0, 0);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 0, 0);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 0, 0);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 0, 0);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 0, 0);
test(S("abcdeabcdeabcdeabcde"), S(""), 1, 1);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 1, 5);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 1, 5);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 1, 5);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 1, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 10, 10);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 10, 10);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 10, 10);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 10, 10);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 10, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 19, 19);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 19, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 19, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 19, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 19, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 20, 20);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 20, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 20, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 20, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 20, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 21, S::npos);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 21, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 21, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 21, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 21, S::npos);
More information about the libcxx-commits
mailing list