2008-05-21 Eric Blake <ebb9@byu.net>
Optimize the generic strchr.
* libc/string/strchr.c (strchr): Pre-align data so unaligned
searches aren't penalized. Special-case searching for 0.
Index: libc/string/strchr.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/string/strchr.c,v
retrieving revision 1.2
diff -c -r1.2 strchr.c
*** libc/string/strchr.c 10 May 2002 17:51:18 -0000 1.2
--- libc/string/strchr.c 21 May 2008 22:11:18 -0000
***************
*** 63,108 ****
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;
! while (*s && *s != c)
! {
! s++;
! }
! if (*s != c)
{
! s = NULL;
}
! return (char *) s;
! #else
! unsigned char c = (unsigned char)i;
! unsigned long mask,j;
! unsigned long *aligned_addr;
!
! if (!UNALIGNED (s))
{
! 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))
! 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;
! }
while (*s && *s != c)
! s++;
if (*s == c)
return (char *)s;
return NULL;
- #endif /* not PREFER_SIZE_OVER_SPEED */
}
--- 63,123 ----
int i)
{
_CONST unsigned char *s = (_CONST unsigned char *)s1;
! unsigned char c = i;
! #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
! unsigned long mask,j;
! unsigned long *aligned_addr;
! /* Special case for finding 0. */
! if (!c)
{
! 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++;
! /* Found the end of string. */
! s = (const unsigned char *) aligned_addr;
! while (*s)
! s++;
! return (char *) s;
}
! /* 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;
}