Skip to content

Commit d814824

Browse files
authored
[libc++] Decrease instantiation cost of __constexpr_memmove (llvm#125109)
Using `if constexpr` in `__constexpr_memmove` makes the instantiation three times faster for the same type, since it avoids a bunch of class instantiations and SFINAE for constexpr support that's never actually used. Given that `__constexpr_memmove` is used quite a bit through `std::copy` and is instantiated multiple times when just including `<__string/char_traits.h>` this can provide a nice compile time speedup for a very simple change.
1 parent bd30838 commit d814824

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

libcxx/include/__string/constexpr_c_functions.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,23 +204,26 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __assign_trivially_copy
204204
return __dest;
205205
}
206206

207-
template <class _Tp, class _Up, __enable_if_t<__is_always_bitcastable<_Up, _Tp>::value, int> = 0>
207+
template <class _Tp, class _Up>
208208
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp*
209209
__constexpr_memmove(_Tp* __dest, _Up* __src, __element_count __n) {
210+
static_assert(__is_always_bitcastable<_Up, _Tp>::value);
210211
size_t __count = static_cast<size_t>(__n);
211212
if (__libcpp_is_constant_evaluated()) {
212213
#ifdef _LIBCPP_COMPILER_CLANG_BASED
213-
if (is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value) {
214+
if _LIBCPP_CONSTEXPR (is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value) {
214215
::__builtin_memmove(__dest, __src, __count * sizeof(_Tp));
215216
return __dest;
216-
}
217+
} else
217218
#endif
218-
if (std::__is_pointer_in_range(__src, __src + __count, __dest)) {
219-
for (; __count > 0; --__count)
220-
std::__assign_trivially_copyable(__dest[__count - 1], __src[__count - 1]);
221-
} else {
222-
for (size_t __i = 0; __i != __count; ++__i)
223-
std::__assign_trivially_copyable(__dest[__i], __src[__i]);
219+
{
220+
if (std::__is_pointer_in_range(__src, __src + __count, __dest)) {
221+
for (; __count > 0; --__count)
222+
std::__assign_trivially_copyable(__dest[__count - 1], __src[__count - 1]);
223+
} else {
224+
for (size_t __i = 0; __i != __count; ++__i)
225+
std::__assign_trivially_copyable(__dest[__i], __src[__i]);
226+
}
224227
}
225228
} else if (__count > 0) {
226229
::__builtin_memmove(__dest, __src, (__count - 1) * sizeof(_Tp) + __datasizeof_v<_Tp>);

0 commit comments

Comments
 (0)