]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/sbitmap.c
Update copyright years.
[thirdparty/gcc.git] / gcc / sbitmap.c
CommitLineData
152bf224 1/* Simple bitmaps.
fbd26352 2 Copyright (C) 1999-2019 Free Software Foundation, Inc.
152bf224 3
f12b58b3 4This file is part of GCC.
152bf224 5
f12b58b3 6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8c4c00c1 8Software Foundation; either version 3, or (at your option) any later
f12b58b3 9version.
152bf224 10
f12b58b3 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
152bf224 15
16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
152bf224 19
20#include "config.h"
21#include "system.h"
805e22b2 22#include "coretypes.h"
0f71a633 23#include "sbitmap.h"
00112593 24#include "selftest.h"
152bf224 25
7ffb8e03 26typedef SBITMAP_ELT_TYPE *sbitmap_ptr;
27typedef const SBITMAP_ELT_TYPE *const_sbitmap_ptr;
28
64764082 29/* Return the size in bytes of a bitmap MAP. */
30
31static inline unsigned int sbitmap_size_bytes (const_sbitmap map)
32{
33 return map->size * sizeof (SBITMAP_ELT_TYPE);
34}
35
8effb48f 36
152bf224 37/* Bitmap manipulation routines. */
38
39/* Allocate a simple bitmap of N_ELMS bits. */
40
41sbitmap
60b8c5b3 42sbitmap_alloc (unsigned int n_elms)
152bf224 43{
43bf47e9 44 unsigned int bytes, size, amt;
152bf224 45 sbitmap bmap;
46
47 size = SBITMAP_SET_SIZE (n_elms);
48 bytes = size * sizeof (SBITMAP_ELT_TYPE);
49 amt = (sizeof (struct simple_bitmap_def)
50 + bytes - sizeof (SBITMAP_ELT_TYPE));
f7f3687c 51 bmap = (sbitmap) xmalloc (amt);
152bf224 52 bmap->n_bits = n_elms;
53 bmap->size = size;
152bf224 54 return bmap;
55}
56
e52a3bed 57/* Resize a simple bitmap BMAP to N_ELMS bits. If increasing the
58 size of BMAP, clear the new bits to zero if the DEF argument
59 is zero, and set them to one otherwise. */
60
61sbitmap
60b8c5b3 62sbitmap_resize (sbitmap bmap, unsigned int n_elms, int def)
e52a3bed 63{
64 unsigned int bytes, size, amt;
65 unsigned int last_bit;
66
67 size = SBITMAP_SET_SIZE (n_elms);
68 bytes = size * sizeof (SBITMAP_ELT_TYPE);
64764082 69 if (bytes > sbitmap_size_bytes (bmap))
e52a3bed 70 {
71 amt = (sizeof (struct simple_bitmap_def)
72 + bytes - sizeof (SBITMAP_ELT_TYPE));
f7f3687c 73 bmap = (sbitmap) xrealloc (bmap, amt);
e52a3bed 74 }
75
76 if (n_elms > bmap->n_bits)
77 {
78 if (def)
79 {
48e1416a 80 memset (bmap->elms + bmap->size, -1,
64764082 81 bytes - sbitmap_size_bytes (bmap));
e52a3bed 82
83 /* Set the new bits if the original last element. */
84 last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
85 if (last_bit)
86 bmap->elms[bmap->size - 1]
87 |= ~((SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit));
88
89 /* Clear the unused bit in the new last element. */
90 last_bit = n_elms % SBITMAP_ELT_BITS;
91 if (last_bit)
92 bmap->elms[size - 1]
93 &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
94 }
95 else
87f8e12b 96 memset (bmap->elms + bmap->size, 0, bytes - sbitmap_size_bytes (bmap));
e52a3bed 97 }
98 else if (n_elms < bmap->n_bits)
99 {
037845e5 100 /* Clear the surplus bits in the last word. */
e52a3bed 101 last_bit = n_elms % SBITMAP_ELT_BITS;
102 if (last_bit)
87f8e12b 103 bmap->elms[size - 1]
104 &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
e52a3bed 105 }
106
107 bmap->n_bits = n_elms;
108 bmap->size = size;
e52a3bed 109 return bmap;
110}
111
dac49aa5 112/* Re-allocate a simple bitmap of N_ELMS bits. New storage is uninitialized. */
4ee9c684 113
114sbitmap
115sbitmap_realloc (sbitmap src, unsigned int n_elms)
116{
117 unsigned int bytes, size, amt;
118 sbitmap bmap;
119
120 size = SBITMAP_SET_SIZE (n_elms);
121 bytes = size * sizeof (SBITMAP_ELT_TYPE);
122 amt = (sizeof (struct simple_bitmap_def)
123 + bytes - sizeof (SBITMAP_ELT_TYPE));
124
64764082 125 if (sbitmap_size_bytes (src) >= bytes)
4ee9c684 126 {
127 src->n_bits = n_elms;
128 return src;
129 }
130
131 bmap = (sbitmap) xrealloc (src, amt);
132 bmap->n_bits = n_elms;
133 bmap->size = size;
4ee9c684 134 return bmap;
135}
136
152bf224 137/* Allocate a vector of N_VECS bitmaps of N_ELMS bits. */
138
139sbitmap *
60b8c5b3 140sbitmap_vector_alloc (unsigned int n_vecs, unsigned int n_elms)
152bf224 141{
43bf47e9 142 unsigned int i, bytes, offset, elm_bytes, size, amt, vector_bytes;
152bf224 143 sbitmap *bitmap_vector;
144
145 size = SBITMAP_SET_SIZE (n_elms);
146 bytes = size * sizeof (SBITMAP_ELT_TYPE);
147 elm_bytes = (sizeof (struct simple_bitmap_def)
148 + bytes - sizeof (SBITMAP_ELT_TYPE));
149 vector_bytes = n_vecs * sizeof (sbitmap *);
150
151 /* Round up `vector_bytes' to account for the alignment requirements
152 of an sbitmap. One could allocate the vector-table and set of sbitmaps
153 separately, but that requires maintaining two pointers or creating
154 a cover struct to hold both pointers (so our result is still just
155 one pointer). Neither is a bad idea, but this is simpler for now. */
156 {
157 /* Based on DEFAULT_ALIGNMENT computation in obstack.c. */
158 struct { char x; SBITMAP_ELT_TYPE y; } align;
159 int alignment = (char *) & align.y - & align.x;
160 vector_bytes = (vector_bytes + alignment - 1) & ~ (alignment - 1);
161 }
162
163 amt = vector_bytes + (n_vecs * elm_bytes);
f7f3687c 164 bitmap_vector = (sbitmap *) xmalloc (amt);
152bf224 165
43bf47e9 166 for (i = 0, offset = vector_bytes; i < n_vecs; i++, offset += elm_bytes)
152bf224 167 {
168 sbitmap b = (sbitmap) ((char *) bitmap_vector + offset);
43bf47e9 169
152bf224 170 bitmap_vector[i] = b;
171 b->n_bits = n_elms;
172 b->size = size;
152bf224 173 }
174
175 return bitmap_vector;
176}
177
178/* Copy sbitmap SRC to DST. */
179
180void
53c5d9d4 181bitmap_copy (sbitmap dst, const_sbitmap src)
152bf224 182{
5f531f13 183 gcc_checking_assert (src->size <= dst->size);
184
fe766efd 185 memcpy (dst->elms, src->elms, sizeof (SBITMAP_ELT_TYPE) * dst->size);
8effb48f 186}
187
1be87b72 188/* Determine if a == b. */
e0d1ffe3 189int
53c5d9d4 190bitmap_equal_p (const_sbitmap a, const_sbitmap b)
e0d1ffe3 191{
5f531f13 192 bitmap_check_sizes (a, b);
193
e0d1ffe3 194 return !memcmp (a->elms, b->elms, sizeof (SBITMAP_ELT_TYPE) * a->size);
195}
739c050b 196
3072d30e 197/* Return true if the bitmap is empty. */
198
199bool
53c5d9d4 200bitmap_empty_p (const_sbitmap bmap)
3072d30e 201{
202 unsigned int i;
203 for (i=0; i<bmap->size; i++)
204 if (bmap->elms[i])
205 return false;
206
207 return true;
208}
209
79286215 210/* Clear COUNT bits from START in BMAP. */
211
212void
213bitmap_clear_range (sbitmap bmap, unsigned int start, unsigned int count)
214{
215 if (count == 0)
216 return;
217
5f531f13 218 bitmap_check_index (bmap, start + count - 1);
219
79286215 220 unsigned int start_word = start / SBITMAP_ELT_BITS;
221 unsigned int start_bitno = start % SBITMAP_ELT_BITS;
222
223 /* Clearing less than a full word, starting at the beginning of a word. */
224 if (start_bitno == 0 && count < SBITMAP_ELT_BITS)
225 {
226 SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << count) - 1;
227 bmap->elms[start_word] &= ~mask;
228 return;
229 }
230
231 unsigned int end_word = (start + count) / SBITMAP_ELT_BITS;
232 unsigned int end_bitno = (start + count) % SBITMAP_ELT_BITS;
233
234 /* Clearing starts somewhere in the middle of the first word. Clear up to
235 the end of the first word or the end of the requested region, whichever
236 comes first. */
237 if (start_bitno != 0)
238 {
239 unsigned int nbits = ((start_word == end_word)
240 ? end_bitno - start_bitno
241 : SBITMAP_ELT_BITS - start_bitno);
242 SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << nbits) - 1;
243 mask <<= start_bitno;
244 bmap->elms[start_word] &= ~mask;
245 start_word++;
246 count -= nbits;
247 }
248
249 if (count == 0)
250 return;
251
252 /* Now clear words at a time until we hit a partial word. */
253 unsigned int nwords = (end_word - start_word);
254 if (nwords)
255 {
256 memset (&bmap->elms[start_word], 0, nwords * sizeof (SBITMAP_ELT_TYPE));
257 count -= nwords * sizeof (SBITMAP_ELT_TYPE) * BITS_PER_UNIT;
258 start_word += nwords;
259 }
260
261 if (count == 0)
262 return;
263
264 /* Now handle residuals in the last word. */
265 SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << count) - 1;
266 bmap->elms[start_word] &= ~mask;
267}
268
269/* Set COUNT bits from START in BMAP. */
270void
271bitmap_set_range (sbitmap bmap, unsigned int start, unsigned int count)
272{
273 if (count == 0)
274 return;
275
5f531f13 276 bitmap_check_index (bmap, start + count - 1);
277
79286215 278 unsigned int start_word = start / SBITMAP_ELT_BITS;
279 unsigned int start_bitno = start % SBITMAP_ELT_BITS;
280
281 /* Setting less than a full word, starting at the beginning of a word. */
282 if (start_bitno == 0 && count < SBITMAP_ELT_BITS)
283 {
284 SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << count) - 1;
285 bmap->elms[start_word] |= mask;
286 return;
287 }
288
289 unsigned int end_word = (start + count) / SBITMAP_ELT_BITS;
290 unsigned int end_bitno = (start + count) % SBITMAP_ELT_BITS;
291
292 /* Setting starts somewhere in the middle of the first word. Set up to
293 the end of the first word or the end of the requested region, whichever
294 comes first. */
295 if (start_bitno != 0)
296 {
297 unsigned int nbits = ((start_word == end_word)
298 ? end_bitno - start_bitno
299 : SBITMAP_ELT_BITS - start_bitno);
300 SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << nbits) - 1;
301 mask <<= start_bitno;
302 bmap->elms[start_word] |= mask;
303 start_word++;
304 count -= nbits;
305 }
306
307 if (count == 0)
308 return;
309
310 /* Now set words at a time until we hit a partial word. */
311 unsigned int nwords = (end_word - start_word);
312 if (nwords)
313 {
314 memset (&bmap->elms[start_word], 0xff,
315 nwords * sizeof (SBITMAP_ELT_TYPE));
316 count -= nwords * sizeof (SBITMAP_ELT_TYPE) * BITS_PER_UNIT;
317 start_word += nwords;
318 }
319
320 if (count == 0)
321 return;
322
323 /* Now handle residuals in the last word. */
324 SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << count) - 1;
325 bmap->elms[start_word] |= mask;
326}
327
1b487905 328/* Return TRUE if any bit between START and END inclusive is set within
329 the simple bitmap BMAP. Return FALSE otherwise. */
330
331bool
332bitmap_bit_in_range_p (const_sbitmap bmap, unsigned int start, unsigned int end)
333{
00112593 334 gcc_checking_assert (start <= end);
5f531f13 335 bitmap_check_index (bmap, end);
336
1b487905 337 unsigned int start_word = start / SBITMAP_ELT_BITS;
338 unsigned int start_bitno = start % SBITMAP_ELT_BITS;
339
1b487905 340 unsigned int end_word = end / SBITMAP_ELT_BITS;
341 unsigned int end_bitno = end % SBITMAP_ELT_BITS;
342
00112593 343 /* Check beginning of first word if different from zero. */
1b487905 344 if (start_bitno != 0)
345 {
00112593 346 SBITMAP_ELT_TYPE high_mask = ~(SBITMAP_ELT_TYPE)0;
347 if (start_word == end_word && end_bitno + 1 < SBITMAP_ELT_BITS)
348 high_mask = ((SBITMAP_ELT_TYPE)1 << (end_bitno + 1)) - 1;
349
350 SBITMAP_ELT_TYPE low_mask = ((SBITMAP_ELT_TYPE)1 << start_bitno) - 1;
351 SBITMAP_ELT_TYPE mask = high_mask - low_mask;
1b487905 352 if (bmap->elms[start_word] & mask)
353 return true;
354 start_word++;
355 }
356
357 if (start_word > end_word)
358 return false;
359
360 /* Now test words at a time until we hit a partial word. */
361 unsigned int nwords = (end_word - start_word);
362 while (nwords)
363 {
364 if (bmap->elms[start_word])
365 return true;
366 start_word++;
367 nwords--;
368 }
369
370 /* Now handle residuals in the last word. */
00112593 371 SBITMAP_ELT_TYPE mask = ~(SBITMAP_ELT_TYPE)0;
372 if (end_bitno + 1 < SBITMAP_ELT_BITS)
373 mask = ((SBITMAP_ELT_TYPE)1 << (end_bitno + 1)) - 1;
1b487905 374 return (bmap->elms[start_word] & mask) != 0;
375}
376
79286215 377#if GCC_VERSION < 3400
378/* Table of number of set bits in a character, indexed by value of char. */
379static const unsigned char popcount_table[] =
380{
381 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
382 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
383 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
384 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
385 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
386 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
387 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
388 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
389};
390
391static unsigned long
392sbitmap_popcount (SBITMAP_ELT_TYPE a)
393{
394 unsigned long ret = 0;
395 unsigned i;
396
397 /* Just do this the table way for now */
398 for (i = 0; i < HOST_BITS_PER_WIDEST_FAST_INT; i += 8)
399 ret += popcount_table[(a >> i) & 0xff];
400 return ret;
401}
402#endif
403
404/* Count and return the number of bits set in the bitmap BMAP. */
405
406unsigned int
407bitmap_count_bits (const_sbitmap bmap)
408{
409 unsigned int count = 0;
410 for (unsigned int i = 0; i < bmap->size; i++)
411 if (bmap->elms[i])
412 {
413#if GCC_VERSION < 3400
414 count += sbitmap_popcount (bmap->elms[i]);
415#else
416# if HOST_BITS_PER_WIDEST_FAST_INT == HOST_BITS_PER_LONG
417 count += __builtin_popcountl (bmap->elms[i]);
418# elif HOST_BITS_PER_WIDEST_FAST_INT == HOST_BITS_PER_LONGLONG
419 count += __builtin_popcountll (bmap->elms[i]);
420# else
421 count += __builtin_popcount (bmap->elms[i]);
422# endif
423#endif
424 }
425 return count;
426}
349621f0 427
152bf224 428/* Zero all elements in a bitmap. */
429
430void
53c5d9d4 431bitmap_clear (sbitmap bmap)
152bf224 432{
64764082 433 memset (bmap->elms, 0, sbitmap_size_bytes (bmap));
152bf224 434}
435
43bf47e9 436/* Set all elements in a bitmap to ones. */
152bf224 437
438void
53c5d9d4 439bitmap_ones (sbitmap bmap)
152bf224 440{
4076a367 441 unsigned int last_bit;
442
64764082 443 memset (bmap->elms, -1, sbitmap_size_bytes (bmap));
4076a367 444
43bf47e9 445 last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
4076a367 446 if (last_bit)
87f8e12b 447 bmap->elms[bmap->size - 1]
448 = (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
152bf224 449}
450
451/* Zero a vector of N_VECS bitmaps. */
452
453void
53c5d9d4 454bitmap_vector_clear (sbitmap *bmap, unsigned int n_vecs)
152bf224 455{
43bf47e9 456 unsigned int i;
152bf224 457
458 for (i = 0; i < n_vecs; i++)
53c5d9d4 459 bitmap_clear (bmap[i]);
152bf224 460}
461
43bf47e9 462/* Set a vector of N_VECS bitmaps to ones. */
152bf224 463
464void
53c5d9d4 465bitmap_vector_ones (sbitmap *bmap, unsigned int n_vecs)
152bf224 466{
43bf47e9 467 unsigned int i;
152bf224 468
469 for (i = 0; i < n_vecs; i++)
53c5d9d4 470 bitmap_ones (bmap[i]);
152bf224 471}
472
473/* Set DST to be A union (B - C).
474 DST = A | (B & ~C).
739c050b 475 Returns true if any change is made. */
152bf224 476
739c050b 477bool
53c5d9d4 478bitmap_ior_and_compl (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
152bf224 479{
5f531f13 480 bitmap_check_sizes (a, b);
481 bitmap_check_sizes (b, c);
482
739c050b 483 unsigned int i, n = dst->size;
484 sbitmap_ptr dstp = dst->elms;
ac0ff66f 485 const_sbitmap_ptr ap = a->elms;
486 const_sbitmap_ptr bp = b->elms;
487 const_sbitmap_ptr cp = c->elms;
739c050b 488 SBITMAP_ELT_TYPE changed = 0;
489
490 for (i = 0; i < n; i++)
152bf224 491 {
ac0ff66f 492 const SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & ~*cp++);
739c050b 493 changed |= *dstp ^ tmp;
494 *dstp++ = tmp;
152bf224 495 }
43bf47e9 496
739c050b 497 return changed != 0;
498}
499
152bf224 500/* Set bitmap DST to the bitwise negation of the bitmap SRC. */
501
502void
53c5d9d4 503bitmap_not (sbitmap dst, const_sbitmap src)
152bf224 504{
5f531f13 505 bitmap_check_sizes (src, dst);
506
739c050b 507 unsigned int i, n = dst->size;
508 sbitmap_ptr dstp = dst->elms;
ac0ff66f 509 const_sbitmap_ptr srcp = src->elms;
93036b9b 510 unsigned int last_bit;
152bf224 511
739c050b 512 for (i = 0; i < n; i++)
513 *dstp++ = ~*srcp++;
93036b9b 514
53c5d9d4 515 /* Zero all bits past n_bits, by ANDing dst with bitmap_ones. */
93036b9b 516 last_bit = src->n_bits % SBITMAP_ELT_BITS;
517 if (last_bit)
518 dst->elms[n-1] = dst->elms[n-1]
519 & ((SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit));
152bf224 520}
521
522/* Set the bits in DST to be the difference between the bits
43bf47e9 523 in A and the bits in B. i.e. dst = a & (~b). */
152bf224 524
525void
53c5d9d4 526bitmap_and_compl (sbitmap dst, const_sbitmap a, const_sbitmap b)
152bf224 527{
5f531f13 528 bitmap_check_sizes (a, b);
529 bitmap_check_sizes (b, dst);
530
cb5c5698 531 unsigned int i, dst_size = dst->size;
532 unsigned int min_size = dst->size;
739c050b 533 sbitmap_ptr dstp = dst->elms;
ac0ff66f 534 const_sbitmap_ptr ap = a->elms;
535 const_sbitmap_ptr bp = b->elms;
60b8c5b3 536
cb5c5698 537 /* A should be at least as large as DEST, to have a defined source. */
04e579b6 538 gcc_assert (a->size >= dst_size);
cb5c5698 539 /* If minuend is smaller, we simply pretend it to be zero bits, i.e.
540 only copy the subtrahend into dest. */
541 if (b->size < min_size)
542 min_size = b->size;
543 for (i = 0; i < min_size; i++)
544 *dstp++ = *ap++ & (~*bp++);
545 /* Now fill the rest of dest from A, if B was too short.
546 This makes sense only when destination and A differ. */
547 if (dst != a && i != dst_size)
548 for (; i < dst_size; i++)
549 *dstp++ = *ap++;
152bf224 550}
551
7d0585a5 552/* Return true if there are any bits set in A are also set in B.
553 Return false otherwise. */
554
555bool
53c5d9d4 556bitmap_intersect_p (const_sbitmap a, const_sbitmap b)
7d0585a5 557{
5f531f13 558 bitmap_check_sizes (a, b);
559
ac0ff66f 560 const_sbitmap_ptr ap = a->elms;
561 const_sbitmap_ptr bp = b->elms;
7d0585a5 562 unsigned int i, n;
563
564 n = MIN (a->size, b->size);
565 for (i = 0; i < n; i++)
566 if ((*ap++ & *bp++) != 0)
567 return true;
568
569 return false;
570}
571
4076a367 572/* Set DST to be (A and B).
f712a0dc 573 Return nonzero if any change is made. */
152bf224 574
739c050b 575bool
53c5d9d4 576bitmap_and (sbitmap dst, const_sbitmap a, const_sbitmap b)
739c050b 577{
5f531f13 578 bitmap_check_sizes (a, b);
579 bitmap_check_sizes (b, dst);
580
739c050b 581 unsigned int i, n = dst->size;
582 sbitmap_ptr dstp = dst->elms;
ac0ff66f 583 const_sbitmap_ptr ap = a->elms;
584 const_sbitmap_ptr bp = b->elms;
620aadcf 585 SBITMAP_ELT_TYPE changed = 0;
739c050b 586
587 for (i = 0; i < n; i++)
8effb48f 588 {
ac0ff66f 589 const SBITMAP_ELT_TYPE tmp = *ap++ & *bp++;
620aadcf 590 SBITMAP_ELT_TYPE wordchanged = *dstp ^ tmp;
8effb48f 591 *dstp++ = tmp;
620aadcf 592 changed |= wordchanged;
8effb48f 593 }
620aadcf 594 return changed != 0;
152bf224 595}
43bf47e9 596
e0d1ffe3 597/* Set DST to be (A xor B)).
f712a0dc 598 Return nonzero if any change is made. */
e0d1ffe3 599
739c050b 600bool
53c5d9d4 601bitmap_xor (sbitmap dst, const_sbitmap a, const_sbitmap b)
739c050b 602{
5f531f13 603 bitmap_check_sizes (a, b);
604 bitmap_check_sizes (b, dst);
605
739c050b 606 unsigned int i, n = dst->size;
607 sbitmap_ptr dstp = dst->elms;
ac0ff66f 608 const_sbitmap_ptr ap = a->elms;
609 const_sbitmap_ptr bp = b->elms;
620aadcf 610 SBITMAP_ELT_TYPE changed = 0;
739c050b 611
612 for (i = 0; i < n; i++)
8effb48f 613 {
ac0ff66f 614 const SBITMAP_ELT_TYPE tmp = *ap++ ^ *bp++;
620aadcf 615 SBITMAP_ELT_TYPE wordchanged = *dstp ^ tmp;
8effb48f 616 *dstp++ = tmp;
620aadcf 617 changed |= wordchanged;
8effb48f 618 }
620aadcf 619 return changed != 0;
e0d1ffe3 620}
621
152bf224 622/* Set DST to be (A or B)).
f712a0dc 623 Return nonzero if any change is made. */
152bf224 624
739c050b 625bool
53c5d9d4 626bitmap_ior (sbitmap dst, const_sbitmap a, const_sbitmap b)
739c050b 627{
5f531f13 628 bitmap_check_sizes (a, b);
629 bitmap_check_sizes (b, dst);
630
739c050b 631 unsigned int i, n = dst->size;
632 sbitmap_ptr dstp = dst->elms;
ac0ff66f 633 const_sbitmap_ptr ap = a->elms;
634 const_sbitmap_ptr bp = b->elms;
620aadcf 635 SBITMAP_ELT_TYPE changed = 0;
739c050b 636
637 for (i = 0; i < n; i++)
8effb48f 638 {
ac0ff66f 639 const SBITMAP_ELT_TYPE tmp = *ap++ | *bp++;
620aadcf 640 SBITMAP_ELT_TYPE wordchanged = *dstp ^ tmp;
8effb48f 641 *dstp++ = tmp;
620aadcf 642 changed |= wordchanged;
8effb48f 643 }
620aadcf 644 return changed != 0;
152bf224 645}
43bf47e9 646
f712a0dc 647/* Return nonzero if A is a subset of B. */
a4d05baf 648
739c050b 649bool
53c5d9d4 650bitmap_subset_p (const_sbitmap a, const_sbitmap b)
a4d05baf 651{
5f531f13 652 bitmap_check_sizes (a, b);
653
739c050b 654 unsigned int i, n = a->size;
ac0ff66f 655 const_sbitmap_ptr ap, bp;
a4d05baf 656
739c050b 657 for (ap = a->elms, bp = b->elms, i = 0; i < n; i++, ap++, bp++)
af122f0a 658 if ((*ap | *bp) != *bp)
739c050b 659 return false;
43bf47e9 660
739c050b 661 return true;
a4d05baf 662}
152bf224 663
664/* Set DST to be (A or (B and C)).
f712a0dc 665 Return nonzero if any change is made. */
152bf224 666
739c050b 667bool
53c5d9d4 668bitmap_or_and (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
152bf224 669{
5f531f13 670 bitmap_check_sizes (a, b);
671 bitmap_check_sizes (b, c);
672 bitmap_check_sizes (c, dst);
673
739c050b 674 unsigned int i, n = dst->size;
675 sbitmap_ptr dstp = dst->elms;
ac0ff66f 676 const_sbitmap_ptr ap = a->elms;
677 const_sbitmap_ptr bp = b->elms;
678 const_sbitmap_ptr cp = c->elms;
739c050b 679 SBITMAP_ELT_TYPE changed = 0;
680
681 for (i = 0; i < n; i++)
152bf224 682 {
ac0ff66f 683 const SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & *cp++);
739c050b 684 changed |= *dstp ^ tmp;
685 *dstp++ = tmp;
152bf224 686 }
43bf47e9 687
739c050b 688 return changed != 0;
689}
690
43bf47e9 691/* Set DST to be (A and (B or C)).
f712a0dc 692 Return nonzero if any change is made. */
152bf224 693
739c050b 694bool
53c5d9d4 695bitmap_and_or (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
152bf224 696{
5f531f13 697 bitmap_check_sizes (a, b);
698 bitmap_check_sizes (b, c);
699 bitmap_check_sizes (c, dst);
700
739c050b 701 unsigned int i, n = dst->size;
702 sbitmap_ptr dstp = dst->elms;
ac0ff66f 703 const_sbitmap_ptr ap = a->elms;
704 const_sbitmap_ptr bp = b->elms;
705 const_sbitmap_ptr cp = c->elms;
739c050b 706 SBITMAP_ELT_TYPE changed = 0;
707
708 for (i = 0; i < n; i++)
152bf224 709 {
ac0ff66f 710 const SBITMAP_ELT_TYPE tmp = *ap++ & (*bp++ | *cp++);
739c050b 711 changed |= *dstp ^ tmp;
712 *dstp++ = tmp;
152bf224 713 }
43bf47e9 714
739c050b 715 return changed != 0;
716}
717
7fcadf62 718/* Return number of first bit set in the bitmap, -1 if none. */
719
720int
53c5d9d4 721bitmap_first_set_bit (const_sbitmap bmap)
7fcadf62 722{
86c1585a 723 unsigned int n = 0;
3e790786 724 sbitmap_iterator sbi;
43bf47e9 725
0d211963 726 EXECUTE_IF_SET_IN_BITMAP (bmap, 0, n, sbi)
3e790786 727 return n;
7fcadf62 728 return -1;
729}
730
731/* Return number of last bit set in the bitmap, -1 if none. */
732
733int
53c5d9d4 734bitmap_last_set_bit (const_sbitmap bmap)
7fcadf62 735{
736 int i;
ac0ff66f 737 const SBITMAP_ELT_TYPE *const ptr = bmap->elms;
43bf47e9 738
7fcadf62 739 for (i = bmap->size - 1; i >= 0; i--)
740 {
ac0ff66f 741 const SBITMAP_ELT_TYPE word = ptr[i];
43bf47e9 742
743 if (word != 0)
744 {
745 unsigned int index = (i + 1) * SBITMAP_ELT_BITS - 1;
746 SBITMAP_ELT_TYPE mask
747 = (SBITMAP_ELT_TYPE) 1 << (SBITMAP_ELT_BITS - 1);
748
749 while (1)
750 {
751 if ((word & mask) != 0)
752 return index;
753
754 mask >>= 1;
755 index--;
756 }
757 }
7fcadf62 758 }
43bf47e9 759
7fcadf62 760 return -1;
761}
762
152bf224 763void
53c5d9d4 764dump_bitmap (FILE *file, const_sbitmap bmap)
152bf224 765{
43bf47e9 766 unsigned int i, n, j;
767 unsigned int set_size = bmap->size;
768 unsigned int total_bits = bmap->n_bits;
152bf224 769
770 fprintf (file, " ");
771 for (i = n = 0; i < set_size && n < total_bits; i++)
43bf47e9 772 for (j = 0; j < SBITMAP_ELT_BITS && n < total_bits; j++, n++)
773 {
774 if (n != 0 && n % 10 == 0)
775 fprintf (file, " ");
776
777 fprintf (file, "%d",
778 (bmap->elms[i] & ((SBITMAP_ELT_TYPE) 1 << j)) != 0);
779 }
780
152bf224 781 fprintf (file, "\n");
782}
783
c7d89805 784DEBUG_FUNCTION void
785debug_raw (simple_bitmap_def &ref)
786{
787 dump_bitmap (stderr, &ref);
788}
789
790DEBUG_FUNCTION void
791debug_raw (simple_bitmap_def *ptr)
792{
793 if (ptr)
794 debug_raw (*ptr);
795 else
796 fprintf (stderr, "<nil>\n");
797}
798
43bf47e9 799void
53c5d9d4 800dump_bitmap_file (FILE *file, const_sbitmap bmap)
43bf47e9 801{
802 unsigned int i, pos;
803
cb5c5698 804 fprintf (file, "n_bits = %d, set = {", bmap->n_bits);
43bf47e9 805
806 for (pos = 30, i = 0; i < bmap->n_bits; i++)
08b7917c 807 if (bitmap_bit_p (bmap, i))
43bf47e9 808 {
809 if (pos > 70)
810 {
cb5c5698 811 fprintf (file, "\n ");
43bf47e9 812 pos = 0;
813 }
814
cb5c5698 815 fprintf (file, "%d ", i);
816 pos += 2 + (i >= 10) + (i >= 100) + (i >= 1000);
43bf47e9 817 }
818
cb5c5698 819 fprintf (file, "}\n");
820}
821
4b987fac 822DEBUG_FUNCTION void
53c5d9d4 823debug_bitmap (const_sbitmap bmap)
cb5c5698 824{
53c5d9d4 825 dump_bitmap_file (stderr, bmap);
43bf47e9 826}
827
c7d89805 828DEBUG_FUNCTION void
829debug (simple_bitmap_def &ref)
830{
831 dump_bitmap_file (stderr, &ref);
832}
833
834DEBUG_FUNCTION void
835debug (simple_bitmap_def *ptr)
836{
837 if (ptr)
838 debug (*ptr);
839 else
840 fprintf (stderr, "<nil>\n");
841}
842
152bf224 843void
53c5d9d4 844dump_bitmap_vector (FILE *file, const char *title, const char *subtitle,
60b8c5b3 845 sbitmap *bmaps, int n_maps)
152bf224 846{
34ad4b87 847 int i;
152bf224 848
849 fprintf (file, "%s\n", title);
34ad4b87 850 for (i = 0; i < n_maps; i++)
152bf224 851 {
34ad4b87 852 fprintf (file, "%s %d\n", subtitle, i);
53c5d9d4 853 dump_bitmap (file, bmaps[i]);
152bf224 854 }
43bf47e9 855
152bf224 856 fprintf (file, "\n");
857}
00112593 858
859#if CHECKING_P
860
861namespace selftest {
862
863/* Selftests for sbitmaps. */
864
a68b0049 865/* Checking function that uses both bitmap_bit_in_range_p and
866 loop of bitmap_bit_p and verifies consistent results. */
00112593 867
a68b0049 868static bool
869bitmap_bit_in_range_p_checking (sbitmap s, unsigned int start,
870 unsigned end)
871{
872 bool r1 = bitmap_bit_in_range_p (s, start, end);
873 bool r2 = false;
874
875 for (unsigned int i = start; i <= end; i++)
876 if (bitmap_bit_p (s, i))
877 {
878 r2 = true;
879 break;
880 }
881
882 ASSERT_EQ (r1, r2);
883 return r1;
884}
885
886/* Verify bitmap_set_range functions for sbitmap. */
887
888static void
889test_set_range ()
890{
891 sbitmap s = sbitmap_alloc (16);
892 bitmap_clear (s);
893
894 bitmap_set_range (s, 0, 1);
895 ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 0, 0));
896 ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 1, 15));
897 bitmap_set_range (s, 15, 1);
898 ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 1, 14));
899 ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 15, 15));
ffb6710c 900 sbitmap_free (s);
a68b0049 901
902 s = sbitmap_alloc (1024);
903 bitmap_clear (s);
904 bitmap_set_range (s, 512, 1);
905 ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 0, 511));
906 ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 513, 1023));
907 ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 512, 512));
908 ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 508, 512));
909 ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 508, 513));
910 ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 508, 511));
911
912 bitmap_clear (s);
913 bitmap_set_range (s, 512, 64);
914 ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 0, 511));
915 ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 512 + 64, 1023));
916 ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 512, 512));
917 ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 512 + 63, 512 + 63));
ffb6710c 918 sbitmap_free (s);
a68b0049 919}
920
921/* Verify bitmap_bit_in_range_p functions for sbitmap. */
00112593 922
923static void
a68b0049 924test_bit_in_range ()
00112593 925{
926 sbitmap s = sbitmap_alloc (1024);
927 bitmap_clear (s);
928
929 ASSERT_FALSE (bitmap_bit_in_range_p (s, 512, 1023));
930 bitmap_set_bit (s, 100);
931
932 ASSERT_FALSE (bitmap_bit_in_range_p (s, 512, 1023));
933 ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 99));
934 ASSERT_FALSE (bitmap_bit_in_range_p (s, 101, 1023));
935 ASSERT_TRUE (bitmap_bit_in_range_p (s, 1, 100));
936 ASSERT_TRUE (bitmap_bit_in_range_p (s, 64, 100));
937 ASSERT_TRUE (bitmap_bit_in_range_p (s, 100, 100));
938 ASSERT_TRUE (bitmap_bit_p (s, 100));
939
ffb6710c 940 sbitmap_free (s);
941
00112593 942 s = sbitmap_alloc (64);
943 bitmap_clear (s);
944 bitmap_set_bit (s, 63);
945 ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 63));
946 ASSERT_TRUE (bitmap_bit_in_range_p (s, 1, 63));
947 ASSERT_TRUE (bitmap_bit_in_range_p (s, 63, 63));
948 ASSERT_TRUE (bitmap_bit_p (s, 63));
ffb6710c 949 sbitmap_free (s);
00112593 950
951 s = sbitmap_alloc (1024);
952 bitmap_clear (s);
953 bitmap_set_bit (s, 128);
954 ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 127));
955 ASSERT_FALSE (bitmap_bit_in_range_p (s, 129, 1023));
956
957 ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 128));
958 ASSERT_TRUE (bitmap_bit_in_range_p (s, 1, 128));
959 ASSERT_TRUE (bitmap_bit_in_range_p (s, 128, 255));
960 ASSERT_TRUE (bitmap_bit_in_range_p (s, 128, 254));
961 ASSERT_TRUE (bitmap_bit_p (s, 128));
962
963 bitmap_clear (s);
964 bitmap_set_bit (s, 8);
965 ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 8));
966 ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 12));
967 ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 63));
968 ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 127));
969 ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 512));
970 ASSERT_TRUE (bitmap_bit_in_range_p (s, 8, 8));
971 ASSERT_TRUE (bitmap_bit_p (s, 8));
972
973 bitmap_clear (s);
974 ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 0));
975 ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 8));
976 ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 63));
977 ASSERT_FALSE (bitmap_bit_in_range_p (s, 1, 63));
978 ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 256));
979
980 bitmap_set_bit (s, 0);
981 bitmap_set_bit (s, 16);
982 bitmap_set_bit (s, 32);
983 bitmap_set_bit (s, 48);
984 bitmap_set_bit (s, 64);
985 ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 0));
986 ASSERT_TRUE (bitmap_bit_in_range_p (s, 1, 16));
987 ASSERT_TRUE (bitmap_bit_in_range_p (s, 48, 63));
988 ASSERT_TRUE (bitmap_bit_in_range_p (s, 64, 64));
989 ASSERT_FALSE (bitmap_bit_in_range_p (s, 1, 15));
990 ASSERT_FALSE (bitmap_bit_in_range_p (s, 17, 31));
991 ASSERT_FALSE (bitmap_bit_in_range_p (s, 49, 63));
992 ASSERT_FALSE (bitmap_bit_in_range_p (s, 65, 1023));
ffb6710c 993 sbitmap_free (s);
00112593 994}
995
996/* Run all of the selftests within this file. */
997
998void
999sbitmap_c_tests ()
1000{
a68b0049 1001 test_set_range ();
1002 test_bit_in_range ();
00112593 1003}
1004
1005} // namespace selftest
1006#endif /* CHECKING_P */