This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

faster strchr [was: rawmemchr]


Jeff Johnston <jjohnstn <at> redhat.com> writes:

> > So, OK to apply this patch?
> >
> >   
> Yes, go ahead.  I assume you have verified that the function still works 
> correctly.
> 

Yes - I built cygwin using the improved version, then ran through the test 
suites of several programs that use strchr.  It passed all my tests whether the 
byte is found or not, and whether the byte is 0 or not.  So I committed it.

OK for this followon, which changes the generic C code in the same manner (also 
tested)?

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;
  }




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]