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:
		| @@ -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 */ | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user