This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[PATCH] <bits/string2.h> changes for GCC 3.2+ and 3.4+
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Ulrich Drepper <drepper at redhat dot com>
- Cc: Glibc hackers <libc-hacker at sources dot redhat dot com>, gcc at gcc dot gnu dot org
- Date: Wed, 26 May 2004 14:46:59 +0200
- Subject: [PATCH] <bits/string2.h> changes for GCC 3.2+ and 3.4+
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
I went through <bits/string2.h> and GCC 3.2.3, 3.3.3, 3.4.0 and trunk.
This patch is removing memset macro for GCC 3.0+, since GCC really does
in most cases as good or better job as glibc and certainly has far more
information that glibc.
mempcpy in 3.4+ has all the optimizations glibc provided, similarly stpcpy.
The strchr macro is kept, as the optimization of strchr (p, '\0') to
__rawmemchr (p, '\0') is worthy, but was changed to optimize cases like
strchr ("foobar", '\0') with GCC 3.2+.
_USE_STRING_ARCH_mempcpy is not defined in any of the bits/string.h headers,
so I have removed that case from strncpy inline.
For strncpy and strncat GCC 3.2+ has the same optimizations as glibc did.
For strcmp, with GCC 3.2+ we can now optimize comparision of two constant
strings, yet the macro is kept for strcmp (p, "ab") cases (where one string
is literal with up to 4 characters).
For strcspn, strspn and strpbrk with GCC 3.2+ the macros have been changed
to handle both arguments string literals.
2004-05-26 Jakub Jelinek <jakub@redhat.com>
* include/string.h (mempcpy, stpcpy): Add libc_hidden_builtin_proto.
* string/bits/string2.h (memset): Disable macro for GCC 3.0+.
(__mempcpy): Use __builtin_mempcpy for GCC 3.4+.
(strchr): For GCC 3.2+, only use __rawmemchr if second argument is
constant '\0' and first argument is not constant.
(__stpcpy): Use __builtin_stpcpy for GCC 3.4+.
(strncpy): Remove #ifdef _USE_STRING_ARCH_mempcpy variant.
For GCC 3.2+ use __builtin_strncpy.
(strncat): For GCC 3.2+ use __builtin_strncat.
(strcmp): For GCC 3.2+ use __builtin_strcmp if both arguments are
constant.
(strcspn, strspn, strpbrk): For GCC 3.2+, use builtin function
if both arguments are constant.
--- libc/include/string.h.jj 2004-04-13 10:42:51.000000000 +0200
+++ libc/include/string.h 2004-05-26 16:08:50.082921658 +0200
@@ -83,6 +83,7 @@ libc_hidden_proto (__strxfrm_l)
libc_hidden_builtin_proto (memchr)
libc_hidden_builtin_proto (memcpy)
+libc_hidden_builtin_proto (mempcpy)
libc_hidden_builtin_proto (memcmp)
libc_hidden_builtin_proto (memmove)
libc_hidden_builtin_proto (memset)
@@ -95,6 +96,7 @@ libc_hidden_builtin_proto (strlen)
libc_hidden_builtin_proto (strncmp)
libc_hidden_builtin_proto (strncpy)
libc_hidden_builtin_proto (strpbrk)
+libc_hidden_builtin_proto (stpcpy)
libc_hidden_builtin_proto (strrchr)
libc_hidden_builtin_proto (strspn)
libc_hidden_builtin_proto (strstr)
--- libc/string/bits/string2.h.jj 2004-05-07 14:32:32.000000000 +0200
+++ libc/string/bits/string2.h 2004-05-26 15:57:38.423291808 +0200
@@ -30,7 +30,7 @@
means the code size increases a lot. Instead the definitions here
optimize some functions in a way which do not dramatically
increase the code size and which do not use assembler. The main
- trick is to use GNU CC's `__builtin_constant_p' function.
+ trick is to use GCC's `__builtin_constant_p' function.
Every function XXX which has a defined version in
<bits/string.h> must be accompanied by a symbol _HAVE_STRING_ARCH_XXX
@@ -94,7 +94,7 @@ __STRING2_COPY_TYPE (8);
((size_t)(const void *)((__x) + 1) - (size_t)(const void *)(__x) == 1)
/* Set N bytes of S to C. */
-#ifndef _HAVE_STRING_ARCH_memset
+#if !defined _HAVE_STRING_ARCH_memset && ! __GNUC_PREREQ (3, 0)
# if _STRING_ARCH_unaligned
# define memset(s, c, n) \
(__extension__ (__builtin_constant_p (n) && (n) <= 16 \
@@ -178,12 +178,10 @@ __STRING2_COPY_TYPE (8);
\
__s; })
# else
-# if ! __GNUC_PREREQ (3, 0)
-# define memset(s, c, n) \
+# define memset(s, c, n) \
(__extension__ (__builtin_constant_p (c) && (c) == '\0' \
? ({ void *__s = (s); __bzero (__s, n); __s; }) \
: memset (s, c, n)))
-# endif
# endif
/* GCC optimizes memset(s, 0, n) but not bzero(s, n).
@@ -200,7 +198,9 @@ __STRING2_COPY_TYPE (8);
#ifdef __USE_GNU
# if !defined _HAVE_STRING_ARCH_mempcpy || defined _FORCE_INLINES
# ifndef _HAVE_STRING_ARCH_mempcpy
-# if __GNUC_PREREQ (3, 0)
+# if __GNUC_PREREQ (3, 4)
+# define __mempcpy(dest, src, n) __builtin_mempcpy (dest, src, n)
+# elif __GNUC_PREREQ (3, 0)
# define __mempcpy(dest, src, n) \
(__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \
&& __string2_1bptr_p (src) && n <= 8 \
@@ -387,10 +387,18 @@ __mempcpy_small (void *__dest, char __sr
/* Return pointer to C in S. */
#ifndef _HAVE_STRING_ARCH_strchr
extern void *__rawmemchr (const void *__s, int __c);
-# define strchr(s, c) \
+# if __GNUC_PREREQ (3, 2)
+# define strchr(s, c) \
+ (__extension__ (__builtin_constant_p (c) && !__builtin_constant_p (s) \
+ && (c) == '\0' \
+ ? (char *) __rawmemchr (s, c) \
+ : __builtin_strchr (s, c)))
+# else
+# define strchr(s, c) \
(__extension__ (__builtin_constant_p (c) && (c) == '\0' \
? (char *) __rawmemchr (s, c) \
: strchr (s, c)))
+# endif
#endif
@@ -560,7 +568,9 @@ __strcpy_small (char *__dest,
#ifdef __USE_GNU
# if !defined _HAVE_STRING_ARCH_stpcpy || defined _FORCE_INLINES
# ifndef _HAVE_STRING_ARCH_stpcpy
-# if __GNUC_PREREQ (3, 0)
+# if __GNUC_PREREQ (3, 4)
+# define __stpcpy(dest, src) __builtin_stpcpy (dest, src)
+# elif __GNUC_PREREQ (3, 0)
# define __stpcpy(dest, src) \
(__extension__ (__builtin_constant_p (src) \
? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 \
@@ -742,16 +752,8 @@ __stpcpy_small (char *__dest,
/* Copy no more than N characters of SRC to DEST. */
#ifndef _HAVE_STRING_ARCH_strncpy
-# if defined _USE_STRING_ARCH_memset && defined _USE_STRING_ARCH_mempcpy
-# define strncpy(dest, src, n) \
- (__extension__ ({ char *__dest = (dest); \
- __builtin_constant_p (src) && __builtin_constant_p (n) \
- ? (strlen (src) + 1 >= ((size_t) (n)) \
- ? (char *) memcpy (__dest, src, n) \
- : (memset (__mempcpy (__dest, src, strlen (src)), \
- '\0', n - strlen (src)), \
- __dest)) \
- : strncpy (__dest, src, n); }))
+# if __GNUC_PREREQ (3, 2)
+# define strncpy(dest, src, n) __builtin_strncpy (dest, src, n)
# else
# define strncpy(dest, src, n) \
(__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \
@@ -774,6 +776,8 @@ __stpcpy_small (char *__dest,
: (*((char *) __mempcpy (strchr (__dest, '\0'), \
src, n)) = '\0', __dest)) \
: strncat (dest, src, n); }))
+# elif __GNUC_PREREQ (3, 2)
+# define strncat(dest, src, n) __builtin_strncat (dest, src, n)
# else
# define strncat(dest, src, n) \
(__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \
@@ -787,7 +791,28 @@ __stpcpy_small (char *__dest,
/* Compare characters of S1 and S2. */
#ifndef _HAVE_STRING_ARCH_strcmp
-# define strcmp(s1, s2) \
+# if __GNUC_PREREQ (3, 2)
+# define strcmp(s1, s2) \
+ __extension__ \
+ ({ size_t __s1_len, __s2_len; \
+ (__builtin_constant_p (s1) && __builtin_constant_p (s2) \
+ && (__s1_len = strlen (s1), __s2_len = strlen (s2), \
+ (!__string2_1bptr_p (s1) || __s1_len >= 4) \
+ && (!__string2_1bptr_p (s2) || __s2_len >= 4)) \
+ ? __builtin_strcmp (s1, s2) \
+ : (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
+ && (__s1_len = strlen (s1), __s1_len < 4) \
+ ? (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \
+ ? __builtin_strcmp (s1, s2) \
+ : __strcmp_cg (s1, s2, __s1_len)) \
+ : (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \
+ && (__s2_len = strlen (s2), __s2_len < 4) \
+ ? (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
+ ? __builtin_strcmp (s1, s2) \
+ : __strcmp_gc (s1, s2, __s2_len)) \
+ : __builtin_strcmp (s1, s2)))); })
+# else
+# define strcmp(s1, s2) \
__extension__ \
({ size_t __s1_len, __s2_len; \
(__builtin_constant_p (s1) && __builtin_constant_p (s2) \
@@ -807,6 +832,7 @@ __stpcpy_small (char *__dest,
? __strcmp_cc (s1, s2, __s2_len) \
: __strcmp_gc (s1, s2, __s2_len)) \
: strcmp (s1, s2)))); })
+#endif
# define __strcmp_cc(s1, s2, l) \
(__extension__ ({ register int __result = \
@@ -900,7 +926,25 @@ __stpcpy_small (char *__dest,
consists entirely of characters not in REJECT. */
#if !defined _HAVE_STRING_ARCH_strcspn || defined _FORCE_INLINES
# ifndef _HAVE_STRING_ARCH_strcspn
-# define strcspn(s, reject) \
+# if __GNUC_PREREQ (3, 2)
+# define strcspn(s, reject) \
+ __extension__ \
+ ({ char __r0, __r1, __r2; \
+ (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \
+ ? ((__builtin_constant_p (s) && __string2_1bptr_p (s)) \
+ ? __builtin_strcspn (s, reject) \
+ : ((__r0 = ((__const char *) (reject))[0], __r0 == '\0') \
+ ? strlen (s) \
+ : ((__r1 = ((__const char *) (reject))[1], __r1 == '\0') \
+ ? __strcspn_c1 (s, __r0) \
+ : ((__r2 = ((__const char *) (reject))[2], __r2 == '\0') \
+ ? __strcspn_c2 (s, __r0, __r1) \
+ : (((__const char *) (reject))[3] == '\0' \
+ ? __strcspn_c3 (s, __r0, __r1, __r2) \
+ : __builtin_strcspn (s, reject)))))) \
+ : __builtin_strcspn (s, reject)); })
+# else
+# define strcspn(s, reject) \
__extension__ \
({ char __r0, __r1, __r2; \
(__builtin_constant_p (reject) && __string2_1bptr_p (reject) \
@@ -913,7 +957,8 @@ __stpcpy_small (char *__dest,
: (((__const char *) (reject))[3] == '\0' \
? __strcspn_c3 (s, __r0, __r1, __r2) \
: strcspn (s, reject))))) \
- : strcspn (s, reject)); })
+ : strcspn (s, reject)); })
+# endif
# endif
__STRING_INLINE size_t __strcspn_c1 (__const char *__s, int __reject);
@@ -957,7 +1002,25 @@ __strcspn_c3 (__const char *__s, int __r
consists entirely of characters in ACCEPT. */
#if !defined _HAVE_STRING_ARCH_strspn || defined _FORCE_INLINES
# ifndef _HAVE_STRING_ARCH_strspn
-# define strspn(s, accept) \
+# if __GNUC_PREREQ (3, 2)
+# define strspn(s, accept) \
+ __extension__ \
+ ({ char __a0, __a1, __a2; \
+ (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \
+ ? ((__builtin_constant_p (s) && __string2_1bptr_p (s)) \
+ ? __builtin_strspn (s, accept) \
+ : ((__a0 = ((__const char *) (accept))[0], __a0 == '\0') \
+ ? ((void) (s), 0) \
+ : ((__a1 = ((__const char *) (accept))[1], __a1 == '\0') \
+ ? __strspn_c1 (s, __a0) \
+ : ((__a2 = ((__const char *) (accept))[2], __a2 == '\0') \
+ ? __strspn_c2 (s, __a0, __a1) \
+ : (((__const char *) (accept))[3] == '\0' \
+ ? __strspn_c3 (s, __a0, __a1, __a2) \
+ : __builtin_strspn (s, accept)))))) \
+ : __builtin_strspn (s, accept)); })
+# else
+# define strspn(s, accept) \
__extension__ \
({ char __a0, __a1, __a2; \
(__builtin_constant_p (accept) && __string2_1bptr_p (accept) \
@@ -971,6 +1034,7 @@ __strcspn_c3 (__const char *__s, int __r
? __strspn_c3 (s, __a0, __a1, __a2) \
: strspn (s, accept))))) \
: strspn (s, accept)); })
+# endif
# endif
__STRING_INLINE size_t __strspn_c1 (__const char *__s, int __accept);
@@ -1014,6 +1078,24 @@ __strspn_c3 (__const char *__s, int __ac
/* Find the first occurrence in S of any character in ACCEPT. */
#if !defined _HAVE_STRING_ARCH_strpbrk || defined _FORCE_INLINES
# ifndef _HAVE_STRING_ARCH_strpbrk
+# if __GNUC_PREREQ (3, 2)
+# define strpbrk(s, accept) \
+ __extension__ \
+ ({ char __a0, __a1, __a2; \
+ (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \
+ ? ((__builtin_constant_p (s) && __string2_1bptr_p (s)) \
+ ? __builtin_strpbrk (s, accept) \
+ : ((__a0 = ((__const char *) (accept))[0], __a0 == '\0') \
+ ? ((void) (s), (char *) NULL) \
+ : ((__a1 = ((__const char *) (accept))[1], __a1 == '\0') \
+ ? __builtin_strchr (s, __a0) \
+ : ((__a2 = ((__const char *) (accept))[2], __a2 == '\0') \
+ ? __strpbrk_c2 (s, __a0, __a1) \
+ : (((__const char *) (accept))[3] == '\0' \
+ ? __strpbrk_c3 (s, __a0, __a1, __a2) \
+ : __builtin_strpbrk (s, accept)))))) \
+ : __builtin_strpbrk (s, accept)); })
+# else
# define strpbrk(s, accept) \
__extension__ \
({ char __a0, __a1, __a2; \
@@ -1028,6 +1110,7 @@ __strspn_c3 (__const char *__s, int __ac
? __strpbrk_c3 (s, __a0, __a1, __a2) \
: strpbrk (s, accept))))) \
: strpbrk (s, accept)); })
+# endif
# endif
__STRING_INLINE char *__strpbrk_c2 (__const char *__s, int __accept1,
Jakub