Optimize the generic strchr.
* libc/string/strchr.c (strchr) [!__OPTIMIZE_SIZE__]: Pre-align data so unaligned searches aren't penalized. Special-case searching for 0.
This commit is contained in:
parent
0b99028af4
commit
ae47b14a12
|
@ -1,8 +1,14 @@
|
|||
2008-05-21 Eric Blake <ebb9@byu.net>
|
||||
|
||||
Optimize the generic strchr.
|
||||
* libc/string/strchr.c (strchr) [!__OPTIMIZE_SIZE__]: Pre-align
|
||||
data so unaligned searches aren't penalized. Special-case
|
||||
searching for 0.
|
||||
|
||||
Optimize strchr for x86.
|
||||
* libc/machine/i386/strchr.S (strchr): Pre-align data so unaligned
|
||||
searches aren't penalized. Special-case searching for 0.
|
||||
* libc/machine/i386/strchr.S (strchr) [!__OPTIMIZE_SIZE__]:
|
||||
Pre-align data so unaligned searches aren't penalized.
|
||||
Special-case searching for 0.
|
||||
|
||||
2008-05-20 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ QUICKREF
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* DETECTCHAR returns nonzero if (long)X contains the byte used
|
||||
/* DETECTCHAR returns nonzero if (long)X contains the byte used
|
||||
to fill (long)MASK. */
|
||||
#define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK))
|
||||
|
||||
|
@ -63,46 +63,61 @@ _DEFUN (strchr, (s1, i),
|
|||
int i)
|
||||
{
|
||||
_CONST unsigned char *s = (_CONST unsigned char *)s1;
|
||||
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
|
||||
unsigned char c = (unsigned int)i;
|
||||
unsigned char c = i;
|
||||
|
||||
while (*s && *s != c)
|
||||
{
|
||||
s++;
|
||||
}
|
||||
|
||||
if (*s != c)
|
||||
{
|
||||
s = NULL;
|
||||
}
|
||||
|
||||
return (char *) s;
|
||||
#else
|
||||
unsigned char c = (unsigned char)i;
|
||||
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
|
||||
unsigned long mask,j;
|
||||
unsigned long *aligned_addr;
|
||||
|
||||
if (!UNALIGNED (s))
|
||||
/* Special case for finding 0. */
|
||||
if (!c)
|
||||
{
|
||||
mask = 0;
|
||||
for (j = 0; j < LBLOCKSIZE; j++)
|
||||
mask = (mask << 8) | c;
|
||||
|
||||
aligned_addr = (unsigned long*)s;
|
||||
while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask))
|
||||
while (UNALIGNED (s))
|
||||
{
|
||||
if (!*s)
|
||||
return (char *) s;
|
||||
s++;
|
||||
}
|
||||
/* Operate a word at a time. */
|
||||
aligned_addr = (unsigned long *) s;
|
||||
while (!DETECTNULL (*aligned_addr))
|
||||
aligned_addr++;
|
||||
|
||||
/* The block of bytes currently pointed to by aligned_addr
|
||||
contains either a null or the target char, or both. We
|
||||
catch it using the bytewise search. */
|
||||
|
||||
s = (unsigned char*)aligned_addr;
|
||||
/* Found the end of string. */
|
||||
s = (const unsigned char *) aligned_addr;
|
||||
while (*s)
|
||||
s++;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
while (*s && *s != c)
|
||||
/* All other bytes. Align the pointer, then search a long at a time. */
|
||||
while (UNALIGNED (s))
|
||||
{
|
||||
if (!*s)
|
||||
return NULL;
|
||||
if (*s == c)
|
||||
return (char *) s;
|
||||
s++;
|
||||
}
|
||||
|
||||
mask = c;
|
||||
for (j = 8; j < LBLOCKSIZE * 8; j <<= 1)
|
||||
mask = (mask << j) | mask;
|
||||
|
||||
aligned_addr = (unsigned long *) s;
|
||||
while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask))
|
||||
aligned_addr++;
|
||||
|
||||
/* The block of bytes currently pointed to by aligned_addr
|
||||
contains either a null or the target char, or both. We
|
||||
catch it using the bytewise search. */
|
||||
|
||||
s = (unsigned char *) aligned_addr;
|
||||
|
||||
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||
|
||||
while (*s && *s != c)
|
||||
s++;
|
||||
if (*s == c)
|
||||
return (char *)s;
|
||||
return NULL;
|
||||
#endif /* not PREFER_SIZE_OVER_SPEED */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue