[libc-commits] [PATCH] D77949: [libc] Add SIMD strlen implementation .
Thorsten via Phabricator via libc-commits
libc-commits at lists.llvm.org
Sat Apr 11 10:07:52 PDT 2020
tschuett created this revision.
tschuett added reviewers: sivachandra, abrachet, PaulkaToast.
tschuett added a project: libc-project.
It tries to improve the performance of strlen by processing multiple bytes at a time.
Bear with me. This is my first contribution and I have no commit access.
https://reviews.llvm.org/D77949
Files:
libc/src/string/strlen.cpp
libc/test/src/string/strlen_test.cpp
Index: libc/test/src/string/strlen_test.cpp
===================================================================
--- libc/test/src/string/strlen_test.cpp
+++ libc/test/src/string/strlen_test.cpp
@@ -22,3 +22,24 @@
size_t result = __llvm_libc::strlen(any);
ASSERT_EQ((size_t)12, result);
}
+
+TEST(StrLenTest, EightBytes) {
+ const char *eight = "1234567";
+
+ size_t result = __llvm_libc::strlen(eight);
+ ASSERT_EQ((size_t)7, result);
+}
+
+TEST(StrLenTest, FourBytes) {
+ const char *four = "123";
+
+ size_t result = __llvm_libc::strlen(four);
+ ASSERT_EQ((size_t)3, result);
+}
+
+TEST(StrLenTest, TwoBytes) {
+ const char *two = "1";
+
+ size_t result = __llvm_libc::strlen(two);
+ ASSERT_EQ((size_t)1, result);
+}
Index: libc/src/string/strlen.cpp
===================================================================
--- libc/src/string/strlen.cpp
+++ libc/src/string/strlen.cpp
@@ -10,15 +10,57 @@
#include "src/__support/common.h"
+#include <stdint.h>
+
namespace __llvm_libc {
-// TODO: investigate the performance of this function.
-// There might be potential for compiler optimization.
+// For LLP64, i.e., Windows, pointers are 64 bit and long is only 32 bit
+// Thus, this implementation uses uintptr_t instead of long
+
size_t LLVM_LIBC_ENTRYPOINT(strlen)(const char *src) {
- const char *end = src;
- while (*end != '\0')
- ++end;
- return end - src;
+ const char *char_ptr;
+ const uintptr_t *ptr_ptr;
+ uintptr_t high_mask = 0x80808080L;
+ uintptr_t low_mask = 0x01010101L;
+
+ if (sizeof(uintptr_t) == 4) {
+ // do nothing
+ } else if (sizeof(uintptr_t) == 8) {
+ // setup 64 bit masks
+ high_mask = ((high_mask << 16) << 16) | high_mask;
+ low_mask = ((low_mask << 16) << 16) | low_mask;
+ } else {
+ // fallback to slow path
+ const char *end = src;
+ while (*end != '\0')
+ ++end;
+ return end - src;
+ }
+
+ // align char_ptr to multiple of sizeof(uintptr_t)
+ for (char_ptr = src; ((uintptr_t)char_ptr & (sizeof(uintptr_t) - 1)) != 0;
+ ++char_ptr) {
+ if (*char_ptr == '\0')
+ return char_ptr - src;
+ }
+
+ ptr_ptr = (const uintptr_t *)char_ptr;
+
+ // process sizeof(uintptr_t) bytes at a time
+ for (;;) {
+ uintptr_t value = *ptr_ptr;
+
+ if (((value - low_mask) & ~value & high_mask) != 0) {
+ // found a zero byte
+ const char *cp = (const char *)ptr_ptr;
+
+ for (unsigned i = 0; i < sizeof(uintptr_t); ++i)
+ if (cp[i] == 0)
+ return cp - src + i;
+ }
+
+ ptr_ptr++;
+ }
}
} // namespace __llvm_libc
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D77949.256780.patch
Type: text/x-patch
Size: 2567 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libc-commits/attachments/20200411/7bdc0e6a/attachment-0001.bin>
More information about the libc-commits
mailing list