[libc-commits] [libc] c8f7989 - [libc] Add a trivial implementation for bcmp
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Thu Aug 19 10:55:28 PDT 2021
Author: Guillaume Chatelet
Date: 2021-08-19T17:55:16Z
New Revision: c8f79892af4c2fd8660180d326e02d95731f8c25
URL: https://github.com/llvm/llvm-project/commit/c8f79892af4c2fd8660180d326e02d95731f8c25
DIFF: https://github.com/llvm/llvm-project/commit/c8f79892af4c2fd8660180d326e02d95731f8c25.diff
LOG: [libc] Add a trivial implementation for bcmp
Differential Revision: https://reviews.llvm.org/D108225
Added:
libc/src/string/bcmp.cpp
libc/src/string/bcmp.h
libc/test/src/string/bcmp_test.cpp
Modified:
libc/benchmarks/CMakeLists.txt
libc/benchmarks/LibcMemoryBenchmarkMain.cpp
libc/benchmarks/LibcMemoryGoogleBenchmarkMain.cpp
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/x86_64/entrypoints.txt
libc/spec/llvm_libc_ext.td
libc/src/string/CMakeLists.txt
libc/test/src/string/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/benchmarks/CMakeLists.txt b/libc/benchmarks/CMakeLists.txt
index ba46faeaca839..3eece745096f9 100644
--- a/libc/benchmarks/CMakeLists.txt
+++ b/libc/benchmarks/CMakeLists.txt
@@ -171,6 +171,7 @@ add_libc_multi_impl_benchmark(memcpy)
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
@@ -188,6 +189,7 @@ target_link_libraries(libc.benchmarks.memory_functions.opt_host
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
diff --git a/libc/benchmarks/LibcMemoryBenchmarkMain.cpp b/libc/benchmarks/LibcMemoryBenchmarkMain.cpp
index 30bbfd44cd9b6..8539402a8cdaa 100644
--- a/libc/benchmarks/LibcMemoryBenchmarkMain.cpp
+++ b/libc/benchmarks/LibcMemoryBenchmarkMain.cpp
@@ -27,6 +27,7 @@ extern void *memcpy(void *__restrict, const void *__restrict, size_t);
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
@@ -76,6 +77,9 @@ using BenchmarkSetup = SetSetup;
#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
diff --git a/libc/benchmarks/LibcMemoryGoogleBenchmarkMain.cpp b/libc/benchmarks/LibcMemoryGoogleBenchmarkMain.cpp
index 055f9902fcdc6..e48b3a79c06c4 100644
--- a/libc/benchmarks/LibcMemoryGoogleBenchmarkMain.cpp
+++ b/libc/benchmarks/LibcMemoryGoogleBenchmarkMain.cpp
@@ -28,6 +28,7 @@ extern void *memcpy(void *__restrict, const void *__restrict, size_t);
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
@@ -38,6 +39,9 @@ static constexpr MemcpyConfiguration kMemcpyConfigurations[] = {
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"}};
@@ -116,6 +120,8 @@ BENCHMARK_MEMORY_FUNCTION(BM_Memcpy, CopySetup, MemcpyConfiguration,
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,
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 21bbaa466e4bb..0bb899cbc7d0b 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -21,6 +21,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.errno.__errno_location
# string.h entrypoints
+ libc.src.string.bcmp
libc.src.string.bzero
libc.src.string.memchr
libc.src.string.memcmp
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 6e163c11c9090..e99fb4e47cac4 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -21,6 +21,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.errno.__errno_location
# string.h entrypoints
+ libc.src.string.bcmp
libc.src.string.bzero
libc.src.string.memchr
libc.src.string.memcmp
diff --git a/libc/spec/llvm_libc_ext.td b/libc/spec/llvm_libc_ext.td
index a70eb18dd61b7..cffeb2e4bf37c 100644
--- a/libc/spec/llvm_libc_ext.td
+++ b/libc/spec/llvm_libc_ext.td
@@ -8,8 +8,21 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
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>]
>,
]
>;
@@ -23,10 +36,7 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
FunctionSpec<
"__assert_fail",
RetValSpec<NoReturn>,
- [ArgSpec<ConstCharPtr>,
- ArgSpec<ConstCharPtr>,
- ArgSpec<UnsignedType>,
- ArgSpec<ConstCharPtr>,]
+ [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<UnsignedType>, ArgSpec<ConstCharPtr>]
>,
]
diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt
index a7dbac375d2ea..e41f0e1ec6062 100644
--- a/libc/src/string/CMakeLists.txt
+++ b/libc/src/string/CMakeLists.txt
@@ -331,3 +331,35 @@ else()
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()
diff --git a/libc/src/string/bcmp.cpp b/libc/src/string/bcmp.cpp
new file mode 100644
index 0000000000000..196f3272eab1a
--- /dev/null
+++ b/libc/src/string/bcmp.cpp
@@ -0,0 +1,27 @@
+//===-- 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
diff --git a/libc/src/string/bcmp.h b/libc/src/string/bcmp.h
new file mode 100644
index 0000000000000..6503240319ed2
--- /dev/null
+++ b/libc/src/string/bcmp.h
@@ -0,0 +1,20 @@
+//===-- 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
diff --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt
index ee9121094fea3..c8e8812c6817b 100644
--- a/libc/test/src/string/CMakeLists.txt
+++ b/libc/test/src/string/CMakeLists.txt
@@ -199,4 +199,5 @@ add_libc_multi_impl_test(memcpy SRCS memcpy_test.cpp)
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)
diff --git a/libc/test/src/string/bcmp_test.cpp b/libc/test/src/string/bcmp_test.cpp
new file mode 100644
index 0000000000000..7c2353fcd7fc0
--- /dev/null
+++ b/libc/test/src/string/bcmp_test.cpp
@@ -0,0 +1,58 @@
+//===-- 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';
+ }
+}
More information about the libc-commits
mailing list