Skip to content

Commit

Permalink
Create and use single_1bit_pos32()
Browse files Browse the repository at this point in the history
This moves the code from regcomp.c to inline.h that calculates the
position of the lone set bit in a U32.  This is in preparation for use
by other call sites.
  • Loading branch information
khwilliamson committed Jul 23, 2021
1 parent dab96fc commit 8ca9ebc
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 10 deletions.
1 change: 1 addition & 0 deletions embed.fnc
Expand Up @@ -1141,6 +1141,7 @@ ATdmoR |bool |is_utf8_invariant_string|NN const U8* const s \
ATidRp |bool |is_utf8_invariant_string_loc|NN const U8* const s \
|STRLEN len \
|NULLOK const U8 ** ep
CTiRp |unsigned|single_1bit_pos32|U32 word
#ifndef EBCDIC
CTiRp |unsigned int|variant_byte_number|PERL_UINTMAX_T word
#endif
Expand Down
1 change: 1 addition & 0 deletions embed.h
Expand Up @@ -561,6 +561,7 @@
#define set_context Perl_set_context
#define setdefout(a) Perl_setdefout(aTHX_ a)
#define share_hek(a,b,c) Perl_share_hek(aTHX_ a,b,c)
#define single_1bit_pos32 Perl_single_1bit_pos32
#define sortsv(a,b,c) Perl_sortsv(aTHX_ a,b,c)
#define sortsv_flags(a,b,c,d) Perl_sortsv_flags(aTHX_ a,b,c,d)
#define stack_grow(a,b,c) Perl_stack_grow(aTHX_ a,b,c)
Expand Down
1 change: 1 addition & 0 deletions globvar.sym
Expand Up @@ -12,6 +12,7 @@ PL_c9_utf8_dfa_tab
PL_charclass
PL_check
PL_core_reg_engine
PL_deBruijn_bitpos_tab32
PL_EXACTFish_bitmask
PL_EXACT_REQ8_bitmask
PL_extended_utf8_dfa_tab
Expand Down
19 changes: 19 additions & 0 deletions inline.h
Expand Up @@ -664,6 +664,25 @@ Perl_is_utf8_invariant_string_loc(const U8* const s, STRLEN len, const U8 ** ep)
return TRUE;
}

PERL_STATIC_INLINE unsigned
Perl_single_1bit_pos32(U32 word)
{
/* Given a 32-bit word known to contain all zero bits except one 1 bit,
* find and return the 1's position: 0..31 */

#ifdef PERL_CORE /* macro not exported */
ASSUME(isPOWER_OF_2(word));
#else
ASSUME(word && (word & (word-1)) == 0);
#endif

/* 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_tab32[(word * PERL_deBruijnMagic32_)
>> PERL_deBruijnShift32_];
}

#ifndef EBCDIC

PERL_STATIC_INLINE unsigned int
Expand Down
12 changes: 12 additions & 0 deletions perl.h
Expand Up @@ -5842,6 +5842,13 @@ PL_valid_types_IV_set[] = { 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1 };
EXTCONST bool
PL_valid_types_NV_set[] = { 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };

EXTCONST U8
PL_deBruijn_bitpos_tab32[] = {
/* https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn */
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};

#else

EXTCONST bool PL_valid_types_IVX[];
Expand All @@ -5850,9 +5857,14 @@ EXTCONST bool PL_valid_types_PVX[];
EXTCONST bool PL_valid_types_RV[];
EXTCONST bool PL_valid_types_IV_set[];
EXTCONST bool PL_valid_types_NV_set[];
EXTCONST U8 PL_deBruijn_bitpos_tab32[];

#endif

/* The constants for using PL_deBruijn_bitpos_tab */
#define PERL_deBruijnMagic32_ 0x077CB531
#define PERL_deBruijnShift32_ 27

/* In C99 we could use designated (named field) union initializers.
* In C89 we need to initialize the member declared first.
* In C++ we need extern C initializers.
Expand Down
6 changes: 6 additions & 0 deletions proto.h
Expand Up @@ -3246,6 +3246,12 @@ PERL_CALLCONV Signal_t Perl_sighandler1(int sig);
#define PERL_ARGS_ASSERT_SIGHANDLER1
PERL_CALLCONV Signal_t Perl_sighandler3(int sig, Siginfo_t *info, void *uap);
#define PERL_ARGS_ASSERT_SIGHANDLER3
#ifndef PERL_NO_INLINE_FUNCTIONS
PERL_STATIC_INLINE unsigned Perl_single_1bit_pos32(U32 word)
__attribute__warn_unused_result__;
#define PERL_ARGS_ASSERT_SINGLE_1BIT_POS32
#endif

PERL_CALLCONV char* Perl_skipspace_flags(pTHX_ char *s, U32 flags)
__attribute__warn_unused_result__;
#define PERL_ARGS_ASSERT_SKIPSPACE_FLAGS \
Expand Down
11 changes: 1 addition & 10 deletions regcomp.c
Expand Up @@ -19398,17 +19398,8 @@ S_optimize_regclass(pTHX_
bool already_inverted;
bool are_equivalent;

/* Compute which bit is set, which is the same thing as, e.g.,
* ANYOF_CNTRL. From
* https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
* */
static const int MultiplyDeBruijnBitPosition2[32] = {
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
};

namedclass = MultiplyDeBruijnBitPosition2[(posixl
* 0x077CB531U) >> 27];
namedclass = single_1bit_pos32(posixl);
classnum = namedclass_to_classnum(namedclass);

/* The named classes are such that the inverted number is one
Expand Down

0 comments on commit 8ca9ebc

Please sign in to comment.