1 //===-- Memcmp implementation for x86_64 ------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 #ifndef LIBC_SRC_STRING_MEMORY_UTILS_X86_64_MEMCMP_IMPLEMENTATIONS_H
9 #define LIBC_SRC_STRING_MEMORY_UTILS_X86_64_MEMCMP_IMPLEMENTATIONS_H
11 #include "src/__support/macros/config.h" // LIBC_INLINE
12 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
13 #include "src/string/memory_utils/op_generic.h"
14 #include "src/string/memory_utils/op_x86.h"
15 #include "src/string/memory_utils/utils.h" // MemcmpReturnType
17 namespace __llvm_libc
{
19 [[maybe_unused
]] LIBC_INLINE MemcmpReturnType
20 inline_memcmp_generic_gt16(CPtr p1
, CPtr p2
, size_t count
) {
21 if (LIBC_UNLIKELY(count
>= 384)) {
22 if (auto value
= generic::Memcmp
<16>::block(p1
, p2
))
24 align_to_next_boundary
<16, Arg::P1
>(p1
, p2
, count
);
26 return generic::Memcmp
<16>::loop_and_tail(p1
, p2
, count
);
29 [[maybe_unused
]] LIBC_INLINE MemcmpReturnType
30 inline_memcmp_x86_sse2_gt16(CPtr p1
, CPtr p2
, size_t count
) {
31 if (LIBC_UNLIKELY(count
>= 384)) {
32 if (auto value
= x86::sse2::Memcmp
<16>::block(p1
, p2
))
34 align_to_next_boundary
<16, Arg::P1
>(p1
, p2
, count
);
36 return x86::sse2::Memcmp
<16>::loop_and_tail(p1
, p2
, count
);
39 [[maybe_unused
]] LIBC_INLINE MemcmpReturnType
40 inline_memcmp_x86_avx2_gt16(CPtr p1
, CPtr p2
, size_t count
) {
42 return x86::sse2::Memcmp
<16>::head_tail(p1
, p2
, count
);
44 return x86::avx2::Memcmp
<32>::head_tail(p1
, p2
, count
);
46 return x86::avx2::Memcmp
<64>::head_tail(p1
, p2
, count
);
47 if (LIBC_UNLIKELY(count
>= 384)) {
48 if (auto value
= x86::avx2::Memcmp
<32>::block(p1
, p2
))
50 align_to_next_boundary
<32, Arg::P1
>(p1
, p2
, count
);
52 return x86::avx2::Memcmp
<32>::loop_and_tail(p1
, p2
, count
);
55 [[maybe_unused
]] LIBC_INLINE MemcmpReturnType
56 inline_memcmp_x86_avx512bw_gt16(CPtr p1
, CPtr p2
, size_t count
) {
58 return x86::sse2::Memcmp
<16>::head_tail(p1
, p2
, count
);
60 return x86::avx2::Memcmp
<32>::head_tail(p1
, p2
, count
);
62 return x86::avx512bw::Memcmp
<64>::head_tail(p1
, p2
, count
);
63 if (LIBC_UNLIKELY(count
>= 384)) {
64 if (auto value
= x86::avx512bw::Memcmp
<64>::block(p1
, p2
))
66 align_to_next_boundary
<64, Arg::P1
>(p1
, p2
, count
);
68 return x86::avx512bw::Memcmp
<64>::loop_and_tail(p1
, p2
, count
);
71 LIBC_INLINE MemcmpReturnType
inline_memcmp_x86(CPtr p1
, CPtr p2
, size_t count
) {
74 return MemcmpReturnType::ZERO();
76 return generic::Memcmp
<1>::block(p1
, p2
);
78 return generic::Memcmp
<2>::block(p1
, p2
);
80 return generic::Memcmp
<3>::block(p1
, p2
);
82 return generic::Memcmp
<4>::head_tail(p1
, p2
, count
);
84 return generic::Memcmp
<8>::head_tail(p1
, p2
, count
);
85 if constexpr (x86::kAvx512BW
)
86 return inline_memcmp_x86_avx512bw_gt16(p1
, p2
, count
);
87 else if constexpr (x86::kAvx2
)
88 return inline_memcmp_x86_avx2_gt16(p1
, p2
, count
);
89 else if constexpr (x86::kSse2
)
90 return inline_memcmp_x86_sse2_gt16(p1
, p2
, count
);
92 return inline_memcmp_generic_gt16(p1
, p2
, count
);
94 } // namespace __llvm_libc
96 #endif // LIBC_SRC_STRING_MEMORY_UTILS_X86_64_MEMCMP_IMPLEMENTATIONS_H