From 4a96df73e770bcca6396d3c8ffe3fd1693c73e50 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Sun, 21 Sep 2014 17:25:49 -0700 Subject: [PATCH] mesa: Replace a priori knowledge of gcc builtins with configure tests. Presumbly this will let clang and other compilers use the built-ins as well. Notice two changes specifically: - in _mesa_next_pow_two_64(), always use __builtin_clzll and add a static assertion that this is safe. - in macros.h, remove the clang-specific definition since it should be able to detect __builtin_unreachable in configure. Reviewed-by: Jason Ekstrand [C bits] Reviewed-by: Ian Romanick --- configure.ac | 9 +++++ scons/gallium.py | 18 ++++++++++ src/mesa/drivers/dri/i965/brw_blorp_blit.cpp | 2 +- src/mesa/main/imports.c | 12 ++++--- src/mesa/main/imports.h | 35 +++++++++++--------- src/util/macros.h | 14 ++------ 6 files changed, 57 insertions(+), 33 deletions(-) diff --git a/configure.ac b/configure.ac index bad152800c7..db134a2f35b 100644 --- a/configure.ac +++ b/configure.ac @@ -130,6 +130,15 @@ fi dnl Check for compiler builtins AX_GCC_BUILTIN([__builtin_bswap32]) AX_GCC_BUILTIN([__builtin_bswap64]) +AX_GCC_BUILTIN([__builtin_clz]) +AX_GCC_BUILTIN([__builtin_clzll]) +AX_GCC_BUILTIN([__builtin_ctz]) +AX_GCC_BUILTIN([__builtin_expect]) +AX_GCC_BUILTIN([__builtin_ffs]) +AX_GCC_BUILTIN([__builtin_ffsll]) +AX_GCC_BUILTIN([__builtin_popcount]) +AX_GCC_BUILTIN([__builtin_popcountll]) +AX_GCC_BUILTIN([__builtin_unreachable]) AM_CONDITIONAL([GEN_ASM_OFFSETS], test "x$GEN_ASM_OFFSETS" = xyes) diff --git a/scons/gallium.py b/scons/gallium.py index 1dcfa6b243c..ef6df1ae1a9 100755 --- a/scons/gallium.py +++ b/scons/gallium.py @@ -583,6 +583,24 @@ def generate(env): env.Append(CCFLAGS = ['-fopenmp']) env.Append(LIBS = ['gomp']) + if gcc_compat: + ccversion = env['CCVERSION'] + cppdefines += [ + 'HAVE___BUILTIN_EXPECT', + 'HAVE___BUILTIN_FFS', + 'HAVE___BUILTIN_FFSLL', + ] + if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('3.4'): + cppdefines += [ + 'HAVE___BUILTIN_CTZ', + 'HAVE___BUILTIN_POPCOUNT', + 'HAVE___BUILTIN_POPCOUNTLL', + 'HAVE___BUILTIN_CLZ', + 'HAVE___BUILTIN_CLZLL', + ] + if distutils.version.LooseVersion(ccversion) >= distutils.version.LooseVersion('4.5'): + cppdefines += ['HAVE___BUILTIN_UNREACHABLE'] + # Load tools env.Tool('lex') env.Tool('yacc') diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp index 105acdd11b7..844f5e43029 100644 --- a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp +++ b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp @@ -1343,7 +1343,7 @@ brw_blorp_blit_program::single_to_blend() */ inline int count_trailing_one_bits(unsigned value) { -#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ +#ifdef HAVE___BUILTIN_CTZ return __builtin_ctz(~value); #else return _mesa_bitcount(value & ~(value + 1)); diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c index 2c2d11e35ac..b8c75481516 100644 --- a/src/mesa/main/imports.c +++ b/src/mesa/main/imports.c @@ -217,7 +217,7 @@ _mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize, /*@{*/ -#ifndef __GNUC__ +#ifndef HAVE___BUILTIN_FFS /** * Find the first bit set in a word. */ @@ -246,8 +246,9 @@ ffs(int i) } return bit; } +#endif - +#ifndef HAVE___BUILTIN_FFSLL /** * Find position of first bit set in given value. * XXX Warning: this function can only be used on 64-bit systems! @@ -271,11 +272,10 @@ ffsll(long long int val) return 0; } -#endif /* __GNUC__ */ +#endif -#if !defined(__GNUC__) ||\ - ((__GNUC__ * 100 + __GNUC_MINOR__) < 304) /* Not gcc 3.4 or later */ +#ifndef HAVE___BUILTIN_POPCOUNT /** * Return number of bits set in given GLuint. */ @@ -288,7 +288,9 @@ _mesa_bitcount(unsigned int n) } return bits; } +#endif +#ifndef HAVE___BUILTIN_POPCOUNTLL /** * Return number of bits set in given 64-bit uint. */ diff --git a/src/mesa/main/imports.h b/src/mesa/main/imports.h index 4cd2f3f3172..436d1651a82 100644 --- a/src/mesa/main/imports.h +++ b/src/mesa/main/imports.h @@ -377,8 +377,7 @@ _mesa_is_pow_two(int x) static inline int32_t _mesa_next_pow_two_32(uint32_t x) { -#if defined(__GNUC__) && \ - ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ +#ifdef HAVE___BUILTIN_CLZ uint32_t y = (x != 1); return (1 + y) << ((__builtin_clz(x - y) ^ 31) ); #else @@ -396,13 +395,10 @@ _mesa_next_pow_two_32(uint32_t x) static inline int64_t _mesa_next_pow_two_64(uint64_t x) { -#if defined(__GNUC__) && \ - ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ +#ifdef HAVE___BUILTIN_CLZLL uint64_t y = (x != 1); - if (sizeof(x) == sizeof(long)) - return (1 + y) << ((__builtin_clzl(x - y) ^ 63)); - else - return (1 + y) << ((__builtin_clzll(x - y) ^ 63)); + STATIC_ASSERT(sizeof(x) == sizeof(long long)); + return (1 + y) << ((__builtin_clzll(x - y) ^ 63)); #else x--; x |= x >> 1; @@ -423,8 +419,7 @@ _mesa_next_pow_two_64(uint64_t x) static inline GLuint _mesa_logbase2(GLuint n) { -#if defined(__GNUC__) && \ - ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ +#ifdef HAVE___BUILTIN_CLZ return (31 - __builtin_clz(n | 1)); #else GLuint pos = 0; @@ -476,22 +471,30 @@ _mesa_exec_free( void *addr ); #ifndef FFS_DEFINED #define FFS_DEFINED 1 -#ifdef __GNUC__ +#ifdef HAVE___BUILTIN_FFS #define ffs __builtin_ffs -#define ffsll __builtin_ffsll #else extern int ffs(int i); +#endif + +#ifdef HAVE___BUILTIN_FFSLL +#define ffsll __builtin_ffsll +#else extern int ffsll(long long int i); -#endif /*__ GNUC__ */ +#endif #endif /* FFS_DEFINED */ -#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */ +#ifdef HAVE___BUILTIN_POPCOUNT #define _mesa_bitcount(i) __builtin_popcount(i) -#define _mesa_bitcount_64(i) __builtin_popcountll(i) #else extern unsigned int _mesa_bitcount(unsigned int n); +#endif + +#ifdef HAVE___BUILTIN_POPCOUNTLL +#define _mesa_bitcount_64(i) __builtin_popcountll(i) +#else extern unsigned int _mesa_bitcount_64(uint64_t n); #endif @@ -504,7 +507,7 @@ _mesa_bitcount_64(uint64_t n); static inline unsigned int _mesa_fls(unsigned int n) { -#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) +#ifdef HAVE___BUILTIN_CLZ return n == 0 ? 0 : 32 - __builtin_clz(n); #else unsigned int v = 1; diff --git a/src/util/macros.h b/src/util/macros.h index ee05e05a4a8..2e2f90f587c 100644 --- a/src/util/macros.h +++ b/src/util/macros.h @@ -33,12 +33,12 @@ /** * __builtin_expect macros */ -#if !defined(__GNUC__) +#if !defined(HAVE___BUILTIN_EXPECT) # define __builtin_expect(x, y) (x) #endif #ifndef likely -# ifdef __GNUC__ +# ifdef HAVE___BUILTIN_EXPECT # define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __builtin_expect(!!(x), 0) # else @@ -63,20 +63,12 @@ * Unreachable macro. Useful for suppressing "control reaches end of non-void * function" warnings. */ -#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 5 +#ifdef HAVE___BUILTIN_UNREACHABLE #define unreachable(str) \ do { \ assert(!str); \ __builtin_unreachable(); \ } while (0) -#elif (defined(__clang__) && defined(__has_builtin)) -# if __has_builtin(__builtin_unreachable) -# define unreachable(str) \ -do { \ - assert(!str); \ - __builtin_unreachable(); \ -} while (0) -# endif #endif #ifndef unreachable -- 2.30.2