diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -271,7 +271,7 @@ function(add_bcmp bcmp_name) add_implementation(bcmp ${bcmp_name} - SRCS ${LIBC_BCMP_SRC} + SRCS ${LIBC_SOURCE_DIR}/src/string/bcmp.cpp HDRS ${LIBC_SOURCE_DIR}/src/string/bcmp.h DEPENDS .memory_utils.memory_utils @@ -284,7 +284,6 @@ endfunction() if(${LIBC_TARGET_ARCHITECTURE_IS_X86}) - set(LIBC_BCMP_SRC ${LIBC_SOURCE_DIR}/src/string/bcmp.cpp) add_bcmp(bcmp_x86_64_opt_sse2 COMPILE_OPTIONS -march=k8 REQUIRE SSE2) add_bcmp(bcmp_x86_64_opt_sse4 COMPILE_OPTIONS -march=nehalem REQUIRE SSE4_2) add_bcmp(bcmp_x86_64_opt_avx2 COMPILE_OPTIONS -march=haswell REQUIRE AVX2) @@ -292,7 +291,6 @@ add_bcmp(bcmp_opt_host COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}) add_bcmp(bcmp) else() - set(LIBC_BCMP_SRC ${LIBC_SOURCE_DIR}/src/string/bcmp.cpp) add_bcmp(bcmp_opt_host COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE}) add_bcmp(bcmp) endif() diff --git a/libc/src/string/bcmp.cpp b/libc/src/string/bcmp.cpp --- a/libc/src/string/bcmp.cpp +++ b/libc/src/string/bcmp.cpp @@ -8,20 +8,14 @@ #include "src/string/bcmp.h" #include "src/__support/common.h" +#include "src/string/memory_utils/bcmp_implementations.h" namespace __llvm_libc { LLVM_LIBC_FUNCTION(int, bcmp, (const void *lhs, const void *rhs, size_t count)) { - const unsigned char *_lhs = reinterpret_cast(lhs); - const unsigned char *_rhs = reinterpret_cast(rhs); - for (size_t i = 0; i < count; ++i) { - if (_lhs[i] != _rhs[i]) { - return 1; - } - } - // count is 0 or _lhs and _rhs are the same. - return 0; + return inline_bcmp(static_cast(lhs), + static_cast(rhs), count); } } // namespace __llvm_libc diff --git a/libc/src/string/memory_utils/CMakeLists.txt b/libc/src/string/memory_utils/CMakeLists.txt --- a/libc/src/string/memory_utils/CMakeLists.txt +++ b/libc/src/string/memory_utils/CMakeLists.txt @@ -3,6 +3,10 @@ HDRS utils.h elements.h + bcmp_implementations.h + memcmp_implementations.h + memcpy_implementations.h + memset_implementations.h ) add_header_library( diff --git a/libc/src/string/memory_utils/bcmp_implementations.h b/libc/src/string/memory_utils/bcmp_implementations.h new file mode 100644 --- /dev/null +++ b/libc/src/string/memory_utils/bcmp_implementations.h @@ -0,0 +1,61 @@ +//===-- Implementation of bcmp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BCMP_IMPLEMENTATIONS_H +#define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BCMP_IMPLEMENTATIONS_H + +#include "src/__support/architectures.h" +#include "src/__support/common.h" +#include "src/string/memory_utils/elements.h" + +#include // size_t + +namespace __llvm_libc { + +// Fixed-size difference between 'lhs' and 'rhs'. +template bool Differs(const char *lhs, const char *rhs) { + return !Element::Equals(lhs, rhs); +} +// Runtime-size difference between 'lhs' and 'rhs'. +template +bool Differs(const char *lhs, const char *rhs, size_t size) { + return !Element::Equals(lhs, rhs, size); +} + +static inline int inline_bcmp(const char *lhs, const char *rhs, size_t count) { +#if defined(LLVM_LIBC_ARCH_X86) + using namespace ::__llvm_libc::x86; +#elif defined(LLVM_LIBC_ARCH_AARCH64) + using namespace ::__llvm_libc::aarch64; +#else + using namespace ::__llvm_libc::scalar; +#endif + if (count == 0) + return 0; + if (count == 1) + return Differs<_1>(lhs, rhs); + if (count == 2) + return Differs<_2>(lhs, rhs); + if (count == 3) + return Differs<_3>(lhs, rhs); + if (count <= 8) + return Differs>(lhs, rhs, count); + if (count <= 16) + return Differs>(lhs, rhs, count); + if (count <= 32) + return Differs>(lhs, rhs, count); + if (count <= 64) + return Differs>(lhs, rhs, count); + if (count <= 128) + return Differs>(lhs, rhs, count); + return Differs::Then>>(lhs, rhs, count); +} + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BCMP_IMPLEMENTATIONS_H diff --git a/libc/test/src/string/bcmp_test.cpp b/libc/test/src/string/bcmp_test.cpp --- a/libc/test/src/string/bcmp_test.cpp +++ b/libc/test/src/string/bcmp_test.cpp @@ -24,13 +24,13 @@ TEST(LlvmLibcBcmpTest, LhsBeforeRhsLexically) { const char *lhs = "ab"; const char *rhs = "ac"; - EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, 2), 1); + EXPECT_NE(__llvm_libc::bcmp(lhs, rhs, 2), 0); } TEST(LlvmLibcBcmpTest, LhsAfterRhsLexically) { const char *lhs = "ac"; const char *rhs = "ab"; - EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, 2), 1); + EXPECT_NE(__llvm_libc::bcmp(lhs, rhs, 2), 0); } TEST(LlvmLibcBcmpTest, Sweep) { @@ -52,7 +52,7 @@ reset(rhs); for (size_t i = 0; i < kMaxSize; ++i) { rhs[i] = 'b'; - EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, kMaxSize), 1); + EXPECT_NE(__llvm_libc::bcmp(lhs, rhs, kMaxSize), 0); rhs[i] = 'a'; } }