[libcxx-commits] [libcxx] Improve string allocation (PR #92652)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat May 18 07:41:57 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Valery Mironov (MBkkt)
<details>
<summary>Changes</summary>
* Remove unnecessary std::max in shrink_to_fit
* Remove unnecessary condition in __recommend
* Fix allocation for string with small_size required less bytes (24 instead of 26, 12 instead of 11, etc)
https://godbolt.org/z/fGP6e11ed
```
#include <cstddef>
#include <cstdint>
using size_type = size_t;
template <typename long_type>
struct __long {
long_type x;
long_type y;
long_type z;
};
template <typename value_type, typename long_type>
static constexpr size_type min_cap =
(sizeof(__long<long_type>) - 1) / sizeof(value_type) > 2
? (sizeof(__long<long_type>) - 1) / sizeof(value_type)
: 2;
template <typename long_type>
static constexpr size_type alignment = sizeof(long_type);
template <size_type __a>
static constexpr size_type __align_it(size_type __s) noexcept {
return (__s + (__a - 1)) & ~(__a - 1);
}
template <typename value_type, typename long_type, size_type __endian_factor>
static constexpr size_type __recommend(size_type __s) noexcept {
constexpr auto __min_cap = min_cap<value_type, long_type>;
constexpr auto __alignment = alignment<long_type>;
if (__s < __min_cap) {
return static_cast<size_type>(__min_cap) - 1;
}
const size_type __boundary = sizeof(value_type) < __alignment
? __alignment / sizeof(value_type)
: __endian_factor;
size_type __guess = __align_it<__boundary>(__s + 1) - 1;
//if (__guess == __min_cap) __guess += __endian_factor;
return __guess;
}
template <typename value_type, typename long_type, size_type __endian_factor>
static constexpr auto to_alloc(size_type s) {
return __recommend<value_type, long_type, __endian_factor>(s) + 1;
}
int main() {
static constexpr auto char8_64 = min_cap<char, long>;
static_assert(char8_64 == 23);
static constexpr auto char16_64 = min_cap<char16_t, long>;
static_assert(char16_64 == 11);
static constexpr auto char32_64 = min_cap<char32_t, long>;
static_assert(char32_64 == 5);
static constexpr auto char64_64 = min_cap<long, long>;
static_assert(char64_64 == 2);
static constexpr auto char8_32 = min_cap<char, int>;
static_assert(char8_32 == 11);
static constexpr auto char16_32 = min_cap<char16_t, int>;
static_assert(char16_32 == 5);
static constexpr auto char32_32 = min_cap<char32_t, int>;
static_assert(char32_32 == 2);
static constexpr auto char64_32 = min_cap<long, int>;
static_assert(char64_32 == 2);
// 64 bit system, __endian_factor = 1
static_assert(to_alloc<char, long, 1>(0) == char8_64);
static_assert(to_alloc<char16_t, long, 1>(0) == char16_64);
static_assert(to_alloc<char32_t, long, 1>(0) == char32_64);
static_assert(to_alloc<long, long, 1>(0) == char64_64);
static_assert(to_alloc<char, long, 1>(char8_64) == char8_64 + 1);
static_assert(to_alloc<char16_t, long, 1>(char16_64) == char16_64 + 1);
static_assert(to_alloc<char32_t, long, 1>(char32_64) == char32_64 + 1);
static_assert(to_alloc<long, long, 1>(char64_64) == char64_64 + 1);
static_assert(to_alloc<char, long, 1>(char8_64 + 1) == 32);
static_assert(to_alloc<char16_t, long, 1>(char16_64 + 1) == 16);
static_assert(to_alloc<char32_t, long, 1>(char32_64 + 1) == 8);
static_assert(to_alloc<long, long, 1>(char64_64 + 1) == 4);
// 64 bit system, __endian_factor = 2
static_assert(to_alloc<char, long, 2>(0) == char8_64);
static_assert(to_alloc<char16_t, long, 2>(0) == char16_64);
static_assert(to_alloc<char32_t, long, 2>(0) == char32_64);
static_assert(to_alloc<long, long, 2>(0) == char64_64);
static_assert(to_alloc<char, long, 2>(char8_64) == char8_64 + 1);
static_assert(to_alloc<char16_t, long, 2>(char16_64) == char16_64 + 1);
static_assert(to_alloc<char32_t, long, 2>(char32_64) == char32_64 + 1);
static_assert(to_alloc<long, long, 2>(char64_64) == char64_64 + 2);
static_assert(to_alloc<char, long, 2>(char8_64 + 1) == 32);
static_assert(to_alloc<char16_t, long, 2>(char16_64 + 1) == 16);
static_assert(to_alloc<char32_t, long, 2>(char32_64 + 1) == 8);
static_assert(to_alloc<long, long, 2>(char64_64 + 1) == 4);
// 32 bit system, __endian_factor = 1
static_assert(to_alloc<char, int, 1>(0) == char8_32);
static_assert(to_alloc<char16_t, int, 1>(0) == char16_32);
static_assert(to_alloc<char32_t, int, 1>(0) == char32_32);
static_assert(to_alloc<long, int, 1>(0) == char64_32);
static_assert(to_alloc<char, int, 1>(char8_32) == char8_32 + 1);
static_assert(to_alloc<char16_t, int, 1>(char16_32) == char16_32 + 1);
static_assert(to_alloc<char32_t, int, 1>(char32_32) == char32_32 + 1);
static_assert(to_alloc<long, int, 1>(char64_32) == char64_32 + 1);
static_assert(to_alloc<char, int, 1>(char8_32 + 1) == 16);
static_assert(to_alloc<char16_t, int, 1>(char16_32 + 1) == 8);
static_assert(to_alloc<char32_t, int, 1>(char32_32 + 1) == 4);
static_assert(to_alloc<long, int, 1>(char64_32 + 1) == 4);
// 32 bit system, __endian_factor = 2
static_assert(to_alloc<char, int, 2>(0) == char8_32);
static_assert(to_alloc<char16_t, int, 2>(0) == char16_32);
static_assert(to_alloc<char32_t, int, 2>(0) == char32_32);
static_assert(to_alloc<long, int, 2>(0) == char64_32);
static_assert(to_alloc<char, int, 2>(char8_32) == char8_32 + 1);
static_assert(to_alloc<char16_t, int, 2>(char16_32) == char16_32 + 1);
static_assert(to_alloc<char32_t, int, 2>(char32_32) == 4);
static_assert(to_alloc<long, int, 2>(char64_32) == 4);
static_assert(to_alloc<char, int, 2>(char8_32 + 1) == 16);
static_assert(to_alloc<char16_t, int, 2>(char16_32 + 1) == 8);
static_assert(to_alloc<char32_t, int, 2>(char32_32 + 1) == 4);
static_assert(to_alloc<long, int, 2>(char64_32 + 1) == 4);
}
```
---
Full diff: https://github.com/llvm/llvm-project/pull/92652.diff
1 Files Affected:
- (modified) libcxx/include/string (+1-7)
``````````diff
diff --git a/libcxx/include/string b/libcxx/include/string
index 1db803e822d72..4d66e1a6be31e 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1984,13 +1984,8 @@ private:
}
enum { __alignment = 8 };
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __recommend(size_type __s) _NOEXCEPT {
- if (__s < __min_cap) {
- return static_cast<size_type>(__min_cap) - 1;
- }
const size_type __boundary = sizeof(value_type) < __alignment ? __alignment / sizeof(value_type) : __endian_factor;
size_type __guess = __align_it<__boundary>(__s + 1) - 1;
- if (__guess == __min_cap)
- __guess += __endian_factor;
return __guess;
}
@@ -3249,8 +3244,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::re
if (__requested_capacity <= capacity())
return;
- size_type __target_capacity = std::max(__requested_capacity, size());
- __target_capacity = __recommend(__target_capacity);
+ __target_capacity = __recommend(__target_capacity);
if (__target_capacity == capacity())
return;
``````````
</details>
https://github.com/llvm/llvm-project/pull/92652
More information about the libcxx-commits
mailing list