[libc-commits] [libc] af059df - [libc] Add a reasonably optimized version for bcmp
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Tue Nov 30 02:52:43 PST 2021
Author: Guillaume Chatelet
Date: 2021-11-30T10:52:34Z
New Revision: af059dfef5a766ceb0ac29318dfb7102131d933e
URL: https://github.com/llvm/llvm-project/commit/af059dfef5a766ceb0ac29318dfb7102131d933e
DIFF: https://github.com/llvm/llvm-project/commit/af059dfef5a766ceb0ac29318dfb7102131d933e.diff
LOG: [libc] Add a reasonably optimized version for bcmp
This is based on current memcmp implementation.
Differential Revision: https://reviews.llvm.org/D114432
Added:
libc/src/string/memory_utils/bcmp_implementations.h
Modified:
libc/src/string/CMakeLists.txt
libc/src/string/bcmp.cpp
libc/src/string/memory_utils/CMakeLists.txt
libc/test/src/string/bcmp_test.cpp
Removed:
################################################################################
diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt
index 2d52b3689161c..9bd1f538cfe92 100644
--- a/libc/src/string/CMakeLists.txt
+++ b/libc/src/string/CMakeLists.txt
@@ -271,7 +271,7 @@ endfunction()
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 @@ function(add_bcmp bcmp_name)
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 @@ if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
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
index 196f3272eab1a..963a7f5bce17c 100644
--- 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<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;
+ return inline_bcmp(static_cast<const char *>(lhs),
+ static_cast<const char *>(rhs), count);
}
} // namespace __llvm_libc
diff --git a/libc/src/string/memory_utils/CMakeLists.txt b/libc/src/string/memory_utils/CMakeLists.txt
index f2bc09ec0cf59..51bbff3d27bfa 100644
--- a/libc/src/string/memory_utils/CMakeLists.txt
+++ b/libc/src/string/memory_utils/CMakeLists.txt
@@ -3,6 +3,10 @@ add_header_library(
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
index 0000000000000..ec94af28c6a68
--- /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 <stddef.h> // size_t
+
+namespace __llvm_libc {
+
+// Fixed-size
diff erence between 'lhs' and 'rhs'.
+template <typename Element> bool Differs(const char *lhs, const char *rhs) {
+ return !Element::Equals(lhs, rhs);
+}
+// Runtime-size
diff erence between 'lhs' and 'rhs'.
+template <typename Element>
+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<HeadTail<_4>>(lhs, rhs, count);
+ if (count <= 16)
+ return Differs<HeadTail<_8>>(lhs, rhs, count);
+ if (count <= 32)
+ return Differs<HeadTail<_16>>(lhs, rhs, count);
+ if (count <= 64)
+ return Differs<HeadTail<_32>>(lhs, rhs, count);
+ if (count <= 128)
+ return Differs<HeadTail<_64>>(lhs, rhs, count);
+ return Differs<Align<_32>::Then<Loop<_32>>>(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
index 7c2353fcd7fc0..dfcad7aff259a 100644
--- a/libc/test/src/string/bcmp_test.cpp
+++ b/libc/test/src/string/bcmp_test.cpp
@@ -24,13 +24,13 @@ TEST(LlvmLibcBcmpTest, LhsRhsAreTheSame) {
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 @@ TEST(LlvmLibcBcmpTest, Sweep) {
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';
}
}
More information about the libc-commits
mailing list