configure: check for __builtin_bswapXX()

defines HAVE_BUILTIN_BSWAP16/32/64
updated endian_inl.h to have a non-configure fallback for gcc and clang
BSwap16() now uses __builtin_bswap16 if available

Change-Id: Ia04ee07b39303c4b247df96d84f298fb8a81f389
This commit is contained in:
James Zern 2014-07-04 16:56:41 -07:00
parent 6422e683af
commit 6781423b7d
2 changed files with 50 additions and 11 deletions

View File

@ -112,6 +112,26 @@ AC_DEFUN([LIBCHECK_EPILOGUE],
CPPFLAGS=$SAVED_CPPFLAGS
LIBS=$SAVED_LIBS])
dnl === Check for gcc builtins
dnl === CHECK_FOR_BUILTIN([builtin], [param], [define])
dnl === links a C AC_LANG_PROGRAM, with <builtin>(<param>)
dnl === AC_DEFINE'ing <define> if successful.
AC_DEFUN([CHECK_FOR_BUILTIN],
[AC_LANG_PUSH([C])
AC_MSG_CHECKING([for $1])
AC_LINK_IFELSE([AC_LANG_PROGRAM([], [$1($2)])],
[AC_MSG_RESULT([yes])
AC_DEFINE([$3], [1],
[Set to 1 if $1 is available])],
[AC_MSG_RESULT([no])]),
AC_LANG_POP])
dnl AC_CHECK_FUNC doesn't work with builtin's.
CHECK_FOR_BUILTIN([__builtin_bswap16], [1u << 15], [HAVE_BUILTIN_BSWAP16])
CHECK_FOR_BUILTIN([__builtin_bswap32], [1u << 31], [HAVE_BUILTIN_BSWAP32])
CHECK_FOR_BUILTIN([__builtin_bswap64], [1ull << 63], [HAVE_BUILTIN_BSWAP64])
dnl === Check for pthread support
AC_ARG_ENABLE([threading],
AS_HELP_STRING([--disable-threading],

View File

@ -33,24 +33,43 @@
#define HToLE16(x) (x)
#endif
// gcc 4.3 has builtin functions for swap32/swap64
// TODO(jzern): this should have a corresponding autoconf check.
#if defined(__GNUC__) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
#define HAVE_BUILTIN_BSWAP
#if !defined(HAVE_CONFIG_H)
#ifdef __GNUC__
# define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
#else
# define LOCAL_GCC_VERSION 0
#endif // __GNUC__
#ifdef __clang__
# define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__)
#else
# define LOCAL_CLANG_VERSION 0
#endif // __clang__
// clang-3.3 and gcc-4.3 have builtin functions for swap32/swap64
#if LOCAL_GCC_VERSION >= 0x403 || LOCAL_CLANG_VERSION >= 0x303
#define HAVE_BUILTIN_BSWAP32
#define HAVE_BUILTIN_BSWAP64
#endif
// clang-3.3 and gcc-4.8 have a builtin function for swap16
#if LOCAL_GCC_VERSION >= 0x408 || LOCAL_CLANG_VERSION >= 0x303
#define HAVE_BUILTIN_BSWAP16
#endif
#endif // !HAVE_CONFIG_H
static WEBP_INLINE uint16_t BSwap16(uint16_t x) {
#if defined(_MSC_VER)
#if defined(HAVE_BUILTIN_BSWAP16)
return __builtin_bswap16(x);
#elif defined(_MSC_VER)
return _byteswap_ushort(x);
#else
// gcc will recognize a 'rorw $8, ...' here:
return (x >> 8) | ((x & 0xff) << 8);
#endif // _MSC_VER
#endif // HAVE_BUILTIN_BSWAP16
}
static WEBP_INLINE uint32_t BSwap32(uint32_t x) {
#if defined(HAVE_BUILTIN_BSWAP)
#if defined(HAVE_BUILTIN_BSWAP32)
return __builtin_bswap32(x);
#elif defined(__i386__) || defined(__x86_64__)
uint32_t swapped_bytes;
@ -60,11 +79,11 @@ static WEBP_INLINE uint32_t BSwap32(uint32_t x) {
return (uint32_t)_byteswap_ulong(x);
#else
return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
#endif // HAVE_BUILTIN_BSWAP
#endif // HAVE_BUILTIN_BSWAP32
}
static WEBP_INLINE uint64_t BSwap64(uint64_t x) {
#if defined(HAVE_BUILTIN_BSWAP)
#if defined(HAVE_BUILTIN_BSWAP64)
return __builtin_bswap64(x);
#elif defined(__x86_64__)
uint64_t swapped_bytes;
@ -77,7 +96,7 @@ static WEBP_INLINE uint64_t BSwap64(uint64_t x) {
x = ((x & 0xffff0000ffff0000ull) >> 16) | ((x & 0x0000ffff0000ffffull) << 16);
x = ((x & 0xff00ff00ff00ff00ull) >> 8) | ((x & 0x00ff00ff00ff00ffull) << 8);
return x;
#endif // HAVE_BUILTIN_BSWAP
#endif // HAVE_BUILTIN_BSWAP64
}
#endif // WEBP_UTILS_ENDIAN_INL_H_