xref: /llvm-project/libc/test/src/string/memory_utils/op_tests.cpp (revision ded080152acceca5d68014d63f5027a6d8266cbb)
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