forked from OSchip/llvm-project
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
This commit is contained in:
parent
ad497658d2
commit
f87d30cba2
|
@ -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)) \
|
||||
|
|
|
@ -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,16 +2291,19 @@ 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)
|
||||
{
|
||||
__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 (this != &__str) {
|
||||
__copy_assign_alloc(__str);
|
||||
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;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
|
Loading…
Reference in New Issue