aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert2013-10-07 14:37:19 -0700
committerPaul Eggert2013-10-07 14:37:19 -0700
commit595e113b15e2ce80b95d39d1851ce78f25ffa1f4 (patch)
tree42c02de46a13e0af39fcc83de9d57c29e309f99e /lib
parentddb317ba828f05eb48e98fda530443955485e75d (diff)
downloademacs-595e113b15e2ce80b95d39d1851ce78f25ffa1f4.tar.gz
emacs-595e113b15e2ce80b95d39d1851ce78f25ffa1f4.zip
Improve support for popcount and counting trailing zeros.
Do this by using the Gnulib modules for this. This should generate faster code on non-GCC, non-MSC platforms, and make the code a bit more portable, at least in theory. * admin/merge-gnulib (GNULIB_MODULES): Add count-one-bits and count-trailing-zeros. * lib/count-one-bits.c, lib/count-one-bits.h: * lib/count-trailing-zeros.c, lib/count-trailing-zeros.h: * m4/count-one-bits.m4, m4/count-trailing-zeros.m4: New files, copied from gnulib. * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * nt/gnulib.mk: Merge changes from lib/gnulib.mk. * src/data.c: Include <count-one-bits.h>, <count-trailing-zeros.h>. (USE_MSC_POPCOUNT, POPCOUNT_STATIC_INLINE) (NEED_GENERIC_POPCOUNT, popcount_size_t_generic) (popcount_size_t_msc, popcount_size_t_gcc): Remove; now done by Gnulib. (popcount_size_t): Now a macro that defers to Gnulib. (count_trailing_zero_bits): Return int, for consistency with Gnulib and because Emacs prefers signed to unsigned int. Don't assume that size_t is either unsigned int or unsigned long or unsigned long long. (size_t_to_host_endian): Do not assume that size_t is either exactly 32 or exactly 64 bits wide. * src/lisp.h (BITS_PER_SIZE_T): Define consistently with BITS_PER_LONG etc., so that it's now an enum constant, not a macro. No need to assume that it's either 32 or 64. Fixes: debbugs:15550
Diffstat (limited to 'lib')
-rw-r--r--lib/count-one-bits.c7
-rw-r--r--lib/count-one-bits.h136
-rw-r--r--lib/count-trailing-zeros.c3
-rw-r--r--lib/count-trailing-zeros.h106
-rw-r--r--lib/gnulib.mk18
5 files changed, 269 insertions, 1 deletions
diff --git a/lib/count-one-bits.c b/lib/count-one-bits.c
new file mode 100644
index 00000000000..66341d77cda
--- /dev/null
+++ b/lib/count-one-bits.c
@@ -0,0 +1,7 @@
1#include <config.h>
2#define COUNT_ONE_BITS_INLINE _GL_EXTERN_INLINE
3#include "count-one-bits.h"
4
5#if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
6int popcount_support = -1;
7#endif
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
new file mode 100644
index 00000000000..2a7e93c3f40
--- /dev/null
+++ b/lib/count-one-bits.h
@@ -0,0 +1,136 @@
1/* count-one-bits.h -- counts the number of 1-bits in a word.
2 Copyright (C) 2007-2013 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17/* Written by Ben Pfaff. */
18
19#ifndef COUNT_ONE_BITS_H
20#define COUNT_ONE_BITS_H 1
21
22#include <limits.h>
23#include <stdlib.h>
24
25#ifndef _GL_INLINE_HEADER_BEGIN
26 #error "Please include config.h first."
27#endif
28_GL_INLINE_HEADER_BEGIN
29#ifndef COUNT_ONE_BITS_INLINE
30# define COUNT_ONE_BITS_INLINE _GL_INLINE
31#endif
32
33/* Expand to code that computes the number of 1-bits of the local
34 variable 'x' of type TYPE (an unsigned integer type) and return it
35 from the current function. */
36#define COUNT_ONE_BITS_GENERIC(TYPE) \
37 do \
38 { \
39 int count = 0; \
40 int bits; \
41 for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32) \
42 { \
43 count += count_one_bits_32 (x); \
44 x = x >> 31 >> 1; \
45 } \
46 return count; \
47 } \
48 while (0)
49
50/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
51 expand to code that computes the number of 1-bits of the local
52 variable 'x' of type TYPE (an unsigned integer type) and return it
53 from the current function. */
54#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
55# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) return BUILTIN (x)
56#else
57
58/* Compute and return the number of 1-bits set in the least
59 significant 32 bits of X. */
60COUNT_ONE_BITS_INLINE int
61count_one_bits_32 (unsigned int x)
62{
63 x = ((x & 0xaaaaaaaaU) >> 1) + (x & 0x55555555U);
64 x = ((x & 0xccccccccU) >> 2) + (x & 0x33333333U);
65 x = (x >> 16) + (x & 0xffff);
66 x = ((x & 0xf0f0) >> 4) + (x & 0x0f0f);
67 return (x >> 8) + (x & 0x00ff);
68}
69
70# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
71
72/* While gcc falls back to its own generic code if the machine
73 on which it's running doesn't support popcount, with Microsoft's
74 compiler we need to detect and fallback ourselves. */
75# pragma intrinsic __cpuid
76# pragma intrinsic __popcnt
77# pragma intrinsic __popcnt64
78
79/* Return nonzero if popcount is supported. */
80
81/* 1 if supported, 0 if not supported, -1 if unknown. */
82extern int popcount_support;
83
84COUNT_ONE_BITS_INLINE int
85popcount_supported (void)
86{
87 if (popcount_support < 0)
88 {
89 int cpu_info[4];
90 __cpuid (cpu_info, 1);
91 popcount_support = (cpu_info[2] >> 23) & 1; /* See MSDN. */
92 }
93 return popcount_support;
94}
95
96# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) \
97 do \
98 { \
99 if (popcount_supported ()) \
100 return MSC_BUILTIN (x); \
101 else \
102 COUNT_ONE_BITS_GENERIC (TYPE); \
103 } \
104 while (0)
105# else
106# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) \
107 COUNT_ONE_BITS_GENERIC (TYPE)
108# endif
109#endif
110
111/* Compute and return the number of 1-bits set in X. */
112COUNT_ONE_BITS_INLINE int
113count_one_bits (unsigned int x)
114{
115 COUNT_ONE_BITS (__builtin_popcount, __popcnt, unsigned int);
116}
117
118/* Compute and return the number of 1-bits set in X. */
119COUNT_ONE_BITS_INLINE int
120count_one_bits_l (unsigned long int x)
121{
122 COUNT_ONE_BITS (__builtin_popcountl, __popcnt, unsigned long int);
123}
124
125#if HAVE_UNSIGNED_LONG_LONG_INT
126/* Compute and return the number of 1-bits set in X. */
127COUNT_ONE_BITS_INLINE int
128count_one_bits_ll (unsigned long long int x)
129{
130 COUNT_ONE_BITS (__builtin_popcountll, __popcnt64, unsigned long long int);
131}
132#endif
133
134_GL_INLINE_HEADER_END
135
136#endif /* COUNT_ONE_BITS_H */
diff --git a/lib/count-trailing-zeros.c b/lib/count-trailing-zeros.c
new file mode 100644
index 00000000000..f3da8867428
--- /dev/null
+++ b/lib/count-trailing-zeros.c
@@ -0,0 +1,3 @@
1#include <config.h>
2#define COUNT_TRAILING_ZEROS_INLINE _GL_EXTERN_INLINE
3#include "count-trailing-zeros.h"
diff --git a/lib/count-trailing-zeros.h b/lib/count-trailing-zeros.h
new file mode 100644
index 00000000000..1dab45dc11d
--- /dev/null
+++ b/lib/count-trailing-zeros.h
@@ -0,0 +1,106 @@
1/* count-trailing-zeros.h -- counts the number of trailing 0 bits in a word.
2 Copyright 2013 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17/* Written by Paul Eggert. */
18
19#ifndef COUNT_TRAILING_ZEROS_H
20#define COUNT_TRAILING_ZEROS_H 1
21
22#include <limits.h>
23#include <stdlib.h>
24
25#ifndef _GL_INLINE_HEADER_BEGIN
26 #error "Please include config.h first."
27#endif
28_GL_INLINE_HEADER_BEGIN
29#ifndef COUNT_TRAILING_ZEROS_INLINE
30# define COUNT_TRAILING_ZEROS_INLINE _GL_INLINE
31#endif
32
33/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
34 expand to code that computes the number of trailing zeros of the local
35 variable 'x' of type TYPE (an unsigned integer type) and return it
36 from the current function. */
37#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
38# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
39 return x ? BUILTIN (x) : CHAR_BIT * sizeof x;
40#elif _MSC_VER
41# pragma intrinsic _BitScanForward
42# pragma intrinsic _BitScanForward64
43# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
44 do \
45 { \
46 unsigned long result; \
47 return MSC_BUILTIN (&result, x) ? result : CHAR_BIT * sizeof x; \
48 } \
49 while (0)
50#else
51# define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \
52 do \
53 { \
54 int count = 0; \
55 if (! x) \
56 return CHAR_BIT * sizeof x; \
57 for (count = 0; \
58 (count < CHAR_BIT * sizeof x - 32 \
59 && ! (x & 0xffffffffU)); \
60 count += 32) \
61 x = x >> 31 >> 1; \
62 return count + count_trailing_zeros_32 (x); \
63 } \
64 while (0)
65
66/* Compute and return the number of trailing zeros in the least
67 significant 32 bits of X. One of these bits must be nonzero. */
68COUNT_TRAILING_ZEROS_INLINE int
69count_trailing_zeros_32 (unsigned int x)
70{
71 /* http://graphics.stanford.edu/~seander/bithacks.html */
72 static const char de_Bruijn_lookup[32] = {
73 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
74 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
75 };
76 return de_Bruijn_lookup[(((x & -x) * 0x077cb531U) & 0xffffffffU) >> 27];
77}
78#endif
79
80/* Compute and return the number of trailing zeros in X. */
81COUNT_TRAILING_ZEROS_INLINE int
82count_trailing_zeros (unsigned int x)
83{
84 COUNT_TRAILING_ZEROS (__builtin_ctz, _BitScanForward, unsigned int);
85}
86
87/* Compute and return the number of trailing zeros in X. */
88COUNT_TRAILING_ZEROS_INLINE int
89count_trailing_zeros_l (unsigned long int x)
90{
91 COUNT_TRAILING_ZEROS (__builtin_ctzl, _BitScanForward, unsigned long int);
92}
93
94#if HAVE_UNSIGNED_LONG_LONG_INT
95/* Compute and return the number of trailing zeros in X. */
96COUNT_TRAILING_ZEROS_INLINE int
97count_trailing_zeros_ll (unsigned long long int x)
98{
99 COUNT_TRAILING_ZEROS (__builtin_ctzll, _BitScanForward64,
100 unsigned long long int);
101}
102#endif
103
104_GL_INLINE_HEADER_END
105
106#endif
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index 73381f2bdce..69fc06bbe06 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -21,7 +21,7 @@
21# the same distribution terms as the rest of that program. 21# the same distribution terms as the rest of that program.
22# 22#
23# Generated by gnulib-tool. 23# Generated by gnulib-tool.
24# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt byteswap c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings 24# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=sys_types --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qacl readlink readlinkat sig2str socklen stat-time stdalign stdarg stdbool stdio strftime strtoimax strtoumax symlink sys_stat sys_time time timer-time timespec-add timespec-sub unsetenv utimens warnings
25 25
26 26
27MOSTLYCLEANFILES += core *.stackdump 27MOSTLYCLEANFILES += core *.stackdump
@@ -132,6 +132,22 @@ EXTRA_DIST += close-stream.h
132 132
133## end gnulib module close-stream 133## end gnulib module close-stream
134 134
135## begin gnulib module count-one-bits
136
137libgnu_a_SOURCES += count-one-bits.c
138
139EXTRA_DIST += count-one-bits.h
140
141## end gnulib module count-one-bits
142
143## begin gnulib module count-trailing-zeros
144
145libgnu_a_SOURCES += count-trailing-zeros.c
146
147EXTRA_DIST += count-trailing-zeros.h
148
149## end gnulib module count-trailing-zeros
150
135## begin gnulib module crypto/md5 151## begin gnulib module crypto/md5
136 152
137libgnu_a_SOURCES += md5.c 153libgnu_a_SOURCES += md5.c