Add GCC specific optimisation for log base 2 operations.
authorErik de Castro Lopo <erikd@mega-nerd.com>
Fri, 30 Mar 2012 10:55:08 +0000 (21:55 +1100)
committerErik de Castro Lopo <erikd@mega-nerd.com>
Fri, 30 Mar 2012 10:55:08 +0000 (21:55 +1100)
Based on a patch from Cristian Rodríguez.

src/libFLAC/bitmath.c
src/libFLAC/bitreader.c
src/libFLAC/include/private/bitmath.h

index 043bb49..189977c 100644 (file)
  * ilog2(17) = 4
  * ilog2(18) = 4
  */
+
+#ifndef __GNUC__
+
+/* For GNUC, use static inline version in include/private/bitmath.h. */
+
 unsigned FLAC__bitmath_ilog2(FLAC__uint32 v)
 {
-       unsigned l = 0;
-       FLAC__ASSERT(v > 0);
+       unsigned l = 0;
+    if (v == 0)
+               return 0;
        while(v >>= 1)
                l++;
        return l;
@@ -70,11 +76,13 @@ unsigned FLAC__bitmath_ilog2(FLAC__uint32 v)
 unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v)
 {
        unsigned l = 0;
-       FLAC__ASSERT(v > 0);
+    if (v == 0)
+               return 0;
        while(v >>= 1)
                l++;
        return l;
 }
+#endif
 
 /* An example of what FLAC__bitmath_silog2() computes:
  *
index c3edd16..ef24951 100644 (file)
@@ -55,14 +55,24 @@ typedef FLAC__uint32 brword;
 #else
 #define SWAP_BE_WORD_TO_HOST(x) ENDSWAP_32(x)
 #endif
+
+#if defined(__GNUC__)
+/*  "int __builtin_clz (unsigned int x) If x is 0, the result is undefined" */
+static inline uint32_t
+COUNT_ZERO_MSBS (uint32_t word)
+{
+       if (word == 0)
+               return 32;
+       return __builtin_clz (word);
+}
+#else
 /* counts the # of zero MSBs in a word */
 #define COUNT_ZERO_MSBS(word) ( \
        (word) <= 0xffff ? \
                ( (word) <= 0xff? byte_to_unary_table[word] + 24 : byte_to_unary_table[(word) >> 8] + 16 ) : \
                ( (word) <= 0xffffff? byte_to_unary_table[word >> 16] + 8 : byte_to_unary_table[(word) >> 24] ) \
 )
-/* this alternate might be slightly faster on some systems/compilers: */
-#define COUNT_ZERO_MSBS2(word) ( (word) <= 0xff ? byte_to_unary_table[word] + 24 : ((word) <= 0xffff ? byte_to_unary_table[(word) >> 8] + 16 : ((word) <= 0xffffff ? byte_to_unary_table[(word) >> 16] + 8 : byte_to_unary_table[(word) >> 24])) )
+#endif
 
 
 /*
index 67b70ba..b3d18f4 100644 (file)
 
 #include "FLAC/ordinals.h"
 
+
+#if defined(__GNUC__)
+
+static inline unsigned FLAC__bitmath_ilog2(FLAC__uint32 v)
+{
+    if (v == 0)
+               return 0;
+    return sizeof(FLAC__uint32) * __CHAR_BIT__  - 1 - __builtin_clz(v);
+}
+
+static inline unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v)
+{
+    if (v == 0)
+               return 0;
+    return sizeof(FLAC__uint64) * __CHAR_BIT__ - 1 - __builtin_clzll(v);
+}
+
+#else
+
 unsigned FLAC__bitmath_ilog2(FLAC__uint32 v);
 unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v);
+
+#endif
+
 unsigned FLAC__bitmath_silog2(int v);
 unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v);