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);