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 <jason.ekstrand@intel.com> [C bits]
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Matt Turner
2014-09-21 17:25:49 -07:00
parent 3e00822619
commit 4a96df73e7
6 changed files with 57 additions and 33 deletions

View File

@@ -130,6 +130,15 @@ fi
dnl Check for compiler builtins dnl Check for compiler builtins
AX_GCC_BUILTIN([__builtin_bswap32]) AX_GCC_BUILTIN([__builtin_bswap32])
AX_GCC_BUILTIN([__builtin_bswap64]) 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) AM_CONDITIONAL([GEN_ASM_OFFSETS], test "x$GEN_ASM_OFFSETS" = xyes)

View File

@@ -583,6 +583,24 @@ def generate(env):
env.Append(CCFLAGS = ['-fopenmp']) env.Append(CCFLAGS = ['-fopenmp'])
env.Append(LIBS = ['gomp']) 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 # Load tools
env.Tool('lex') env.Tool('lex')
env.Tool('yacc') env.Tool('yacc')

View File

@@ -1343,7 +1343,7 @@ brw_blorp_blit_program::single_to_blend()
*/ */
inline int count_trailing_one_bits(unsigned value) 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); return __builtin_ctz(~value);
#else #else
return _mesa_bitcount(value & ~(value + 1)); return _mesa_bitcount(value & ~(value + 1));

View File

@@ -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. * Find the first bit set in a word.
*/ */
@@ -246,8 +246,9 @@ ffs(int i)
} }
return bit; return bit;
} }
#endif
#ifndef HAVE___BUILTIN_FFSLL
/** /**
* Find position of first bit set in given value. * Find position of first bit set in given value.
* XXX Warning: this function can only be used on 64-bit systems! * XXX Warning: this function can only be used on 64-bit systems!
@@ -271,11 +272,10 @@ ffsll(long long int val)
return 0; return 0;
} }
#endif /* __GNUC__ */ #endif
#if !defined(__GNUC__) ||\ #ifndef HAVE___BUILTIN_POPCOUNT
((__GNUC__ * 100 + __GNUC_MINOR__) < 304) /* Not gcc 3.4 or later */
/** /**
* Return number of bits set in given GLuint. * Return number of bits set in given GLuint.
*/ */
@@ -288,7 +288,9 @@ _mesa_bitcount(unsigned int n)
} }
return bits; return bits;
} }
#endif
#ifndef HAVE___BUILTIN_POPCOUNTLL
/** /**
* Return number of bits set in given 64-bit uint. * Return number of bits set in given 64-bit uint.
*/ */

View File

@@ -377,8 +377,7 @@ _mesa_is_pow_two(int x)
static inline int32_t static inline int32_t
_mesa_next_pow_two_32(uint32_t x) _mesa_next_pow_two_32(uint32_t x)
{ {
#if defined(__GNUC__) && \ #ifdef HAVE___BUILTIN_CLZ
((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */
uint32_t y = (x != 1); uint32_t y = (x != 1);
return (1 + y) << ((__builtin_clz(x - y) ^ 31) ); return (1 + y) << ((__builtin_clz(x - y) ^ 31) );
#else #else
@@ -396,13 +395,10 @@ _mesa_next_pow_two_32(uint32_t x)
static inline int64_t static inline int64_t
_mesa_next_pow_two_64(uint64_t x) _mesa_next_pow_two_64(uint64_t x)
{ {
#if defined(__GNUC__) && \ #ifdef HAVE___BUILTIN_CLZLL
((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */
uint64_t y = (x != 1); uint64_t y = (x != 1);
if (sizeof(x) == sizeof(long)) STATIC_ASSERT(sizeof(x) == sizeof(long long));
return (1 + y) << ((__builtin_clzl(x - y) ^ 63)); return (1 + y) << ((__builtin_clzll(x - y) ^ 63));
else
return (1 + y) << ((__builtin_clzll(x - y) ^ 63));
#else #else
x--; x--;
x |= x >> 1; x |= x >> 1;
@@ -423,8 +419,7 @@ _mesa_next_pow_two_64(uint64_t x)
static inline GLuint static inline GLuint
_mesa_logbase2(GLuint n) _mesa_logbase2(GLuint n)
{ {
#if defined(__GNUC__) && \ #ifdef HAVE___BUILTIN_CLZ
((__GNUC__ * 100 + __GNUC_MINOR__) >= 304) /* gcc 3.4 or later */
return (31 - __builtin_clz(n | 1)); return (31 - __builtin_clz(n | 1));
#else #else
GLuint pos = 0; GLuint pos = 0;
@@ -476,22 +471,30 @@ _mesa_exec_free( void *addr );
#ifndef FFS_DEFINED #ifndef FFS_DEFINED
#define FFS_DEFINED 1 #define FFS_DEFINED 1
#ifdef __GNUC__ #ifdef HAVE___BUILTIN_FFS
#define ffs __builtin_ffs #define ffs __builtin_ffs
#define ffsll __builtin_ffsll
#else #else
extern int ffs(int i); extern int ffs(int i);
#endif
#ifdef HAVE___BUILTIN_FFSLL
#define ffsll __builtin_ffsll
#else
extern int ffsll(long long int i); extern int ffsll(long long int i);
#endif /*__ GNUC__ */ #endif
#endif /* FFS_DEFINED */ #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(i) __builtin_popcount(i)
#define _mesa_bitcount_64(i) __builtin_popcountll(i)
#else #else
extern unsigned int extern unsigned int
_mesa_bitcount(unsigned int n); _mesa_bitcount(unsigned int n);
#endif
#ifdef HAVE___BUILTIN_POPCOUNTLL
#define _mesa_bitcount_64(i) __builtin_popcountll(i)
#else
extern unsigned int extern unsigned int
_mesa_bitcount_64(uint64_t n); _mesa_bitcount_64(uint64_t n);
#endif #endif
@@ -504,7 +507,7 @@ _mesa_bitcount_64(uint64_t n);
static inline unsigned int static inline unsigned int
_mesa_fls(unsigned int n) _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); return n == 0 ? 0 : 32 - __builtin_clz(n);
#else #else
unsigned int v = 1; unsigned int v = 1;

View File

@@ -33,12 +33,12 @@
/** /**
* __builtin_expect macros * __builtin_expect macros
*/ */
#if !defined(__GNUC__) #if !defined(HAVE___BUILTIN_EXPECT)
# define __builtin_expect(x, y) (x) # define __builtin_expect(x, y) (x)
#endif #endif
#ifndef likely #ifndef likely
# ifdef __GNUC__ # ifdef HAVE___BUILTIN_EXPECT
# define likely(x) __builtin_expect(!!(x), 1) # define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0) # define unlikely(x) __builtin_expect(!!(x), 0)
# else # else
@@ -63,20 +63,12 @@
* Unreachable macro. Useful for suppressing "control reaches end of non-void * Unreachable macro. Useful for suppressing "control reaches end of non-void
* function" warnings. * function" warnings.
*/ */
#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 5 #ifdef HAVE___BUILTIN_UNREACHABLE
#define unreachable(str) \ #define unreachable(str) \
do { \ do { \
assert(!str); \ assert(!str); \
__builtin_unreachable(); \ __builtin_unreachable(); \
} while (0) } 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 #endif
#ifndef unreachable #ifndef unreachable