From patchwork Tue Nov 22 20:26:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wilco Dijkstra X-Patchwork-Id: 17714 Received: (qmail 29726 invoked by alias); 22 Nov 2016 20:26:33 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 29712 invoked by uid 89); 22 Nov 2016 20:26:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_00, KAM_LOTSOFHASH, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=no version=3.3.2 spammy=786, 235, 1216, 8487 X-HELO: EUR03-VE1-obe.outbound.protection.outlook.com From: Wilco Dijkstra To: "libc-alpha@sourceware.org" CC: Florian Weimer , nd , Joseph Myers Subject: [PATCH v3] Remove defines to builtins in string2.h Date: Tue, 22 Nov 2016 20:26:16 +0000 Message-ID: References: , <4c9be96f-5cbf-483b-89d8-b5c1f11e1e78@redhat.com> , , In-Reply-To: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Wilco.Dijkstra@arm.com; x-microsoft-exchange-diagnostics: 1; AM5PR0802MB2609; 7:tZkuKZ9ekZxe0auf5nFctk332gQVm2K9rBIa7fw392Fp8FVW9+/a9CCtSpJFBrlk140syoS8X9Zhta1XolFlQbMfDXljaNd5lnZJJf8LbT1kC7yTD37p4J06cgYLj83dRfbQMfQHQ2+zBMDEsFlsDwnJCa0zhexwhb1Bc+p64E7LkS+Oo0Imi7EZYNb8ticzt2snUlsYatfXjg8s21U8R+xvH246TUx4rbcr97Pow6S1s4aiGdx8bK49CMH9pFPlrBK8gELdK5IueZ9L2kWgKETP1WtesPd8O4PsFs1jjZOJycA2F5C6NLF9eSUQEiqVJdppw6K7IVowkdWSZPNm93Cxn5LwddNMlytY+/nrEEg= x-ms-office365-filtering-correlation-id: a1ed6ca8-53ad-42c7-0729-08d41315cfc3 x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:AM5PR0802MB2609; nodisclaimer: True x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(180628864354917); x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(6060326)(6040307)(6045199)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046)(6055026)(6041248)(6061324)(6072148); SRVR:AM5PR0802MB2609; BCL:0; PCL:0; RULEID:; SRVR:AM5PR0802MB2609; x-forefront-prvs: 0134AD334F x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(6009001)(7916002)(54534003)(189002)(377424004)(199003)(7846002)(33656002)(50986999)(5660300001)(76176999)(8676002)(54356999)(2906002)(7736002)(305945005)(3846002)(4326007)(102836003)(6116002)(77096005)(66066001)(4001150100001)(3280700002)(97736004)(189998001)(92566002)(5640700001)(122556002)(2900100001)(106356001)(3660700001)(86362001)(74316002)(93886004)(105586002)(575784001)(106116001)(6916009)(9686002)(81166006)(101416001)(110136003)(7696004)(81156014)(2950100002)(38730400001)(76576001)(6506003)(8936002)(2501003)(68736007)(2351001); DIR:OUT; SFP:1101; SCL:1; SRVR:AM5PR0802MB2609; H:AM5PR0802MB2610.eurprd08.prod.outlook.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-originalarrivaltime: 22 Nov 2016 20:26:16.5036 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0802MB2609 As discussed in https://sourceware.org/ml/libc-alpha/2016-11/msg00625.html, there is no need to use a define to redirect to the GCC builtin as an optimization (other headers already ensure symbols are redirected if necessary to avoid name space clashes, for example when using non-C90 symbols). Remove all redundant redirects from string/bits/string2.h. The strncat define is redundant since _USE_STRING_ARCH_strchr is not defined for any target, except for x86 where it may be defined, but if it is, this redirect is then unused. Redirects are kept for __bzero and __stpcpy as these are used in a few places in GLIBC (and so using GCC builtins is a useful optimization) - when those uses have been changed, the redirects can be removed too. All unused _HAVE_STRING_ARCH_* defines are removed - this has no effect as they are defined but not used or used in a #ifndef but not defined. Verified no differences on AArch64 in all .so files in the install. ChangeLog: 2015-11-22 Wilco Dijkstra * string/string-inlines.c: Remove include of bits/string2.h. * string/bits/string2.h (__bzero): Always redirect to memset. (strchr) Remove define. (__stpcpy): Keep redirection for internal use. (stpcpy): Remove define. (strncpy): Likewise. (strncat): Likewise. (strcspn): Likewise. (strspn): Likewise. (strpbrk): Likewise. (_HAVE_STRING_ARCH_strdup): Likewise. * sysdeps/s390/bits/string.h (_HAVE_STRING_ARCH_strlen): Remove. (_HAVE_STRING_ARCH_strcpy): Likewise. (_HAVE_STRING_ARCH_strncpy): Likewise. (_HAVE_STRING_ARCH_strcat): Likewise. (_HAVE_STRING_ARCH_strncat): Likewise. (_HAVE_STRING_ARCH_memchr): Likewise. * sysdeps/sparc/bits/string.h (_HAVE_STRING_ARCH_strchr): Remove. * sysdeps/x86/bits/string.h (_HAVE_STRING_ARCH_memcpy): Remove. (_HAVE_STRING_ARCH_memmove): Likewise. (_HAVE_STRING_ARCH_memcmp): Likewise. (_HAVE_STRING_ARCH_memset): Likewise. (_USE_STRING_ARCH_memset): Likewise. (_HAVE_STRING_ARCH_memchr): Likewise. (_HAVE_STRING_ARCH_memrchr): Likewise. (_HAVE_STRING_ARCH_rawmemchr): Likewise. (_HAVE_STRING_ARCH_strlen): Likewise. (_HAVE_STRING_ARCH_strcpy): Likewise. (_HAVE_STRING_ARCH_strpcpy): Likewise. (_HAVE_STRING_ARCH_strncpy): Likewise. (_HAVE_STRING_ARCH_strncat): Likewise. (_HAVE_STRING_ARCH_strchr): Likewise. (_USE_STRING_ARCH_strchr): Likewise. (_HAVE_STRING_ARCH_strnchr): Likewise. (_HAVE_STRING_ARCH_strchrnul): Likewise. (_HAVE_STRING_ARCH_strrchr): Likewise. (_HAVE_STRING_ARCH_index): Likewise. (_HAVE_STRING_ARCH_rindex): Likewise. (_HAVE_STRING_ARCH_strcspn): Likewise. (_HAVE_STRING_ARCH_strspn): Likewise. (_HAVE_STRING_ARCH_strpbrk): Likewise. (_HAVE_STRING_ARCH_strstr): Likewise. (_HAVE_STRING_ARCH_ffs): Likewise. diff --git a/string/bits/string2.h b/string/bits/string2.h index c8799c5aeccc070f2a975fafa660d7814fa304cc..c2edfdc2feebe04d7aad41b1b79c8cb32c3c19c6 100644 --- a/string/bits/string2.h +++ b/string/bits/string2.h @@ -53,50 +53,13 @@ ((size_t)(const void *)((__x) + 1) - (size_t)(const void *)(__x) == 1) /* Set N bytes of S to 0. */ -#if !defined _HAVE_STRING_ARCH_memset -# define __bzero(s, n) __builtin_memset (s, '\0', n) -#endif - - -#ifndef _HAVE_STRING_ARCH_strchr -# define strchr(s, c) __builtin_strchr (s, c) -#endif - +#define __bzero(s, n) __builtin_memset (s, '\0', n) /* Copy SRC to DEST, returning pointer to final NUL byte. */ -#ifdef __USE_GNU -# ifndef _HAVE_STRING_ARCH_stpcpy -# define __stpcpy(dest, src) __builtin_stpcpy (dest, src) -/* In glibc we use this function frequently but for namespace reasons - we have to use the name `__stpcpy'. */ -# define stpcpy(dest, src) __stpcpy (dest, src) -# endif -#endif - - -/* Copy no more than N characters of SRC to DEST. */ -#ifndef _HAVE_STRING_ARCH_strncpy -# define strncpy(dest, src, n) __builtin_strncpy (dest, src, n) -#endif - - -/* Append no more than N characters from SRC onto DEST. */ -#ifndef _HAVE_STRING_ARCH_strncat -# ifdef _USE_STRING_ARCH_strchr -# define strncat(dest, src, n) \ - (__extension__ ({ char *__dest = (dest); \ - __builtin_constant_p (src) && __builtin_constant_p (n) \ - ? (strlen (src) < ((size_t) (n)) \ - ? strcat (__dest, src) \ - : (*((char *) __mempcpy (strchr (__dest, '\0'), \ - src, n)) = '\0', __dest)) \ - : strncat (dest, src, n); })) -# else -# define strncat(dest, src, n) __builtin_strncat (dest, src, n) -# endif +#ifndef __stpcpy +# define __stpcpy(dest, src) __builtin_stpcpy (dest, src) #endif - /* Compare characters of S1 and S2. */ #ifndef _HAVE_STRING_ARCH_strcmp # define strcmp(s1, s2) \ @@ -155,40 +118,16 @@ #endif -/* Return the length of the initial segment of S which - consists entirely of characters not in REJECT. */ -#ifndef _HAVE_STRING_ARCH_strcspn -# define strcspn(s, reject) __builtin_strcspn (s, reject) -#endif - - -/* Return the length of the initial segment of S which - consists entirely of characters in ACCEPT. */ -#ifndef _HAVE_STRING_ARCH_strspn -# define strspn(s, accept) __builtin_strspn (s, accept) -#endif - - -/* Find the first occurrence in S of any character in ACCEPT. */ -#ifndef _HAVE_STRING_ARCH_strpbrk -# define strpbrk(s, accept) __builtin_strpbrk (s, accept) -#endif - - /* We need the memory allocation functions for inline strdup(). Referring to stdlib.h (even minimally) is not allowed in any of the tight standards compliant modes. */ #ifdef __USE_MISC -# if !defined _HAVE_STRING_ARCH_strdup || !defined _HAVE_STRING_ARCH_strndup -# define __need_malloc_and_calloc -# include -# endif - -# ifndef _HAVE_STRING_ARCH_strdup +# define __need_malloc_and_calloc +# include extern char *__strdup (const char *__string) __THROW __attribute_malloc__; -# define __strdup(s) \ +# define __strdup(s) \ (__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \ ? (((const char *) (s))[0] == '\0' \ ? (char *) calloc ((size_t) 1, (size_t) 1) \ @@ -199,16 +138,14 @@ extern char *__strdup (const char *__string) __THROW __attribute_malloc__; __retval; })) \ : __strdup (s))) -# if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 -# define strdup(s) __strdup (s) -# endif +# if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8 +# define strdup(s) __strdup (s) # endif -# ifndef _HAVE_STRING_ARCH_strndup extern char *__strndup (const char *__string, size_t __n) __THROW __attribute_malloc__; -# define __strndup(s, n) \ +# define __strndup(s, n) \ (__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \ ? (((const char *) (s))[0] == '\0' \ ? (char *) calloc ((size_t) 1, (size_t) 1) \ @@ -227,9 +164,8 @@ extern char *__strndup (const char *__string, size_t __n) __retval; })) \ : __strndup (s, n))) -# ifdef __USE_XOPEN2K8 -# define strndup(s, n) __strndup (s, n) -# endif +# ifdef __USE_XOPEN2K8 +# define strndup(s, n) __strndup (s, n) # endif #endif /* Use misc. or use GNU. */ diff --git a/string/string-inlines.c b/string/string-inlines.c index 7b1de7180f8be3dca1515e23553a9ecbdc76f5e2..6d0c0c51b3027f99d26aace85523d7f337df8308 100644 --- a/string/string-inlines.c +++ b/string/string-inlines.c @@ -31,7 +31,6 @@ #undef __NO_INLINE__ #include -#include #include "shlib-compat.h" diff --git a/sysdeps/s390/bits/string.h b/sysdeps/s390/bits/string.h index 39e0b7fe7c7a100c7f4e2a3c13f815951815e854..a707ce8ce18d047d649b78dac4b8a360c4436199 100644 --- a/sysdeps/s390/bits/string.h +++ b/sysdeps/s390/bits/string.h @@ -37,7 +37,6 @@ # endif #endif -#define _HAVE_STRING_ARCH_strlen 1 #ifndef _FORCE_INLINES #define strlen(str) __strlen_g ((str)) @@ -60,7 +59,6 @@ __strlen_g (const char *__str) #endif /* Copy SRC to DEST. */ -#define _HAVE_STRING_ARCH_strcpy 1 #ifndef _FORCE_INLINES #define strcpy(dest, src) __strcpy_g ((dest), (src)) @@ -80,7 +78,6 @@ __strcpy_g (char *__dest, const char *__src) } #endif -#define _HAVE_STRING_ARCH_strncpy 1 #ifndef _FORCE_INLINES #define strncpy(dest, src, n) __strncpy_g ((dest), (src), (n)) @@ -124,7 +121,6 @@ __strncpy_g (char *__dest, const char *__src, size_t __n) #endif /* Append SRC onto DEST. */ -#define _HAVE_STRING_ARCH_strcat 1 #ifndef _FORCE_INLINES #define strcat(dest, src) __strcat_g ((dest), (src)) @@ -156,7 +152,6 @@ __strcat_g (char *__dest, const char *__src) #endif /* Append no more than N characters from SRC onto DEST. */ -#define _HAVE_STRING_ARCH_strncat 1 #ifndef _FORCE_INLINES #define strncat(dest, src, n) __strncat_g ((dest), (src), (n)) @@ -204,7 +199,6 @@ __strncat_g (char *__dest, const char *__src, size_t __n) #endif /* Search N bytes of S for C. */ -#define _HAVE_STRING_ARCH_memchr 1 #ifndef _FORCE_INLINES __STRING_INLINE void * memchr (const void *__str, int __c, size_t __n) diff --git a/sysdeps/sparc/bits/string.h b/sysdeps/sparc/bits/string.h index 10beca6a5a98cc126e39227cae5ff25a1ac09857..75a3eb31f3edc7109c360550c95d3d00402204a7 100644 --- a/sysdeps/sparc/bits/string.h +++ b/sysdeps/sparc/bits/string.h @@ -23,9 +23,5 @@ /* sparc uses the aligned string inline ABI. */ #define _STRING_INLINE_unaligned 0 -/* sparc32 and sparc64 strchr(x, '\0') perform better than - __rawmemchr(x, '\0'). */ -#define _HAVE_STRING_ARCH_strchr 1 - /* Don't inline mempcpy into memcpy as sparc has an optimized mempcpy. */ #define _HAVE_STRING_ARCH_mempcpy 1 diff --git a/sysdeps/x86/bits/string.h b/sysdeps/x86/bits/string.h index 805d33f0a2d13743e763e18c5c474c9507186a15..849ba9377498eb6f8d2218226dbfad6214e0fb35 100644 --- a/sysdeps/x86/bits/string.h +++ b/sysdeps/x86/bits/string.h @@ -66,7 +66,6 @@ /* Copy N bytes of SRC to DEST. */ -# define _HAVE_STRING_ARCH_memcpy 1 # define memcpy(dest, src, n) \ (__extension__ (__builtin_constant_p (n) \ ? __memcpy_c ((dest), (src), (n)) \ @@ -155,7 +154,6 @@ __memcpy_g (void *__dest, const void *__src, size_t __n) return __dest; } -# define _HAVE_STRING_ARCH_memmove 1 # ifndef _FORCE_INLINES /* Copy N bytes of SRC to DEST, guaranteeing correct behavior for overlapping strings. */ @@ -194,7 +192,6 @@ __memmove_g (void *__dest, const void *__src, size_t __n) # endif /* Compare N bytes of S1 and S2. */ -# define _HAVE_STRING_ARCH_memcmp 1 # ifndef _FORCE_INLINES # ifndef __PIC__ /* gcc has problems to spill registers when using PIC. */ @@ -222,8 +219,6 @@ memcmp (const void *__s1, const void *__s2, size_t __n) # endif /* Set N bytes of S to C. */ -# define _HAVE_STRING_ARCH_memset 1 -# define _USE_STRING_ARCH_memset 1 # define memset(s, c, n) \ (__extension__ (__builtin_constant_p (n) && (n) <= 16 \ ? ((n) == 1 \ @@ -449,7 +444,6 @@ __memset_gcn_by2 (void *__s, int __c, size_t __n) /* Search N bytes of S for C. */ -# define _HAVE_STRING_ARCH_memchr 1 # ifndef _FORCE_INLINES __STRING_INLINE void * memchr (const void *__s, int __c, size_t __n) @@ -486,7 +480,6 @@ memchr (const void *__s, int __c, size_t __n) } # endif -# define _HAVE_STRING_ARCH_memrchr 1 # ifndef _FORCE_INLINES __STRING_INLINE void *__memrchr (const void *__s, int __c, size_t __n); @@ -532,7 +525,6 @@ __memrchr (const void *__s, int __c, size_t __n) # endif /* Return pointer to C in S. */ -# define _HAVE_STRING_ARCH_rawmemchr 1 __STRING_INLINE void *__rawmemchr (const void *__s, int __c); # ifndef _FORCE_INLINES @@ -561,7 +553,6 @@ rawmemchr (const void *__s, int __c) /* Return the length of S. */ -# define _HAVE_STRING_ARCH_strlen 1 # define strlen(str) \ (__extension__ (__builtin_constant_p (str) \ ? __builtin_strlen (str) \ @@ -588,7 +579,6 @@ __strlen_g (const char *__str) /* Copy SRC to DEST. */ -# define _HAVE_STRING_ARCH_strcpy 1 # define strcpy(dest, src) \ (__extension__ (__builtin_constant_p (src) \ ? (sizeof ((src)[0]) == 1 && strlen (src) + 1 <= 8 \ @@ -673,7 +663,6 @@ __strcpy_g (char *__dest, const char *__src) # ifdef __USE_GNU -# define _HAVE_STRING_ARCH_stpcpy 1 /* Copy SRC to DEST. */ # define __stpcpy(dest, src) \ (__extension__ (__builtin_constant_p (src) \ @@ -848,7 +837,6 @@ __stpcpy_g (char *__dest, const char *__src) /* Copy no more than N characters of SRC to DEST. */ -# define _HAVE_STRING_ARCH_strncpy 1 # define strncpy(dest, src, n) \ (__extension__ (__builtin_constant_p (src) \ ? ((strlen (src) + 1 >= ((size_t) (n)) \ @@ -980,7 +968,6 @@ __strncpy_gg (char *__dest, const char *__src, size_t __n) /* Append SRC onto DEST. */ -# define _HAVE_STRING_ARCH_strcat 1 # define strcat(dest, src) \ (__extension__ (__builtin_constant_p (src) \ ? __strcat_c ((dest), (src), strlen (src) + 1) \ @@ -1051,7 +1038,6 @@ __strcat_g (char *__dest, const char *__src) /* Append no more than N characters from SRC onto DEST. */ -# define _HAVE_STRING_ARCH_strncat 1 # define strncat(dest, src, n) \ (__extension__ ({ char *__dest = (dest); \ __builtin_constant_p (src) && __builtin_constant_p (n) \ @@ -1263,8 +1249,6 @@ __strncmp_g (const char *__s1, const char *__s2, size_t __n) /* Find the first occurrence of C in S. */ -# define _HAVE_STRING_ARCH_strchr 1 -# define _USE_STRING_ARCH_strchr 1 # define strchr(s, c) \ (__extension__ (__builtin_constant_p (c) \ ? ((c) == '\0' \ @@ -1323,7 +1307,6 @@ __strchr_g (const char *__s, int __c) /* Find the first occurrence of C in S or the final NUL byte. */ -# define _HAVE_STRING_ARCH_strchrnul 1 # define __strchrnul(s, c) \ (__extension__ (__builtin_constant_p (c) \ ? ((c) == '\0' \ @@ -1386,7 +1369,6 @@ __strchrnul_g (const char *__s, int __c) # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED /* Find the first occurrence of C in S. This is the BSD name. */ -# define _HAVE_STRING_ARCH_index 1 # define index(s, c) \ (__extension__ (__builtin_constant_p (c) \ ? __strchr_c ((s), ((c) & 0xff) << 8) \ @@ -1395,7 +1377,6 @@ __strchrnul_g (const char *__s, int __c) /* Find the last occurrence of C in S. */ -# define _HAVE_STRING_ARCH_strrchr 1 # define strrchr(s, c) \ (__extension__ (__builtin_constant_p (c) \ ? __strrchr_c ((s), ((c) & 0xff) << 8) \ @@ -1500,7 +1481,6 @@ __strrchr_g (const char *__s, int __c) # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED /* Find the last occurrence of C in S. This is the BSD name. */ -# define _HAVE_STRING_ARCH_rindex 1 # define rindex(s, c) \ (__extension__ (__builtin_constant_p (c) \ ? __strrchr_c ((s), ((c) & 0xff) << 8) \ @@ -1510,7 +1490,6 @@ __strrchr_g (const char *__s, int __c) /* Return the length of the initial segment of S which consists entirely of characters not in REJECT. */ -# define _HAVE_STRING_ARCH_strcspn 1 # define strcspn(s, reject) \ (__extension__ (__builtin_constant_p (reject) && sizeof ((reject)[0]) == 1 \ ? ((reject)[0] == '\0' \ @@ -1631,7 +1610,6 @@ __strcspn_g (const char *__s, const char *__reject) /* Return the length of the initial segment of S which consists entirely of characters in ACCEPT. */ -# define _HAVE_STRING_ARCH_strspn 1 # define strspn(s, accept) \ (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \ ? ((accept)[0] == '\0' \ @@ -1751,7 +1729,6 @@ __strspn_g (const char *__s, const char *__accept) /* Find the first occurrence in S of any character in ACCEPT. */ -# define _HAVE_STRING_ARCH_strpbrk 1 # define strpbrk(s, accept) \ (__extension__ (__builtin_constant_p (accept) && sizeof ((accept)[0]) == 1 \ ? ((accept)[0] == '\0' \ @@ -1858,7 +1835,6 @@ __strpbrk_g (const char *__s, const char *__accept) /* Find the first occurrence of NEEDLE in HAYSTACK. */ -# define _HAVE_STRING_ARCH_strstr 1 # define strstr(haystack, needle) \ (__extension__ (__builtin_constant_p (needle) && sizeof ((needle)[0]) == 1 \ ? ((needle)[0] == '\0' \ @@ -1970,7 +1946,6 @@ __strstr_g (const char *__haystack, const char *__needle) processors gcc generates good code. */ # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED # ifdef __i686__ -# define _HAVE_STRING_ARCH_ffs 1 # define ffs(word) (__builtin_constant_p (word) \ ? __builtin_ffs (word) \ : ({ int __cnt, __tmp; \