[libcxx-commits] [libcxx] [libc++] Fold __search_substring into _Traits::find in case the second string has length 1 (PR #160076)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Sep 22 04:27:33 PDT 2025
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/160076
None
>From dd1885ac1d47bf910307b670c3ef89c29b234bda Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 22 Sep 2025 13:27:10 +0200
Subject: [PATCH] [libc++] Fold __search_substring into _Traits::find in case
the second string has length 1
---
libcxx/include/__string/char_traits.h | 7 +++
.../benchmarks/containers/string.bench.cpp | 43 +++++++++++++++++++
2 files changed, 50 insertions(+)
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..6528ae6a04f52 100644
--- a/libcxx/test/benchmarks/containers/string.bench.cpp
+++ b/libcxx/test/benchmarks/containers/string.bench.cpp
@@ -60,6 +60,49 @@ static void BM_StringFindMatch2(benchmark::State& state) {
}
BENCHMARK(BM_StringFindMatch2)->Range(1, MAX_STRING_LEN / 4);
+static void BM_string_literal(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")); // "b" is a string literal, it should be longer
+ benchmark::ClobberMemory();
+ }
+}
+
+BENCHMARK(BM_string_literal)->RangeMultiplier(2)->Range(8, 8<<10);
+
+static void BM_char_literal(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')); // 'b' is a char literal, it should be faster
+ benchmark::ClobberMemory();
+ }
+}
+BENCHMARK(BM_char_literal)->RangeMultiplier(2)->Range(8, 8<<10);
+
static void BM_StringCtorDefault(benchmark::State& state) {
for (auto _ : state) {
std::string Default;
More information about the libcxx-commits
mailing list