aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/gcc/ebitmap.c
diff options
context:
space:
mode:
authorJing Yu <jingyu@google.com>2010-07-22 14:03:48 -0700
committerJing Yu <jingyu@google.com>2010-07-22 14:03:48 -0700
commitb094d6c4bf572654a031ecc4afe675154c886dc5 (patch)
tree89394c56b05e13a5413ee60237d65b0214fd98e2 /gcc-4.4.3/gcc/ebitmap.c
parentdc34721ac3bf7e3c406fba8cfe9d139393345ec5 (diff)
downloadtoolchain_gcc-b094d6c4bf572654a031ecc4afe675154c886dc5.tar.gz
toolchain_gcc-b094d6c4bf572654a031ecc4afe675154c886dc5.tar.bz2
toolchain_gcc-b094d6c4bf572654a031ecc4afe675154c886dc5.zip
commit gcc-4.4.3 which is used to build gcc-4.4.3 Android toolchain in master.
The source is based on fsf gcc-4.4.3 and contains local patches which are recorded in gcc-4.4.3/README.google. Change-Id: Id8c6d6927df274ae9749196a1cc24dbd9abc9887
Diffstat (limited to 'gcc-4.4.3/gcc/ebitmap.c')
-rw-r--r--gcc-4.4.3/gcc/ebitmap.c1018
1 files changed, 1018 insertions, 0 deletions
diff --git a/gcc-4.4.3/gcc/ebitmap.c b/gcc-4.4.3/gcc/ebitmap.c
new file mode 100644
index 000000000..a18a21efb
--- /dev/null
+++ b/gcc-4.4.3/gcc/ebitmap.c
@@ -0,0 +1,1018 @@
+/* Sparse array-based bitmaps.
+ Copyright (C) 2007, 2008 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 "tm.h"
+#include "rtl.h"
+#include "flags.h"
+#include "obstack.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
+ebitmap_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
+ebitmap_clear (ebitmap map)
+{
+ ebitmap_array_clear (map);
+ sbitmap_zero (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);
+ sbitmap_zero (ret->wordmask);
+ ret->numwords = 0;
+ ret->cache = NULL;
+ ret->cacheindex = 0;
+
+ return ret;
+}
+
+/* Clear BIT from ebitmap MAP. */
+
+void
+ebitmap_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
+ || !TEST_BIT (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 && map->cacheindex == eltwordindex)
+ map->cache = NULL;
+
+ RESET_BIT (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
+ebitmap_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 (!TEST_BIT (map->wordmask, wordindex))
+ {
+ unsigned long count;
+ unsigned int i;
+
+ SET_BIT (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
+ebitmap_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
+ || !TEST_BIT (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
+ebitmap_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);
+ sbitmap_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_ebitmap (FILE *file, ebitmap bmap)
+{
+ unsigned int pos;
+ unsigned int i;
+ int res;
+ unsigned int size;
+
+ res = sbitmap_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 (ebitmap_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. */
+
+void
+debug_ebitmap (ebitmap bmap)
+{
+ dump_ebitmap (stderr, bmap);
+}
+
+/* Perform the operation DST &= SRC. */
+
+void
+ebitmap_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)
+ {
+ ebitmap_clear (dst);
+ return;
+ }
+
+ /* AND the masks, then walk the words that may actually appear in
+ the result, AND'ing them. */
+ sbitmap_a_and_b (dst->wordmask, dst->wordmask, src->wordmask);
+
+ EXECUTE_IF_SET_IN_SBITMAP (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
+ RESET_BIT (dst->wordmask, i);
+ }
+#ifdef EBITMAP_DEBUGGING
+ {
+ unsigned int i;
+
+ for (i = 0; i < dst->numwords; i++)
+ gcc_assert (dst->elts[i] != 0);
+
+ 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
+ebitmap_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)
+ {
+ ebitmap_clear (dst);
+ return;
+ }
+
+ dst->wordmask
+ = sbitmap_resize (dst->wordmask,
+ MIN (src1->wordmask->n_bits, src2->wordmask->n_bits),
+ 0);
+ sbitmap_a_and_b (dst->wordmask, src1->wordmask, src2->wordmask);
+
+ EXECUTE_IF_SET_IN_SBITMAP (dst->wordmask, 0, i, sbi)
+ {
+ bool src1hasword, src2hasword;
+
+ src1hasword = TEST_BIT (src1->wordmask, i);
+ src2hasword = TEST_BIT (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
+ RESET_BIT (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 (ebitmap_bit_p (src2, i))
+ gcc_assert (ebitmap_bit_p (dst, i));
+
+ for (i = 0; i < dst->numwords; i++)
+ gcc_assert (dst->elts[i] != 0);
+
+ 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
+ebitmap_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);
+ ebitmap_copy (dstcopy, dst);
+#endif
+
+ dst->cache = NULL;
+ if (dst == src)
+ return false;
+
+ if (dst->numwords == 0 && src->numwords != 0)
+ {
+ ebitmap_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));
+ sbitmap_zero (tempmask);
+ if (srcsize == dstsize)
+ {
+ sbitmap_a_or_b (tempmask, dst->wordmask, src->wordmask);
+ }
+ else
+ {
+ dst->wordmask = sbitmap_resize (dst->wordmask, MAX (srcsize, dstsize),
+ 0);
+ if (srcsize >= dstsize)
+ {
+ sbitmap_copy_n (tempmask, dst->wordmask, dst->wordmask->size);
+ sbitmap_a_or_b (tempmask, tempmask, src->wordmask);
+ }
+ else
+ {
+ sbitmap_copy_n (tempmask, src->wordmask, src->wordmask->size);
+ sbitmap_a_or_b (tempmask, tempmask, dst->wordmask);
+ }
+ }
+ newarraysize = src->numwords + dst->numwords;
+ newarray = XNEWVEC (EBITMAP_ELT_TYPE, newarraysize);
+
+ EXECUTE_IF_SET_IN_SBITMAP (tempmask, 0, i, sbi)
+ {
+ bool dsthasword, srchasword;
+
+ dsthasword = (i < dst->wordmask->n_bits
+ && TEST_BIT (dst->wordmask, i));
+ srchasword = (i < src->wordmask->n_bits
+ && TEST_BIT (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);
+ SET_BIT (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 (ebitmap_bit_p (dst, i));
+ EXECUTE_IF_SET_IN_EBITMAP (dstcopy, 0, i, ebi)
+ gcc_assert (ebitmap_bit_p (dst, i));
+
+ verify_popcount (dst->wordmask);
+ gcc_assert (changed == !ebitmap_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
+ebitmap_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);
+ ebitmap_copy (dstcopy, dst);
+#endif
+
+ dst->cache = NULL;
+ tempmask = sbitmap_alloc_with_popcount (MAX (src1size, src2size));
+ sbitmap_zero (tempmask);
+ if (src1size == src2size)
+ {
+ sbitmap_a_or_b (tempmask, src1->wordmask, src2->wordmask);
+ }
+ else
+ {
+ if (src1size >= src2size)
+ {
+ sbitmap_copy_n (tempmask, src2->wordmask, src2->wordmask->size);
+ sbitmap_a_or_b (tempmask, tempmask, src1->wordmask);
+ }
+ else
+ {
+ sbitmap_copy_n (tempmask, src1->wordmask, src1->wordmask->size);
+ sbitmap_a_or_b (tempmask, tempmask, src2->wordmask);
+ }
+ }
+ newarraysize = src1->numwords + src2->numwords;
+ newarray = XNEWVEC (EBITMAP_ELT_TYPE, newarraysize);
+
+ EXECUTE_IF_SET_IN_SBITMAP (tempmask, 0, i, sbi)
+ {
+ bool src1hasword, src2hasword;
+ EBITMAP_ELT_TYPE tmpword;
+ src1hasword = (i < src1->wordmask->n_bits
+ && TEST_BIT (src1->wordmask, i));
+ src2hasword = (i < src2->wordmask->n_bits
+ && TEST_BIT (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 || !TEST_BIT (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 (ebitmap_bit_p (dst, i));
+
+ EXECUTE_IF_SET_IN_EBITMAP (src2, 0, i, ebi)
+ gcc_assert (ebitmap_bit_p (dst, i));
+ }
+ verify_popcount (dst->wordmask);
+ gcc_assert (changed == !ebitmap_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
+ebitmap_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);
+ ebitmap_copy (dstcopy, dst);
+#endif
+
+ gcc_assert (dst != src);
+ dst->cache = NULL;
+ if (src->numwords == 0)
+ return false;
+
+ EXECUTE_IF_SET_IN_SBITMAP (dst->wordmask, 0, i, sbi)
+ {
+ bool srchasword;
+
+ srchasword = (i < src->wordmask->n_bits
+ && TEST_BIT (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
+ RESET_BIT (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 (!ebitmap_bit_p (src, i))
+ gcc_assert (ebitmap_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);
+ verify_popcount (dst->wordmask);
+ gcc_assert (changed == !ebitmap_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
+ebitmap_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);
+ sbitmap_zero (tempmask);
+ sbitmap_copy (tempmask, src1->wordmask);
+
+ newarraysize = src1->numwords;
+ newarray = XNEWVEC (EBITMAP_ELT_TYPE, newarraysize);
+
+ EXECUTE_IF_SET_IN_SBITMAP (src1->wordmask, 0, i, sbi)
+ {
+ bool src2hasword;
+ EBITMAP_ELT_TYPE tmpword;
+
+ src2hasword = (i < src2->wordmask->n_bits
+ && TEST_BIT (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
+ RESET_BIT (tempmask, i);
+
+ }
+ else
+ {
+ tmpword = ebitmap_array_get (src1, src1eltindex++);
+ gcc_assert (tmpword != 0);
+ newarray[neweltindex++] = tmpword;
+ }
+
+ if (i >= dst->wordmask->n_bits || !TEST_BIT (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 (!ebitmap_bit_p (src2, i))
+ gcc_assert (ebitmap_bit_p (dst, i));
+ }
+ for (i = 0; i < dst->numwords; i++)
+ gcc_assert (dst->elts[i] != 0);
+
+ 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
+ebitmap_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);
+ ebitmap_copy (dstcopy, dst);
+#endif
+
+ dst->cache = NULL;
+ ebitmap_and_compl (temp, b, c);
+ changed = ebitmap_ior (dst, a, temp);
+#ifdef EBITMAP_DEBUGGING
+ {
+ ebitmap_iterator ebi;
+ unsigned int i;
+
+ EXECUTE_IF_SET_IN_EBITMAP (a, 0, i, ebi)
+ gcc_assert (ebitmap_bit_p (dst, i));
+
+ EXECUTE_IF_SET_IN_EBITMAP (b, 0, i, ebi)
+ if (!ebitmap_bit_p (c, i))
+ gcc_assert (ebitmap_bit_p (dst, i));
+ gcc_assert (changed == !ebitmap_equal_p (dst, dstcopy));
+ }
+#endif
+ ebitmap_free (temp);
+
+ return changed;
+}
+
+/* Return true if ebitmap DST is equal to ebitmap SRC. */
+
+bool
+ebitmap_equal_p (ebitmap dst, ebitmap src)
+{
+ unsigned int which = MIN (dst->wordmask->size, src->wordmask->size);
+
+ if (dst->numwords != src->numwords)
+ return false;
+
+ /* sbitmap_equal 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
+ && !sbitmap_equal (dst->wordmask, src->wordmask))
+ return false;
+ else if (which == src->wordmask->size
+ && !sbitmap_equal (src->wordmask, dst->wordmask))
+ return false;
+
+ return memcmp (dst->elts, src->elts,
+ dst->numwords * sizeof (EBITMAP_ELT_TYPE)) == 0;
+ return true;
+}