add_libc_multi_impl_benchmark(memset)
add_libc_multi_impl_benchmark(bzero)
add_libc_multi_impl_benchmark(memcmp)
+add_libc_multi_impl_benchmark(bcmp)
#==============================================================================
# Google Benchmarking tool
PRIVATE
libc-memory-benchmark
libc.src.string.memcmp_opt_host
+ libc.src.string.bcmp_opt_host
libc.src.string.memcpy_opt_host
libc.src.string.memset_opt_host
libc.src.string.bzero_opt_host
extern void *memset(void *, int, size_t);
extern void bzero(void *, size_t);
extern int memcmp(const void *, const void *, size_t);
+extern int bcmp(const void *, const void *, size_t);
} // namespace __llvm_libc
#elif defined(LIBC_BENCHMARK_FUNCTION_MEMCMP)
#define LIBC_BENCHMARK_FUNCTION LIBC_BENCHMARK_FUNCTION_MEMCMP
using BenchmarkSetup = ComparisonSetup;
+#elif defined(LIBC_BENCHMARK_FUNCTION_BCMP)
+#define LIBC_BENCHMARK_FUNCTION LIBC_BENCHMARK_FUNCTION_BCMP
+using BenchmarkSetup = ComparisonSetup;
#else
#error "Missing LIBC_BENCHMARK_FUNCTION_XXX definition"
#endif
extern void *memset(void *, int, size_t);
extern void bzero(void *, size_t);
extern int memcmp(const void *, const void *, size_t);
+extern int bcmp(const void *, const void *, size_t);
} // namespace __llvm_libc
static constexpr MemcmpConfiguration kMemcmpConfigurations[] = {
{__llvm_libc::memcmp, "__llvm_libc::memcmp"}};
+static constexpr MemcmpConfiguration kBcmpConfigurations[] = {
+ {__llvm_libc::bcmp, "__llvm_libc::bcmp"}};
+
static constexpr MemsetConfiguration kMemsetConfigurations[] = {
{__llvm_libc::memset, "__llvm_libc::memset"}};
llvm::makeArrayRef(kMemcpyConfigurations));
BENCHMARK_MEMORY_FUNCTION(BM_Memcmp, ComparisonSetup, MemcmpConfiguration,
llvm::makeArrayRef(kMemcmpConfigurations));
+BENCHMARK_MEMORY_FUNCTION(BM_Bcmp, ComparisonSetup, MemcmpConfiguration,
+ llvm::makeArrayRef(kBcmpConfigurations));
BENCHMARK_MEMORY_FUNCTION(BM_Memset, SetSetup, MemsetConfiguration,
llvm::makeArrayRef(kMemsetConfigurations));
BENCHMARK_MEMORY_FUNCTION(BM_Bzero, SetSetup, BzeroConfiguration,
libc.src.errno.__errno_location
# string.h entrypoints
+ libc.src.string.bcmp
libc.src.string.bzero
libc.src.string.memchr
libc.src.string.memcmp
libc.src.errno.__errno_location
# string.h entrypoints
+ libc.src.string.bcmp
libc.src.string.bzero
libc.src.string.memchr
libc.src.string.memcmp
FunctionSpec<
"bzero",
RetValSpec<VoidType>,
- [ArgSpec<VoidPtr>,
- ArgSpec<SizeTType>]
+ [ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
+ >,
+ ]
+ >;
+
+ HeaderSpec String = HeaderSpec<
+ "string.h",
+ [], // Macros
+ [], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "bcmp",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstVoidPtr>, ArgSpec<ConstVoidPtr>, ArgSpec<SizeTType>]
>,
]
>;
FunctionSpec<
"__assert_fail",
RetValSpec<NoReturn>,
- [ArgSpec<ConstCharPtr>,
- ArgSpec<ConstCharPtr>,
- ArgSpec<UnsignedType>,
- ArgSpec<ConstCharPtr>,]
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<UnsignedType>, ArgSpec<ConstCharPtr>]
>,
]
add_memcmp(memcmp_opt_host COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
add_memcmp(memcmp)
endif()
+
+# ------------------------------------------------------------------------------
+# bcmp
+# ------------------------------------------------------------------------------
+
+function(add_bcmp bcmp_name)
+ add_implementation(bcmp ${bcmp_name}
+ SRCS ${LIBC_BCMP_SRC}
+ HDRS ${LIBC_SOURCE_DIR}/src/string/bcmp.h
+ DEPENDS
+ .memory_utils.memory_utils
+ libc.include.string
+ COMPILE_OPTIONS
+ -fno-builtin-memcmp
+ -fno-builtin-bcmp
+ ${ARGN}
+ )
+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)
+ add_bcmp(bcmp_x86_64_opt_avx512 COMPILE_OPTIONS -march=skylake-avx512 REQUIRE AVX512F)
+ 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()
--- /dev/null
+//===-- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/string/bcmp.h"
+#include "src/__support/common.h"
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, bcmp,
+ (const void *lhs, const void *rhs, size_t count)) {
+ const unsigned char *_lhs = reinterpret_cast<const unsigned char *>(lhs);
+ const unsigned char *_rhs = reinterpret_cast<const unsigned char *>(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;
+}
+
+} // namespace __llvm_libc
--- /dev/null
+//===-- Implementation header for bzero -------------------------*- C++ -*-===//
+//
+// 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_BCMP_H
+#define LLVM_LIBC_SRC_STRING_BCMP_H
+
+#include <stddef.h> // size_t
+
+namespace __llvm_libc {
+
+int bcmp(const void *lhs, const void *rhs, size_t count);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_STRING_BCMP_H
add_libc_multi_impl_test(memset SRCS memset_test.cpp)
add_libc_multi_impl_test(bzero SRCS bzero_test.cpp)
add_libc_multi_impl_test(memcmp SRCS memcmp_test.cpp)
+add_libc_multi_impl_test(bcmp SRCS bcmp_test.cpp)
add_libc_multi_impl_test(memmove SRCS memmove_test.cpp)
--- /dev/null
+//===-- Unittests for 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/string/bcmp.h"
+#include "utils/UnitTest/Test.h"
+
+TEST(LlvmLibcBcmpTest, CmpZeroByte) {
+ const char *lhs = "ab";
+ const char *rhs = "bc";
+ EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, 0), 0);
+}
+
+TEST(LlvmLibcBcmpTest, LhsRhsAreTheSame) {
+ const char *lhs = "ab";
+ const char *rhs = "ab";
+ EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, 2), 0);
+}
+
+TEST(LlvmLibcBcmpTest, LhsBeforeRhsLexically) {
+ const char *lhs = "ab";
+ const char *rhs = "ac";
+ EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, 2), 1);
+}
+
+TEST(LlvmLibcBcmpTest, LhsAfterRhsLexically) {
+ const char *lhs = "ac";
+ const char *rhs = "ab";
+ EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, 2), 1);
+}
+
+TEST(LlvmLibcBcmpTest, Sweep) {
+ static constexpr size_t kMaxSize = 1024;
+ char lhs[kMaxSize];
+ char rhs[kMaxSize];
+
+ const auto reset = [](char *const ptr) {
+ for (size_t i = 0; i < kMaxSize; ++i)
+ ptr[i] = 'a';
+ };
+
+ reset(lhs);
+ reset(rhs);
+ for (size_t i = 0; i < kMaxSize; ++i)
+ EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, i), 0);
+
+ reset(lhs);
+ reset(rhs);
+ for (size_t i = 0; i < kMaxSize; ++i) {
+ rhs[i] = 'b';
+ EXPECT_EQ(__llvm_libc::bcmp(lhs, rhs, kMaxSize), 1);
+ rhs[i] = 'a';
+ }
+}