1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 17:32:44 +01:00

core/bitarithm: use __builtin_clz() for bitarithm_msb()

The `clz` instruction pretty much implements getting the most significant bit
in hardware, so use it instead of the software implementation.

This reults in both a reduction in code size as in a speedup:

master:

  text    data     bss     dec     hex filename
 14816     136    2424   17376    43e0 tests/bitarithm_timings/bin/same54-xpro/tests_bitarithm_timings.elf

 + bitarithm_msb: 3529411 iterations per second

this patch:

  text    data     bss     dec     hex filename
 14768     136    2424   17328    43b0 tests/bitarithm_timings/bin/same54-xpro/tests_bitarithm_timings.elf

 + bitarithm_msb: 9230761 iterations per second
This commit is contained in:
Benjamin Valentin 2020-08-04 15:06:07 +02:00
parent 52bf3096cf
commit 14144030fa
2 changed files with 27 additions and 11 deletions

View File

@ -23,11 +23,9 @@
#include "bitarithm.h" #include "bitarithm.h"
unsigned bitarithm_msb(unsigned v) unsigned bitarith_msb_32bit_no_native_clz(unsigned v)
{ {
register unsigned r; /* result of log2(v) will go here */ register unsigned r; /* result of log2(v) will go here */
#if ARCH_32_BIT
register unsigned shift; register unsigned shift;
/* begin{code-style-ignore} */ /* begin{code-style-ignore} */
@ -37,13 +35,6 @@ unsigned bitarithm_msb(unsigned v)
shift = (v > 0x3 ) << 1; v >>= shift; r |= shift; shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
r |= (v >> 1); r |= (v >> 1);
/* end{code-style-ignore} */ /* end{code-style-ignore} */
#else
r = 0;
while (v >>= 1) { /* unroll for more speed... */
r++;
}
#endif
return r; return r;
} }

View File

@ -102,7 +102,7 @@ extern "C" {
* *
* Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious * Source: http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
*/ */
unsigned bitarithm_msb(unsigned v); static inline unsigned bitarithm_msb(unsigned v);
/** /**
* @brief Returns the number of the lowest '1' bit in a value * @brief Returns the number of the lowest '1' bit in a value
@ -136,8 +136,33 @@ static inline uint8_t bitarithm_bits_set_u32(uint32_t v)
uint8_t bitarithm_bits_set_u32(uint32_t v); uint8_t bitarithm_bits_set_u32(uint32_t v);
#endif #endif
/**
* @brief Returns the number of the highest '1' bit in a value
*
* Internal software implementation for 32 bit platforms,
* use @see bitarithm_msb in application code.
* @param[in] v Input value
* @return Bit Number
*/
unsigned bitarith_msb_32bit_no_native_clz(unsigned v);
/* implementations */ /* implementations */
static inline unsigned bitarithm_msb(unsigned v)
{
#if defined(BITARITHM_HAS_CLZ)
return 8 * sizeof(v) - __builtin_clz(v) - 1;
#elif ARCH_32_BIT
return bitarith_msb_32bit_no_native_clz(v);
#else
unsigned r = 0;
while (v >>= 1) { /* unroll for more speed... */
++r;
}
return r;
#endif
}
static inline unsigned bitarithm_lsb(unsigned v) static inline unsigned bitarithm_lsb(unsigned v)
#if defined(BITARITHM_LSB_BUILTIN) #if defined(BITARITHM_LSB_BUILTIN)
{ {