forked from OSchip/llvm-project
[libc] Add a trivial implementation for bcmp
Differential Revision: https://reviews.llvm.org/D108225
This commit is contained in:
parent
6c75ce1b8b
commit
c8f79892af
|
@ -171,6 +171,7 @@ add_libc_multi_impl_benchmark(memcpy)
|
||||||
add_libc_multi_impl_benchmark(memset)
|
add_libc_multi_impl_benchmark(memset)
|
||||||
add_libc_multi_impl_benchmark(bzero)
|
add_libc_multi_impl_benchmark(bzero)
|
||||||
add_libc_multi_impl_benchmark(memcmp)
|
add_libc_multi_impl_benchmark(memcmp)
|
||||||
|
add_libc_multi_impl_benchmark(bcmp)
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
# Google Benchmarking tool
|
# Google Benchmarking tool
|
||||||
|
@ -188,6 +189,7 @@ target_link_libraries(libc.benchmarks.memory_functions.opt_host
|
||||||
PRIVATE
|
PRIVATE
|
||||||
libc-memory-benchmark
|
libc-memory-benchmark
|
||||||
libc.src.string.memcmp_opt_host
|
libc.src.string.memcmp_opt_host
|
||||||
|
libc.src.string.bcmp_opt_host
|
||||||
libc.src.string.memcpy_opt_host
|
libc.src.string.memcpy_opt_host
|
||||||
libc.src.string.memset_opt_host
|
libc.src.string.memset_opt_host
|
||||||
libc.src.string.bzero_opt_host
|
libc.src.string.bzero_opt_host
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern void *memcpy(void *__restrict, const void *__restrict, size_t);
|
||||||
extern void *memset(void *, int, size_t);
|
extern void *memset(void *, int, size_t);
|
||||||
extern void bzero(void *, size_t);
|
extern void bzero(void *, size_t);
|
||||||
extern int memcmp(const void *, const void *, size_t);
|
extern int memcmp(const void *, const void *, size_t);
|
||||||
|
extern int bcmp(const void *, const void *, size_t);
|
||||||
|
|
||||||
} // namespace __llvm_libc
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
@ -76,6 +77,9 @@ using BenchmarkSetup = SetSetup;
|
||||||
#elif defined(LIBC_BENCHMARK_FUNCTION_MEMCMP)
|
#elif defined(LIBC_BENCHMARK_FUNCTION_MEMCMP)
|
||||||
#define LIBC_BENCHMARK_FUNCTION LIBC_BENCHMARK_FUNCTION_MEMCMP
|
#define LIBC_BENCHMARK_FUNCTION LIBC_BENCHMARK_FUNCTION_MEMCMP
|
||||||
using BenchmarkSetup = ComparisonSetup;
|
using BenchmarkSetup = ComparisonSetup;
|
||||||
|
#elif defined(LIBC_BENCHMARK_FUNCTION_BCMP)
|
||||||
|
#define LIBC_BENCHMARK_FUNCTION LIBC_BENCHMARK_FUNCTION_BCMP
|
||||||
|
using BenchmarkSetup = ComparisonSetup;
|
||||||
#else
|
#else
|
||||||
#error "Missing LIBC_BENCHMARK_FUNCTION_XXX definition"
|
#error "Missing LIBC_BENCHMARK_FUNCTION_XXX definition"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,6 +28,7 @@ extern void *memcpy(void *__restrict, const void *__restrict, size_t);
|
||||||
extern void *memset(void *, int, size_t);
|
extern void *memset(void *, int, size_t);
|
||||||
extern void bzero(void *, size_t);
|
extern void bzero(void *, size_t);
|
||||||
extern int memcmp(const void *, const void *, size_t);
|
extern int memcmp(const void *, const void *, size_t);
|
||||||
|
extern int bcmp(const void *, const void *, size_t);
|
||||||
|
|
||||||
} // namespace __llvm_libc
|
} // namespace __llvm_libc
|
||||||
|
|
||||||
|
@ -38,6 +39,9 @@ static constexpr MemcpyConfiguration kMemcpyConfigurations[] = {
|
||||||
static constexpr MemcmpConfiguration kMemcmpConfigurations[] = {
|
static constexpr MemcmpConfiguration kMemcmpConfigurations[] = {
|
||||||
{__llvm_libc::memcmp, "__llvm_libc::memcmp"}};
|
{__llvm_libc::memcmp, "__llvm_libc::memcmp"}};
|
||||||
|
|
||||||
|
static constexpr MemcmpConfiguration kBcmpConfigurations[] = {
|
||||||
|
{__llvm_libc::bcmp, "__llvm_libc::bcmp"}};
|
||||||
|
|
||||||
static constexpr MemsetConfiguration kMemsetConfigurations[] = {
|
static constexpr MemsetConfiguration kMemsetConfigurations[] = {
|
||||||
{__llvm_libc::memset, "__llvm_libc::memset"}};
|
{__llvm_libc::memset, "__llvm_libc::memset"}};
|
||||||
|
|
||||||
|
@ -116,6 +120,8 @@ BENCHMARK_MEMORY_FUNCTION(BM_Memcpy, CopySetup, MemcpyConfiguration,
|
||||||
llvm::makeArrayRef(kMemcpyConfigurations));
|
llvm::makeArrayRef(kMemcpyConfigurations));
|
||||||
BENCHMARK_MEMORY_FUNCTION(BM_Memcmp, ComparisonSetup, MemcmpConfiguration,
|
BENCHMARK_MEMORY_FUNCTION(BM_Memcmp, ComparisonSetup, MemcmpConfiguration,
|
||||||
llvm::makeArrayRef(kMemcmpConfigurations));
|
llvm::makeArrayRef(kMemcmpConfigurations));
|
||||||
|
BENCHMARK_MEMORY_FUNCTION(BM_Bcmp, ComparisonSetup, MemcmpConfiguration,
|
||||||
|
llvm::makeArrayRef(kBcmpConfigurations));
|
||||||
BENCHMARK_MEMORY_FUNCTION(BM_Memset, SetSetup, MemsetConfiguration,
|
BENCHMARK_MEMORY_FUNCTION(BM_Memset, SetSetup, MemsetConfiguration,
|
||||||
llvm::makeArrayRef(kMemsetConfigurations));
|
llvm::makeArrayRef(kMemsetConfigurations));
|
||||||
BENCHMARK_MEMORY_FUNCTION(BM_Bzero, SetSetup, BzeroConfiguration,
|
BENCHMARK_MEMORY_FUNCTION(BM_Bzero, SetSetup, BzeroConfiguration,
|
||||||
|
|
|
@ -21,6 +21,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||||
libc.src.errno.__errno_location
|
libc.src.errno.__errno_location
|
||||||
|
|
||||||
# string.h entrypoints
|
# string.h entrypoints
|
||||||
|
libc.src.string.bcmp
|
||||||
libc.src.string.bzero
|
libc.src.string.bzero
|
||||||
libc.src.string.memchr
|
libc.src.string.memchr
|
||||||
libc.src.string.memcmp
|
libc.src.string.memcmp
|
||||||
|
|
|
@ -21,6 +21,7 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||||
libc.src.errno.__errno_location
|
libc.src.errno.__errno_location
|
||||||
|
|
||||||
# string.h entrypoints
|
# string.h entrypoints
|
||||||
|
libc.src.string.bcmp
|
||||||
libc.src.string.bzero
|
libc.src.string.bzero
|
||||||
libc.src.string.memchr
|
libc.src.string.memchr
|
||||||
libc.src.string.memcmp
|
libc.src.string.memcmp
|
||||||
|
|
|
@ -8,8 +8,21 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> {
|
||||||
FunctionSpec<
|
FunctionSpec<
|
||||||
"bzero",
|
"bzero",
|
||||||
RetValSpec<VoidType>,
|
RetValSpec<VoidType>,
|
||||||
[ArgSpec<VoidPtr>,
|
[ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
|
||||||
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<
|
FunctionSpec<
|
||||||
"__assert_fail",
|
"__assert_fail",
|
||||||
RetValSpec<NoReturn>,
|
RetValSpec<NoReturn>,
|
||||||
[ArgSpec<ConstCharPtr>,
|
[ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>, ArgSpec<UnsignedType>, ArgSpec<ConstCharPtr>]
|
||||||
ArgSpec<ConstCharPtr>,
|
|
||||||
ArgSpec<UnsignedType>,
|
|
||||||
ArgSpec<ConstCharPtr>,]
|
|
||||||
|
|
||||||
>,
|
>,
|
||||||
]
|
]
|
||||||
|
|
|
@ -331,3 +331,35 @@ else()
|
||||||
add_memcmp(memcmp_opt_host COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
|
add_memcmp(memcmp_opt_host COMPILE_OPTIONS ${LIBC_COMPILE_OPTIONS_NATIVE})
|
||||||
add_memcmp(memcmp)
|
add_memcmp(memcmp)
|
||||||
endif()
|
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()
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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(memset SRCS memset_test.cpp)
|
||||||
add_libc_multi_impl_test(bzero SRCS bzero_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(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)
|
add_libc_multi_impl_test(memmove SRCS memmove_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';
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue