gnulib: import count-one-bits module and use it

For a fix I intend to submit, I would need a function that counts the
number of set bits in a word.  There is  __builtin_popcount that is
supported by gcc and clang, but there is also a gnulib module that wraps
that and provides a fallback for other compilers, so I think it would be
good to use it.

I also noticed that there is a bitcount function in arch/arm.c, so I
thought that as a first step I would replace that one with the gnulib
count-one-bits module.  This is what this patch does.

The gnulib module provides multiple functions, with various parameter
length (unsigned int, unsigned long int, unsigned long long int), I
chose the one that made sense for each call site based on the argument
type.

gnulib/ChangeLog:

	* update-gnulib.sh (IMPORTED_GNULIB_MODULES): Import
	count-one-bits module.
	* configure: Re-generate.
	* aclocal.m4: Re-generate.
	* Makefile.in: Re-generate.
	* import/count-one-bits.c: New file.
	* import/count-one-bits.h: New file.
	* import/Makefile.am: Re-generate.
	* import/Makefile.in: Re-generate.
	* import/m4/gnulib-cache.m4: Re-generate.
	* import/m4/gnulib-comp.m4: Re-generate.
	* import/m4/count-one-bits.m4: New file.

gdb/ChangeLog:

	* arm-tdep.c: Include count-one-bits.h.
	(cleanup_block_store_pc): Use count_one_bits.
	(cleanup_block_load_pc): Use count_one_bits.
	(arm_copy_block_xfer): Use count_one_bits.
	(thumb2_copy_block_xfer): Use count_one_bits.
	(thumb_copy_pop_pc_16bit): Use count_one_bits.
	* arch/arm-get-next-pcs.c: Include count-one-bits.h.
	(thumb_get_next_pcs_raw): Use count_one_bits.
	(arm_get_next_pcs_raw): Use count_one_bits_l.
	* arch/arm.c (bitcount): Remove.
	* arch/arm.h (bitcount): Remove.
This commit is contained in:
Simon Marchi 2020-02-14 14:41:07 -05:00
parent 8084e579e1
commit 5f661e0397
17 changed files with 303 additions and 103 deletions

View File

@ -1,3 +1,17 @@
2020-02-14 Simon Marchi <simon.marchi@efficios.com>
* arm-tdep.c: Include count-one-bits.h.
(cleanup_block_store_pc): Use count_one_bits.
(cleanup_block_load_pc): Use count_one_bits.
(arm_copy_block_xfer): Use count_one_bits.
(thumb2_copy_block_xfer): Use count_one_bits.
(thumb_copy_pop_pc_16bit): Use count_one_bits.
* arch/arm-get-next-pcs.c: Include count-one-bits.h.
(thumb_get_next_pcs_raw): Use count_one_bits.
(arm_get_next_pcs_raw): Use count_one_bits_l.
* arch/arm.c (bitcount): Remove.
* arch/arm.h (bitcount): Remove.
2020-02-14 Tom Tromey <tromey@adacore.com>
* dwarf2/frame-tailcall.c (dwarf2_tailcall_sniffer_first):

View File

@ -22,6 +22,7 @@
#include "gdbsupport/common-regcache.h"
#include "arm.h"
#include "arm-get-next-pcs.h"
#include "count-one-bits.h"
/* See arm-get-next-pcs.h. */
@ -408,8 +409,8 @@ thumb_get_next_pcs_raw (struct arm_get_next_pcs *self)
/* Fetch the saved PC from the stack. It's stored above
all of the other registers. */
unsigned long offset = bitcount (bits (inst1, 0, 7))
* ARM_INT_REGISTER_SIZE;
unsigned long offset
= count_one_bits (bits (inst1, 0, 7)) * ARM_INT_REGISTER_SIZE;
sp = regcache_raw_get_unsigned (regcache, ARM_SP_REGNUM);
nextpc = self->ops->read_mem_uint (sp + offset, 4, byte_order);
}
@ -496,7 +497,7 @@ thumb_get_next_pcs_raw (struct arm_get_next_pcs *self)
/* LDMIA or POP */
if (!bit (inst2, 15))
load_pc = 0;
offset = bitcount (inst2) * 4 - 4;
offset = count_one_bits (inst2) * 4 - 4;
}
else if (!bit (inst1, 7) && bit (inst1, 8))
{
@ -864,7 +865,7 @@ arm_get_next_pcs_raw (struct arm_get_next_pcs *self)
{
/* up */
unsigned long reglist = bits (this_instr, 0, 14);
offset = bitcount (reglist) * 4;
offset = count_one_bits_l (reglist) * 4;
if (bit (this_instr, 24)) /* pre */
offset += 4;
}

View File

@ -41,17 +41,6 @@ thumb_insn_size (unsigned short inst1)
/* See arm.h. */
int
bitcount (unsigned long val)
{
int nbits;
for (nbits = 0; val != 0; nbits++)
val &= val - 1; /* Delete rightmost 1-bit in val. */
return nbits;
}
/* See arm.h. */
int
condition_true (unsigned long cond, unsigned long status_reg)
{

View File

@ -160,9 +160,6 @@ int thumb_insn_size (unsigned short inst1);
/* Returns true if the condition evaluates to true. */
int condition_true (unsigned long cond, unsigned long status_reg);
/* Return number of 1-bits in VAL. */
int bitcount (unsigned long val);
/* Return 1 if THIS_INSTR might change control flow, 0 otherwise. */
int arm_instruction_changes_pc (uint32_t this_instr);

View File

@ -45,6 +45,7 @@
#include "target-descriptions.h"
#include "user-regs.h"
#include "observable.h"
#include "count-one-bits.h"
#include "arch/arm.h"
#include "arch/arm-get-next-pcs.h"
@ -5798,7 +5799,8 @@ cleanup_block_store_pc (struct gdbarch *gdbarch, struct regcache *regs,
{
uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int store_executed = condition_true (dsc->u.block.cond, status);
CORE_ADDR pc_stored_at, transferred_regs = bitcount (dsc->u.block.regmask);
CORE_ADDR pc_stored_at, transferred_regs
= count_one_bits (dsc->u.block.regmask);
CORE_ADDR stm_insn_addr;
uint32_t pc_val;
long offset;
@ -5850,7 +5852,7 @@ cleanup_block_load_pc (struct gdbarch *gdbarch,
uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
int load_executed = condition_true (dsc->u.block.cond, status);
unsigned int mask = dsc->u.block.regmask, write_reg = ARM_PC_REGNUM;
unsigned int regs_loaded = bitcount (mask);
unsigned int regs_loaded = count_one_bits (mask);
unsigned int num_to_shuffle = regs_loaded, clobbered;
/* The method employed here will fail if the register list is fully populated
@ -5982,7 +5984,7 @@ arm_copy_block_xfer (struct gdbarch *gdbarch, uint32_t insn,
contiguous chunk r0...rX before doing the transfer, then shuffling
registers into the correct places in the cleanup routine. */
unsigned int regmask = insn & 0xffff;
unsigned int num_in_list = bitcount (regmask), new_regmask;
unsigned int num_in_list = count_one_bits (regmask), new_regmask;
unsigned int i;
for (i = 0; i < num_in_list; i++)
@ -6084,7 +6086,7 @@ thumb2_copy_block_xfer (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
else
{
unsigned int regmask = dsc->u.block.regmask;
unsigned int num_in_list = bitcount (regmask), new_regmask;
unsigned int num_in_list = count_one_bits (regmask), new_regmask;
unsigned int i;
for (i = 0; i < num_in_list; i++)
@ -7102,7 +7104,7 @@ thumb_copy_pop_pc_16bit (struct gdbarch *gdbarch, uint16_t insn1,
}
else
{
unsigned int num_in_list = bitcount (dsc->u.block.regmask);
unsigned int num_in_list = count_one_bits (dsc->u.block.regmask);
unsigned int i;
unsigned int new_regmask;

View File

@ -1,3 +1,18 @@
2020-02-14 Simon Marchi <simon.marchi@efficios.com>
* update-gnulib.sh (IMPORTED_GNULIB_MODULES): Import
count-one-bits module.
* configure: Re-generate.
* aclocal.m4: Re-generate.
* Makefile.in: Re-generate.
* import/count-one-bits.c: New file.
* import/count-one-bits.h: New file.
* import/Makefile.am: Re-generate.
* import/Makefile.in: Re-generate.
* import/m4/gnulib-cache.m4: Re-generate.
* import/m4/gnulib-comp.m4: Re-generate.
* import/m4/count-one-bits.m4: New file.
2019-12-16 Christian Biesinger <cbiesinger@google.com>
* Makefile.am: Set MAKEOVERRIDES.

View File

@ -123,6 +123,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/import/m4/close.m4 \
$(top_srcdir)/import/m4/closedir.m4 \
$(top_srcdir)/import/m4/codeset.m4 \
$(top_srcdir)/import/m4/count-one-bits.m4 \
$(top_srcdir)/import/m4/d-ino.m4 \
$(top_srcdir)/import/m4/d-type.m4 \
$(top_srcdir)/import/m4/dirent_h.m4 \

1
gnulib/aclocal.m4 vendored
View File

@ -1195,6 +1195,7 @@ m4_include([import/m4/chdir-long.m4])
m4_include([import/m4/close.m4])
m4_include([import/m4/closedir.m4])
m4_include([import/m4/codeset.m4])
m4_include([import/m4/count-one-bits.m4])
m4_include([import/m4/d-ino.m4])
m4_include([import/m4/d-type.m4])
m4_include([import/m4/dirent_h.m4])

118
gnulib/configure vendored
View File

@ -6234,6 +6234,7 @@ fi
# Code from module cloexec:
# Code from module close:
# Code from module closedir:
# Code from module count-one-bits:
# Code from module d-ino:
# Code from module d-type:
# Code from module dirent:
@ -7779,6 +7780,63 @@ $as_echo "#define HAVE_MSVC_INVALID_PARAMETER_HANDLER 1" >>confdefs.h
REPLACE_FDOPENDIR=0;
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5
$as_echo_n "checking for unsigned long long int... " >&6; }
if ${ac_cv_type_unsigned_long_long_int+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_type_unsigned_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* For now, do not test the preprocessor; as of 2007 there are too many
implementations with broken preprocessors. Perhaps this can
be revisited in 2012. In the meantime, code should not expect
#if to work with literals wider than 32 bits. */
/* Test literals. */
long long int ll = 9223372036854775807ll;
long long int nll = -9223372036854775807LL;
unsigned long long int ull = 18446744073709551615ULL;
/* Test constant expressions. */
typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
? 1 : -1)];
typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
? 1 : -1)];
int i = 63;
int
main ()
{
/* Test availability of runtime routines for shift and division. */
long long int llmax = 9223372036854775807ll;
unsigned long long int ullmax = 18446744073709551615ull;
return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
| (llmax / ll) | (llmax % ll)
| (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
| (ullmax / ull) | (ullmax % ull));
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
else
ac_cv_type_unsigned_long_long_int=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5
$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; }
if test $ac_cv_type_unsigned_long_long_int = yes; then
$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h
fi
@ -11015,63 +11073,6 @@ $as_echo "$gl_cv_type_wint_t_too_small" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5
$as_echo_n "checking for unsigned long long int... " >&6; }
if ${ac_cv_type_unsigned_long_long_int+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_type_unsigned_long_long_int=yes
if test "x${ac_cv_prog_cc_c99-no}" = xno; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* For now, do not test the preprocessor; as of 2007 there are too many
implementations with broken preprocessors. Perhaps this can
be revisited in 2012. In the meantime, code should not expect
#if to work with literals wider than 32 bits. */
/* Test literals. */
long long int ll = 9223372036854775807ll;
long long int nll = -9223372036854775807LL;
unsigned long long int ull = 18446744073709551615ULL;
/* Test constant expressions. */
typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
? 1 : -1)];
typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
? 1 : -1)];
int i = 63;
int
main ()
{
/* Test availability of runtime routines for shift and division. */
long long int llmax = 9223372036854775807ll;
unsigned long long int ullmax = 18446744073709551615ull;
return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
| (llmax / ll) | (llmax % ll)
| (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
| (ullmax / ull) | (ullmax % ull));
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
else
ac_cv_type_unsigned_long_long_int=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5
$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; }
if test $ac_cv_type_unsigned_long_long_int = yes; then
$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5
$as_echo_n "checking for long long int... " >&6; }
@ -16279,6 +16280,9 @@ $as_echo "#define GNULIB_TEST_CLOSEDIR 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for d_ino member in directory struct" >&5
$as_echo_n "checking for d_ino member in directory struct... " >&6; }
if ${gl_cv_struct_dirent_d_ino+:} false; then :

View File

@ -35,6 +35,7 @@
# --no-vc-files \
# alloca \
# canonicalize-lgpl \
# count-one-bits \
# dirent \
# dirfd \
# errno \
@ -236,6 +237,14 @@ EXTRA_libgnu_a_SOURCES += closedir.c
## end gnulib module closedir
## begin gnulib module count-one-bits
libgnu_a_SOURCES += count-one-bits.c
EXTRA_DIST += count-one-bits.h
## end gnulib module count-one-bits
## begin gnulib module dirent
BUILT_SOURCES += dirent.h

View File

@ -49,6 +49,7 @@
# --no-vc-files \
# alloca \
# canonicalize-lgpl \
# count-one-bits \
# dirent \
# dirfd \
# errno \
@ -178,6 +179,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/import/m4/close.m4 \
$(top_srcdir)/import/m4/closedir.m4 \
$(top_srcdir)/import/m4/codeset.m4 \
$(top_srcdir)/import/m4/count-one-bits.m4 \
$(top_srcdir)/import/m4/d-ino.m4 \
$(top_srcdir)/import/m4/d-type.m4 \
$(top_srcdir)/import/m4/dirent_h.m4 \
@ -326,14 +328,15 @@ am__v_AR_1 =
libgnu_a_AR = $(AR) $(ARFLAGS)
am__DEPENDENCIES_1 =
am__dirstamp = $(am__leading_dot)dirstamp
am_libgnu_a_OBJECTS = cloexec.$(OBJEXT) dirname-lgpl.$(OBJEXT) \
basename-lgpl.$(OBJEXT) stripslash.$(OBJEXT) \
exitfail.$(OBJEXT) fd-hook.$(OBJEXT) fd-safer-flag.$(OBJEXT) \
dup-safer-flag.$(OBJEXT) filenamecat-lgpl.$(OBJEXT) \
getprogname.$(OBJEXT) hard-locale.$(OBJEXT) \
localcharset.$(OBJEXT) glthread/lock.$(OBJEXT) \
malloca.$(OBJEXT) math.$(OBJEXT) openat-die.$(OBJEXT) \
save-cwd.$(OBJEXT) malloc/scratch_buffer_grow.$(OBJEXT) \
am_libgnu_a_OBJECTS = cloexec.$(OBJEXT) count-one-bits.$(OBJEXT) \
dirname-lgpl.$(OBJEXT) basename-lgpl.$(OBJEXT) \
stripslash.$(OBJEXT) exitfail.$(OBJEXT) fd-hook.$(OBJEXT) \
fd-safer-flag.$(OBJEXT) dup-safer-flag.$(OBJEXT) \
filenamecat-lgpl.$(OBJEXT) getprogname.$(OBJEXT) \
hard-locale.$(OBJEXT) localcharset.$(OBJEXT) \
glthread/lock.$(OBJEXT) malloca.$(OBJEXT) math.$(OBJEXT) \
openat-die.$(OBJEXT) save-cwd.$(OBJEXT) \
malloc/scratch_buffer_grow.$(OBJEXT) \
malloc/scratch_buffer_grow_preserve.$(OBJEXT) \
malloc/scratch_buffer_set_array_size.$(OBJEXT) \
stat-time.$(OBJEXT) strnlen1.$(OBJEXT) sys_socket.$(OBJEXT) \
@ -1620,15 +1623,15 @@ noinst_LTLIBRARIES =
EXTRA_DIST = m4/gnulib-cache.m4 alloca.c alloca.in.h arpa_inet.in.h \
assure.h openat-priv.h openat-proc.c canonicalize-lgpl.c \
chdir-long.c chdir-long.h cloexec.h close.c closedir.c \
dirent-private.h dirent.in.h dirfd.c dirname.h dosname.h dup.c \
dup2.c errno.in.h error.c error.h exitfail.h fchdir.c fcntl.c \
fcntl.in.h fd-hook.h fdopendir.c filename.h filenamecat.h \
flexmember.h float.c float.in.h itold.c fnmatch.c \
fnmatch_loop.c fnmatch.in.h fpucw.h frexp.c frexp.c frexpl.c \
fstat.c stat-w32.c stat-w32.h at-func.c fstatat.c getcwd.c \
getcwd-lgpl.c getdtablesize.c getlogin_r.c gettimeofday.c \
glob.c glob_internal.h glob_pattern_p.c globfree.c glob-libc.h \
glob.in.h hard-locale.h \
dirent-private.h count-one-bits.h dirent.in.h dirfd.c \
dirname.h dosname.h dup.c dup2.c errno.in.h error.c error.h \
exitfail.h fchdir.c fcntl.c fcntl.in.h fd-hook.h fdopendir.c \
filename.h filenamecat.h flexmember.h float.c float.in.h \
itold.c fnmatch.c fnmatch_loop.c fnmatch.in.h fpucw.h frexp.c \
frexp.c frexpl.c fstat.c stat-w32.c stat-w32.h at-func.c \
fstatat.c getcwd.c getcwd-lgpl.c getdtablesize.c getlogin_r.c \
gettimeofday.c glob.c glob_internal.h glob_pattern_p.c \
globfree.c glob-libc.h glob.in.h hard-locale.h \
$(top_srcdir)/import/extra/config.rpath inet_ntop.c intprops.h \
inttypes.in.h float+.h isnan.c isnand-nolibm.h isnand.c \
float+.h isnan.c isnanl-nolibm.h isnanl.c cdefs.h \
@ -1682,12 +1685,12 @@ DISTCLEANFILES =
MAINTAINERCLEANFILES =
AM_CPPFLAGS =
AM_CFLAGS =
libgnu_a_SOURCES = cloexec.c dirname-lgpl.c basename-lgpl.c \
stripslash.c exitfail.c fd-hook.c fd-safer-flag.c \
dup-safer-flag.c filenamecat-lgpl.c getprogname.h \
getprogname.c gettext.h hard-locale.c localcharset.c \
glthread/lock.h glthread/lock.c malloca.c math.c openat-die.c \
save-cwd.c malloc/scratch_buffer_grow.c \
libgnu_a_SOURCES = cloexec.c count-one-bits.c dirname-lgpl.c \
basename-lgpl.c stripslash.c exitfail.c fd-hook.c \
fd-safer-flag.c dup-safer-flag.c filenamecat-lgpl.c \
getprogname.h getprogname.c gettext.h hard-locale.c \
localcharset.c glthread/lock.h glthread/lock.c malloca.c \
math.c openat-die.c save-cwd.c malloc/scratch_buffer_grow.c \
malloc/scratch_buffer_grow_preserve.c \
malloc/scratch_buffer_set_array_size.c stat-time.c strnlen1.h \
strnlen1.c sys_socket.c tempname.c glthread/threadlib.c \
@ -1827,6 +1830,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cloexec.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/close.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/closedir.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/count-one-bits.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirfd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirname-lgpl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dup-safer-flag.Po@am__quote@

View File

@ -0,0 +1,7 @@
#include <config.h>
#define COUNT_ONE_BITS_INLINE _GL_EXTERN_INLINE
#include "count-one-bits.h"
#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
int popcount_support = -1;
#endif

View File

@ -0,0 +1,136 @@
/* count-one-bits.h -- counts the number of 1-bits in a word.
Copyright (C) 2007-2019 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* Written by Ben Pfaff. */
#ifndef COUNT_ONE_BITS_H
#define COUNT_ONE_BITS_H 1
#include <limits.h>
#include <stdlib.h>
#ifndef _GL_INLINE_HEADER_BEGIN
#error "Please include config.h first."
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef COUNT_ONE_BITS_INLINE
# define COUNT_ONE_BITS_INLINE _GL_INLINE
#endif
/* Expand to code that computes the number of 1-bits of the local
variable 'x' of type TYPE (an unsigned integer type) and return it
from the current function. */
#define COUNT_ONE_BITS_GENERIC(TYPE) \
do \
{ \
int count = 0; \
int bits; \
for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32) \
{ \
count += count_one_bits_32 (x); \
x = x >> 31 >> 1; \
} \
return count; \
} \
while (0)
/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
expand to code that computes the number of 1-bits of the local
variable 'x' of type TYPE (an unsigned integer type) and return it
from the current function. */
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) return BUILTIN (x)
#else
/* Compute and return the number of 1-bits set in the least
significant 32 bits of X. */
COUNT_ONE_BITS_INLINE int
count_one_bits_32 (unsigned int x)
{
x = ((x & 0xaaaaaaaaU) >> 1) + (x & 0x55555555U);
x = ((x & 0xccccccccU) >> 2) + (x & 0x33333333U);
x = (x >> 16) + (x & 0xffff);
x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f);
return (x >> 8) + (x & 0x00ff);
}
# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
/* While gcc falls back to its own generic code if the machine
on which it's running doesn't support popcount, with Microsoft's
compiler we need to detect and fallback ourselves. */
# pragma intrinsic __cpuid
# pragma intrinsic __popcnt
# pragma intrinsic __popcnt64
/* Return nonzero if popcount is supported. */
/* 1 if supported, 0 if not supported, -1 if unknown. */
extern int popcount_support;
COUNT_ONE_BITS_INLINE int
popcount_supported (void)
{
if (popcount_support < 0)
{
int cpu_info[4];
__cpuid (cpu_info, 1);
popcount_support = (cpu_info[2] >> 23) & 1; /* See MSDN. */
}
return popcount_support;
}
# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) \
do \
{ \
if (popcount_supported ()) \
return MSC_BUILTIN (x); \
else \
COUNT_ONE_BITS_GENERIC (TYPE); \
} \
while (0)
# else
# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) \
COUNT_ONE_BITS_GENERIC (TYPE)
# endif
#endif
/* Compute and return the number of 1-bits set in X. */
COUNT_ONE_BITS_INLINE int
count_one_bits (unsigned int x)
{
COUNT_ONE_BITS (__builtin_popcount, __popcnt, unsigned int);
}
/* Compute and return the number of 1-bits set in X. */
COUNT_ONE_BITS_INLINE int
count_one_bits_l (unsigned long int x)
{
COUNT_ONE_BITS (__builtin_popcountl, __popcnt, unsigned long int);
}
#if HAVE_UNSIGNED_LONG_LONG_INT
/* Compute and return the number of 1-bits set in X. */
COUNT_ONE_BITS_INLINE int
count_one_bits_ll (unsigned long long int x)
{
COUNT_ONE_BITS (__builtin_popcountll, __popcnt64, unsigned long long int);
}
#endif
_GL_INLINE_HEADER_END
#endif /* COUNT_ONE_BITS_H */

View File

@ -0,0 +1,12 @@
# count-one-bits.m4 serial 3
dnl Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_COUNT_ONE_BITS],
[
dnl We don't need (and can't compile) count_one_bits_ll
dnl unless the type 'unsigned long long int' exists.
AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
])

View File

@ -40,6 +40,7 @@
# --no-vc-files \
# alloca \
# canonicalize-lgpl \
# count-one-bits \
# dirent \
# dirfd \
# errno \
@ -79,6 +80,7 @@ gl_LOCAL_DIR([])
gl_MODULES([
alloca
canonicalize-lgpl
count-one-bits
dirent
dirfd
errno

View File

@ -57,6 +57,7 @@ AC_DEFUN([gl_EARLY],
# Code from module cloexec:
# Code from module close:
# Code from module closedir:
# Code from module count-one-bits:
# Code from module d-ino:
# Code from module d-type:
# Code from module dirent:
@ -250,6 +251,7 @@ AC_DEFUN([gl_INIT],
AC_LIBOBJ([closedir])
fi
gl_DIRENT_MODULE_INDICATOR([closedir])
gl_COUNT_ONE_BITS
gl_CHECK_TYPE_STRUCT_DIRENT_D_INO
gl_CHECK_TYPE_STRUCT_DIRENT_D_TYPE
gl_DIRENT_H
@ -855,6 +857,8 @@ AC_DEFUN([gl_FILE_LIST], [
lib/cloexec.h
lib/close.c
lib/closedir.c
lib/count-one-bits.c
lib/count-one-bits.h
lib/dirent-private.h
lib/dirent.in.h
lib/dirfd.c
@ -1045,6 +1049,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/close.m4
m4/closedir.m4
m4/codeset.m4
m4/count-one-bits.m4
m4/d-ino.m4
m4/d-type.m4
m4/dirent_h.m4

View File

@ -32,6 +32,7 @@
IMPORTED_GNULIB_MODULES="\
alloca \
canonicalize-lgpl \
count-one-bits \
dirent \
dirfd \
errno \