aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2013-10-07 14:37:19 -0700
committerPaul Eggert2013-10-07 14:37:19 -0700
commit595e113b15e2ce80b95d39d1851ce78f25ffa1f4 (patch)
tree42c02de46a13e0af39fcc83de9d57c29e309f99e
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
-rw-r--r--ChangeLog12
-rw-r--r--admin/ChangeLog6
-rwxr-xr-xadmin/merge-gnulib3
-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
-rw-r--r--m4/count-one-bits.m412
-rw-r--r--m4/count-trailing-zeros.m412
-rw-r--r--m4/gnulib-comp.m410
-rw-r--r--nt/ChangeLog5
-rw-r--r--nt/gnulib.mk18
-rw-r--r--src/ChangeLog19
-rw-r--r--src/data.c179
-rw-r--r--src/lisp.h7
16 files changed, 409 insertions, 144 deletions
diff --git a/ChangeLog b/ChangeLog
index 4769f5d575d..f1eec73689f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
12013-10-07 Paul Eggert <eggert@cs.ucla.edu>
2
3 Improve support for popcount and counting trailing zeros (Bug#15550).
4 Do this by using the Gnulib modules for this.
5 This should generate faster code on non-GCC, non-MSC platforms,
6 and make the code a bit more portable, at least in theory.
7 * lib/count-one-bits.c, lib/count-one-bits.h:
8 * lib/count-trailing-zeros.c, lib/count-trailing-zeros.h:
9 * m4/count-one-bits.m4, m4/count-trailing-zeros.m4:
10 New files, copied from gnulib.
11 * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
12
12013-10-04 Paul Eggert <eggert@cs.ucla.edu> 132013-10-04 Paul Eggert <eggert@cs.ucla.edu>
2 14
3 Use hardware insns for byteswapping on glibc hosts that support it. 15 Use hardware insns for byteswapping on glibc hosts that support it.
diff --git a/admin/ChangeLog b/admin/ChangeLog
index 837a0a2e6d2..31247765a26 100644
--- a/admin/ChangeLog
+++ b/admin/ChangeLog
@@ -1,3 +1,9 @@
12013-10-07 Paul Eggert <eggert@cs.ucla.edu>
2
3 Improve support for popcount and counting trailing zeros (Bug#15550).
4 * merge-gnulib (GNULIB_MODULES): Add count-one-bits
5 and count-trailing-zeros.
6
12013-10-04 Paul Eggert <eggert@cs.ucla.edu> 72013-10-04 Paul Eggert <eggert@cs.ucla.edu>
2 8
3 Use hardware support for byteswapping on glibc x86 etc. 9 Use hardware support for byteswapping on glibc x86 etc.
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index aba0fa67a1a..a5bd622f4c0 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -27,7 +27,8 @@ GNULIB_URL=git://git.savannah.gnu.org/gnulib.git
27 27
28GNULIB_MODULES=' 28GNULIB_MODULES='
29 alloca-opt byteswap c-ctype c-strcase 29 alloca-opt byteswap c-ctype c-strcase
30 careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 30 careadlinkat close-stream count-one-bits count-trailing-zeros
31 crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512
31 dtoastr dtotimespec dup2 environ execinfo faccessat 32 dtoastr dtotimespec dup2 environ execinfo faccessat
32 fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync 33 fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync
33 getloadavg getopt-gnu gettime gettimeofday 34 getloadavg getopt-gnu gettime gettimeofday
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
diff --git a/m4/count-one-bits.m4 b/m4/count-one-bits.m4
new file mode 100644
index 00000000000..07289641d4a
--- /dev/null
+++ b/m4/count-one-bits.m4
@@ -0,0 +1,12 @@
1# count-one-bits.m4 serial 3
2dnl Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_COUNT_ONE_BITS],
8[
9 dnl We don't need (and can't compile) count_one_bits_ll
10 dnl unless the type 'unsigned long long int' exists.
11 AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
12])
diff --git a/m4/count-trailing-zeros.m4 b/m4/count-trailing-zeros.m4
new file mode 100644
index 00000000000..b4a13c14397
--- /dev/null
+++ b/m4/count-trailing-zeros.m4
@@ -0,0 +1,12 @@
1# count-trailing-zeros.m4
2dnl Copyright (C) 2013 Free Software Foundation, Inc.
3dnl This file is free software; the Free Software Foundation
4dnl gives unlimited permission to copy and/or distribute it,
5dnl with or without modifications, as long as this notice is preserved.
6
7AC_DEFUN([gl_COUNT_TRAILING_ZEROS],
8[
9 dnl We don't need (and can't compile) count_trailing_zeros_ll
10 dnl unless the type 'unsigned long long int' exists.
11 AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
12])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index ff36981c8d0..534d56f5bac 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -48,6 +48,8 @@ AC_DEFUN([gl_EARLY],
48 # Code from module careadlinkat: 48 # Code from module careadlinkat:
49 # Code from module clock-time: 49 # Code from module clock-time:
50 # Code from module close-stream: 50 # Code from module close-stream:
51 # Code from module count-one-bits:
52 # Code from module count-trailing-zeros:
51 # Code from module crypto/md5: 53 # Code from module crypto/md5:
52 # Code from module crypto/sha1: 54 # Code from module crypto/sha1:
53 # Code from module crypto/sha256: 55 # Code from module crypto/sha256:
@@ -175,6 +177,8 @@ AC_DEFUN([gl_INIT],
175 gl_CLOCK_TIME 177 gl_CLOCK_TIME
176 gl_CLOSE_STREAM 178 gl_CLOSE_STREAM
177 gl_MODULE_INDICATOR([close-stream]) 179 gl_MODULE_INDICATOR([close-stream])
180 gl_COUNT_ONE_BITS
181 gl_COUNT_TRAILING_ZEROS
178 gl_MD5 182 gl_MD5
179 gl_SHA1 183 gl_SHA1
180 gl_SHA256 184 gl_SHA256
@@ -806,6 +810,10 @@ AC_DEFUN([gl_FILE_LIST], [
806 lib/careadlinkat.h 810 lib/careadlinkat.h
807 lib/close-stream.c 811 lib/close-stream.c
808 lib/close-stream.h 812 lib/close-stream.h
813 lib/count-one-bits.c
814 lib/count-one-bits.h
815 lib/count-trailing-zeros.c
816 lib/count-trailing-zeros.h
809 lib/dirent.in.h 817 lib/dirent.in.h
810 lib/dosname.h 818 lib/dosname.h
811 lib/dtoastr.c 819 lib/dtoastr.c
@@ -919,6 +927,8 @@ AC_DEFUN([gl_FILE_LIST], [
919 m4/c-strtod.m4 927 m4/c-strtod.m4
920 m4/clock_time.m4 928 m4/clock_time.m4
921 m4/close-stream.m4 929 m4/close-stream.m4
930 m4/count-one-bits.m4
931 m4/count-trailing-zeros.m4
922 m4/dirent_h.m4 932 m4/dirent_h.m4
923 m4/dup2.m4 933 m4/dup2.m4
924 m4/environ.m4 934 m4/environ.m4
diff --git a/nt/ChangeLog b/nt/ChangeLog
index 94bd71d28fd..390a8eb0227 100644
--- a/nt/ChangeLog
+++ b/nt/ChangeLog
@@ -1,3 +1,8 @@
12013-10-07 Paul Eggert <eggert@cs.ucla.edu>
2
3 Improve support for popcount and counting trailing zeros (Bug#15550).
4 * gnulib.mk: Merge changes from ../lib/gnulib.mk.
5
12013-10-04 Paul Eggert <eggert@cs.ucla.edu> 62013-10-04 Paul Eggert <eggert@cs.ucla.edu>
2 7
3 * gnulib.mk: Create <byteswap.h> from <byteswap.in.h>. 8 * gnulib.mk: Create <byteswap.h> from <byteswap.in.h>.
diff --git a/nt/gnulib.mk b/nt/gnulib.mk
index ff46e9f09a6..f6a34013659 100644
--- a/nt/gnulib.mk
+++ b/nt/gnulib.mk
@@ -43,7 +43,7 @@
43# the same distribution terms as the rest of that program. 43# the same distribution terms as the rest of that program.
44# 44#
45# Generated by gnulib-tool. 45# Generated by gnulib-tool.
46# 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=dup --avoid=fchdir --avoid=fcntl --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 c-ctype c-strcase careadlinkat close-stream crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday ignore-value intprops largefile lstat manywarnings memrchr mktime 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 46# 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
47 47
48 48
49MOSTLYCLEANFILES += core *.stackdump 49MOSTLYCLEANFILES += core *.stackdump
@@ -121,6 +121,22 @@ EXTRA_DIST += close-stream.h
121 121
122## end gnulib module close-stream 122## end gnulib module close-stream
123 123
124## begin gnulib module count-one-bits
125
126libgnu_a_SOURCES += count-one-bits.c
127
128EXTRA_DIST += count-one-bits.h
129
130## end gnulib module count-one-bits
131
132## begin gnulib module count-trailing-zeros
133
134libgnu_a_SOURCES += count-trailing-zeros.c
135
136EXTRA_DIST += count-trailing-zeros.h
137
138## end gnulib module count-trailing-zeros
139
124## begin gnulib module crypto/md5 140## begin gnulib module crypto/md5
125 141
126libgnu_a_SOURCES += md5.c 142libgnu_a_SOURCES += md5.c
diff --git a/src/ChangeLog b/src/ChangeLog
index 8e22e4f7cf1..753e123378c 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,22 @@
12013-10-07 Paul Eggert <eggert@cs.ucla.edu>
2
3 Improve support for popcount and counting trailing zeros (Bug#15550).
4 * data.c: Include <count-one-bits.h>, <count-trailing-zeros.h>.
5 (USE_MSC_POPCOUNT, POPCOUNT_STATIC_INLINE)
6 (NEED_GENERIC_POPCOUNT, popcount_size_t_generic)
7 (popcount_size_t_msc, popcount_size_t_gcc):
8 Remove; now done by Gnulib.
9 (popcount_size_t): Now a macro that defers to Gnulib.
10 (count_trailing_zero_bits): Return int, for consistency with
11 Gnulib and because Emacs prefers signed to unsigned int.
12 Don't assume that size_t is either unsigned int or unsigned long
13 or unsigned long long.
14 (size_t_to_host_endian): Do not assume that size_t is either
15 exactly 32 or exactly 64 bits wide.
16 * lisp.h (BITS_PER_SIZE_T): Define consistently with BITS_PER_LONG
17 etc., so that it's now an enum constant, not a macro.
18 No need to assume that it's either 32 or 64.
19
12013-10-07 Jan Djärv <jan.h.d@swipnet.se> 202013-10-07 Jan Djärv <jan.h.d@swipnet.se>
2 21
3 * nsterm.m (windowDidEnterFullScreen:): setPresentationOptions only 22 * nsterm.m (windowDidEnterFullScreen:): setPresentationOptions only
diff --git a/src/data.c b/src/data.c
index a6bfe50a3bb..4ef326e4cfd 100644
--- a/src/data.c
+++ b/src/data.c
@@ -22,6 +22,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22#include <stdio.h> 22#include <stdio.h>
23 23
24#include <byteswap.h> 24#include <byteswap.h>
25#include <count-one-bits.h>
26#include <count-trailing-zeros.h>
25#include <intprops.h> 27#include <intprops.h>
26 28
27#include "lisp.h" 29#include "lisp.h"
@@ -2971,108 +2973,16 @@ bool_vector_spare_mask (ptrdiff_t nr_bits)
2971 return (((size_t) 1) << (nr_bits % BITS_PER_SIZE_T)) - 1; 2973 return (((size_t) 1) << (nr_bits % BITS_PER_SIZE_T)) - 1;
2972} 2974}
2973 2975
2974#if _MSC_VER >= 1500 && (defined _M_IX86 || defined _M_X64) 2976#if SIZE_MAX <= UINT_MAX
2975# define USE_MSC_POPCOUNT 2977# define popcount_size_t count_one_bits
2976# define POPCOUNT_STATIC_INLINE static inline 2978#elif SIZE_MAX <= ULONG_MAX
2977#elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) 2979# define popcount_size_t count_one_bits_l
2978# define USE_GCC_POPCOUNT 2980#elif SIZE_MAX <= ULLONG_MAX
2979# if 199901L <= __STDC_VERSION__ || !__STRICT_ANSI__ 2981# define popcount_size_t count_one_bits_ll
2980# define POPCOUNT_STATIC_INLINE static inline
2981# endif
2982#else 2982#else
2983# define NEED_GENERIC_POPCOUNT 2983# error "size_t wider than long long? Please file a bug report."
2984#endif
2985#ifndef POPCOUNT_STATIC_INLINE
2986# define POPCOUNT_STATIC_INLINE static
2987#endif
2988
2989#ifdef USE_MSC_POPCOUNT
2990# define NEED_GENERIC_POPCOUNT
2991#endif
2992
2993#ifdef NEED_GENERIC_POPCOUNT
2994POPCOUNT_STATIC_INLINE unsigned int
2995popcount_size_t_generic (size_t val)
2996{
2997 unsigned short j;
2998 unsigned int count = 0;
2999
3000 for (j = 0; j < BITS_PER_SIZE_T; ++j)
3001 count += !!((((size_t) 1) << j) & val);
3002
3003 return count;
3004}
3005#endif 2984#endif
3006 2985
3007#ifdef USE_MSC_POPCOUNT
3008POPCOUNT_STATIC_INLINE unsigned int
3009popcount_size_t_msc (size_t val)
3010{
3011 unsigned int count;
3012
3013#pragma intrinsic __cpuid
3014 /* While gcc falls back to its own generic code if the machine on
3015 which it's running doesn't support popcount, we need to perform the
3016 detection and fallback ourselves when compiling with Microsoft's
3017 compiler. */
3018
3019 static enum {
3020 popcount_unknown_support,
3021 popcount_use_generic,
3022 popcount_use_intrinsic
3023 } popcount_state;
3024
3025 if (popcount_state == popcount_unknown_support)
3026 {
3027 int cpu_info[4];
3028 __cpuid (cpu_info, 1);
3029 if (cpu_info[2] & (1<<23)) /* See MSDN. */
3030 popcount_state = popcount_use_intrinsic;
3031 else
3032 popcount_state = popcount_use_generic;
3033 }
3034
3035 if (popcount_state == popcount_use_intrinsic)
3036 {
3037# if BITS_PER_SIZE_T == 64
3038# pragma intrinsic __popcnt64
3039 count = __popcnt64 (val);
3040# else
3041# pragma intrinsic __popcnt
3042 count = __popcnt (val);
3043# endif
3044 }
3045 else
3046 count = popcount_size_t_generic (val);
3047
3048 return count;
3049}
3050#endif /* USE_MSC_POPCOUNT */
3051
3052#ifdef USE_GCC_POPCOUNT
3053POPCOUNT_STATIC_INLINE unsigned int
3054popcount_size_t_gcc (size_t val)
3055{
3056# if BITS_PER_SIZE_T == 64
3057 return __builtin_popcountll (val);
3058# else
3059 return __builtin_popcount (val);
3060# endif
3061}
3062#endif /* USE_GCC_POPCOUNT */
3063
3064POPCOUNT_STATIC_INLINE unsigned int
3065popcount_size_t (size_t val)
3066{
3067#if defined USE_MSC_POPCOUNT
3068 return popcount_size_t_msc (val);
3069#elif defined USE_GCC_POPCOUNT
3070 return popcount_size_t_gcc (val);
3071#else
3072 return popcount_size_t_generic (val);
3073#endif
3074}
3075
3076enum bool_vector_op { bool_vector_exclusive_or, 2986enum bool_vector_op { bool_vector_exclusive_or,
3077 bool_vector_union, 2987 bool_vector_union,
3078 bool_vector_intersection, 2988 bool_vector_intersection,
@@ -3143,55 +3053,54 @@ bool_vector_binop_driver (Lisp_Object op1,
3143 3053
3144/* Compute the number of trailing zero bits in val. If val is zero, 3054/* Compute the number of trailing zero bits in val. If val is zero,
3145 return the number of bits in val. */ 3055 return the number of bits in val. */
3146static unsigned int 3056static int
3147count_trailing_zero_bits (size_t val) 3057count_trailing_zero_bits (size_t val)
3148{ 3058{
3059 if (SIZE_MAX == UINT_MAX)
3060 return count_trailing_zeros (val);
3061 if (SIZE_MAX == ULONG_MAX)
3062 return count_trailing_zeros_l (val);
3063# if HAVE_UNSIGNED_LONG_LONG_INT
3064 if (SIZE_MAX == ULLONG_MAX)
3065 return count_trailing_zeros_ll (val);
3066# endif
3067
3068 /* The rest of this code is for the unlikely platform where size_t differs
3069 in width from unsigned int, unsigned long, and unsigned long long. */
3149 if (val == 0) 3070 if (val == 0)
3150 return CHAR_BIT * sizeof (val); 3071 return CHAR_BIT * sizeof (val);
3151 3072 if (SIZE_MAX <= UINT_MAX)
3152#if defined USE_GCC_POPCOUNT && BITS_PER_SIZE_T == 64 3073 return count_trailing_zeros (val);
3153 return __builtin_ctzll (val); 3074 if (SIZE_MAX <= ULONG_MAX)
3154#elif defined USE_GCC_POPCOUNT && BITS_PER_SIZE_T == 32 3075 return count_trailing_zeros_l (val);
3155 return __builtin_ctz (val);
3156#elif _MSC_VER && BITS_PER_SIZE_T == 64
3157# pragma intrinsic _BitScanForward64
3158 { 3076 {
3159 /* No support test needed: support since 386. */ 3077# if HAVE_UNSIGNED_LONG_LONG_INT
3160 unsigned long result; 3078 verify (SIZE_MAX <= ULLONG_MAX);
3161 _BitScanForward64 (&result, val); 3079 return count_trailing_zeros_ll (val);
3162 return (unsigned int) result; 3080# else
3163 } 3081 verify (SIZE_MAX <= ULONG_MAX);
3164#elif _MSC_VER && BITS_PER_SIZE_T == 32 3082# endif
3165# pragma intrinsic _BitScanForward
3166 {
3167 /* No support test needed: support since 386. */
3168 unsigned long result;
3169 _BitScanForward (&result, val);
3170 return (unsigned int) result;
3171 }
3172#else
3173 {
3174 unsigned int count;
3175 count = 0;
3176 for (val = ~val; val & 1; val >>= 1)
3177 ++count;
3178
3179 return count;
3180 } 3083 }
3181#endif
3182} 3084}
3183 3085
3184static size_t 3086static size_t
3185size_t_to_host_endian (size_t val) 3087size_t_to_host_endian (size_t val)
3186{ 3088{
3187#ifdef WORDS_BIGENDIAN 3089#ifndef WORDS_BIGENDIAN
3188# if BITS_PER_SIZE_T == 64 3090 return val;
3189 return bswap_64 (val); 3091#elif SIZE_MAX >> 31 == 1
3190# else
3191 return bswap_32 (val); 3092 return bswap_32 (val);
3192# endif 3093#elif SIZE_MAX >> 31 >> 31 >> 1 == 1
3094 return bswap_64 (val);
3193#else 3095#else
3194 return val; 3096 int i;
3097 size_t r = 0;
3098 for (i = 0; i < sizeof val; i++)
3099 {
3100 r = (r << CHAR_BIT) | (val & ((1u << CHAR_BIT) - 1));
3101 val >>= CHAR_BIT;
3102 }
3103 return r;
3195#endif 3104#endif
3196} 3105}
3197 3106
diff --git a/src/lisp.h b/src/lisp.h
index c7f13e21e55..b8863d6821d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -71,6 +71,7 @@ enum
71 BITS_PER_SHORT = CHAR_BIT * sizeof (short), 71 BITS_PER_SHORT = CHAR_BIT * sizeof (short),
72 BITS_PER_INT = CHAR_BIT * sizeof (int), 72 BITS_PER_INT = CHAR_BIT * sizeof (int),
73 BITS_PER_LONG = CHAR_BIT * sizeof (long int), 73 BITS_PER_LONG = CHAR_BIT * sizeof (long int),
74 BITS_PER_SIZE_T = CHAR_BIT * sizeof (size_t),
74 BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT) 75 BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT)
75 }; 76 };
76 77
@@ -4366,12 +4367,6 @@ functionp (Lisp_Object object)
4366 return 0; 4367 return 0;
4367} 4368}
4368 4369
4369#if ((SIZE_MAX >> 31) >> 1) & 1
4370# define BITS_PER_SIZE_T 64
4371#else
4372# define BITS_PER_SIZE_T 32
4373#endif
4374
4375/* Round x to the next multiple of y. Does not overflow. Evaluates 4370/* Round x to the next multiple of y. Does not overflow. Evaluates
4376 arguments repeatedly. */ 4371 arguments repeatedly. */
4377#define ROUNDUP(x,y) ((y)*((x)/(y) + ((x)%(y)!=0))) 4372#define ROUNDUP(x,y) ((y)*((x)/(y) + ((x)%(y)!=0)))