169090143SGuillaume Chatelet //===-- Unittests for op_ files -------------------------------------------===// 269090143SGuillaume Chatelet // 369090143SGuillaume Chatelet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 469090143SGuillaume Chatelet // See https://llvm.org/LICENSE.txt for license information. 569090143SGuillaume Chatelet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 669090143SGuillaume Chatelet // 769090143SGuillaume Chatelet //===----------------------------------------------------------------------===// 869090143SGuillaume Chatelet 93635195eSGuillaume Chatelet #include "memory_check_utils.h" 105ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 11*ded08015SSirui Mu #include "src/__support/macros/properties/os.h" 12a84e66a9SGuillaume Chatelet #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT64 1369090143SGuillaume Chatelet #include "src/string/memory_utils/op_aarch64.h" 1469090143SGuillaume Chatelet #include "src/string/memory_utils/op_builtin.h" 1507d7b9c2SGuillaume Chatelet #include "src/string/memory_utils/op_generic.h" 161c814c99SGuillaume Chatelet #include "src/string/memory_utils/op_riscv.h" 1769090143SGuillaume Chatelet #include "src/string/memory_utils/op_x86.h" 18af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h" 1969090143SGuillaume Chatelet 205ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 2169090143SGuillaume Chatelet 22458734b8SGuillaume Chatelet template <typename T> struct has_head_tail { 23458734b8SGuillaume Chatelet template <typename C> static char sfinae(decltype(&C::head_tail)); 24458734b8SGuillaume Chatelet template <typename C> static uint16_t sfinae(...); 25458734b8SGuillaume Chatelet static constexpr bool value = sizeof(sfinae<T>(0)) == sizeof(char); 26458734b8SGuillaume Chatelet }; 27458734b8SGuillaume Chatelet 28458734b8SGuillaume Chatelet template <typename T> struct has_loop_and_tail { 29458734b8SGuillaume Chatelet template <typename C> static char sfinae(decltype(&C::loop_and_tail)); 30458734b8SGuillaume Chatelet template <typename C> static uint16_t sfinae(...); 31458734b8SGuillaume Chatelet static constexpr bool value = sizeof(sfinae<T>(0)) == sizeof(char); 32458734b8SGuillaume Chatelet }; 33458734b8SGuillaume Chatelet 3469090143SGuillaume Chatelet // Allocates two Buffer and extracts two spans out of them, one 3569090143SGuillaume Chatelet // aligned and one misaligned. Tests are run on both spans. 3669090143SGuillaume Chatelet struct Buffers { 3769090143SGuillaume Chatelet Buffers(size_t size) 3869090143SGuillaume Chatelet : aligned_buffer(size, Aligned::YES), 3969090143SGuillaume Chatelet misaligned_buffer(size, Aligned::NO) {} 4069090143SGuillaume Chatelet 4169090143SGuillaume Chatelet // Returns two spans of 'size' bytes. The first is aligned on 4269090143SGuillaume Chatelet // Buffer::kAlign and the second one is unaligned. 4369090143SGuillaume Chatelet cpp::array<cpp::span<char>, 2> spans() { 4469090143SGuillaume Chatelet return {aligned_buffer.span(), misaligned_buffer.span()}; 4569090143SGuillaume Chatelet } 4669090143SGuillaume Chatelet 4769090143SGuillaume Chatelet Buffer aligned_buffer; 4869090143SGuillaume Chatelet Buffer misaligned_buffer; 4969090143SGuillaume Chatelet }; 5069090143SGuillaume Chatelet 5169090143SGuillaume Chatelet using MemcpyImplementations = testing::TypeList< 5269090143SGuillaume Chatelet #ifdef LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE 5369090143SGuillaume Chatelet builtin::Memcpy<1>, // 5469090143SGuillaume Chatelet builtin::Memcpy<2>, // 5569090143SGuillaume Chatelet builtin::Memcpy<3>, // 5669090143SGuillaume Chatelet builtin::Memcpy<4>, // 5769090143SGuillaume Chatelet builtin::Memcpy<8>, // 5869090143SGuillaume Chatelet builtin::Memcpy<16>, // 5969090143SGuillaume Chatelet builtin::Memcpy<32>, // 6069090143SGuillaume Chatelet builtin::Memcpy<64> 6169090143SGuillaume Chatelet #endif // LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE 6269090143SGuillaume Chatelet >; 6369090143SGuillaume Chatelet 643635195eSGuillaume Chatelet // Convenient helper to turn a span into cpp::byte *. 653635195eSGuillaume Chatelet static inline cpp::byte *as_byte(cpp::span<char> span) { 663635195eSGuillaume Chatelet return reinterpret_cast<cpp::byte *>(span.data()); 6769090143SGuillaume Chatelet } 6869090143SGuillaume Chatelet 693635195eSGuillaume Chatelet // Adapt CheckMemcpy signature to op implementation signatures. 703635195eSGuillaume Chatelet template <auto FnImpl> 713635195eSGuillaume Chatelet void CopyAdaptor(cpp::span<char> dst, cpp::span<char> src, size_t size) { 723635195eSGuillaume Chatelet FnImpl(as_byte(dst), as_byte(src), size); 733635195eSGuillaume Chatelet } 743635195eSGuillaume Chatelet template <size_t Size, auto FnImpl> 753635195eSGuillaume Chatelet void CopyBlockAdaptor(cpp::span<char> dst, cpp::span<char> src, size_t size) { 763635195eSGuillaume Chatelet FnImpl(as_byte(dst), as_byte(src)); 7769090143SGuillaume Chatelet } 7869090143SGuillaume Chatelet 7969090143SGuillaume Chatelet TYPED_TEST(LlvmLibcOpTest, Memcpy, MemcpyImplementations) { 8069090143SGuillaume Chatelet using Impl = ParamType; 8169090143SGuillaume Chatelet constexpr size_t kSize = Impl::SIZE; 8269090143SGuillaume Chatelet { // Test block operation 833635195eSGuillaume Chatelet static constexpr auto BlockImpl = CopyBlockAdaptor<kSize, Impl::block>; 8469090143SGuillaume Chatelet Buffers SrcBuffer(kSize); 8569090143SGuillaume Chatelet Buffers DstBuffer(kSize); 8669090143SGuillaume Chatelet for (auto src : SrcBuffer.spans()) { 8769090143SGuillaume Chatelet Randomize(src); 8869090143SGuillaume Chatelet for (auto dst : DstBuffer.spans()) { 893635195eSGuillaume Chatelet ASSERT_TRUE(CheckMemcpy<BlockImpl>(dst, src, kSize)); 9069090143SGuillaume Chatelet } 9169090143SGuillaume Chatelet } 9269090143SGuillaume Chatelet } 9369090143SGuillaume Chatelet { // Test head tail operations from kSize to 2 * kSize. 943635195eSGuillaume Chatelet static constexpr auto HeadTailImpl = CopyAdaptor<Impl::head_tail>; 9569090143SGuillaume Chatelet Buffer SrcBuffer(2 * kSize); 9669090143SGuillaume Chatelet Buffer DstBuffer(2 * kSize); 9769090143SGuillaume Chatelet Randomize(SrcBuffer.span()); 9869090143SGuillaume Chatelet for (size_t size = kSize; size < 2 * kSize; ++size) { 9969090143SGuillaume Chatelet auto src = SrcBuffer.span().subspan(0, size); 10069090143SGuillaume Chatelet auto dst = DstBuffer.span().subspan(0, size); 1013635195eSGuillaume Chatelet ASSERT_TRUE(CheckMemcpy<HeadTailImpl>(dst, src, size)); 10269090143SGuillaume Chatelet } 10369090143SGuillaume Chatelet } 10469090143SGuillaume Chatelet { // Test loop operations from kSize to 3 * kSize. 10569090143SGuillaume Chatelet if constexpr (kSize > 1) { 1063635195eSGuillaume Chatelet static constexpr auto LoopImpl = CopyAdaptor<Impl::loop_and_tail>; 10769090143SGuillaume Chatelet Buffer SrcBuffer(3 * kSize); 10869090143SGuillaume Chatelet Buffer DstBuffer(3 * kSize); 10969090143SGuillaume Chatelet Randomize(SrcBuffer.span()); 11069090143SGuillaume Chatelet for (size_t size = kSize; size < 3 * kSize; ++size) { 11169090143SGuillaume Chatelet auto src = SrcBuffer.span().subspan(0, size); 11269090143SGuillaume Chatelet auto dst = DstBuffer.span().subspan(0, size); 1133635195eSGuillaume Chatelet ASSERT_TRUE(CheckMemcpy<LoopImpl>(dst, src, size)); 11469090143SGuillaume Chatelet } 11569090143SGuillaume Chatelet } 11669090143SGuillaume Chatelet } 11769090143SGuillaume Chatelet } 11869090143SGuillaume Chatelet 11969090143SGuillaume Chatelet using MemsetImplementations = testing::TypeList< 12069090143SGuillaume Chatelet #ifdef LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE 12169090143SGuillaume Chatelet builtin::Memset<1>, // 12269090143SGuillaume Chatelet builtin::Memset<2>, // 12369090143SGuillaume Chatelet builtin::Memset<3>, // 12469090143SGuillaume Chatelet builtin::Memset<4>, // 12569090143SGuillaume Chatelet builtin::Memset<8>, // 12669090143SGuillaume Chatelet builtin::Memset<16>, // 12769090143SGuillaume Chatelet builtin::Memset<32>, // 12869090143SGuillaume Chatelet builtin::Memset<64>, 12969090143SGuillaume Chatelet #endif 130a84e66a9SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_INT64 1311a4696d9SGuillaume Chatelet generic::Memset<uint64_t>, generic::Memset<cpp::array<uint64_t, 2>>, 132a84e66a9SGuillaume Chatelet #endif // LIBC_TYPES_HAS_INT64 13369090143SGuillaume Chatelet #ifdef __AVX512F__ 1341c814c99SGuillaume Chatelet generic::Memset<generic_v512>, generic::Memset<cpp::array<generic_v512, 2>>, 13569090143SGuillaume Chatelet #endif 1361a4696d9SGuillaume Chatelet #ifdef __AVX__ 1371c814c99SGuillaume Chatelet generic::Memset<generic_v256>, generic::Memset<cpp::array<generic_v256, 2>>, 1381a4696d9SGuillaume Chatelet #endif 1391a4696d9SGuillaume Chatelet #ifdef __SSE2__ 1401c814c99SGuillaume Chatelet generic::Memset<generic_v128>, generic::Memset<cpp::array<generic_v128, 2>>, 1411a4696d9SGuillaume Chatelet #endif 1421a4696d9SGuillaume Chatelet generic::Memset<uint32_t>, generic::Memset<cpp::array<uint32_t, 2>>, // 1431a4696d9SGuillaume Chatelet generic::Memset<uint16_t>, generic::Memset<cpp::array<uint16_t, 2>>, // 144458734b8SGuillaume Chatelet generic::Memset<uint8_t>, generic::Memset<cpp::array<uint8_t, 2>>, // 145458734b8SGuillaume Chatelet generic::MemsetSequence<uint8_t, uint8_t>, // 146458734b8SGuillaume Chatelet generic::MemsetSequence<uint16_t, uint8_t>, // 147458734b8SGuillaume Chatelet generic::MemsetSequence<uint32_t, uint16_t, uint8_t> // 14869090143SGuillaume Chatelet >; 14969090143SGuillaume Chatelet 1503635195eSGuillaume Chatelet // Adapt CheckMemset signature to op implementation signatures. 15169090143SGuillaume Chatelet template <auto FnImpl> 1523635195eSGuillaume Chatelet void SetAdaptor(cpp::span<char> dst, uint8_t value, size_t size) { 153d7917fdcSGuillaume Chatelet FnImpl(as_byte(dst), value, size); 15469090143SGuillaume Chatelet } 1553635195eSGuillaume Chatelet template <size_t Size, auto FnImpl> 1563635195eSGuillaume Chatelet void SetBlockAdaptor(cpp::span<char> dst, uint8_t value, size_t size) { 1573635195eSGuillaume Chatelet FnImpl(as_byte(dst), value); 15869090143SGuillaume Chatelet } 15969090143SGuillaume Chatelet 16069090143SGuillaume Chatelet TYPED_TEST(LlvmLibcOpTest, Memset, MemsetImplementations) { 16169090143SGuillaume Chatelet using Impl = ParamType; 16269090143SGuillaume Chatelet constexpr size_t kSize = Impl::SIZE; 16369090143SGuillaume Chatelet { // Test block operation 1643635195eSGuillaume Chatelet static constexpr auto BlockImpl = SetBlockAdaptor<kSize, Impl::block>; 16569090143SGuillaume Chatelet Buffers DstBuffer(kSize); 16669090143SGuillaume Chatelet for (uint8_t value : cpp::array<uint8_t, 3>{0, 1, 255}) { 16769090143SGuillaume Chatelet for (auto dst : DstBuffer.spans()) { 1683635195eSGuillaume Chatelet ASSERT_TRUE(CheckMemset<BlockImpl>(dst, value, kSize)); 16969090143SGuillaume Chatelet } 17069090143SGuillaume Chatelet } 17169090143SGuillaume Chatelet } 172458734b8SGuillaume Chatelet if constexpr (has_head_tail<Impl>::value) { 173458734b8SGuillaume Chatelet // Test head tail operations from kSize to 2 * kSize. 1743635195eSGuillaume Chatelet static constexpr auto HeadTailImpl = SetAdaptor<Impl::head_tail>; 17569090143SGuillaume Chatelet Buffer DstBuffer(2 * kSize); 17669090143SGuillaume Chatelet for (size_t size = kSize; size < 2 * kSize; ++size) { 17769090143SGuillaume Chatelet const char value = size % 10; 17869090143SGuillaume Chatelet auto dst = DstBuffer.span().subspan(0, size); 1793635195eSGuillaume Chatelet ASSERT_TRUE(CheckMemset<HeadTailImpl>(dst, value, size)); 18069090143SGuillaume Chatelet } 18169090143SGuillaume Chatelet } 182458734b8SGuillaume Chatelet if constexpr (has_loop_and_tail<Impl>::value) { 183458734b8SGuillaume Chatelet // Test loop operations from kSize to 3 * kSize. 18469090143SGuillaume Chatelet if constexpr (kSize > 1) { 1853635195eSGuillaume Chatelet static constexpr auto LoopImpl = SetAdaptor<Impl::loop_and_tail>; 18669090143SGuillaume Chatelet Buffer DstBuffer(3 * kSize); 18769090143SGuillaume Chatelet for (size_t size = kSize; size < 3 * kSize; ++size) { 18869090143SGuillaume Chatelet const char value = size % 10; 18969090143SGuillaume Chatelet auto dst = DstBuffer.span().subspan(0, size); 1903635195eSGuillaume Chatelet ASSERT_TRUE((CheckMemset<LoopImpl>(dst, value, size))); 19169090143SGuillaume Chatelet } 19269090143SGuillaume Chatelet } 19369090143SGuillaume Chatelet } 19469090143SGuillaume Chatelet } 19569090143SGuillaume Chatelet 19688f0dc48SOverMighty #ifdef LIBC_TARGET_ARCH_IS_X86_64 19788f0dc48SOverMighty // Prevent GCC warning due to ignored __aligned__ attributes when passing x86 19888f0dc48SOverMighty // SIMD types as template arguments. 19988f0dc48SOverMighty #pragma GCC diagnostic push 20088f0dc48SOverMighty #pragma GCC diagnostic ignored "-Wignored-attributes" 20188f0dc48SOverMighty #endif // LIBC_TARGET_ARCH_IS_X86_64 20288f0dc48SOverMighty 20369090143SGuillaume Chatelet using BcmpImplementations = testing::TypeList< 2041c814c99SGuillaume Chatelet #ifdef LIBC_TARGET_ARCH_IS_X86_64 2051c814c99SGuillaume Chatelet #ifdef __SSE4_1__ 2061c814c99SGuillaume Chatelet generic::Bcmp<__m128i>, 2071c814c99SGuillaume Chatelet #endif // __SSE4_1__ 20869090143SGuillaume Chatelet #ifdef __AVX2__ 2091c814c99SGuillaume Chatelet generic::Bcmp<__m256i>, 2101c814c99SGuillaume Chatelet #endif // __AVX2__ 21169090143SGuillaume Chatelet #ifdef __AVX512BW__ 2121c814c99SGuillaume Chatelet generic::Bcmp<__m512i>, 2131c814c99SGuillaume Chatelet #endif // __AVX512BW__ 2141c814c99SGuillaume Chatelet 2151c814c99SGuillaume Chatelet #endif // LIBC_TARGET_ARCH_IS_X86_64 216a2569a76SGuillaume Chatelet #ifdef LIBC_TARGET_ARCH_IS_AARCH64 21769090143SGuillaume Chatelet aarch64::Bcmp<16>, // 2181c814c99SGuillaume Chatelet aarch64::Bcmp<32>, 21969090143SGuillaume Chatelet #endif 2201c814c99SGuillaume Chatelet #ifndef LIBC_TARGET_ARCH_IS_ARM // Removing non uint8_t types for ARM 2211c814c99SGuillaume Chatelet generic::Bcmp<uint16_t>, 2221c814c99SGuillaume Chatelet generic::Bcmp<uint32_t>, // 223a84e66a9SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_INT64 2241c814c99SGuillaume Chatelet generic::Bcmp<uint64_t>, 225a84e66a9SGuillaume Chatelet #endif // LIBC_TYPES_HAS_INT64 2261c814c99SGuillaume Chatelet generic::BcmpSequence<uint16_t, uint8_t>, 2271c814c99SGuillaume Chatelet generic::BcmpSequence<uint32_t, uint8_t>, // 2281c814c99SGuillaume Chatelet generic::BcmpSequence<uint32_t, uint16_t>, // 2291c814c99SGuillaume Chatelet generic::BcmpSequence<uint32_t, uint16_t, uint8_t>, 2301c814c99SGuillaume Chatelet #endif // LIBC_TARGET_ARCH_IS_ARM 2311c814c99SGuillaume Chatelet generic::BcmpSequence<uint8_t, uint8_t>, 2321c814c99SGuillaume Chatelet generic::BcmpSequence<uint8_t, uint8_t, uint8_t>, // 2331c814c99SGuillaume Chatelet generic::Bcmp<uint8_t>>; 23469090143SGuillaume Chatelet 23588f0dc48SOverMighty #ifdef LIBC_TARGET_ARCH_IS_X86_64 23688f0dc48SOverMighty #pragma GCC diagnostic pop 23788f0dc48SOverMighty #endif // LIBC_TARGET_ARCH_IS_X86_64 23888f0dc48SOverMighty 2393635195eSGuillaume Chatelet // Adapt CheckBcmp signature to op implementation signatures. 24069090143SGuillaume Chatelet template <auto FnImpl> 2413635195eSGuillaume Chatelet int CmpAdaptor(cpp::span<char> p1, cpp::span<char> p2, size_t size) { 2423635195eSGuillaume Chatelet return (int)FnImpl(as_byte(p1), as_byte(p2), size); 24369090143SGuillaume Chatelet } 2443635195eSGuillaume Chatelet template <size_t Size, auto FnImpl> 2453635195eSGuillaume Chatelet int CmpBlockAdaptor(cpp::span<char> p1, cpp::span<char> p2, size_t size) { 2463635195eSGuillaume Chatelet return (int)FnImpl(as_byte(p1), as_byte(p2)); 24769090143SGuillaume Chatelet } 24869090143SGuillaume Chatelet 24969090143SGuillaume Chatelet TYPED_TEST(LlvmLibcOpTest, Bcmp, BcmpImplementations) { 25069090143SGuillaume Chatelet using Impl = ParamType; 25169090143SGuillaume Chatelet constexpr size_t kSize = Impl::SIZE; 25269090143SGuillaume Chatelet { // Test block operation 2533635195eSGuillaume Chatelet static constexpr auto BlockImpl = CmpBlockAdaptor<kSize, Impl::block>; 25469090143SGuillaume Chatelet Buffers Buffer1(kSize); 25569090143SGuillaume Chatelet Buffers Buffer2(kSize); 25669090143SGuillaume Chatelet for (auto span1 : Buffer1.spans()) { 25769090143SGuillaume Chatelet Randomize(span1); 25869090143SGuillaume Chatelet for (auto span2 : Buffer2.spans()) 2593635195eSGuillaume Chatelet ASSERT_TRUE((CheckBcmp<BlockImpl>(span1, span2, kSize))); 26069090143SGuillaume Chatelet } 26169090143SGuillaume Chatelet } 2621c814c99SGuillaume Chatelet if constexpr (has_head_tail<Impl>::value) { 2631c814c99SGuillaume Chatelet // Test head tail operations from kSize to 2 * kSize. 2643635195eSGuillaume Chatelet static constexpr auto HeadTailImpl = CmpAdaptor<Impl::head_tail>; 26569090143SGuillaume Chatelet Buffer Buffer1(2 * kSize); 26669090143SGuillaume Chatelet Buffer Buffer2(2 * kSize); 26769090143SGuillaume Chatelet Randomize(Buffer1.span()); 26869090143SGuillaume Chatelet for (size_t size = kSize; size < 2 * kSize; ++size) { 26969090143SGuillaume Chatelet auto span1 = Buffer1.span().subspan(0, size); 27069090143SGuillaume Chatelet auto span2 = Buffer2.span().subspan(0, size); 2713635195eSGuillaume Chatelet ASSERT_TRUE((CheckBcmp<HeadTailImpl>(span1, span2, size))); 27269090143SGuillaume Chatelet } 27369090143SGuillaume Chatelet } 2741c814c99SGuillaume Chatelet if constexpr (has_loop_and_tail<Impl>::value) { 2751c814c99SGuillaume Chatelet // Test loop operations from kSize to 3 * kSize. 27669090143SGuillaume Chatelet if constexpr (kSize > 1) { 2773635195eSGuillaume Chatelet static constexpr auto LoopImpl = CmpAdaptor<Impl::loop_and_tail>; 27869090143SGuillaume Chatelet Buffer Buffer1(3 * kSize); 27969090143SGuillaume Chatelet Buffer Buffer2(3 * kSize); 28069090143SGuillaume Chatelet Randomize(Buffer1.span()); 28169090143SGuillaume Chatelet for (size_t size = kSize; size < 3 * kSize; ++size) { 28269090143SGuillaume Chatelet auto span1 = Buffer1.span().subspan(0, size); 28369090143SGuillaume Chatelet auto span2 = Buffer2.span().subspan(0, size); 2843635195eSGuillaume Chatelet ASSERT_TRUE((CheckBcmp<LoopImpl>(span1, span2, size))); 28569090143SGuillaume Chatelet } 28669090143SGuillaume Chatelet } 28769090143SGuillaume Chatelet } 28869090143SGuillaume Chatelet } 28969090143SGuillaume Chatelet 29088f0dc48SOverMighty #ifdef LIBC_TARGET_ARCH_IS_X86_64 29188f0dc48SOverMighty // Prevent GCC warning due to ignored __aligned__ attributes when passing x86 29288f0dc48SOverMighty // SIMD types as template arguments. 29388f0dc48SOverMighty #pragma GCC diagnostic push 29488f0dc48SOverMighty #pragma GCC diagnostic ignored "-Wignored-attributes" 29588f0dc48SOverMighty #endif // LIBC_TARGET_ARCH_IS_X86_64 29688f0dc48SOverMighty 29769090143SGuillaume Chatelet using MemcmpImplementations = testing::TypeList< 298*ded08015SSirui Mu #if defined(LIBC_TARGET_ARCH_IS_X86_64) && !defined(LIBC_TARGET_OS_IS_WINDOWS) 29969090143SGuillaume Chatelet #ifdef __SSE2__ 3001c814c99SGuillaume Chatelet generic::Memcmp<__m128i>, // 30169090143SGuillaume Chatelet #endif 30269090143SGuillaume Chatelet #ifdef __AVX2__ 3031c814c99SGuillaume Chatelet generic::Memcmp<__m256i>, // 30469090143SGuillaume Chatelet #endif 30569090143SGuillaume Chatelet #ifdef __AVX512BW__ 3061c814c99SGuillaume Chatelet generic::Memcmp<__m512i>, // 30769090143SGuillaume Chatelet #endif 3081c814c99SGuillaume Chatelet #endif // LIBC_TARGET_ARCH_IS_X86_64 3091c814c99SGuillaume Chatelet #ifdef LIBC_TARGET_ARCH_IS_AARCH64 3101c814c99SGuillaume Chatelet generic::Memcmp<uint8x16_t>, // 3111c814c99SGuillaume Chatelet generic::Memcmp<uint8x16x2_t>, 3121c814c99SGuillaume Chatelet #endif 3131c814c99SGuillaume Chatelet #ifndef LIBC_TARGET_ARCH_IS_ARM // Removing non uint8_t types for ARM 3141c814c99SGuillaume Chatelet generic::Memcmp<uint16_t>, 3151c814c99SGuillaume Chatelet generic::Memcmp<uint32_t>, // 316a84e66a9SGuillaume Chatelet #ifdef LIBC_TYPES_HAS_INT64 3171c814c99SGuillaume Chatelet generic::Memcmp<uint64_t>, 318a84e66a9SGuillaume Chatelet #endif // LIBC_TYPES_HAS_INT64 3191c814c99SGuillaume Chatelet generic::MemcmpSequence<uint16_t, uint8_t>, 3201c814c99SGuillaume Chatelet generic::MemcmpSequence<uint32_t, uint16_t, uint8_t>, // 3211c814c99SGuillaume Chatelet #endif // LIBC_TARGET_ARCH_IS_ARM 3221c814c99SGuillaume Chatelet generic::MemcmpSequence<uint8_t, uint8_t>, 3231c814c99SGuillaume Chatelet generic::MemcmpSequence<uint8_t, uint8_t, uint8_t>, 3241c814c99SGuillaume Chatelet generic::Memcmp<uint8_t>>; 32569090143SGuillaume Chatelet 32688f0dc48SOverMighty #ifdef LIBC_TARGET_ARCH_IS_X86_64 32788f0dc48SOverMighty #pragma GCC diagnostic pop 32888f0dc48SOverMighty #endif // LIBC_TARGET_ARCH_IS_X86_64 32988f0dc48SOverMighty 33069090143SGuillaume Chatelet TYPED_TEST(LlvmLibcOpTest, Memcmp, MemcmpImplementations) { 33169090143SGuillaume Chatelet using Impl = ParamType; 33269090143SGuillaume Chatelet constexpr size_t kSize = Impl::SIZE; 33369090143SGuillaume Chatelet { // Test block operation 3343635195eSGuillaume Chatelet static constexpr auto BlockImpl = CmpBlockAdaptor<kSize, Impl::block>; 33569090143SGuillaume Chatelet Buffers Buffer1(kSize); 33669090143SGuillaume Chatelet Buffers Buffer2(kSize); 33769090143SGuillaume Chatelet for (auto span1 : Buffer1.spans()) { 33869090143SGuillaume Chatelet Randomize(span1); 33969090143SGuillaume Chatelet for (auto span2 : Buffer2.spans()) 3403635195eSGuillaume Chatelet ASSERT_TRUE((CheckMemcmp<BlockImpl>(span1, span2, kSize))); 34169090143SGuillaume Chatelet } 34269090143SGuillaume Chatelet } 3431c814c99SGuillaume Chatelet if constexpr (has_head_tail<Impl>::value) { 3441c814c99SGuillaume Chatelet // Test head tail operations from kSize to 2 * kSize. 3453635195eSGuillaume Chatelet static constexpr auto HeadTailImpl = CmpAdaptor<Impl::head_tail>; 34669090143SGuillaume Chatelet Buffer Buffer1(2 * kSize); 34769090143SGuillaume Chatelet Buffer Buffer2(2 * kSize); 34869090143SGuillaume Chatelet Randomize(Buffer1.span()); 34969090143SGuillaume Chatelet for (size_t size = kSize; size < 2 * kSize; ++size) { 35069090143SGuillaume Chatelet auto span1 = Buffer1.span().subspan(0, size); 35169090143SGuillaume Chatelet auto span2 = Buffer2.span().subspan(0, size); 3523635195eSGuillaume Chatelet ASSERT_TRUE((CheckMemcmp<HeadTailImpl>(span1, span2, size))); 35369090143SGuillaume Chatelet } 35469090143SGuillaume Chatelet } 3551c814c99SGuillaume Chatelet if constexpr (has_loop_and_tail<Impl>::value) { 3561c814c99SGuillaume Chatelet // Test loop operations from kSize to 3 * kSize. 35769090143SGuillaume Chatelet if constexpr (kSize > 1) { 3583635195eSGuillaume Chatelet static constexpr auto LoopImpl = CmpAdaptor<Impl::loop_and_tail>; 35969090143SGuillaume Chatelet Buffer Buffer1(3 * kSize); 36069090143SGuillaume Chatelet Buffer Buffer2(3 * kSize); 36169090143SGuillaume Chatelet Randomize(Buffer1.span()); 36269090143SGuillaume Chatelet for (size_t size = kSize; size < 3 * kSize; ++size) { 36369090143SGuillaume Chatelet auto span1 = Buffer1.span().subspan(0, size); 36469090143SGuillaume Chatelet auto span2 = Buffer2.span().subspan(0, size); 3653635195eSGuillaume Chatelet ASSERT_TRUE((CheckMemcmp<LoopImpl>(span1, span2, size))); 36669090143SGuillaume Chatelet } 36769090143SGuillaume Chatelet } 36869090143SGuillaume Chatelet } 36969090143SGuillaume Chatelet } 37069090143SGuillaume Chatelet 3715ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 372