Skip to content

Commit

Permalink
Use 'count leading zeros', if have it
Browse files Browse the repository at this point in the history
This changes two functions to use clz if available.  On platforms with
that instruction, the expansion is likely to just it and a subtract,
beating the deBruijn method previously used.

And if that instruction isn't present, the libc emulation is likely to
be as fast as possible, again beating the hand-rolled deBruijn method.
  • Loading branch information
khwilliamson committed Jun 14, 2021
1 parent 6fa9fa6 commit 8c8502f
Showing 1 changed file with 18 additions and 0 deletions.
18 changes: 18 additions & 0 deletions inline.h
Expand Up @@ -591,11 +591,19 @@ Perl_single_1bit_pos(PERL_UINTMAX_T word)
ASSUME(isPOWER_OF_2(word));
#endif

#ifdef PERL_USE_CLZ

return my_msbit_pos(word);

#else

/* The position of the only set bit in a word can be quickly calculated
* using deBruijn sequences. See for example
* https://en.wikipedia.org/wiki/De_Bruijn_sequence */
return PL_deBruijn_bitpos_tab[(word * PERL_deBruijnMagic_)
>> PERL_deBruijnShift_];
#endif

}

PERL_STATIC_INLINE unsigned
Expand All @@ -606,6 +614,13 @@ Perl_my_msbit_pos(PERL_UINTMAX_T word)

ASSUME(word != 0);

#ifdef PERL_USE_CLZ

/* First set bit is the complement of how many leading unset bits */
return (PERL_UINTMAX_SIZE * CHARBITS) - 1 - PERL_USE_CLZ(word);

#else

/* Isolate the msb; http://codeforces.com/blog/entry/10330
*
* Only the most significant set bit matters. Or'ing word with its right
Expand All @@ -630,6 +645,9 @@ Perl_my_msbit_pos(PERL_UINTMAX_T word)

/* Now we have a single bit set */
return single_1bit_pos(word);

#endif

}

PERL_STATIC_INLINE unsigned
Expand Down

0 comments on commit 8c8502f

Please sign in to comment.