Commit f87d30cb authored by Martijn Vels's avatar Martijn Vels
Browse files

Partially inline basic_string::operator=(const basic_string&)

Summary:
This change partially inlines operator=(const basic_string&) where both the input and current instance are short strings, making the assignment a fixed length inlined memcpy.

Assignments where either of the strings are long are delegate to __assign_no_alias<__is_short>(), which is templated for the long / short branch already observed in the caller.

Stable:
```
--------------------------------------------------------------------------------
Benchmark                                     Time             CPU   Iterations
--------------------------------------------------------------------------------
BM_StringAssignStr_Empty_Opaque            2.65 ns         2.66 ns    263745536
BM_StringAssignStr_Empty_Transparent       2.95 ns         2.96 ns    236494848
BM_StringAssignStr_Small_Opaque            2.93 ns         2.94 ns    237301760
BM_StringAssignStr_Small_Transparent       2.69 ns         2.69 ns    265809920
BM_StringAssignStr_Large_Opaque            19.6 ns         19.6 ns     35573760
BM_StringAssignStr_Large_Transparent       19.1 ns         19.1 ns     36716544
BM_StringAssignStr_Huge_Opaque             1901 ns         1901 ns       364544
BM_StringAssignStr_Huge_Transparent        1889 ns         1889 ns       360448
```

Unstable
```
--------------------------------------------------------------------------------
Benchmark                                     Time             CPU   Iterations
--------------------------------------------------------------------------------
BM_StringAssignStr_Empty_Opaque            1.29 ns         1.29 ns    540454912
BM_StringAssignStr_Empty_Transparent       1.11 ns         1.12 ns    628482048
BM_StringAssignStr_Small_Opaque            1.29 ns         1.29 ns    541216768
BM_StringAssignStr_Small_Transparent       1.11 ns         1.11 ns    629469184
BM_StringAssignStr_Large_Opaque            15.6 ns         15.6 ns     44945408
BM_StringAssignStr_Large_Transparent       14.9 ns         14.9 ns     46764032
BM_StringAssignStr_Huge_Opaque             1713 ns         1713 ns       401408
BM_StringAssignStr_Huge_Transparent        1704 ns         1704 ns       397312

```

Subscribers: libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D75211
parent ad497658
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -165,6 +165,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \
  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__assign_no_alias<false>(value_type const*, size_type)) \
  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__assign_no_alias<true>(value_type const*, size_type)) \
  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
@@ -179,7 +181,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \
  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
+34 −8
Original line number Diff line number Diff line
@@ -1571,6 +1571,12 @@ private:
                               size_type __n_copy,  size_type __n_del,
                               size_type __n_add, const value_type* __p_new_stuff);

    // __assign_no_alias is invoked for assignment operations where we
    // have proof that the input does not alias the current instance.
    // For example, operator=(basic_string) performs a 'self' check.
    template <bool __is_short>
    void __assign_no_alias(const value_type* __s, size_type __n);

    _LIBCPP_INLINE_VISIBILITY
    void __erase_to_end(size_type __pos);

@@ -2202,6 +2208,23 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by(size_type __old_cap, size_t

// assign

template <class _CharT, class _Traits, class _Allocator>
template <bool __is_short>
void basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(
    const value_type* __s, size_type __n) {
  size_type __cap = __is_short ? __min_cap : __get_long_cap();
  if (__n < __cap) {
    pointer __p = __is_short ? __get_short_pointer() : __get_long_pointer();
    __is_short ? __set_short_size(__n) : __set_long_size(__n);
    traits_type::copy(_VSTD::__to_address(__p), __s, __n);
    traits_type::assign(__p[__n], value_type());
    __invalidate_iterators_past(__n);
  } else {
    size_type __sz = __is_short ? __get_short_size() : __get_long_size();
    __grow_by_and_replace(__cap - 1, __n - __cap + 1, __sz, 0, __sz, __n, __s);
  }
}

template <class _CharT, class _Traits, class _Allocator>
basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n)
@@ -2268,14 +2291,17 @@ template <class _CharT, class _Traits, class _Allocator>
basic_string<_CharT, _Traits, _Allocator>&
basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
{
    if (this != &__str)
    {
  if (this != &__str) {
    __copy_assign_alloc(__str);
        const bool __str_is_long = __str.__is_long(); // Force single branch
        if (__is_long() || __str_is_long) {
          return assign(__str.data(), __str.size());
        }
    if (!__is_long()) {
      if (!__str.__is_long()) {
        __r_.first().__r = __str.__r_.first().__r;
      } else {
        __assign_no_alias<true>(__str.data(), __str.size());
      }
    } else {
      __assign_no_alias<false>(__str.data(), __str.size());
    }
  }
  return *this;
}