diff options
author | Ondřej Bílka <neleai@seznam.cz> | 2015-06-29 17:47:01 +0200 |
---|---|---|
committer | Ondřej Bílka <neleai@seznam.cz> | 2015-08-20 09:53:36 +0200 |
commit | 0e974603c566e8e25ffcf8a86d214c400f111090 (patch) | |
tree | fc40bcc79e8bf8df9818fc6546e620db534fd679 | |
parent | 165308eb2c66542c88d002d63dc68df112f5c818 (diff) | |
download | glibc-0e974603c566e8e25ffcf8a86d214c400f111090.tar.gz glibc-0e974603c566e8e25ffcf8a86d214c400f111090.tar.xz glibc-0e974603c566e8e25ffcf8a86d214c400f111090.zip |
Improve generic strpbrk. neleai/string-x64
-rw-r--r-- | string/strcspn.c | 43 | ||||
-rw-r--r-- | string/strpbrk.c | 120 | ||||
-rw-r--r-- | string/test-strcspn.c | 15 | ||||
-rw-r--r-- | string/test-strpbrk.c | 14 | ||||
-rw-r--r-- | sysdeps/x86_64/multiarch/Makefile | 3 | ||||
-rw-r--r-- | sysdeps/x86_64/multiarch/strcspn.S | 21 | ||||
-rw-r--r-- | sysdeps/x86_64/multiarch/strpbrk_sse2.c | 4 | ||||
-rw-r--r-- | sysdeps/x86_64/multiarch/strpbrk_sse2_late.c | 4 |
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" |