libstdc++: Optimize std::string_view::find [PR 66414]
authorJonathan Wakely <jwakely@redhat.com>
Wed, 27 Jan 2021 13:21:52 +0000 (13:21 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Wed, 27 Jan 2021 13:45:52 +0000 (13:45 +0000)
This reuses the code from std::string::find, which was improved by
r244225, but string_view was not changed to match.

libstdc++-v3/ChangeLog:

PR libstdc++/66414
* include/bits/string_view.tcc
(basic_string_view::find(const CharT*, size_type, size_type)):
Optimize.

libstdc++-v3/include/bits/string_view.tcc

index bcd8fc1..efb0ede 100644 (file)
@@ -50,15 +50,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_requires_string_len(__str, __n);
 
       if (__n == 0)
-       return __pos <= this->_M_len ? __pos : npos;
+       return __pos <= _M_len ? __pos : npos;
+      if (__pos >= _M_len)
+       return npos;
 
-      if (__n <= this->_M_len)
+      const _CharT __elem0 = __str[0];
+      const _CharT* __first = _M_str + __pos;
+      const _CharT* const __last = _M_str + _M_len;
+      size_type __len = _M_len - __pos;
+
+      while (__len >= __n)
        {
-         for (; __pos <= this->_M_len - __n; ++__pos)
-           if (traits_type::eq(this->_M_str[__pos], __str[0])
-               && traits_type::compare(this->_M_str + __pos + 1,
-                                       __str + 1, __n - 1) == 0)
-             return __pos;
+         // Find the first occurrence of __elem0:
+         __first = traits_type::find(__first, __len - __n + 1, __elem0);
+         if (!__first)
+           return npos;
+         // Compare the full strings from the first occurrence of __elem0.
+         // We already know that __first[0] == __s[0] but compare them again
+         // anyway because __s is probably aligned, which helps memcmp.
+         if (traits_type::compare(__first, __str, __n) == 0)
+           return __first - _M_str;
+         __len = __last - ++__first;
        }
       return npos;
     }