aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-10-07 21:25:33 -0700
committerPaul Eggert2013-10-07 21:25:33 -0700
commit87c4314d27420e5da8c2f6f97b4cfd94902f1d04 (patch)
treeb395b1c6c7ef33d35b1795e1659c620230a186dc /src
parent442560600080f6131ec63956ed43eee7d26bf65a (diff)
downloademacs-87c4314d27420e5da8c2f6f97b4cfd94902f1d04.tar.gz
emacs-87c4314d27420e5da8c2f6f97b4cfd94902f1d04.zip
* lisp.h (bits_word, BITS_WORD_MAX): New type and macro.
All uses of 'size_t' and 'SIZE_MAX' changed to use them, when they're talking about words in Lisp bool vectors. (BITS_PER_BITS_WORD): Rename from BITS_PER_SIZE_T. All uses changed.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog7
-rw-r--r--src/alloc.c8
-rw-r--r--src/data.c128
-rw-r--r--src/lisp.h7
4 files changed, 81 insertions, 69 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 753e123378c..755e710c079 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
12013-10-08 Paul Eggert <eggert@cs.ucla.edu>
2
3 * lisp.h (bits_word, BITS_WORD_MAX): New type and macro.
4 All uses of 'size_t' and 'SIZE_MAX' changed to use them, when
5 they're talking about words in Lisp bool vectors.
6 (BITS_PER_BITS_WORD): Rename from BITS_PER_SIZE_T. All uses changed.
7
12013-10-07 Paul Eggert <eggert@cs.ucla.edu> 82013-10-07 Paul Eggert <eggert@cs.ucla.edu>
2 9
3 Improve support for popcount and counting trailing zeros (Bug#15550). 10 Improve support for popcount and counting trailing zeros (Bug#15550).
diff --git a/src/alloc.c b/src/alloc.c
index 990390f5a36..2a00767682d 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -2017,8 +2017,8 @@ INIT must be an integer that represents a character. */)
2017 return val; 2017 return val;
2018} 2018}
2019 2019
2020verify (sizeof (size_t) * CHAR_BIT == BITS_PER_SIZE_T); 2020verify (sizeof (size_t) * CHAR_BIT == BITS_PER_BITS_WORD);
2021verify ((BITS_PER_SIZE_T & (BITS_PER_SIZE_T - 1)) == 0); 2021verify ((BITS_PER_BITS_WORD & (BITS_PER_BITS_WORD - 1)) == 0);
2022 2022
2023static ptrdiff_t 2023static ptrdiff_t
2024bool_vector_payload_bytes (ptrdiff_t nr_bits, 2024bool_vector_payload_bytes (ptrdiff_t nr_bits,
@@ -2030,14 +2030,14 @@ bool_vector_payload_bytes (ptrdiff_t nr_bits,
2030 eassert (nr_bits >= 0); 2030 eassert (nr_bits >= 0);
2031 2031
2032 exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT; 2032 exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT;
2033 needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_SIZE_T) / CHAR_BIT; 2033 needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_BITS_WORD) / CHAR_BIT;
2034 2034
2035 if (needed_bytes == 0) 2035 if (needed_bytes == 0)
2036 { 2036 {
2037 /* Always allocate at least one machine word of payload so that 2037 /* Always allocate at least one machine word of payload so that
2038 bool-vector operations in data.c don't need a special case 2038 bool-vector operations in data.c don't need a special case
2039 for empty vectors. */ 2039 for empty vectors. */
2040 needed_bytes = sizeof (size_t); 2040 needed_bytes = sizeof (bits_word);
2041 } 2041 }
2042 2042
2043 if (exact_needed_bytes_out != NULL) 2043 if (exact_needed_bytes_out != NULL)
diff --git a/src/data.c b/src/data.c
index 4ef326e4cfd..8045cd138ea 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2963,24 +2963,24 @@ lowercase l) for small endian machines. */)
2963/* Because we round up the bool vector allocate size to word_size 2963/* Because we round up the bool vector allocate size to word_size
2964 units, we can safely read past the "end" of the vector in the 2964 units, we can safely read past the "end" of the vector in the
2965 operations below. These extra bits are always zero. Also, we 2965 operations below. These extra bits are always zero. Also, we
2966 always allocate bool vectors with at least one size_t of storage so 2966 always allocate bool vectors with at least one bits_word of storage so
2967 that we don't have to special-case empty bit vectors. */ 2967 that we don't have to special-case empty bit vectors. */
2968 2968
2969static size_t 2969static bits_word
2970bool_vector_spare_mask (ptrdiff_t nr_bits) 2970bool_vector_spare_mask (ptrdiff_t nr_bits)
2971{ 2971{
2972 eassert (nr_bits > 0); 2972 eassert (nr_bits > 0);
2973 return (((size_t) 1) << (nr_bits % BITS_PER_SIZE_T)) - 1; 2973 return (((bits_word) 1) << (nr_bits % BITS_PER_BITS_WORD)) - 1;
2974} 2974}
2975 2975
2976#if SIZE_MAX <= UINT_MAX 2976#if BITS_WORD_MAX <= UINT_MAX
2977# define popcount_size_t count_one_bits 2977# define popcount_bits_word count_one_bits
2978#elif SIZE_MAX <= ULONG_MAX 2978#elif BITS_WORD_MAX <= ULONG_MAX
2979# define popcount_size_t count_one_bits_l 2979# define popcount_bits_word count_one_bits_l
2980#elif SIZE_MAX <= ULLONG_MAX 2980#elif BITS_WORD_MAX <= ULLONG_MAX
2981# define popcount_size_t count_one_bits_ll 2981# define popcount_bits_word count_one_bits_ll
2982#else 2982#else
2983# error "size_t wider than long long? Please file a bug report." 2983# error "bits_word wider than long long? Please file a bug report."
2984#endif 2984#endif
2985 2985
2986enum bool_vector_op { bool_vector_exclusive_or, 2986enum bool_vector_op { bool_vector_exclusive_or,
@@ -2996,10 +2996,10 @@ bool_vector_binop_driver (Lisp_Object op1,
2996 enum bool_vector_op op) 2996 enum bool_vector_op op)
2997{ 2997{
2998 EMACS_INT nr_bits; 2998 EMACS_INT nr_bits;
2999 size_t *adata, *bdata, *cdata; 2999 bits_word *adata, *bdata, *cdata;
3000 ptrdiff_t i; 3000 ptrdiff_t i;
3001 size_t changed = 0; 3001 bits_word changed = 0;
3002 size_t mword; 3002 bits_word mword;
3003 ptrdiff_t nr_words; 3003 ptrdiff_t nr_words;
3004 3004
3005 CHECK_BOOL_VECTOR (op1); 3005 CHECK_BOOL_VECTOR (op1);
@@ -3020,11 +3020,11 @@ bool_vector_binop_driver (Lisp_Object op1,
3020 } 3020 }
3021 3021
3022 eassert (nr_bits >= 0); 3022 eassert (nr_bits >= 0);
3023 nr_words = ROUNDUP (nr_bits, BITS_PER_SIZE_T) / BITS_PER_SIZE_T; 3023 nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD;
3024 3024
3025 adata = (size_t *) XBOOL_VECTOR (dest)->data; 3025 adata = (bits_word *) XBOOL_VECTOR (dest)->data;
3026 bdata = (size_t *) XBOOL_VECTOR (op1)->data; 3026 bdata = (bits_word *) XBOOL_VECTOR (op1)->data;
3027 cdata = (size_t *) XBOOL_VECTOR (op2)->data; 3027 cdata = (bits_word *) XBOOL_VECTOR (op2)->data;
3028 i = 0; 3028 i = 0;
3029 do 3029 do
3030 { 3030 {
@@ -3054,47 +3054,47 @@ bool_vector_binop_driver (Lisp_Object op1,
3054/* 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,
3055 return the number of bits in val. */ 3055 return the number of bits in val. */
3056static int 3056static int
3057count_trailing_zero_bits (size_t val) 3057count_trailing_zero_bits (bits_word val)
3058{ 3058{
3059 if (SIZE_MAX == UINT_MAX) 3059 if (BITS_WORD_MAX == UINT_MAX)
3060 return count_trailing_zeros (val); 3060 return count_trailing_zeros (val);
3061 if (SIZE_MAX == ULONG_MAX) 3061 if (BITS_WORD_MAX == ULONG_MAX)
3062 return count_trailing_zeros_l (val); 3062 return count_trailing_zeros_l (val);
3063# if HAVE_UNSIGNED_LONG_LONG_INT 3063# if HAVE_UNSIGNED_LONG_LONG_INT
3064 if (SIZE_MAX == ULLONG_MAX) 3064 if (BITS_WORD_MAX == ULLONG_MAX)
3065 return count_trailing_zeros_ll (val); 3065 return count_trailing_zeros_ll (val);
3066# endif 3066# endif
3067 3067
3068 /* The rest of this code is for the unlikely platform where size_t differs 3068 /* The rest of this code is for the unlikely platform where bits_word differs
3069 in width from unsigned int, unsigned long, and unsigned long long. */ 3069 in width from unsigned int, unsigned long, and unsigned long long. */
3070 if (val == 0) 3070 if (val == 0)
3071 return CHAR_BIT * sizeof (val); 3071 return CHAR_BIT * sizeof (val);
3072 if (SIZE_MAX <= UINT_MAX) 3072 if (BITS_WORD_MAX <= UINT_MAX)
3073 return count_trailing_zeros (val); 3073 return count_trailing_zeros (val);
3074 if (SIZE_MAX <= ULONG_MAX) 3074 if (BITS_WORD_MAX <= ULONG_MAX)
3075 return count_trailing_zeros_l (val); 3075 return count_trailing_zeros_l (val);
3076 { 3076 {
3077# if HAVE_UNSIGNED_LONG_LONG_INT 3077# if HAVE_UNSIGNED_LONG_LONG_INT
3078 verify (SIZE_MAX <= ULLONG_MAX); 3078 verify (BITS_WORD_MAX <= ULLONG_MAX);
3079 return count_trailing_zeros_ll (val); 3079 return count_trailing_zeros_ll (val);
3080# else 3080# else
3081 verify (SIZE_MAX <= ULONG_MAX); 3081 verify (BITS_WORD_MAX <= ULONG_MAX);
3082# endif 3082# endif
3083 } 3083 }
3084} 3084}
3085 3085
3086static size_t 3086static bits_word
3087size_t_to_host_endian (size_t val) 3087bits_word_to_host_endian (bits_word val)
3088{ 3088{
3089#ifndef WORDS_BIGENDIAN 3089#ifndef WORDS_BIGENDIAN
3090 return val; 3090 return val;
3091#elif SIZE_MAX >> 31 == 1 3091#elif BITS_WORD_MAX >> 31 == 1
3092 return bswap_32 (val); 3092 return bswap_32 (val);
3093#elif SIZE_MAX >> 31 >> 31 >> 1 == 1 3093#elif BITS_WORD_MAX >> 31 >> 31 >> 1 == 1
3094 return bswap_64 (val); 3094 return bswap_64 (val);
3095#else 3095#else
3096 int i; 3096 int i;
3097 size_t r = 0; 3097 bits_word r = 0;
3098 for (i = 0; i < sizeof val; i++) 3098 for (i = 0; i < sizeof val; i++)
3099 { 3099 {
3100 r = (r << CHAR_BIT) | (val & ((1u << CHAR_BIT) - 1)); 3100 r = (r << CHAR_BIT) | (val & ((1u << CHAR_BIT) - 1));
@@ -3167,9 +3167,9 @@ Return the destination vector. */)
3167 (Lisp_Object a, Lisp_Object b) 3167 (Lisp_Object a, Lisp_Object b)
3168{ 3168{
3169 EMACS_INT nr_bits; 3169 EMACS_INT nr_bits;
3170 size_t *bdata, *adata; 3170 bits_word *bdata, *adata;
3171 ptrdiff_t i; 3171 ptrdiff_t i;
3172 size_t mword; 3172 bits_word mword;
3173 3173
3174 CHECK_BOOL_VECTOR (a); 3174 CHECK_BOOL_VECTOR (a);
3175 nr_bits = XBOOL_VECTOR (a)->size; 3175 nr_bits = XBOOL_VECTOR (a)->size;
@@ -3182,20 +3182,20 @@ Return the destination vector. */)
3182 nr_bits = min (nr_bits, XBOOL_VECTOR (b)->size); 3182 nr_bits = min (nr_bits, XBOOL_VECTOR (b)->size);
3183 } 3183 }
3184 3184
3185 bdata = (size_t *) XBOOL_VECTOR (b)->data; 3185 bdata = (bits_word *) XBOOL_VECTOR (b)->data;
3186 adata = (size_t *) XBOOL_VECTOR (a)->data; 3186 adata = (bits_word *) XBOOL_VECTOR (a)->data;
3187 3187
3188 eassert (nr_bits >= 0); 3188 eassert (nr_bits >= 0);
3189 3189
3190 for (i = 0; i < nr_bits / BITS_PER_SIZE_T; i++) 3190 for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; i++)
3191 bdata[i] = ~adata[i]; 3191 bdata[i] = ~adata[i];
3192 3192
3193 if (nr_bits % BITS_PER_SIZE_T) 3193 if (nr_bits % BITS_PER_BITS_WORD)
3194 { 3194 {
3195 mword = size_t_to_host_endian (adata[i]); 3195 mword = bits_word_to_host_endian (adata[i]);
3196 mword = ~mword; 3196 mword = ~mword;
3197 mword &= bool_vector_spare_mask (nr_bits); 3197 mword &= bool_vector_spare_mask (nr_bits);
3198 bdata[i] = size_t_to_host_endian (mword); 3198 bdata[i] = bits_word_to_host_endian (mword);
3199 } 3199 }
3200 3200
3201 return b; 3201 return b;
@@ -3209,28 +3209,28 @@ A must be a bool vector. B is a generalized bool. */)
3209{ 3209{
3210 ptrdiff_t count; 3210 ptrdiff_t count;
3211 EMACS_INT nr_bits; 3211 EMACS_INT nr_bits;
3212 size_t *adata; 3212 bits_word *adata;
3213 size_t match; 3213 bits_word match;
3214 ptrdiff_t i; 3214 ptrdiff_t i;
3215 3215
3216 CHECK_BOOL_VECTOR (a); 3216 CHECK_BOOL_VECTOR (a);
3217 3217
3218 nr_bits = XBOOL_VECTOR (a)->size; 3218 nr_bits = XBOOL_VECTOR (a)->size;
3219 count = 0; 3219 count = 0;
3220 match = NILP (b) ? (size_t) -1 : 0; 3220 match = NILP (b) ? -1 : 0;
3221 adata = (size_t *) XBOOL_VECTOR (a)->data; 3221 adata = (bits_word *) XBOOL_VECTOR (a)->data;
3222 3222
3223 eassert (nr_bits >= 0); 3223 eassert (nr_bits >= 0);
3224 3224
3225 for (i = 0; i < nr_bits / BITS_PER_SIZE_T; ++i) 3225 for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; ++i)
3226 count += popcount_size_t (adata[i] ^ match); 3226 count += popcount_bits_word (adata[i] ^ match);
3227 3227
3228 /* Mask out trailing parts of final mword. */ 3228 /* Mask out trailing parts of final mword. */
3229 if (nr_bits % BITS_PER_SIZE_T) 3229 if (nr_bits % BITS_PER_BITS_WORD)
3230 { 3230 {
3231 size_t mword = adata[i] ^ match; 3231 bits_word mword = adata[i] ^ match;
3232 mword = size_t_to_host_endian (mword); 3232 mword = bits_word_to_host_endian (mword);
3233 count += popcount_size_t (mword & bool_vector_spare_mask (nr_bits)); 3233 count += popcount_bits_word (mword & bool_vector_spare_mask (nr_bits));
3234 } 3234 }
3235 3235
3236 return make_number (count); 3236 return make_number (count);
@@ -3247,9 +3247,9 @@ index into the vector. */)
3247 ptrdiff_t count; 3247 ptrdiff_t count;
3248 EMACS_INT nr_bits; 3248 EMACS_INT nr_bits;
3249 ptrdiff_t offset; 3249 ptrdiff_t offset;
3250 size_t *adata; 3250 bits_word *adata;
3251 size_t twiddle; 3251 bits_word twiddle;
3252 size_t mword; /* Machine word. */ 3252 bits_word mword; /* Machine word. */
3253 ptrdiff_t pos; 3253 ptrdiff_t pos;
3254 ptrdiff_t nr_words; 3254 ptrdiff_t nr_words;
3255 3255
@@ -3260,30 +3260,30 @@ index into the vector. */)
3260 if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */ 3260 if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */
3261 args_out_of_range (a, i); 3261 args_out_of_range (a, i);
3262 3262
3263 adata = (size_t *) XBOOL_VECTOR (a)->data; 3263 adata = (bits_word *) XBOOL_VECTOR (a)->data;
3264 3264
3265 assume (nr_bits >= 0); 3265 assume (nr_bits >= 0);
3266 nr_words = ROUNDUP (nr_bits, BITS_PER_SIZE_T) / BITS_PER_SIZE_T; 3266 nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD;
3267 3267
3268 pos = XFASTINT (i) / BITS_PER_SIZE_T; 3268 pos = XFASTINT (i) / BITS_PER_BITS_WORD;
3269 offset = XFASTINT (i) % BITS_PER_SIZE_T; 3269 offset = XFASTINT (i) % BITS_PER_BITS_WORD;
3270 count = 0; 3270 count = 0;
3271 3271
3272 /* By XORing with twiddle, we transform the problem of "count 3272 /* By XORing with twiddle, we transform the problem of "count
3273 consecutive equal values" into "count the zero bits". The latter 3273 consecutive equal values" into "count the zero bits". The latter
3274 operation usually has hardware support. */ 3274 operation usually has hardware support. */
3275 twiddle = NILP (b) ? 0 : (size_t) -1; 3275 twiddle = NILP (b) ? 0 : -1;
3276 3276
3277 /* Scan the remainder of the mword at the current offset. */ 3277 /* Scan the remainder of the mword at the current offset. */
3278 if (pos < nr_words && offset != 0) 3278 if (pos < nr_words && offset != 0)
3279 { 3279 {
3280 mword = size_t_to_host_endian (adata[pos]); 3280 mword = bits_word_to_host_endian (adata[pos]);
3281 mword ^= twiddle; 3281 mword ^= twiddle;
3282 mword >>= offset; 3282 mword >>= offset;
3283 count = count_trailing_zero_bits (mword); 3283 count = count_trailing_zero_bits (mword);
3284 count = min (count, BITS_PER_SIZE_T - offset); 3284 count = min (count, BITS_PER_BITS_WORD - offset);
3285 pos++; 3285 pos++;
3286 if (count + offset < BITS_PER_SIZE_T) 3286 if (count + offset < BITS_PER_BITS_WORD)
3287 return make_number (count); 3287 return make_number (count);
3288 } 3288 }
3289 3289
@@ -3292,7 +3292,7 @@ index into the vector. */)
3292 endian-independent. */ 3292 endian-independent. */
3293 while (pos < nr_words && adata[pos] == twiddle) 3293 while (pos < nr_words && adata[pos] == twiddle)
3294 { 3294 {
3295 count += BITS_PER_SIZE_T; 3295 count += BITS_PER_BITS_WORD;
3296 ++pos; 3296 ++pos;
3297 } 3297 }
3298 3298
@@ -3300,16 +3300,16 @@ index into the vector. */)
3300 { 3300 {
3301 /* If we stopped because of a mismatch, see how many bits match 3301 /* If we stopped because of a mismatch, see how many bits match
3302 in the current mword. */ 3302 in the current mword. */
3303 mword = size_t_to_host_endian (adata[pos]); 3303 mword = bits_word_to_host_endian (adata[pos]);
3304 mword ^= twiddle; 3304 mword ^= twiddle;
3305 count += count_trailing_zero_bits (mword); 3305 count += count_trailing_zero_bits (mword);
3306 } 3306 }
3307 else if (nr_bits % BITS_PER_SIZE_T != 0) 3307 else if (nr_bits % BITS_PER_BITS_WORD != 0)
3308 { 3308 {
3309 /* If we hit the end, we might have overshot our count. Reduce 3309 /* If we hit the end, we might have overshot our count. Reduce
3310 the total by the number of spare bits at the end of the 3310 the total by the number of spare bits at the end of the
3311 vector. */ 3311 vector. */
3312 count -= BITS_PER_SIZE_T - nr_bits % BITS_PER_SIZE_T; 3312 count -= BITS_PER_BITS_WORD - nr_bits % BITS_PER_BITS_WORD;
3313 } 3313 }
3314 3314
3315 return make_number (count); 3315 return make_number (count);
diff --git a/src/lisp.h b/src/lisp.h
index b8863d6821d..3e63aa0255f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -64,6 +64,11 @@ typedef unsigned int EMACS_UINT;
64# endif 64# endif
65#endif 65#endif
66 66
67/* An unsigned integer type representing a fixed-length bit sequence,
68 suitable for words in a Lisp bool vector. */
69typedef size_t bits_word;
70#define BITS_WORD_MAX SIZE_MAX
71
67/* Number of bits in some machine integer types. */ 72/* Number of bits in some machine integer types. */
68enum 73enum
69 { 74 {
@@ -71,7 +76,7 @@ enum
71 BITS_PER_SHORT = CHAR_BIT * sizeof (short), 76 BITS_PER_SHORT = CHAR_BIT * sizeof (short),
72 BITS_PER_INT = CHAR_BIT * sizeof (int), 77 BITS_PER_INT = CHAR_BIT * sizeof (int),
73 BITS_PER_LONG = CHAR_BIT * sizeof (long int), 78 BITS_PER_LONG = CHAR_BIT * sizeof (long int),
74 BITS_PER_SIZE_T = CHAR_BIT * sizeof (size_t), 79 BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word),
75 BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT) 80 BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT)
76 }; 81 };
77 82