From 458734b8b9ab457e3c88b76e87761a8f4c27a290 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet Date: Tue, 18 Apr 2023 15:16:20 +0000 Subject: [PATCH] [reland][libc] handle memset sequence as a separate struct These sequence of calls don't really make sense for head_tail and loop_and_tail. --- .../string/memory_utils/memset_implementations.h | 2 +- libc/src/string/memory_utils/op_generic.h | 23 ++++++++++++---------- libc/test/src/string/memory_utils/op_tests.cpp | 23 +++++++++++++++++++--- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/libc/src/string/memory_utils/memset_implementations.h b/libc/src/string/memory_utils/memset_implementations.h index dfc7df8..e78a447 100644 --- a/libc/src/string/memory_utils/memset_implementations.h +++ b/libc/src/string/memory_utils/memset_implementations.h @@ -57,7 +57,7 @@ inline_memset_x86(Ptr dst, uint8_t value, size_t count) { if (count == 2) return generic::Memset::block(dst, value); if (count == 3) - return generic::Memset::block(dst, value); + return generic::MemsetSequence::block(dst, value); if (count <= 8) return generic::Memset::head_tail(dst, value, count); if (count <= 16) diff --git a/libc/src/string/memory_utils/op_generic.h b/libc/src/string/memory_utils/op_generic.h index 1d203d6..663f428 100644 --- a/libc/src/string/memory_utils/op_generic.h +++ b/libc/src/string/memory_utils/op_generic.h @@ -165,11 +165,6 @@ template struct SupportedTypes { using TypeFor = typename details::Largest::type; }; -// Returns the sum of the sizeof of all the TS types. -template static constexpr size_t sum_sizeof() { - return (... + sizeof(TS)); -} - // Map from sizes to structures offering static load, store and splat methods. // Note: On platforms lacking vector support, we use the ArrayType below and // decompose the operation in smaller pieces. @@ -213,8 +208,8 @@ using getTypeFor = cpp::conditional_t< // Memset /////////////////////////////////////////////////////////////////////////////// -template struct Memset { - static constexpr size_t SIZE = sum_sizeof(); +template struct Memset { + static constexpr size_t SIZE = sizeof(T); LIBC_INLINE static void block(Ptr dst, uint8_t value) { static_assert(is_element_type_v); @@ -226,8 +221,6 @@ template struct Memset { for (size_t I = 0; I < array_size_v; ++I) store(dst + (I * sizeof(value_type)), Splat); } - if constexpr (sizeof...(TS)) - Memset::block(dst + sizeof(T), value); } LIBC_INLINE static void tail(Ptr dst, uint8_t value, size_t count) { @@ -250,12 +243,22 @@ template struct Memset { } }; +template struct MemsetSequence { + static constexpr size_t SIZE = (sizeof(T) + ... + sizeof(TS)); + LIBC_INLINE static void block(Ptr dst, uint8_t value) { + Memset::block(dst, value); + if constexpr (sizeof...(TS) > 0) { + return MemsetSequence::block(dst + sizeof(T), value); + } + } +}; + /////////////////////////////////////////////////////////////////////////////// // Memmove /////////////////////////////////////////////////////////////////////////////// template struct Memmove { - static constexpr size_t SIZE = sum_sizeof(); + static constexpr size_t SIZE = sizeof(T); LIBC_INLINE static void block(Ptr dst, CPtr src) { store(dst, load(src)); diff --git a/libc/test/src/string/memory_utils/op_tests.cpp b/libc/test/src/string/memory_utils/op_tests.cpp index b63a629..f845f49 100644 --- a/libc/test/src/string/memory_utils/op_tests.cpp +++ b/libc/test/src/string/memory_utils/op_tests.cpp @@ -21,6 +21,18 @@ namespace __llvm_libc { +template struct has_head_tail { + template static char sfinae(decltype(&C::head_tail)); + template static uint16_t sfinae(...); + static constexpr bool value = sizeof(sfinae(0)) == sizeof(char); +}; + +template struct has_loop_and_tail { + template static char sfinae(decltype(&C::loop_and_tail)); + template static uint16_t sfinae(...); + static constexpr bool value = sizeof(sfinae(0)) == sizeof(char); +}; + // Allocates two Buffer and extracts two spans out of them, one // aligned and one misaligned. Tests are run on both spans. struct Buffers { @@ -132,7 +144,10 @@ using MemsetImplementations = testing::TypeList< #endif generic::Memset, generic::Memset>, // generic::Memset, generic::Memset>, // - generic::Memset, generic::Memset> // + generic::Memset, generic::Memset>, // + generic::MemsetSequence, // + generic::MemsetSequence, // + generic::MemsetSequence // >; // Adapt CheckMemset signature to op implementation signatures. @@ -158,7 +173,8 @@ TYPED_TEST(LlvmLibcOpTest, Memset, MemsetImplementations) { } } } - { // Test head tail operations from kSize to 2 * kSize. + if constexpr (has_head_tail::value) { + // Test head tail operations from kSize to 2 * kSize. static constexpr auto HeadTailImpl = SetAdaptor; Buffer DstBuffer(2 * kSize); for (size_t size = kSize; size < 2 * kSize; ++size) { @@ -167,7 +183,8 @@ TYPED_TEST(LlvmLibcOpTest, Memset, MemsetImplementations) { ASSERT_TRUE(CheckMemset(dst, value, size)); } } - { // Test loop operations from kSize to 3 * kSize. + if constexpr (has_loop_and_tail::value) { + // Test loop operations from kSize to 3 * kSize. if constexpr (kSize > 1) { static constexpr auto LoopImpl = SetAdaptor; Buffer DstBuffer(3 * kSize); -- 2.7.4