2020-01-01 08:14:33 +08:00
|
|
|
/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
|
1999-05-18 01:25:32 +08:00
|
|
|
This file is part of the GNU C Library.
|
|
|
|
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
2001-07-06 12:58:11 +08:00
|
|
|
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.
|
1999-05-18 01:25:32 +08:00
|
|
|
|
|
|
|
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
|
2001-07-06 12:58:11 +08:00
|
|
|
Lesser General Public License for more details.
|
1999-05-18 01:25:32 +08:00
|
|
|
|
2001-07-06 12:58:11 +08:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2012-02-10 07:18:22 +08:00
|
|
|
License along with the GNU C Library; if not, see
|
Prefer https to http for gnu.org and fsf.org URLs
Also, change sources.redhat.com to sourceware.org.
This patch was automatically generated by running the following shell
script, which uses GNU sed, and which avoids modifying files imported
from upstream:
sed -ri '
s,(http|ftp)(://(.*\.)?(gnu|fsf|sourceware)\.org($|[^.]|\.[^a-z])),https\2,g
s,(http|ftp)(://(.*\.)?)sources\.redhat\.com($|[^.]|\.[^a-z]),https\2sourceware.org\4,g
' \
$(find $(git ls-files) -prune -type f \
! -name '*.po' \
! -name 'ChangeLog*' \
! -path COPYING ! -path COPYING.LIB \
! -path manual/fdl-1.3.texi ! -path manual/lgpl-2.1.texi \
! -path manual/texinfo.tex ! -path scripts/config.guess \
! -path scripts/config.sub ! -path scripts/install-sh \
! -path scripts/mkinstalldirs ! -path scripts/move-if-change \
! -path INSTALL ! -path locale/programs/charmap-kw.h \
! -path po/libc.pot ! -path sysdeps/gnu/errlist.c \
! '(' -name configure \
-execdir test -f configure.ac -o -f configure.in ';' ')' \
! '(' -name preconfigure \
-execdir test -f preconfigure.ac ';' ')' \
-print)
and then by running 'make dist-prepare' to regenerate files built
from the altered files, and then executing the following to cleanup:
chmod a+x sysdeps/unix/sysv/linux/riscv/configure
# Omit irrelevant whitespace and comment-only changes,
# perhaps from a slightly-different Autoconf version.
git checkout -f \
sysdeps/csky/configure \
sysdeps/hppa/configure \
sysdeps/riscv/configure \
sysdeps/unix/sysv/linux/csky/configure
# Omit changes that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/powerpc/powerpc64/ppc-mcount.S: trailing lines
git checkout -f \
sysdeps/powerpc/powerpc64/ppc-mcount.S \
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
# Omit change that caused a pre-commit check to fail like this:
# remote: *** error: sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S: last line does not end in newline
git checkout -f sysdeps/sparc/sparc64/multiarch/memcpy-ultra3.S
2019-09-07 13:40:42 +08:00
|
|
|
<https://www.gnu.org/licenses/>. */
|
1999-05-18 01:25:32 +08:00
|
|
|
|
2016-11-17 22:26:27 +08:00
|
|
|
/* This file contains compatibility definitions of functions that were
|
|
|
|
formerly defined as "extern inline" in string.h; it's conceivable
|
|
|
|
that old binaries contain references to them. */
|
2003-01-01 07:13:55 +08:00
|
|
|
|
2016-11-17 22:26:27 +08:00
|
|
|
#define __NO_STRING_INLINES
|
1999-05-18 01:25:32 +08:00
|
|
|
#include <string.h>
|
2003-01-01 07:13:55 +08:00
|
|
|
|
Improve generic strcspn performance
Improve strcspn performance using a much faster algorithm. It is kept simple
so it works well on most targets. It is generally at least 10 times faster
than the existing implementation on bench-strcspn on a few AArch64
implementations, and for some tests 100 times as fast (repeatedly calling
strchr on a small string is extremely slow...).
In fact the string/bits/string2.h inlines make no longer sense, as GCC
already uses strlen if reject is an empty string, strchrnul is 5 times as
fast as __strcspn_c1, while __strcspn_c2 and __strcspn_c3 are slower than
the strcspn main loop for large strings (though reject length 2-4 could be
special cased in the future to gain even more performance).
Tested on x86_64, i686, and aarch64.
* string/Version (libc): Add GLIBC_2.24.
* string/strcspn.c (strcspn): Rewrite function.
* string/bits/string2.h (strcspn): Use __builtin_strcspn.
(__strcspn_c1): Remove inline function.
(__strcspn_c2): Likewise.
(__strcspn_c3): Likewise.
* string/string-inline.c
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c1): Add
compatibility symbol.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c2):
Likewise.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c3):
Likewise.
* sysdeps/i386/string-inlines.c: Include generic string-inlines.c.
2016-03-26 03:44:26 +08:00
|
|
|
#include "shlib-compat.h"
|
|
|
|
|
2016-12-14 23:12:18 +08:00
|
|
|
#if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_25)
|
2016-11-17 22:26:27 +08:00
|
|
|
/* These functions were removed from string.h in glibc 2.25. */
|
2016-12-14 23:12:18 +08:00
|
|
|
|
|
|
|
char *
|
|
|
|
__old_strtok_r_1c (char *__s, char __sep, char **__nextp)
|
|
|
|
{
|
|
|
|
char *__result;
|
|
|
|
if (__s == NULL)
|
|
|
|
__s = *__nextp;
|
|
|
|
while (*__s == __sep)
|
|
|
|
++__s;
|
|
|
|
__result = NULL;
|
|
|
|
if (*__s != '\0')
|
|
|
|
{
|
|
|
|
__result = __s++;
|
|
|
|
while (*__s != '\0')
|
|
|
|
if (*__s++ == __sep)
|
|
|
|
{
|
|
|
|
__s[-1] = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*__nextp = __s;
|
|
|
|
return __result;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strtok_r_1c, __strtok_r_1c, GLIBC_2_1_1);
|
2016-12-21 23:16:29 +08:00
|
|
|
|
|
|
|
char *
|
|
|
|
__old_strsep_1c (char **__s, char __reject)
|
|
|
|
{
|
|
|
|
char *__retval = *__s;
|
|
|
|
if (__retval != NULL && (*__s = strchr (__retval, __reject)) != NULL)
|
|
|
|
*(*__s)++ = '\0';
|
|
|
|
return __retval;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strsep_1c, __strsep_1c, GLIBC_2_1_1);
|
|
|
|
|
|
|
|
char *
|
|
|
|
__old_strsep_2c (char **__s, char __reject1, char __reject2)
|
|
|
|
{
|
|
|
|
char *__retval = *__s;
|
|
|
|
if (__retval != NULL)
|
|
|
|
{
|
|
|
|
char *__cp = __retval;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (*__cp == '\0')
|
|
|
|
{
|
|
|
|
__cp = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*__cp == __reject1 || *__cp == __reject2)
|
|
|
|
{
|
|
|
|
*__cp++ = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++__cp;
|
|
|
|
}
|
|
|
|
*__s = __cp;
|
|
|
|
}
|
|
|
|
return __retval;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strsep_2c, __strsep_2c, GLIBC_2_1_1);
|
|
|
|
|
|
|
|
char *
|
|
|
|
__old_strsep_3c (char **__s, char __reject1, char __reject2, char __reject3)
|
|
|
|
{
|
|
|
|
char *__retval = *__s;
|
|
|
|
if (__retval != NULL)
|
|
|
|
{
|
|
|
|
char *__cp = __retval;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (*__cp == '\0')
|
|
|
|
{
|
|
|
|
__cp = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (*__cp == __reject1 || *__cp == __reject2 || *__cp == __reject3)
|
|
|
|
{
|
|
|
|
*__cp++ = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++__cp;
|
|
|
|
}
|
|
|
|
*__s = __cp;
|
|
|
|
}
|
|
|
|
return __retval;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strsep_3c, __strsep_3c, GLIBC_2_1_1);
|
2016-12-14 23:12:18 +08:00
|
|
|
#endif
|
|
|
|
|
Improve generic strcspn performance
Improve strcspn performance using a much faster algorithm. It is kept simple
so it works well on most targets. It is generally at least 10 times faster
than the existing implementation on bench-strcspn on a few AArch64
implementations, and for some tests 100 times as fast (repeatedly calling
strchr on a small string is extremely slow...).
In fact the string/bits/string2.h inlines make no longer sense, as GCC
already uses strlen if reject is an empty string, strchrnul is 5 times as
fast as __strcspn_c1, while __strcspn_c2 and __strcspn_c3 are slower than
the strcspn main loop for large strings (though reject length 2-4 could be
special cased in the future to gain even more performance).
Tested on x86_64, i686, and aarch64.
* string/Version (libc): Add GLIBC_2.24.
* string/strcspn.c (strcspn): Rewrite function.
* string/bits/string2.h (strcspn): Use __builtin_strcspn.
(__strcspn_c1): Remove inline function.
(__strcspn_c2): Likewise.
(__strcspn_c3): Likewise.
* string/string-inline.c
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c1): Add
compatibility symbol.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c2):
Likewise.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c3):
Likewise.
* sysdeps/i386/string-inlines.c: Include generic string-inlines.c.
2016-03-26 03:44:26 +08:00
|
|
|
#if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_24)
|
2016-11-17 22:26:27 +08:00
|
|
|
/* These functions were removed from string.h in glibc 2.24. */
|
|
|
|
|
Improve generic strcspn performance
Improve strcspn performance using a much faster algorithm. It is kept simple
so it works well on most targets. It is generally at least 10 times faster
than the existing implementation on bench-strcspn on a few AArch64
implementations, and for some tests 100 times as fast (repeatedly calling
strchr on a small string is extremely slow...).
In fact the string/bits/string2.h inlines make no longer sense, as GCC
already uses strlen if reject is an empty string, strchrnul is 5 times as
fast as __strcspn_c1, while __strcspn_c2 and __strcspn_c3 are slower than
the strcspn main loop for large strings (though reject length 2-4 could be
special cased in the future to gain even more performance).
Tested on x86_64, i686, and aarch64.
* string/Version (libc): Add GLIBC_2.24.
* string/strcspn.c (strcspn): Rewrite function.
* string/bits/string2.h (strcspn): Use __builtin_strcspn.
(__strcspn_c1): Remove inline function.
(__strcspn_c2): Likewise.
(__strcspn_c3): Likewise.
* string/string-inline.c
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c1): Add
compatibility symbol.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c2):
Likewise.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c3):
Likewise.
* sysdeps/i386/string-inlines.c: Include generic string-inlines.c.
2016-03-26 03:44:26 +08:00
|
|
|
size_t
|
|
|
|
__old_strcspn_c1 (const char *__s, int __reject)
|
|
|
|
{
|
|
|
|
size_t __result = 0;
|
|
|
|
while (__s[__result] != '\0' && __s[__result] != __reject)
|
|
|
|
++__result;
|
|
|
|
return __result;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strcspn_c1, __strcspn_c1, GLIBC_2_1_1);
|
|
|
|
|
|
|
|
size_t
|
|
|
|
__old_strcspn_c2 (const char *__s, int __reject1, int __reject2)
|
|
|
|
{
|
|
|
|
size_t __result = 0;
|
|
|
|
while (__s[__result] != '\0' && __s[__result] != __reject1
|
|
|
|
&& __s[__result] != __reject2)
|
|
|
|
++__result;
|
|
|
|
return __result;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strcspn_c2, __strcspn_c2, GLIBC_2_1_1);
|
|
|
|
|
|
|
|
size_t
|
|
|
|
__old_strcspn_c3 (const char *__s, int __reject1, int __reject2,
|
|
|
|
int __reject3)
|
|
|
|
{
|
|
|
|
size_t __result = 0;
|
|
|
|
while (__s[__result] != '\0' && __s[__result] != __reject1
|
|
|
|
&& __s[__result] != __reject2 && __s[__result] != __reject3)
|
|
|
|
++__result;
|
|
|
|
return __result;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strcspn_c3, __strcspn_c3, GLIBC_2_1_1);
|
Improve generic strspn performance
As for strcspn, this patch improves strspn performance using a much
faster algorithm. It first constructs a 256-entry table based on
the accept string and then uses it as a lookup table for the
input string. 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, i686, and aarch64.
* string/strspn.c (strcspn): Rewrite function.
* string/bits/string2.h (strspn): Use __builtin_strcspn.
(__strspn_c1): Remove inline function.
(__strspn_c2): Likewise.
(__strspn_c3): Likewise.
* string/string-inlines.c
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strspn_c1): Add
compatibility symbol.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strspn_c2):
Likewise.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strspn_c3):
Likewise.
2016-03-27 03:09:07 +08:00
|
|
|
|
|
|
|
size_t
|
|
|
|
__old_strspn_c1 (const char *__s, int __accept)
|
|
|
|
{
|
|
|
|
size_t __result = 0;
|
|
|
|
/* Please note that __accept never can be '\0'. */
|
|
|
|
while (__s[__result] == __accept)
|
|
|
|
++__result;
|
|
|
|
return __result;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strspn_c1, __strspn_c1, GLIBC_2_1_1);
|
|
|
|
|
|
|
|
size_t
|
|
|
|
__old_strspn_c2 (const char *__s, int __accept1, int __accept2)
|
|
|
|
{
|
|
|
|
size_t __result = 0;
|
|
|
|
/* Please note that __accept1 and __accept2 never can be '\0'. */
|
|
|
|
while (__s[__result] == __accept1 || __s[__result] == __accept2)
|
|
|
|
++__result;
|
|
|
|
return __result;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strspn_c2, __strspn_c2, GLIBC_2_1_1);
|
|
|
|
|
|
|
|
size_t
|
|
|
|
__old_strspn_c3 (const char *__s, int __accept1, int __accept2,
|
|
|
|
int __accept3)
|
|
|
|
{
|
|
|
|
size_t __result = 0;
|
|
|
|
/* Please note that __accept1 to __accept3 never can be '\0'. */
|
|
|
|
while (__s[__result] == __accept1 || __s[__result] == __accept2
|
|
|
|
|| __s[__result] == __accept3)
|
|
|
|
++__result;
|
|
|
|
return __result;
|
|
|
|
}
|
|
|
|
compat_symbol (libc, __old_strspn_c3, __strspn_c3, GLIBC_2_1_1);
|
|
|
|
|
2016-03-27 21:33:56 +08:00
|
|
|
char *
|
2016-04-18 22:26:11 +08:00
|
|
|
__old_strpbrk_c2 (const char *__s, int __accept1, int __accept2)
|
2016-03-27 21:33:56 +08:00
|
|
|
{
|
|
|
|
/* 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 *
|
2016-04-18 22:26:11 +08:00
|
|
|
__old_strpbrk_c3 (const char *__s, int __accept1, int __accept2, int __accept3)
|
2016-03-27 21:33:56 +08:00
|
|
|
{
|
|
|
|
/* 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);
|
|
|
|
|
2016-11-17 22:26:27 +08:00
|
|
|
# if defined __mc68020__ || defined __s390__ || defined __i386__
|
|
|
|
# define _STRING_INLINE_unaligned 1
|
|
|
|
# else
|
|
|
|
# define _STRING_INLINE_unaligned 0
|
2016-04-18 22:26:11 +08:00
|
|
|
/* These are a few types we need for the optimizations if we cannot
|
|
|
|
use unaligned memory accesses. */
|
2016-11-17 22:26:27 +08:00
|
|
|
# define __STRING2_COPY_TYPE(N) \
|
2016-04-18 22:26:11 +08:00
|
|
|
typedef struct { unsigned char __arr[N]; } \
|
|
|
|
__attribute__ ((__packed__)) __STRING2_COPY_ARR##N
|
|
|
|
__STRING2_COPY_TYPE (2);
|
|
|
|
__STRING2_COPY_TYPE (3);
|
|
|
|
__STRING2_COPY_TYPE (4);
|
|
|
|
__STRING2_COPY_TYPE (5);
|
|
|
|
__STRING2_COPY_TYPE (6);
|
|
|
|
__STRING2_COPY_TYPE (7);
|
|
|
|
__STRING2_COPY_TYPE (8);
|
2016-11-17 22:26:27 +08:00
|
|
|
# undef __STRING2_COPY_TYPE
|
|
|
|
# endif
|
2016-04-18 22:26:11 +08:00
|
|
|
|
|
|
|
# if _STRING_INLINE_unaligned
|
|
|
|
void *
|
|
|
|
__old_mempcpy_small (void *__dest1,
|
|
|
|
char __src0_1, char __src2_1, char __src4_1, char __src6_1,
|
|
|
|
__uint16_t __src0_2, __uint16_t __src4_2,
|
|
|
|
__uint32_t __src0_4, __uint32_t __src4_4,
|
|
|
|
size_t __srclen)
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
__uint32_t __ui;
|
|
|
|
__uint16_t __usi;
|
|
|
|
unsigned char __uc;
|
|
|
|
unsigned char __c;
|
|
|
|
} *__u = __dest1;
|
|
|
|
switch ((unsigned int) __srclen)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
__u->__c = __src0_1;
|
|
|
|
__u = __extension__ ((void *) __u + 1);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
__u->__usi = __src0_2;
|
|
|
|
__u = __extension__ ((void *) __u + 2);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
__u->__usi = __src0_2;
|
|
|
|
__u = __extension__ ((void *) __u + 2);
|
|
|
|
__u->__c = __src2_1;
|
|
|
|
__u = __extension__ ((void *) __u + 1);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__c = __src4_1;
|
|
|
|
__u = __extension__ ((void *) __u + 1);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__usi = __src4_2;
|
|
|
|
__u = __extension__ ((void *) __u + 2);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__usi = __src4_2;
|
|
|
|
__u = __extension__ ((void *) __u + 2);
|
|
|
|
__u->__c = __src6_1;
|
|
|
|
__u = __extension__ ((void *) __u + 1);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__ui = __src4_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (void *) __u;
|
|
|
|
}
|
|
|
|
|
|
|
|
# else
|
|
|
|
|
|
|
|
void *
|
|
|
|
__old_mempcpy_small (void *__dest, char __src1,
|
|
|
|
__STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
|
|
|
|
__STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
|
|
|
|
__STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
|
|
|
|
__STRING2_COPY_ARR8 __src8, size_t __srclen)
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
char __c;
|
|
|
|
__STRING2_COPY_ARR2 __sca2;
|
|
|
|
__STRING2_COPY_ARR3 __sca3;
|
|
|
|
__STRING2_COPY_ARR4 __sca4;
|
|
|
|
__STRING2_COPY_ARR5 __sca5;
|
|
|
|
__STRING2_COPY_ARR6 __sca6;
|
|
|
|
__STRING2_COPY_ARR7 __sca7;
|
|
|
|
__STRING2_COPY_ARR8 __sca8;
|
|
|
|
} *__u = __dest;
|
|
|
|
switch ((unsigned int) __srclen)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
__u->__c = __src1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
__extension__ __u->__sca2 = __src2;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
__extension__ __u->__sca3 = __src3;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
__extension__ __u->__sca4 = __src4;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
__extension__ __u->__sca5 = __src5;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
__extension__ __u->__sca6 = __src6;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
__extension__ __u->__sca7 = __src7;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
__extension__ __u->__sca8 = __src8;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return __extension__ ((void *) __u + __srclen);
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
compat_symbol (libc, __old_mempcpy_small, __mempcpy_small, GLIBC_2_1_1);
|
|
|
|
|
|
|
|
# if _STRING_INLINE_unaligned
|
|
|
|
char *
|
|
|
|
__old_strcpy_small (char *__dest,
|
|
|
|
__uint16_t __src0_2, __uint16_t __src4_2,
|
|
|
|
__uint32_t __src0_4, __uint32_t __src4_4,
|
|
|
|
size_t __srclen)
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
__uint32_t __ui;
|
|
|
|
__uint16_t __usi;
|
|
|
|
unsigned char __uc;
|
|
|
|
} *__u = (void *) __dest;
|
|
|
|
switch ((unsigned int) __srclen)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
__u->__uc = '\0';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
__u->__usi = __src0_2;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
__u->__usi = __src0_2;
|
|
|
|
__u = __extension__ ((void *) __u + 2);
|
|
|
|
__u->__uc = '\0';
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__uc = '\0';
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__usi = __src4_2;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__usi = __src4_2;
|
|
|
|
__u = __extension__ ((void *) __u + 2);
|
|
|
|
__u->__uc = '\0';
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__ui = __src4_4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return __dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
# else
|
|
|
|
|
|
|
|
char *
|
|
|
|
__old_strcpy_small (char *__dest,
|
|
|
|
__STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
|
|
|
|
__STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
|
|
|
|
__STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
|
|
|
|
__STRING2_COPY_ARR8 __src8, size_t __srclen)
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
char __c;
|
|
|
|
__STRING2_COPY_ARR2 __sca2;
|
|
|
|
__STRING2_COPY_ARR3 __sca3;
|
|
|
|
__STRING2_COPY_ARR4 __sca4;
|
|
|
|
__STRING2_COPY_ARR5 __sca5;
|
|
|
|
__STRING2_COPY_ARR6 __sca6;
|
|
|
|
__STRING2_COPY_ARR7 __sca7;
|
|
|
|
__STRING2_COPY_ARR8 __sca8;
|
|
|
|
} *__u = (void *) __dest;
|
|
|
|
switch ((unsigned int) __srclen)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
__u->__c = '\0';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
__extension__ __u->__sca2 = __src2;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
__extension__ __u->__sca3 = __src3;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
__extension__ __u->__sca4 = __src4;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
__extension__ __u->__sca5 = __src5;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
__extension__ __u->__sca6 = __src6;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
__extension__ __u->__sca7 = __src7;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
__extension__ __u->__sca8 = __src8;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return __dest;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
compat_symbol (libc, __old_strcpy_small, __strcpy_small, GLIBC_2_1_1);
|
|
|
|
|
|
|
|
# if _STRING_INLINE_unaligned
|
|
|
|
char *
|
|
|
|
__old_stpcpy_small (char *__dest,
|
|
|
|
__uint16_t __src0_2, __uint16_t __src4_2,
|
|
|
|
__uint32_t __src0_4, __uint32_t __src4_4,
|
|
|
|
size_t __srclen)
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
unsigned int __ui;
|
|
|
|
unsigned short int __usi;
|
|
|
|
unsigned char __uc;
|
|
|
|
char __c;
|
|
|
|
} *__u = (void *) __dest;
|
|
|
|
switch ((unsigned int) __srclen)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
__u->__uc = '\0';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
__u->__usi = __src0_2;
|
|
|
|
__u = __extension__ ((void *) __u + 1);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
__u->__usi = __src0_2;
|
|
|
|
__u = __extension__ ((void *) __u + 2);
|
|
|
|
__u->__uc = '\0';
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 3);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__uc = '\0';
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__usi = __src4_2;
|
|
|
|
__u = __extension__ ((void *) __u + 1);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__usi = __src4_2;
|
|
|
|
__u = __extension__ ((void *) __u + 2);
|
|
|
|
__u->__uc = '\0';
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
__u->__ui = __src0_4;
|
|
|
|
__u = __extension__ ((void *) __u + 4);
|
|
|
|
__u->__ui = __src4_4;
|
|
|
|
__u = __extension__ ((void *) __u + 3);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return &__u->__c;
|
|
|
|
}
|
|
|
|
|
|
|
|
# else
|
|
|
|
|
|
|
|
char *
|
|
|
|
__old_stpcpy_small (char *__dest,
|
|
|
|
__STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
|
|
|
|
__STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
|
|
|
|
__STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
|
|
|
|
__STRING2_COPY_ARR8 __src8, size_t __srclen)
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
char __c;
|
|
|
|
__STRING2_COPY_ARR2 __sca2;
|
|
|
|
__STRING2_COPY_ARR3 __sca3;
|
|
|
|
__STRING2_COPY_ARR4 __sca4;
|
|
|
|
__STRING2_COPY_ARR5 __sca5;
|
|
|
|
__STRING2_COPY_ARR6 __sca6;
|
|
|
|
__STRING2_COPY_ARR7 __sca7;
|
|
|
|
__STRING2_COPY_ARR8 __sca8;
|
|
|
|
} *__u = (void *) __dest;
|
|
|
|
switch ((unsigned int) __srclen)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
__u->__c = '\0';
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
__extension__ __u->__sca2 = __src2;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
__extension__ __u->__sca3 = __src3;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
__extension__ __u->__sca4 = __src4;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
__extension__ __u->__sca5 = __src5;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
__extension__ __u->__sca6 = __src6;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
__extension__ __u->__sca7 = __src7;
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
__extension__ __u->__sca8 = __src8;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return __dest + __srclen - 1;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
compat_symbol (libc, __old_stpcpy_small, __stpcpy_small, GLIBC_2_1_1);
|
|
|
|
|
Improve generic strcspn performance
Improve strcspn performance using a much faster algorithm. It is kept simple
so it works well on most targets. It is generally at least 10 times faster
than the existing implementation on bench-strcspn on a few AArch64
implementations, and for some tests 100 times as fast (repeatedly calling
strchr on a small string is extremely slow...).
In fact the string/bits/string2.h inlines make no longer sense, as GCC
already uses strlen if reject is an empty string, strchrnul is 5 times as
fast as __strcspn_c1, while __strcspn_c2 and __strcspn_c3 are slower than
the strcspn main loop for large strings (though reject length 2-4 could be
special cased in the future to gain even more performance).
Tested on x86_64, i686, and aarch64.
* string/Version (libc): Add GLIBC_2.24.
* string/strcspn.c (strcspn): Rewrite function.
* string/bits/string2.h (strcspn): Use __builtin_strcspn.
(__strcspn_c1): Remove inline function.
(__strcspn_c2): Likewise.
(__strcspn_c3): Likewise.
* string/string-inline.c
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c1): Add
compatibility symbol.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c2):
Likewise.
[SHLIB_COMPAT(libc, GLIBC_2_1_1, GLIBC_2_24)] (__strcspn_c3):
Likewise.
* sysdeps/i386/string-inlines.c: Include generic string-inlines.c.
2016-03-26 03:44:26 +08:00
|
|
|
#endif
|