Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Improve generic strpbrk performance
With now a faster strcspn implementation, it is faster to just use
it with some return tests than reimplementing strpbrk itself.
As for strcspn optimization, it is generally at least 10 times faster
than the existing implementation on bench-strspn on a few AArch64
implementations.

Also the string/bits/string2.h inlines make no longer sense, as current
implementation will already implement most of the optimizations.

Tested on x86_64, i386, and aarch64.

	* string/strpbrk.c (strpbrk): Rewrite function.
	* string/bits/string2.h (strpbrk): Use __builtin_strpbrk.
	(__strpbrk_c2): Likewise.
	(__strpbrk_c3): Likewise.
	* string/string-inlines.c
	[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strpbrk_c2):
	Likewise.
	[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strpbrk_c3):
	Likewise.
  • Loading branch information
Adhemerval Zanella committed Apr 1, 2016
1 parent 91f3b75 commit 282b71f
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 68 deletions.
10 changes: 10 additions & 0 deletions ChangeLog
@@ -1,5 +1,15 @@
2016-04-01 Adhemerval Zanella <adhemerval.zanella@linaro.org> 2016-04-01 Adhemerval Zanella <adhemerval.zanella@linaro.org>


* string/strpbrk.c (strpbrk): Rewrite function.
* string/bits/string2.h (strpbrk): Use __builtin_strpbrk.
(__strpbrk_c2): Likewise.
(__strpbrk_c3): Likewise.
* string/string-inlines.c
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strpbrk_c2):
Likewise.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strpbrk_c3):
Likewise.

* string/strspn.c (strcspn): Rewrite function. * string/strspn.c (strcspn): Rewrite function.
* string/bits/string2.h (strspn): Use __builtin_strcspn. * string/bits/string2.h (strspn): Use __builtin_strcspn.
(__strspn_c1): Remove inline function. (__strspn_c1): Remove inline function.
Expand Down
61 changes: 3 additions & 58 deletions string/bits/string2.h
Expand Up @@ -922,65 +922,10 @@ __stpcpy_small (char *__dest,




/* Find the first occurrence in S of any character in ACCEPT. */ /* Find the first occurrence in S of any character in ACCEPT. */
#if !defined _HAVE_STRING_ARCH_strpbrk || defined _FORCE_INLINES #ifndef _HAVE_STRING_ARCH_strpbrk
# ifndef _HAVE_STRING_ARCH_strpbrk # if __GNUC_PREREQ (3, 2)
# if __GNUC_PREREQ (3, 2) # define strpbrk(s, accept) __builtin_strpbrk (s, accept)
# define strpbrk(s, accept) \
__extension__ \
({ char __a0, __a1, __a2; \
(__builtin_constant_p (accept) && __string2_1bptr_p (accept) \
? ((__builtin_constant_p (s) && __string2_1bptr_p (s)) \
? __builtin_strpbrk (s, accept) \
: ((__a0 = ((const char *) (accept))[0], __a0 == '\0') \
? ((void) (s), (char *) NULL) \
: ((__a1 = ((const char *) (accept))[1], __a1 == '\0') \
? __builtin_strchr (s, __a0) \
: ((__a2 = ((const char *) (accept))[2], __a2 == '\0') \
? __strpbrk_c2 (s, __a0, __a1) \
: (((const char *) (accept))[3] == '\0' \
? __strpbrk_c3 (s, __a0, __a1, __a2) \
: __builtin_strpbrk (s, accept)))))) \
: __builtin_strpbrk (s, accept)); })
# else
# define strpbrk(s, accept) \
__extension__ \
({ char __a0, __a1, __a2; \
(__builtin_constant_p (accept) && __string2_1bptr_p (accept) \
? ((__a0 = ((const char *) (accept))[0], __a0 == '\0') \
? ((void) (s), (char *) NULL) \
: ((__a1 = ((const char *) (accept))[1], __a1 == '\0') \
? strchr (s, __a0) \
: ((__a2 = ((const char *) (accept))[2], __a2 == '\0') \
? __strpbrk_c2 (s, __a0, __a1) \
: (((const char *) (accept))[3] == '\0' \
? __strpbrk_c3 (s, __a0, __a1, __a2) \
: strpbrk (s, accept))))) \
: strpbrk (s, accept)); })
# endif
# endif # endif

__STRING_INLINE char *__strpbrk_c2 (const char *__s, int __accept1,
int __accept2);
__STRING_INLINE char *
__strpbrk_c2 (const char *__s, int __accept1, int __accept2)
{
/* Please note that __accept1 and __accept2 never can be '\0'. */
while (*__s != '\0' && *__s != __accept1 && *__s != __accept2)
++__s;
return *__s == '\0' ? NULL : (char *) (size_t) __s;
}

__STRING_INLINE char *__strpbrk_c3 (const char *__s, int __accept1,
int __accept2, int __accept3);
__STRING_INLINE char *
__strpbrk_c3 (const char *__s, int __accept1, int __accept2, int __accept3)
{
/* Please note that __accept1 to __accept3 never can be '\0'. */
while (*__s != '\0' && *__s != __accept1 && *__s != __accept2
&& *__s != __accept3)
++__s;
return *__s == '\0' ? NULL : (char *) (size_t) __s;
}
#endif #endif




Expand Down
21 changes: 21 additions & 0 deletions string/string-inlines.c
Expand Up @@ -107,4 +107,25 @@ __old_strspn_c3 (const char *__s, int __accept1, int __accept2,
} }
compat_symbol (libc, __old_strspn_c3, __strspn_c3, GLIBC_2_1_1); compat_symbol (libc, __old_strspn_c3, __strspn_c3, GLIBC_2_1_1);


char *
__strpbrk_c2 (const char *__s, int __accept1, int __accept2)
{
/* Please note that __accept1 and __accept2 never can be '\0'. */
while (*__s != '\0' && *__s != __accept1 && *__s != __accept2)
++__s;
return *__s == '\0' ? NULL : (char *) (size_t) __s;
}
compat_symbol (libc, __old_strpbrk_c2, __strpbrk_c2, GLIBC_2_1_1);

char *
__strpbrk_c3 (const char *__s, int __accept1, int __accept2, int __accept3)
{
/* Please note that __accept1 to __accept3 never can be '\0'. */
while (*__s != '\0' && *__s != __accept1 && *__s != __accept2
&& *__s != __accept3)
++__s;
return *__s == '\0' ? NULL : (char *) (size_t) __s;
}
compat_symbol (libc, __old_strpbrk_c3, __strpbrk_c3, GLIBC_2_1_1);

#endif #endif
12 changes: 2 additions & 10 deletions string/strpbrk.c
Expand Up @@ -27,15 +27,7 @@
char * char *
STRPBRK (const char *s, const char *accept) STRPBRK (const char *s, const char *accept)
{ {
while (*s != '\0') s += strcspn (s, accept);
{ return *s ? (char *)s : NULL;
const char *a = accept;
while (*a != '\0')
if (*a++ == *s)
return (char *) s;
++s;
}

return NULL;
} }
libc_hidden_builtin_def (strpbrk) libc_hidden_builtin_def (strpbrk)

0 comments on commit 282b71f

Please sign in to comment.