faster strchr [was: rawmemchr]

Jeff Johnston jjohnstn@redhat.com
Thu May 22 15:19:00 GMT 2008


Eric Blake wrote:
> 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)?
>
>   

Yes, thanks.

-- Jeff J.
> 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;
>   }
>
>
>
>   



More information about the Newlib mailing list