[libc] Add a trivial implementation for bcmp

Differential Revision: https://reviews.llvm.org/D108225
This commit is contained in:
Guillaume Chatelet 2021-08-19 17:55:16 +00:00
parent 6c75ce1b8b
commit c8f79892af
11 changed files with 168 additions and 6 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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>]
>,
]

View File

@ -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()

27
libc/src/string/bcmp.cpp Normal file
View File

@ -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

20
libc/src/string/bcmp.h Normal file
View File

@ -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

View File

@ -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)

View File

@ -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';
}
}