+++ /dev/null
-/* Sparse array-based bitmaps.
- Copyright (C) 2007-2012 Free Software Foundation, Inc.
- Contributed by Daniel Berlin <dberlin@dberlin.org>
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "ebitmap.h"
-
-/* The ebitmap data structure is a sparse bitmap structure that works
- by having two pieces:
- 1. An array of all nonzero words in the structures, organized as
- an array of HOST_WIDE_INT's.
- 2. A non-sparse bitmap saying which bitmap words are present in the
- array.
-
- As a consequence of this representation, testing whether a bit
- exists in the bitmap is faster than linked-list bitmaps. For bits
- in words that are all zero, the time to test is O(1). For bits in
- words that exist, it requires O(n/sizeof(word)) time to perform the
- test (ignoring the one element cache). It also has much better
- locality than linked-list bitmaps.
-
- To test whether a bit exists, we do the following:
- 1. Test whether the word the bit would appear in exists in the
- bitmap (O(1) check of the mask). If not, fail.
-
- 2. Population count the mask up to the word containing the bit, to
- find the place in the array the word would be (popcount is cached,
- but this is just as slow as the linked-list bitmap)
- 3. Test the word to see if the bit exists.
-
- Just like linked-list bitmaps, we cache the last element that has
- been tested in order to speed up common access patterns.
-
- Most of the other speedups are simply due to better locality of the
- single contiguous array.
-
- As would be expected in a structure like this, insertion into an
- empty word in the middle requires moving bits to make room for the
- new word. As most operations that perform sets perform them in
- order, this is rarely a problem. We also take advantage of the
- same element cache to make repeated sets to the same word O(1).
-
- Operations on the entire bitmap are also more efficient than linked
- list bitmaps, as they are all operating on contiguous memory, and
- can be easily vectorized. They are all O(number of words) +
- O(number of bits that may end up in the destination), as the
- appropriate operation is first performed on the word mask, and then
- only those elements that may generate results are touched.
-
- Memory wise, the ebitmap starts out using less memory than the
- linked-list bitmap, but its size in memory is technically bounded
- by ((index of the highest bit set) / (size of a word) + (index of
- the highest bit set) / ((size of a word) * (size of a word))) This
- is because the mask is non-sparse. The mask could be transformed
- into a sparse bitmap at the cost of making bit testing
- *theoretically* slower (real world numbers have not been computed
- yet as to whether it matters or not). */
-
-/* #define EBITMAP_DEBUGGING */
-
-/* Find the last set bit in ebitmap MAP. */
-
-int
-bitmap_last_set_bit (ebitmap map)
-{
- unsigned int i = 0;
- ebitmap_iterator ebi;
- bool foundbit = false;
-
- /* This is not the fastest way to do this, we could simply look for
- the popcount, and start there, but this function is not used
- anywhere speed critical. */
- EXECUTE_IF_SET_IN_EBITMAP (map, 0, i, ebi)
- {
- foundbit = true;
- }
-
-
- if (foundbit)
- return i;
- return -1;
-}
-
-/* Grow or shrink the internal word array for MAP to NEWSIZE
- elements. */
-
-static inline void
-ebitmap_array_grow (ebitmap map, unsigned int newsize)
-{
- if (newsize <= map->n_elts)
- {
- map->n_elts = newsize;
- return;
- }
-
- newsize += newsize / 4;
-
- map->n_elts = newsize;
- map->elts = XRESIZEVEC (EBITMAP_ELT_TYPE, map->elts, newsize);
-}
-
-/* Grow the internal word array for MAP so it is at least SIZE
- elements. Will not shrink the array if it is already big
- enough. */
-
-static inline void
-ebitmap_array_maybe_grow (ebitmap map, unsigned int size)
-{
- if (size >= map->n_elts)
- ebitmap_array_grow (map, size + 1);
-}
-
-/* Retrieve the IDX'th element from the word array for MAP. */
-
-static inline EBITMAP_ELT_TYPE
-ebitmap_array_get (ebitmap map, unsigned int idx)
-{
- gcc_assert (idx < map->n_elts);
- return map->elts[idx];
-}
-
-/* Retrieve a pointer to the IDX'th element from the word array for
- MAP. If the element index is greater than the size of the array,
- the array will be grown to the correct size. */
-
-static inline EBITMAP_ELT_TYPE *
-ebitmap_array_grow_get (ebitmap map, unsigned int idx)
-{
- if (idx >= map->n_elts)
- ebitmap_array_grow (map, idx + 1);
- return &map->elts[idx];
-}
-
-/* Initialize the internal word array for MAP, so that it is SIZE
- elements. */
-
-static inline void
-ebitmap_array_init (ebitmap map, unsigned int size)
-{
- if (size > 0)
- {
- map->elts = XNEWVEC (EBITMAP_ELT_TYPE, size);
- map->n_elts = size;
- }
- else
- {
- map->n_elts = 0;
- map->elts = NULL;
- }
-}
-
-/* Free the internal word array for MAP. */
-
-static inline void
-ebitmap_array_clear (ebitmap map)
-{
- if (map->elts)
- {
- free (map->elts);
- map->elts = NULL;
- }
- map->n_elts = 0;
-}
-
-/* Clear ebitmap MAP. */
-
-void
-bitmap_clear (ebitmap map)
-{
- ebitmap_array_clear (map);
- bitmap_clear (map->wordmask);
- map->wordmask = sbitmap_resize (map->wordmask, 1, 0);
- map->numwords = 0;
- map->cache = NULL;
- map->cacheindex = 0;
-}
-
-/* Allocate an ebitmap with enough room for SIZE bits to start out. */
-
-ebitmap
-ebitmap_alloc (unsigned int size)
-{
- ebitmap ret = XNEW (struct ebitmap_def);
- if (size == 0)
- size = EBITMAP_ELT_BITS;
- ebitmap_array_init (ret, (size + EBITMAP_ELT_BITS - 1) / EBITMAP_ELT_BITS);
- ret->wordmask = sbitmap_alloc_with_popcount (size);
- bitmap_clear (ret->wordmask);
- ret->numwords = 0;
- ret->cache = NULL;
- ret->cacheindex = 0;
-
- return ret;
-}
-
-/* Clear BIT from ebitmap MAP. */
-
-void
-bitmap_clear_bit (ebitmap map, unsigned int bit)
-{
- unsigned int wordindex = bit / EBITMAP_ELT_BITS;
- unsigned int eltwordindex = 0;
- unsigned int bitindex, shift;
- bool have_eltwordindex = false;
- EBITMAP_ELT_TYPE *elt_ptr;
-
- /* If the bit can't exist in our bitmap, just return. */
- if (map->numwords == 0)
- return;
-
- if (wordindex >= map->wordmask->n_bits
- || !bitmap_bit_p (map->wordmask, wordindex))
- return;
-
- if (map->cache != NULL && map->cacheindex == wordindex)
- elt_ptr = map->cache;
- else
- {
- eltwordindex = sbitmap_popcount (map->wordmask, wordindex);
- elt_ptr = &map->elts[eltwordindex];
- have_eltwordindex = true;
- }
-
- bitindex = bit % EBITMAP_ELT_BITS;
- shift = bitindex;
-
- *(elt_ptr) &= ~(((EBITMAP_ELT_TYPE)1) << shift);
-
- /* Clear out the empty words. */
- if (*(elt_ptr) == 0)
- {
- if (!have_eltwordindex)
- eltwordindex = sbitmap_popcount (map->wordmask, wordindex);
-
- if (map->cache != NULL)
- {
- if (map->cacheindex == wordindex)
- map->cache = NULL;
- else if (map->cacheindex > wordindex)
- map->cache = map->cache - 1;
- }
-
- bitmap_clear_bit_with_popcount (map->wordmask, wordindex);
-
- memmove(&map->elts[eltwordindex], &map->elts[eltwordindex + 1],
- sizeof (EBITMAP_ELT_TYPE) * (map->numwords - eltwordindex));
- map->numwords--;
- }
-}
-
-/* Set BIT in ebitmap MAP. */
-
-void
-bitmap_set_bit (ebitmap map, unsigned int bit)
-{
- unsigned int wordindex = bit / EBITMAP_ELT_BITS;
- unsigned int eltwordindex;
- unsigned int bitindex = bit % EBITMAP_ELT_BITS;
-
- /* If we have this element cached, just set the bit in it. */
- if (map->cache && map->cacheindex == wordindex)
- {
- (*map->cache) |= (EBITMAP_ELT_TYPE)1 << bitindex;
- return;
- }
-
- /* Resize the wordmask if necessary. */
- if (wordindex >= map->wordmask->n_bits)
- map->wordmask = sbitmap_resize (map->wordmask, wordindex + 1, 0);
-
- /* Allocate a new word in the array and move whatever is in it's
- place, if necessary. */
- if (!bitmap_bit_p (map->wordmask, wordindex))
- {
- unsigned long count;
- unsigned int i;
-
- bitmap_set_bit_with_popcount (map->wordmask, wordindex);
- count = sbitmap_popcount (map->wordmask, wordindex);
- gcc_assert (count <= map->numwords);
-
- for (i = map->numwords; i > count; i--)
- {
- EBITMAP_ELT_TYPE *newelt;
- newelt = ebitmap_array_grow_get (map, i);
- *newelt = ebitmap_array_get (map, i - 1);
- }
- map->numwords++;
- eltwordindex = count;
- ebitmap_array_maybe_grow (map, eltwordindex);
- map->elts[eltwordindex] = 0;
- }
- else
- {
- eltwordindex = sbitmap_popcount (map->wordmask, wordindex);
- }
-
- /* Set the actual bit. */
- bitindex = bit % EBITMAP_ELT_BITS;
-
- map->elts[eltwordindex] |= (EBITMAP_ELT_TYPE)1 << bitindex;
- map->cache = &map->elts[eltwordindex];
- map->cacheindex = wordindex;
-}
-
-
-/* Return true if MAP contains BIT. */
-
-bool
-bitmap_bit_p (ebitmap map, unsigned int bit)
-{
- unsigned int wordindex = bit / EBITMAP_ELT_BITS;
- unsigned int bitindex= bit % EBITMAP_ELT_BITS;
-
- /* Trivial empty ebitmap case. */
- if (map->numwords == 0)
- return false;
-
- if (map->cache && map->cacheindex == wordindex)
- return ((*map->cache) >> bitindex) & 1;
-
- /* If the wordindex is greater than the size of the wordmask, *or*
- it's not set in the wordmask, this bit can't exist in our
- ebitmap. */
- if (wordindex >= map->wordmask->n_bits
- || !bitmap_bit_p (map->wordmask, wordindex))
- return false;
-
- /* Find the bit and test it. */
- map->cacheindex = wordindex;
- wordindex = sbitmap_popcount (map->wordmask, wordindex);
- map->cache = &map->elts[wordindex];
-
- return (map->elts[wordindex] >> bitindex) & 1;
-}
-
-/* Copy ebitmap SRC to DST. */
-
-void
-bitmap_copy (ebitmap dst, ebitmap src)
-{
- /* Blow away any existing wordmask, and copy the new one. */
- sbitmap_free (dst->wordmask);
- dst->wordmask = sbitmap_alloc_with_popcount (src->wordmask->n_bits);
- bitmap_copy (dst->wordmask, src->wordmask);
-
- /* Make sure our destination array is big enough, and then copy the
- actual words. */
- ebitmap_array_grow (dst, src->numwords);
- memcpy (dst->elts, src->elts,
- src->numwords * sizeof (EBITMAP_ELT_TYPE));
- dst->numwords = src->numwords;
- dst->cache = NULL;
-}
-
-/* Dump ebitmap BMAP to FILE. */
-
-void
-dump_bitmap (FILE *file, ebitmap bmap)
-{
- unsigned int pos;
- unsigned int i;
- int res;
- unsigned int size;
-
- res = bitmap_last_set_bit (bmap->wordmask);
- if (res == -1)
- size = 0;
- else
- size = (res + 1) * EBITMAP_ELT_BITS;
-
- fprintf (file, "n_words = %d, set = {", bmap->numwords);
-
- for (pos = 30, i = 0; i < size; i++)
- if (bitmap_bit_p (bmap, i))
- {
- if (pos > 70)
- {
- fprintf (file, "\n ");
- pos = 0;
- }
-
- pos += fprintf (file, "%d ", i);
- }
-
- fprintf (file, "}\n");
-}
-
-/* Dump ebitmap BMAP to stderr. */
-
-DEBUG_FUNCTION void
-debug_bitmap (ebitmap bmap)
-{
- dump_bitmap (stderr, bmap);
-}
-
-/* Perform the operation DST &= SRC. */
-
-void
-bitmap_and_into (ebitmap dst, ebitmap src)
-{
- sbitmap_iterator sbi;
- unsigned int i;
- unsigned int neweltindex = 0;
- unsigned int dsteltindex = 0;
- unsigned int srceltindex = 0;
-
- gcc_assert (dst != src);
-
- dst->cache = NULL;
-
- /* Short circuit the empty bitmap cases. */
- if (src->numwords == 0 || dst->numwords == 0)
- {
- bitmap_clear (dst);
- return;
- }
-
- /* AND the masks, then walk the words that may actually appear in
- the result, AND'ing them. */
- bitmap_and (dst->wordmask, dst->wordmask, src->wordmask);
-
- EXECUTE_IF_SET_IN_BITMAP (dst->wordmask, 0, i, sbi)
- {
- EBITMAP_ELT_TYPE tmpword = ebitmap_array_get (src, srceltindex++);
- tmpword &= ebitmap_array_get (dst, dsteltindex++);
- if (tmpword != 0)
- {
- EBITMAP_ELT_TYPE *dstplace;
- dstplace = ebitmap_array_grow_get (dst, neweltindex++);
- *dstplace = tmpword;
- }
- else
- bitmap_clear_bit_with_popcount (dst->wordmask, i);
- }
-#ifdef EBITMAP_DEBUGGING
- {
- unsigned int i;
-
- for (i = 0; i < dst->numwords; i++)
- gcc_assert (dst->elts[i] != 0);
-
- sbitmap_verify_popcount (dst->wordmask);
- gcc_assert (sbitmap_popcount (dst->wordmask,
- dst->wordmask->n_bits) == dst->numwords);
- }
-#endif
- dst->numwords = neweltindex;
-}
-
-/* Perform the operation DST = SRC1 & SRC2. */
-
-void
-bitmap_and (ebitmap dst, ebitmap src1, ebitmap src2)
-{
- sbitmap_iterator sbi;
- unsigned int i;
- unsigned int neweltindex = 0;
- unsigned int src1eltindex = 0;
- unsigned int src2eltindex = 0;
-
- dst->cache = NULL;
- if (src1->numwords == 0 || src2->numwords == 0)
- {
- bitmap_clear (dst);
- return;
- }
-
- dst->wordmask
- = sbitmap_resize (dst->wordmask,
- MIN (src1->wordmask->n_bits, src2->wordmask->n_bits),
- 0);
- bitmap_and (dst->wordmask, src1->wordmask, src2->wordmask);
-
- EXECUTE_IF_SET_IN_BITMAP (dst->wordmask, 0, i, sbi)
- {
- bool src1hasword, src2hasword;
-
- src1hasword = bitmap_bit_p (src1->wordmask, i);
- src2hasword = bitmap_bit_p (src2->wordmask, i);
-
- if (src1hasword && src2hasword)
- {
- EBITMAP_ELT_TYPE tmpword = ebitmap_array_get (src1, src1eltindex++);
- tmpword &= ebitmap_array_get (src2, src2eltindex++);
- if (tmpword != 0)
- {
- EBITMAP_ELT_TYPE *dstplace;
- dstplace = ebitmap_array_grow_get (dst, neweltindex++);
- *dstplace = tmpword;
- }
- else
- bitmap_clear_bit_with_popcount (dst->wordmask, i);
- }
- else if (src1hasword)
- src1eltindex++;
- else
- src2eltindex++;
- }
-#ifdef EBITMAP_DEBUGGING
- {
- ebitmap_iterator ebi;
- unsigned int i;
-
- for (i = 0; i < dst->numwords; i++)
- gcc_assert (dst->elts[i] != 0);
-
- EXECUTE_IF_SET_IN_EBITMAP (src1, 0, i, ebi)
- if (bitmap_bit_p (src2, i))
- gcc_assert (bitmap_bit_p (dst, i));
-
- for (i = 0; i < dst->numwords; i++)
- gcc_assert (dst->elts[i] != 0);
-
- sbitmap_verify_popcount (dst->wordmask);
- gcc_assert (sbitmap_popcount (dst->wordmask,
- dst->wordmask->n_bits) == dst->numwords);
- }
-#endif
- dst->numwords = neweltindex;
-}
-
-/* Perform the operation DST |= SRC. Return true if any bits in DST
- changed. */
-
-bool
-bitmap_ior_into (ebitmap dst, ebitmap src)
-{
- unsigned int dstsize = dst->wordmask->n_bits;
- unsigned int srcsize = src->wordmask->n_bits;
- sbitmap_iterator sbi;
- unsigned int i;
- sbitmap tempmask;
- unsigned int neweltindex = 0;
- unsigned int dsteltindex = 0;
- unsigned int srceltindex = 0;
- bool changed = false;
- EBITMAP_ELT_TYPE *newarray;
- unsigned int newarraysize;
-#ifdef EBITMAP_DEBUGGING
- ebitmap dstcopy = ebitmap_alloc (1);
- bitmap_copy (dstcopy, dst);
-#endif
-
- dst->cache = NULL;
- if (dst == src)
- return false;
-
- if (dst->numwords == 0 && src->numwords != 0)
- {
- bitmap_copy (dst, src);
- return true;
- }
- else if (src->numwords == 0)
- return false;
-
- /* We can do without the temp mask if it's faster, but it would mean
- touching more words in the actual dense vector. */
- tempmask = sbitmap_alloc (MAX (srcsize, dstsize));
- bitmap_clear (tempmask);
- if (srcsize == dstsize)
- {
- bitmap_ior (tempmask, dst->wordmask, src->wordmask);
- }
- else
- {
- dst->wordmask = sbitmap_resize (dst->wordmask, MAX (srcsize, dstsize),
- 0);
- if (srcsize >= dstsize)
- {
- bitmap_copy_n (tempmask, dst->wordmask, dst->wordmask->size);
- bitmap_ior (tempmask, tempmask, src->wordmask);
- }
- else
- {
- bitmap_copy_n (tempmask, src->wordmask, src->wordmask->size);
- bitmap_ior (tempmask, tempmask, dst->wordmask);
- }
- }
- newarraysize = src->numwords + dst->numwords;
- newarray = XNEWVEC (EBITMAP_ELT_TYPE, newarraysize);
-
- EXECUTE_IF_SET_IN_BITMAP (tempmask, 0, i, sbi)
- {
- bool dsthasword, srchasword;
-
- dsthasword = (i < dst->wordmask->n_bits
- && bitmap_bit_p (dst->wordmask, i));
- srchasword = (i < src->wordmask->n_bits
- && bitmap_bit_p (src->wordmask, i));
-
- if (dsthasword && srchasword)
- {
- EBITMAP_ELT_TYPE tmpword = ebitmap_array_get (src, srceltindex++);
- tmpword |= ebitmap_array_get (dst, dsteltindex);
- if (!changed)
- changed |= tmpword != ebitmap_array_get (dst, dsteltindex);
- dsteltindex++;
- newarray[neweltindex++] = tmpword;
- }
- else if (dsthasword)
- {
- newarray [neweltindex++] = ebitmap_array_get (dst, dsteltindex++);
- }
- else
- {
- newarray [neweltindex++] = ebitmap_array_get (src, srceltindex++);
- gcc_assert (i < dst->wordmask->n_bits);
- bitmap_set_bit_with_popcount (dst->wordmask, i);
- changed |= true;
- }
- }
-
- sbitmap_free (tempmask);
- if (changed)
- {
- dst->numwords = neweltindex;
- free (dst->elts);
- dst->elts = newarray;
- dst->n_elts = newarraysize;
- }
- else
- free (newarray);
-
-#ifdef EBITMAP_DEBUGGING
- {
- ebitmap_iterator ebi;
- unsigned int i;
-
- for (i = 0; i < dst->numwords; i++)
- gcc_assert (dst->elts[i] != 0);
-
- EXECUTE_IF_SET_IN_EBITMAP (src, 0, i, ebi)
- gcc_assert (bitmap_bit_p (dst, i));
- EXECUTE_IF_SET_IN_EBITMAP (dstcopy, 0, i, ebi)
- gcc_assert (bitmap_bit_p (dst, i));
-
- sbitmap_verify_popcount (dst->wordmask);
- gcc_assert (changed == !bitmap_equal_p (dst, dstcopy));
- gcc_assert (sbitmap_popcount (dst->wordmask,
- dst->wordmask->n_bits) == dst->numwords);
- }
-#endif
- return changed;
-}
-
-/* Perform the operation DST = SRC1 | SRC2. Return true if any bit
- in DST has changed. */
-
-bool
-bitmap_ior (ebitmap dst, ebitmap src1, ebitmap src2)
-{
- unsigned int src1size = src1->wordmask->n_bits;
- unsigned int src2size = src2->wordmask->n_bits;
- sbitmap_iterator sbi;
- unsigned int i;
- sbitmap tempmask;
- unsigned int neweltindex = 0;
- unsigned int src1eltindex = 0;
- unsigned int src2eltindex = 0;
- bool changed = false;
- EBITMAP_ELT_TYPE *newarray;
- unsigned int newarraysize;
-#ifdef EBITMAP_DEBUGGING
- ebitmap dstcopy = ebitmap_alloc (1);
- bitmap_copy (dstcopy, dst);
-#endif
-
- dst->cache = NULL;
- tempmask = sbitmap_alloc_with_popcount (MAX (src1size, src2size));
- bitmap_clear (tempmask);
- if (src1size == src2size)
- {
- bitmap_ior (tempmask, src1->wordmask, src2->wordmask);
- }
- else
- {
- if (src1size >= src2size)
- {
- bitmap_copy_n (tempmask, src2->wordmask, src2->wordmask->size);
- bitmap_ior (tempmask, tempmask, src1->wordmask);
- }
- else
- {
- bitmap_copy_n (tempmask, src1->wordmask, src1->wordmask->size);
- bitmap_ior (tempmask, tempmask, src2->wordmask);
- }
- }
- newarraysize = src1->numwords + src2->numwords;
- newarray = XNEWVEC (EBITMAP_ELT_TYPE, newarraysize);
-
- EXECUTE_IF_SET_IN_BITMAP (tempmask, 0, i, sbi)
- {
- bool src1hasword, src2hasword;
- EBITMAP_ELT_TYPE tmpword;
- src1hasword = (i < src1->wordmask->n_bits
- && bitmap_bit_p (src1->wordmask, i));
- src2hasword = (i < src2->wordmask->n_bits
- && bitmap_bit_p (src2->wordmask, i));
-
- if (src1hasword && src2hasword)
- {
- tmpword = (ebitmap_array_get (src1, src1eltindex++)
- | ebitmap_array_get (src2, src2eltindex++));
- newarray[neweltindex++] = tmpword;
- }
- else if (src1hasword)
- {
- tmpword = ebitmap_array_get (src1, src1eltindex++);
- newarray [neweltindex++] = tmpword;
- }
- else
- {
- tmpword = ebitmap_array_get (src2, src2eltindex++);
- newarray [neweltindex++] = tmpword;
- }
-
- if (i >= dst->wordmask->n_bits || !bitmap_bit_p (dst->wordmask, i))
- {
- changed = true;
- }
- else if (!changed)
- {
- unsigned int count = sbitmap_popcount (dst->wordmask, i);
- changed |= ebitmap_array_get (dst, count) != tmpword;
- }
- }
-
- if (changed)
- {
- sbitmap_free (dst->wordmask);
- dst->wordmask = tempmask;
- dst->numwords = neweltindex;
- free (dst->elts);
- dst->elts = newarray;
- dst->n_elts = newarraysize;
- }
- else
- {
- sbitmap_free (tempmask);
- free (newarray);
- }
-
-#ifdef EBITMAP_DEBUGGING
- {
- ebitmap_iterator ebi;
- unsigned int i;
-
- for (i = 0; i < dst->numwords; i++)
- gcc_assert (dst->elts[i] != 0);
-
- EXECUTE_IF_SET_IN_EBITMAP (src1, 0, i, ebi)
- gcc_assert (bitmap_bit_p (dst, i));
-
- EXECUTE_IF_SET_IN_EBITMAP (src2, 0, i, ebi)
- gcc_assert (bitmap_bit_p (dst, i));
- }
- sbitmap_verify_popcount (dst->wordmask);
- gcc_assert (changed == !bitmap_equal_p (dst, dstcopy));
- gcc_assert (sbitmap_popcount (dst->wordmask,
- dst->wordmask->n_bits) == dst->numwords);
-#endif
-
- return changed;
-}
-
-/* Perform the operation DST &= ~SRC. Return true if any bit in DST
- has changed. */
-
-bool
-bitmap_and_compl_into (ebitmap dst, ebitmap src)
-{
- bool changed = false;
- unsigned int i;
- unsigned int neweltindex = 0;
- unsigned int dsteltindex = 0;
- sbitmap_iterator sbi;
-#ifdef EBITMAP_DEBUGGING
- ebitmap dstcopy = ebitmap_alloc (1);
- bitmap_copy (dstcopy, dst);
-#endif
-
- gcc_assert (dst != src);
- dst->cache = NULL;
- if (src->numwords == 0)
- return false;
-
- EXECUTE_IF_SET_IN_BITMAP (dst->wordmask, 0, i, sbi)
- {
- bool srchasword;
-
- srchasword = (i < src->wordmask->n_bits
- && bitmap_bit_p (src->wordmask, i));
-
- if (srchasword)
- {
- unsigned int srccount = sbitmap_popcount (src->wordmask, i);
- EBITMAP_ELT_TYPE tmpword = ebitmap_array_get (dst, dsteltindex);
- tmpword &= ~(ebitmap_array_get (src, srccount));
- if (!changed)
- changed |= ebitmap_array_get (dst, dsteltindex) != tmpword;
- dsteltindex++;
- if (tmpword != 0)
- {
- EBITMAP_ELT_TYPE *dstplace;
- dstplace = ebitmap_array_grow_get (dst, neweltindex++);
- *dstplace = tmpword;
- }
- else
- bitmap_clear_bit_with_popcount (dst->wordmask, i);
- }
- else
- {
- dsteltindex++;
- neweltindex++;
- }
- }
-#ifdef EBITMAP_DEBUGGING
- {
- unsigned int i;
- ebitmap_iterator ebi;
-
- EXECUTE_IF_SET_IN_EBITMAP (dstcopy, 0, i, ebi)
- {
- if (!bitmap_bit_p (src, i))
- gcc_assert (bitmap_bit_p (dst, i));
- }
-
- for (i = 0; i < dst->numwords; i++)
- gcc_assert (dst->elts[i] != 0);
-
- gcc_assert (sbitmap_popcount (dst->wordmask,
- dst->wordmask->n_bits) == neweltindex);
- sbitmap_verify_popcount (dst->wordmask);
- gcc_assert (changed == !bitmap_equal_p (dst, dstcopy));
- gcc_assert (sbitmap_popcount (dst->wordmask,
- dst->wordmask->n_bits) == dst->numwords);
- }
-#endif
- dst->numwords = neweltindex;
- /* sbitmap_popcount (dst->wordmask, -1); */
-
- return changed;
-}
-
-/* Perform the operation DST = SRC1 & ~SRC2. Return true if any bit
- in DST has changed. */
-
-bool
-bitmap_and_compl (ebitmap dst, ebitmap src1, ebitmap src2)
-{
- unsigned int src1size = src1->wordmask->n_bits;
- sbitmap_iterator sbi;
- unsigned int i;
- sbitmap tempmask;
- unsigned int neweltindex = 0;
- unsigned int src1eltindex = 0;
- bool changed = false;
- EBITMAP_ELT_TYPE *newarray;
- unsigned int newarraysize;
-
- /* XXX: Optimize like the into version. */
- dst->cache = NULL;
- tempmask = sbitmap_alloc_with_popcount (src1size);
- bitmap_clear (tempmask);
- bitmap_copy (tempmask, src1->wordmask);
-
- newarraysize = src1->numwords;
- newarray = XNEWVEC (EBITMAP_ELT_TYPE, newarraysize);
-
- EXECUTE_IF_SET_IN_BITMAP (src1->wordmask, 0, i, sbi)
- {
- bool src2hasword;
- EBITMAP_ELT_TYPE tmpword;
-
- src2hasword = (i < src2->wordmask->n_bits
- && bitmap_bit_p (src2->wordmask, i));
-
- if (src2hasword)
- {
- unsigned int src2count = sbitmap_popcount (src2->wordmask, i);
- tmpword = ebitmap_array_get (src1, src1eltindex++)
- & ~(ebitmap_array_get (src2, src2count));
- if (tmpword)
- {
- newarray[neweltindex++] = tmpword;
- }
- else
- bitmap_clear_bit_with_popcount (tempmask, i);
-
- }
- else
- {
- tmpword = ebitmap_array_get (src1, src1eltindex++);
- gcc_assert (tmpword != 0);
- newarray[neweltindex++] = tmpword;
- }
-
- if (i >= dst->wordmask->n_bits || !bitmap_bit_p (dst->wordmask, i))
- {
- changed = true;
- }
- else if (!changed)
- {
- unsigned int count = sbitmap_popcount (dst->wordmask, i);
- changed |= ebitmap_array_get (dst, count) != tmpword;
- }
- }
- if (changed)
- {
- sbitmap_free (dst->wordmask);
- dst->wordmask = tempmask;
- dst->numwords = neweltindex;
- free (dst->elts);
- dst->elts = newarray;
- dst->n_elts = newarraysize;
- }
- else
- {
- free (tempmask);
- free (newarray);
- }
-#ifdef EBITMAP_DEBUGGING
- {
- unsigned int i;
- ebitmap_iterator ebi;
-
- EXECUTE_IF_SET_IN_EBITMAP (src1, 0, i, ebi)
- {
- if (!bitmap_bit_p (src2, i))
- gcc_assert (bitmap_bit_p (dst, i));
- }
- for (i = 0; i < dst->numwords; i++)
- gcc_assert (dst->elts[i] != 0);
-
- sbitmap_verify_popcount (dst->wordmask);
- gcc_assert (sbitmap_popcount (dst->wordmask,
- dst->wordmask->n_bits) == dst->numwords);
- }
-#endif
- return changed;
-}
-
-/* Perform the operation DST = A | (B & ~C). */
-
-bool
-bitmap_ior_and_compl (ebitmap dst, ebitmap a, ebitmap b, ebitmap c)
-{
- bool changed;
- ebitmap temp = ebitmap_alloc (1);
-#ifdef EBITMAP_DEBUGGING
- ebitmap dstcopy = ebitmap_alloc (1);
- bitmap_copy (dstcopy, dst);
-#endif
-
- dst->cache = NULL;
- bitmap_and_compl (temp, b, c);
- changed = bitmap_ior (dst, a, temp);
-#ifdef EBITMAP_DEBUGGING
- {
- ebitmap_iterator ebi;
- unsigned int i;
-
- EXECUTE_IF_SET_IN_EBITMAP (a, 0, i, ebi)
- gcc_assert (bitmap_bit_p (dst, i));
-
- EXECUTE_IF_SET_IN_EBITMAP (b, 0, i, ebi)
- if (!bitmap_bit_p (c, i))
- gcc_assert (bitmap_bit_p (dst, i));
- gcc_assert (changed == !bitmap_equal_p (dst, dstcopy));
- }
-#endif
- ebitmap_free (temp);
-
- return changed;
-}
-
-/* Return true if ebitmap DST is equal to ebitmap SRC. */
-
-bool
-bitmap_equal_p (ebitmap dst, ebitmap src)
-{
- unsigned int which = MIN (dst->wordmask->size, src->wordmask->size);
-
- if (dst->numwords != src->numwords)
- return false;
-
- /* bitmap_equal_p compares up to the size of the first argument, so
- if the two sbitmaps are not equally sized, we need to pass the
- smaller one as the first argument, or it will crash. */
- if (which == dst->wordmask->size
- && !bitmap_equal_p (dst->wordmask, src->wordmask))
- return false;
- else if (which == src->wordmask->size
- && !bitmap_equal_p (src->wordmask, dst->wordmask))
- return false;
-
- return memcmp (dst->elts, src->elts,
- dst->numwords * sizeof (EBITMAP_ELT_TYPE)) == 0;
- return true;
-}