Skip to content

[libc++] Optimize char_traits a bit #72799

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 24 additions & 44 deletions libcxx/include/__string/char_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
#define _LIBCPP___STRING_CHAR_TRAITS_H

#include <__algorithm/fill_n.h>
#include <__algorithm/find.h>
#include <__algorithm/find_end.h>
#include <__algorithm/find_first_of.h>
#include <__algorithm/min.h>
#include <__assert>
#include <__compare/ordering.h>
#include <__config>
#include <__functional/hash.h>
#include <__functional/identity.h>
#include <__iterator/iterator_traits.h>
#include <__string/constexpr_c_functions.h>
#include <__type_traits/is_constant_evaluated.h>
Expand Down Expand Up @@ -272,10 +274,14 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> {
return std::__constexpr_memcmp(__s1, __s2, __element_count(__n));
}

static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __s) _NOEXCEPT;
static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __str) _NOEXCEPT {
return std::__constexpr_strlen(__str);
}

_LIBCPP_HIDE_FROM_ABI static constexpr const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
return std::__constexpr_memchr(__s, __a, __n);
}

static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
Expand Down Expand Up @@ -307,25 +313,6 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> {
static inline _LIBCPP_HIDE_FROM_ABI constexpr int_type eof() noexcept { return int_type(EOF); }
};

// TODO use '__builtin_strlen' if it ever supports char8_t ??
inline constexpr size_t char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT {
size_t __len = 0;
for (; !eq(*__s, char_type(0)); ++__s)
++__len;
return __len;
}

// TODO use '__builtin_char_memchr' if it ever supports char8_t ??
inline constexpr const char8_t*
char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
for (; __n; --__n) {
if (eq(*__s, __a))
return __s;
++__s;
}
return nullptr;
}

#endif // _LIBCPP_HAS_NO_CHAR8_T

template <>
Expand Down Expand Up @@ -353,9 +340,15 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> {
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
__identity __proj;
const char_type* __match = std::__find_impl(__s, __s + __n, __a, __proj);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to this patch, but can we rename __find_impl to __find for consistency?

if (__match == __s + __n)
return nullptr;
return __match;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type*
move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
Expand Down Expand Up @@ -408,16 +401,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char16_t>::length(const
return __len;
}

inline _LIBCPP_CONSTEXPR_SINCE_CXX17 const char16_t*
char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
for (; __n; --__n) {
if (eq(*__s, __a))
return __s;
++__s;
}
return nullptr;
}

template <>
struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> {
using char_type = char32_t;
Expand All @@ -443,8 +426,15 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> {
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;

_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
__identity __proj;
const char_type* __match = std::__find_impl(__s, __s + __n, __a, __proj);
if (__match == __s + __n)
return nullptr;
return __match;
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type*
move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
Expand Down Expand Up @@ -496,16 +486,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char32_t>::length(const
return __len;
}

inline _LIBCPP_CONSTEXPR_SINCE_CXX17 const char32_t*
char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
for (; __n; --__n) {
if (eq(*__s, __a))
return __s;
++__s;
}
return nullptr;
}

// helper fns for basic_string and string_view

// __str_find
Expand Down
23 changes: 19 additions & 4 deletions libcxx/include/__string/constexpr_c_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,33 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// of elements as opposed to a number of bytes.
enum class __element_count : size_t {};

inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const char* __str) {
template <class _Tp>
inline const bool __is_char_type = false;

template <>
inline const bool __is_char_type<char> = true;

#ifndef _LIBCPP_HAS_NO_CHAR8_T
template <>
inline const bool __is_char_type<char8_t> = true;
#endif

template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t __constexpr_strlen(const _Tp* __str) _NOEXCEPT {
static_assert(__is_char_type<_Tp>, "__constexpr_strlen only works with char and char8_t");
// GCC currently doesn't support __builtin_strlen for heap-allocated memory during constant evaluation.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816
#ifdef _LIBCPP_COMPILER_GCC
if (__libcpp_is_constant_evaluated()) {
#if _LIBCPP_STD_VER >= 17 && defined(_LIBCPP_COMPILER_CLANG_BASED)
if constexpr (is_same_v<_Tp, char>)
return __builtin_strlen(__str);
#endif
size_t __i = 0;
for (; __str[__i] != '\0'; ++__i)
;
return __i;
}
#endif
return __builtin_strlen(__str);
return __builtin_strlen(reinterpret_cast<const char*>(__str));
}

// Because of __libcpp_is_trivially_lexicographically_comparable we know that comparing the object representations is
Expand Down