summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Bílka <neleai@seznam.cz>2015-06-29 17:47:01 +0200
committerOndřej Bílka <neleai@seznam.cz>2015-08-20 09:53:36 +0200
commit0e974603c566e8e25ffcf8a86d214c400f111090 (patch)
treefc40bcc79e8bf8df9818fc6546e620db534fd679
parent165308eb2c66542c88d002d63dc68df112f5c818 (diff)
downloadglibc-neleai/string-x64.tar.gz
Improve generic strpbrk.neleai/string-x64
-rw-r--r--string/strcspn.c43
-rw-r--r--string/strpbrk.c120
-rw-r--r--string/test-strcspn.c15
-rw-r--r--string/test-strpbrk.c14
-rw-r--r--sysdeps/x86_64/multiarch/Makefile3
-rw-r--r--sysdeps/x86_64/multiarch/strcspn.S21
-rw-r--r--sysdeps/x86_64/multiarch/strpbrk_sse2.c4
-rw-r--r--sysdeps/x86_64/multiarch/strpbrk_sse2_late.c4
8 files changed, 130 insertions, 94 deletions
diff --git a/string/strcspn.c b/string/strcspn.c
index 2694d2ab0e..2a82dd256e 100644
--- a/string/strcspn.c
+++ b/string/strcspn.c
@@ -1,41 +1,2 @@
-/* Copyright (C) 1991-2015 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <string.h>
-
-#undef strcspn
-
-#ifndef STRCSPN
-# define STRCSPN strcspn
-#endif
-
-/* Return the length of the maximum initial segment of S
- which contains no characters from REJECT. */
-size_t
-STRCSPN (const char *s, const char *reject)
-{
- size_t count = 0;
-
- while (*s != '\0')
- if (strchr (reject, *s++) == NULL)
- ++count;
- else
- return count;
-
- return count;
-}
-libc_hidden_builtin_def (strcspn)
+#define AS_STRCSPN
+#include "strpbrk.c"
diff --git a/string/strpbrk.c b/string/strpbrk.c
index 4f1d9b72bb..01cd55afdf 100644
--- a/string/strpbrk.c
+++ b/string/strpbrk.c
@@ -16,26 +16,124 @@
<http://www.gnu.org/licenses/>. */
#include <string.h>
-
+#include <stdint.h>
#undef strpbrk
+#undef strcspn
+
+
+#ifdef AS_STRCSPN
+# ifndef STRPBRK
+# define STRPBRK strcspn
+# endif
+# define RETURN_TYPE size_t
+# define RETURN(c) return c
+#else
+# define RETURN_TYPE char *
+# define RETURN(c) return (char *) (s[c] != '\0' ? s + c : NULL)
+#endif
#ifndef STRPBRK
#define STRPBRK strpbrk
#endif
+
/* Find the first occurrence in S of any character in ACCEPT. */
-char *
-STRPBRK (const char *s, const char *accept)
+RETURN_TYPE
+STRPBRK (const char *_s, const char *_accept)
{
- while (*s != '\0')
+ unsigned char *s = (unsigned char *) _s;
+ unsigned char *a = (unsigned char *) _accept;
+
+#ifndef LATE_CHECK
+ /* We need to align s to 4 bytes. We do check now to avoid expensive table
+ construction. */
+ do
+ {
+ if (s[0] == *a)
+ RETURN(0);
+ }
+ while (*a++);
+ a = (unsigned char *) _accept;
+
+ /* We couldn't do these checks in one loop as gcc
+ messes up register allocation. */
+ do
+ {
+ if (s[1] == *a)
+ RETURN(1);
+ }
+ while (*a++);
+ a = (unsigned char *) _accept;
+
+ do
+ {
+ if (s[2] == *a)
+ RETURN(2);
+ }
+ while (*a++);
+ a = (unsigned char *) _accept;
+
+ do
+ {
+ if (s[3] == *a)
+ RETURN(3);
+ }
+ while (*a++);
+ a = (unsigned char *) _accept;
+
+#endif
+
+ unsigned char table[256];
+ memset (table, 0, 256);
+ do
{
- const char *a = accept;
- while (*a != '\0')
- if (*a++ == *s)
- return (char *) s;
- ++s;
+ table[*a] = 1;
}
+ while (*a++);
+ unsigned char s0, s1, s2, s3;
+ size_t count = 0;
+#ifdef LATE_CHECK
+ s0 = s[count + 0];
+ s1 = s[count + 1];
+ s2 = s[count + 2];
+ s3 = s[count + 3];
+ if (table[s0])
+ goto ret0;
+ if (table[s1])
+ goto ret1;
+ if (table[s2])
+ goto ret2;
+ if (table[s3])
+ goto ret3;
- return NULL;
+#endif
+
+ count = 4 - ((uintptr_t) s) % 4;
+
+ while (1)
+ {
+ s0 = s[count + 0];
+ s1 = s[count + 1];
+ s2 = s[count + 2];
+ s3 = s[count + 3];
+ if (table[s0])
+ goto ret0;
+ if (table[s1])
+ goto ret1;
+ if (table[s2])
+ goto ret2;
+ if (table[s3])
+ goto ret3;
+ count += 4;
+ }
+ ret3:
+ count++;
+ ret2:
+ count++;
+ ret1:
+ count++;
+ ret0:
+ RETURN(count);
}
-libc_hidden_builtin_def (strpbrk)
+
+libc_hidden_builtin_def (STRPBRK)
diff --git a/string/test-strcspn.c b/string/test-strcspn.c
index b60a048c5c..50a06e44c4 100644
--- a/string/test-strcspn.c
+++ b/string/test-strcspn.c
@@ -31,18 +31,9 @@ IMPL (stupid_strcspn, 0)
IMPL (simple_strcspn, 0)
IMPL (strcspn, 1)
-size_t
-simple_strcspn (const char *s, const char *rej)
-{
- const char *r, *str = s;
- char c;
-
- while ((c = *s++) != '\0')
- for (r = rej; *r != '\0'; ++r)
- if (*r == c)
- return s - str - 1;
- return s - str - 1;
-}
+#define AS_STRCSPN
+#define STRPBRK simple_strcspn
+#include "string/strpbrk.c"
size_t
stupid_strcspn (const char *s, const char *rej)
diff --git a/string/test-strpbrk.c b/string/test-strpbrk.c
index b4ac389a71..f389e9dabf 100644
--- a/string/test-strpbrk.c
+++ b/string/test-strpbrk.c
@@ -32,18 +32,8 @@ IMPL (stupid_strpbrk, 0)
IMPL (simple_strpbrk, 0)
IMPL (strpbrk, 1)
-char *
-simple_strpbrk (const char *s, const char *rej)
-{
- const char *r;
- char c;
-
- while ((c = *s++) != '\0')
- for (r = rej; *r != '\0'; ++r)
- if (*r == c)
- return (char *) s - 1;
- return NULL;
-}
+#define STRPBRK simple_strpbrk
+#include "string/strpbrk.c"
char *
stupid_strpbrk (const char *s, const char *rej)
diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile
index 05d5c9ba30..6996d128b2 100644
--- a/sysdeps/x86_64/multiarch/Makefile
+++ b/sysdeps/x86_64/multiarch/Makefile
@@ -19,7 +19,8 @@ sysdep_routines += strncat-c stpncpy-c strncpy-c strcmp-ssse3 \
strcpy-sse2-unaligned strncpy-sse2-unaligned \
stpcpy-sse2-unaligned stpncpy-sse2-unaligned \
strcat-sse2-unaligned strncat-sse2-unaligned \
- strchr-sse2-no-bsf memcmp-ssse3 strstr-sse2-unaligned
+ strchr-sse2-no-bsf memcmp-ssse3 strstr-sse2-unaligned \
+ strcspn_sse2 strpbrk_sse2 strcspn_sse2_late strpbrk_sse2_late
ifeq (yes,$(config-cflags-sse4))
sysdep_routines += strcspn_sse42 strpbrk_sse42 strspn_sse42
diff --git a/sysdeps/x86_64/multiarch/strcspn.S b/sysdeps/x86_64/multiarch/strcspn.S
index 95e882c443..4fe4974812 100644
--- a/sysdeps/x86_64/multiarch/strcspn.S
+++ b/sysdeps/x86_64/multiarch/strcspn.S
@@ -54,22 +54,9 @@ ENTRY(STRCSPN)
leaq STRCSPN_SSE42(%rip), %rax
2: ret
END(STRCSPN)
-
-# undef ENTRY
-# define ENTRY(name) \
- .type STRCSPN_SSE2, @function; \
- .globl STRCSPN_SSE2; \
- .align 16; \
- STRCSPN_SSE2: cfi_startproc; \
- CALL_MCOUNT
-# undef END
-# define END(name) \
- cfi_endproc; .size STRCSPN_SSE2, .-STRCSPN_SSE2
#endif
-#endif /* HAVE_SSE4_SUPPORT */
-#ifdef USE_AS_STRPBRK
-#include "../strpbrk.S"
-#else
-#include "../strcspn.S"
-#endif
+#else /* HAVE_SSE4_SUPPORT */
+weak_alias (STRCSPN_SSE2, STRCSPN)
+#endif /* HAVE_SSE4_SUPPORT */
+libc_hidden_builtin_def (STRCSPN)
diff --git a/sysdeps/x86_64/multiarch/strpbrk_sse2.c b/sysdeps/x86_64/multiarch/strpbrk_sse2.c
new file mode 100644
index 0000000000..317f4fa839
--- /dev/null
+++ b/sysdeps/x86_64/multiarch/strpbrk_sse2.c
@@ -0,0 +1,4 @@
+#define STRPBRK __strpbrk_sse2
+#undef libc_hidden_builtin_def
+#define libc_hidden_builtin_def(x)
+#include "string/strpbrk.c"
diff --git a/sysdeps/x86_64/multiarch/strpbrk_sse2_late.c b/sysdeps/x86_64/multiarch/strpbrk_sse2_late.c
new file mode 100644
index 0000000000..f2e1c4d5f7
--- /dev/null
+++ b/sysdeps/x86_64/multiarch/strpbrk_sse2_late.c
@@ -0,0 +1,4 @@
+#define STRPBRK __strpbrk_sse2_late
+#undef libc_hidden_builtin_def
+#define libc_hidden_builtin_def(x)
+#include "string/strpbrk.c"