14f3511e2SGuillaume Chatelet //===-- Implementation of memcmp ------------------------------------------===//
24f3511e2SGuillaume Chatelet //
34f3511e2SGuillaume Chatelet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44f3511e2SGuillaume Chatelet // See https://llvm.org/LICENSE.txt for license information.
54f3511e2SGuillaume Chatelet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64f3511e2SGuillaume Chatelet //
74f3511e2SGuillaume Chatelet //===----------------------------------------------------------------------===//
84f3511e2SGuillaume Chatelet 
94f3511e2SGuillaume Chatelet #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_MEMCMP_IMPLEMENTATIONS_H
104f3511e2SGuillaume Chatelet #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_MEMCMP_IMPLEMENTATIONS_H
114f3511e2SGuillaume Chatelet 
124f3511e2SGuillaume Chatelet #include "src/__support/architectures.h"
134f3511e2SGuillaume Chatelet #include "src/__support/common.h"
144f3511e2SGuillaume Chatelet #include "src/string/memory_utils/elements.h"
154f3511e2SGuillaume Chatelet 
164f3511e2SGuillaume Chatelet #include <stddef.h> // size_t
174f3511e2SGuillaume Chatelet 
184f3511e2SGuillaume Chatelet namespace __llvm_libc {
194f3511e2SGuillaume Chatelet 
inline_memcmp(const char * lhs,const char * rhs,size_t count)204f3511e2SGuillaume Chatelet static inline int inline_memcmp(const char *lhs, const char *rhs,
214f3511e2SGuillaume Chatelet                                 size_t count) {
224f3511e2SGuillaume Chatelet #if defined(LLVM_LIBC_ARCH_X86)
234f3511e2SGuillaume Chatelet   /////////////////////////////////////////////////////////////////////////////
244f3511e2SGuillaume Chatelet   // LLVM_LIBC_ARCH_X86
254f3511e2SGuillaume Chatelet   /////////////////////////////////////////////////////////////////////////////
264f3511e2SGuillaume Chatelet   using namespace __llvm_libc::x86;
274f3511e2SGuillaume Chatelet   if (count == 0)
284f3511e2SGuillaume Chatelet     return 0;
294f3511e2SGuillaume Chatelet   if (count == 1)
30*1c92911eSMichael Jones     return three_way_compare<_1>(lhs, rhs);
314f3511e2SGuillaume Chatelet   if (count == 2)
32*1c92911eSMichael Jones     return three_way_compare<_2>(lhs, rhs);
334f3511e2SGuillaume Chatelet   if (count == 3)
34*1c92911eSMichael Jones     return three_way_compare<_3>(lhs, rhs);
354f3511e2SGuillaume Chatelet   if (count <= 8)
36*1c92911eSMichael Jones     return three_way_compare<HeadTail<_4>>(lhs, rhs, count);
374f3511e2SGuillaume Chatelet   if (count <= 16)
38*1c92911eSMichael Jones     return three_way_compare<HeadTail<_8>>(lhs, rhs, count);
394f3511e2SGuillaume Chatelet   if (count <= 32)
40*1c92911eSMichael Jones     return three_way_compare<HeadTail<_16>>(lhs, rhs, count);
414f3511e2SGuillaume Chatelet   if (count <= 64)
42*1c92911eSMichael Jones     return three_way_compare<HeadTail<_32>>(lhs, rhs, count);
434f3511e2SGuillaume Chatelet   if (count <= 128)
44*1c92911eSMichael Jones     return three_way_compare<HeadTail<_64>>(lhs, rhs, count);
45*1c92911eSMichael Jones   return three_way_compare<Align<_32>::Then<Loop<_32>>>(lhs, rhs, count);
464f3511e2SGuillaume Chatelet #elif defined(LLVM_LIBC_ARCH_AARCH64)
474f3511e2SGuillaume Chatelet   /////////////////////////////////////////////////////////////////////////////
484f3511e2SGuillaume Chatelet   // LLVM_LIBC_ARCH_AARCH64
494f3511e2SGuillaume Chatelet   /////////////////////////////////////////////////////////////////////////////
504f3511e2SGuillaume Chatelet   using namespace ::__llvm_libc::aarch64;
514f3511e2SGuillaume Chatelet   if (count == 0) // [0, 0]
524f3511e2SGuillaume Chatelet     return 0;
534f3511e2SGuillaume Chatelet   if (count == 1) // [1, 1]
54*1c92911eSMichael Jones     return three_way_compare<_1>(lhs, rhs);
554f3511e2SGuillaume Chatelet   if (count == 2) // [2, 2]
56*1c92911eSMichael Jones     return three_way_compare<_2>(lhs, rhs);
574f3511e2SGuillaume Chatelet   if (count == 3) // [3, 3]
58*1c92911eSMichael Jones     return three_way_compare<_3>(lhs, rhs);
594f3511e2SGuillaume Chatelet   if (count < 8) // [4, 7]
60*1c92911eSMichael Jones     return three_way_compare<HeadTail<_4>>(lhs, rhs, count);
614f3511e2SGuillaume Chatelet   if (count < 16) // [8, 15]
62*1c92911eSMichael Jones     return three_way_compare<HeadTail<_8>>(lhs, rhs, count);
634f3511e2SGuillaume Chatelet   if (unlikely(count >= 128)) // [128, ∞]
64*1c92911eSMichael Jones     return three_way_compare<Align<_16>::Then<Loop<_32>>>(lhs, rhs, count);
65*1c92911eSMichael Jones   if (!equals<_16>(lhs, rhs)) // [16, 16]
66*1c92911eSMichael Jones     return three_way_compare<_16>(lhs, rhs);
674f3511e2SGuillaume Chatelet   if (count < 32) // [17, 31]
68*1c92911eSMichael Jones     return three_way_compare<Tail<_16>>(lhs, rhs, count);
69*1c92911eSMichael Jones   if (!equals<Skip<16>::Then<_16>>(lhs, rhs)) // [32, 32]
70*1c92911eSMichael Jones     return three_way_compare<Skip<16>::Then<_16>>(lhs, rhs);
714f3511e2SGuillaume Chatelet   if (count < 64) // [33, 63]
72*1c92911eSMichael Jones     return three_way_compare<Tail<_32>>(lhs, rhs, count);
734f3511e2SGuillaume Chatelet   // [64, 127]
74*1c92911eSMichael Jones   return three_way_compare<Skip<32>::Then<Loop<_16>>>(lhs, rhs, count);
754f3511e2SGuillaume Chatelet #else
764f3511e2SGuillaume Chatelet   /////////////////////////////////////////////////////////////////////////////
774f3511e2SGuillaume Chatelet   // Default
784f3511e2SGuillaume Chatelet   /////////////////////////////////////////////////////////////////////////////
794f3511e2SGuillaume Chatelet   using namespace ::__llvm_libc::scalar;
804f3511e2SGuillaume Chatelet 
814f3511e2SGuillaume Chatelet   if (count == 0)
824f3511e2SGuillaume Chatelet     return 0;
834f3511e2SGuillaume Chatelet   if (count == 1)
84*1c92911eSMichael Jones     return three_way_compare<_1>(lhs, rhs);
854f3511e2SGuillaume Chatelet   if (count == 2)
86*1c92911eSMichael Jones     return three_way_compare<_2>(lhs, rhs);
874f3511e2SGuillaume Chatelet   if (count == 3)
88*1c92911eSMichael Jones     return three_way_compare<_3>(lhs, rhs);
894f3511e2SGuillaume Chatelet   if (count <= 8)
90*1c92911eSMichael Jones     return three_way_compare<HeadTail<_4>>(lhs, rhs, count);
914f3511e2SGuillaume Chatelet   if (count <= 16)
92*1c92911eSMichael Jones     return three_way_compare<HeadTail<_8>>(lhs, rhs, count);
934f3511e2SGuillaume Chatelet   if (count <= 32)
94*1c92911eSMichael Jones     return three_way_compare<HeadTail<_16>>(lhs, rhs, count);
954f3511e2SGuillaume Chatelet   if (count <= 64)
96*1c92911eSMichael Jones     return three_way_compare<HeadTail<_32>>(lhs, rhs, count);
974f3511e2SGuillaume Chatelet   if (count <= 128)
98*1c92911eSMichael Jones     return three_way_compare<HeadTail<_64>>(lhs, rhs, count);
99*1c92911eSMichael Jones   return three_way_compare<Align<_32>::Then<Loop<_32>>>(lhs, rhs, count);
1004f3511e2SGuillaume Chatelet #endif
1014f3511e2SGuillaume Chatelet }
1024f3511e2SGuillaume Chatelet 
1034f3511e2SGuillaume Chatelet } // namespace __llvm_libc
1044f3511e2SGuillaume Chatelet 
1054f3511e2SGuillaume Chatelet #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_MEMCMP_IMPLEMENTATIONS_H
106