OSDN Git Service

2011-05-27 Alexander Monakov <amonakov@ispras.ru>
[pf3gnuchains/gcc-fork.git] / gcc / sbitmap.c
index 74aa7cd..23d459e 100644 (file)
@@ -1,11 +1,12 @@
 /* Simple bitmaps.
 /* Simple bitmaps.
-   Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2002, 2003, 2004, 2006, 2007, 2008, 2010
+   Free Software Foundation, Inc.
 
 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
 
 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 2, or (at your option) any later
+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
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -14,24 +15,69 @@ 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
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
-#include "rtl.h"
-#include "flags.h"
-#include "hard-reg-set.h"
+#include "coretypes.h"
+#include "sbitmap.h"
+
+#ifdef IN_GCC
+/* FIXME: sbitmap is just a data structure, but we define dataflow functions
+   here also.  This is conditional on IN_GCC (see second #ifdef IN_GCC
+   further down).
+   For now, also only conditionally include basic-block.h, but we should
+   find a better place for the dataflow functions.  Perhaps cfganal.c?  */
 #include "basic-block.h"
 #include "basic-block.h"
+#endif
+
+#if GCC_VERSION >= 3400
+#  if HOST_BITS_PER_WIDEST_FAST_INT == HOST_BITS_PER_LONG
+#    define do_popcount(x) __builtin_popcountl(x)
+#  elif HOST_BITS_PER_WIDEST_FAST_INT == HOST_BITS_PER_LONGLONG
+#    define do_popcount(x) __builtin_popcountll(x)
+#  else
+#    error "internal error: sbitmap.h and hwint.h are inconsistent"
+#  endif
+#else
+static unsigned long sbitmap_elt_popcount (SBITMAP_ELT_TYPE);
+#  define do_popcount(x) sbitmap_elt_popcount((x))
+#endif
+
+typedef SBITMAP_ELT_TYPE *sbitmap_ptr;
+typedef const SBITMAP_ELT_TYPE *const_sbitmap_ptr;
+
+/* This macro controls debugging that is as expensive as the
+   operations it verifies.  */
+
+/* #define BITMAP_DEBUGGING  */
+#ifdef BITMAP_DEBUGGING
+
+/* Verify the population count of sbitmap A matches the cached value,
+   if there is a cached value. */
+
+void
+sbitmap_verify_popcount (const_sbitmap a)
+{
+  unsigned ix;
+  unsigned int lastword;
+
+  if (!a->popcount)
+    return;
+
+  lastword = a->size;
+  for (ix = 0; ix < lastword; ix++)
+    gcc_assert (a->popcount[ix] == do_popcount (a->elms[ix]));
+}
+#endif
 
 /* Bitmap manipulation routines.  */
 
 /* Allocate a simple bitmap of N_ELMS bits.  */
 
 sbitmap
 
 /* Bitmap manipulation routines.  */
 
 /* Allocate a simple bitmap of N_ELMS bits.  */
 
 sbitmap
-sbitmap_alloc (n_elms)
-     unsigned int n_elms;
+sbitmap_alloc (unsigned int n_elms)
 {
   unsigned int bytes, size, amt;
   sbitmap bmap;
 {
   unsigned int bytes, size, amt;
   sbitmap bmap;
@@ -43,15 +89,118 @@ sbitmap_alloc (n_elms)
   bmap = (sbitmap) xmalloc (amt);
   bmap->n_bits = n_elms;
   bmap->size = size;
   bmap = (sbitmap) xmalloc (amt);
   bmap->n_bits = n_elms;
   bmap->size = size;
-  bmap->bytes = bytes;
+  bmap->popcount = NULL;
+  return bmap;
+}
+
+/* Allocate a simple bitmap of N_ELMS bits, and a popcount array.  */
+
+sbitmap
+sbitmap_alloc_with_popcount (unsigned int n_elms)
+{
+  sbitmap const bmap = sbitmap_alloc (n_elms);
+  bmap->popcount = XNEWVEC (unsigned char, bmap->size);
+  return bmap;
+}
+
+/* Resize a simple bitmap BMAP to N_ELMS bits.  If increasing the
+   size of BMAP, clear the new bits to zero if the DEF argument
+   is zero, and set them to one otherwise.  */
+
+sbitmap
+sbitmap_resize (sbitmap bmap, unsigned int n_elms, int def)
+{
+  unsigned int bytes, size, amt;
+  unsigned int last_bit;
+
+  size = SBITMAP_SET_SIZE (n_elms);
+  bytes = size * sizeof (SBITMAP_ELT_TYPE);
+  if (bytes > SBITMAP_SIZE_BYTES (bmap))
+    {
+      amt = (sizeof (struct simple_bitmap_def)
+           + bytes - sizeof (SBITMAP_ELT_TYPE));
+      bmap = (sbitmap) xrealloc (bmap, amt);
+      if (bmap->popcount)
+       bmap->popcount = XRESIZEVEC (unsigned char, bmap->popcount, size);
+    }
+
+  if (n_elms > bmap->n_bits)
+    {
+      if (def)
+       {
+         memset (bmap->elms + bmap->size, -1,
+                 bytes - SBITMAP_SIZE_BYTES (bmap));
+
+         /* Set the new bits if the original last element.  */
+         last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
+         if (last_bit)
+           bmap->elms[bmap->size - 1]
+             |= ~((SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit));
+
+         /* Clear the unused bit in the new last element.  */
+         last_bit = n_elms % SBITMAP_ELT_BITS;
+         if (last_bit)
+           bmap->elms[size - 1]
+             &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+       }
+      else
+       {
+         memset (bmap->elms + bmap->size, 0,
+                 bytes - SBITMAP_SIZE_BYTES (bmap));
+         if (bmap->popcount)
+           memset (bmap->popcount + bmap->size, 0,
+                   (size * sizeof (unsigned char))
+                   - (bmap->size * sizeof (unsigned char)));
+
+       }
+    }
+  else if (n_elms < bmap->n_bits)
+    {
+      /* Clear the surplus bits in the last word.  */
+      last_bit = n_elms % SBITMAP_ELT_BITS;
+      if (last_bit)
+       {
+         bmap->elms[size - 1]
+           &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+         if (bmap->popcount)
+           bmap->popcount[size - 1] = do_popcount (bmap->elms[size - 1]);
+       }
+    }
+
+  bmap->n_bits = n_elms;
+  bmap->size = size;
+  return bmap;
+}
+
+/* Re-allocate a simple bitmap of N_ELMS bits. New storage is uninitialized.  */
+
+sbitmap
+sbitmap_realloc (sbitmap src, unsigned int n_elms)
+{
+  unsigned int bytes, size, amt;
+  sbitmap bmap;
+
+  size = SBITMAP_SET_SIZE (n_elms);
+  bytes = size * sizeof (SBITMAP_ELT_TYPE);
+  amt = (sizeof (struct simple_bitmap_def)
+        + bytes - sizeof (SBITMAP_ELT_TYPE));
+
+  if (SBITMAP_SIZE_BYTES (src)  >= bytes)
+    {
+      src->n_bits = n_elms;
+      return src;
+    }
+
+  bmap = (sbitmap) xrealloc (src, amt);
+  bmap->n_bits = n_elms;
+  bmap->size = size;
   return bmap;
 }
 
 /* Allocate a vector of N_VECS bitmaps of N_ELMS bits.  */
 
 sbitmap *
   return bmap;
 }
 
 /* Allocate a vector of N_VECS bitmaps of N_ELMS bits.  */
 
 sbitmap *
-sbitmap_vector_alloc (n_vecs, n_elms)
-     unsigned int n_vecs, n_elms;
+sbitmap_vector_alloc (unsigned int n_vecs, unsigned int n_elms)
 {
   unsigned int i, bytes, offset, elm_bytes, size, amt, vector_bytes;
   sbitmap *bitmap_vector;
 {
   unsigned int i, bytes, offset, elm_bytes, size, amt, vector_bytes;
   sbitmap *bitmap_vector;
@@ -84,7 +233,7 @@ sbitmap_vector_alloc (n_vecs, n_elms)
       bitmap_vector[i] = b;
       b->n_bits = n_elms;
       b->size = size;
       bitmap_vector[i] = b;
       b->n_bits = n_elms;
       b->size = size;
-      b->bytes = bytes;
+      b->popcount = NULL;
     }
 
   return bitmap_vector;
     }
 
   return bitmap_vector;
@@ -93,51 +242,130 @@ sbitmap_vector_alloc (n_vecs, n_elms)
 /* Copy sbitmap SRC to DST.  */
 
 void
 /* Copy sbitmap SRC to DST.  */
 
 void
-sbitmap_copy (dst, src)
-     sbitmap dst, src;
+sbitmap_copy (sbitmap dst, const_sbitmap src)
 {
   memcpy (dst->elms, src->elms, sizeof (SBITMAP_ELT_TYPE) * dst->size);
 {
   memcpy (dst->elms, src->elms, sizeof (SBITMAP_ELT_TYPE) * dst->size);
+  if (dst->popcount)
+    memcpy (dst->popcount, src->popcount, sizeof (unsigned char) * dst->size);
+}
+
+/* Copy the first N elements of sbitmap SRC to DST.  */
+
+void
+sbitmap_copy_n (sbitmap dst, const_sbitmap src, unsigned int n)
+{
+  memcpy (dst->elms, src->elms, sizeof (SBITMAP_ELT_TYPE) * n);
+  if (dst->popcount)
+    memcpy (dst->popcount, src->popcount, sizeof (unsigned char) * n);
 }
 
 /* Determine if a == b.  */
 int
 }
 
 /* Determine if a == b.  */
 int
-sbitmap_equal (a, b)
-     sbitmap a, b;
+sbitmap_equal (const_sbitmap a, const_sbitmap b)
 {
   return !memcmp (a->elms, b->elms, sizeof (SBITMAP_ELT_TYPE) * a->size);
 }
 
 {
   return !memcmp (a->elms, b->elms, sizeof (SBITMAP_ELT_TYPE) * a->size);
 }
 
+/* Return true if the bitmap is empty.  */
+
+bool
+sbitmap_empty_p (const_sbitmap bmap)
+{
+  unsigned int i;
+  for (i=0; i<bmap->size; i++)
+    if (bmap->elms[i])
+      return false;
+
+  return true;
+}
+
+/* Return false if any of the N bits are set in MAP starting at
+   START.  */
+
+bool
+sbitmap_range_empty_p (const_sbitmap bmap, unsigned int start, unsigned int n)
+{
+  unsigned int i = start / SBITMAP_ELT_BITS;
+  SBITMAP_ELT_TYPE elm;
+  unsigned int shift = start % SBITMAP_ELT_BITS;
+
+  gcc_assert (bmap->n_bits >= start + n);
+
+  elm = bmap->elms[i];
+  elm = elm >> shift;
+
+  if (shift + n <= SBITMAP_ELT_BITS)
+    {
+      /* The bits are totally contained in a single element.  */
+      if (shift + n < SBITMAP_ELT_BITS)
+        elm &= ((1 << n) - 1);
+      return (elm == 0);
+    }
+
+  if (elm)
+    return false;
+
+  n -= SBITMAP_ELT_BITS - shift;
+  i++;
+
+  /* Deal with full elts.  */
+  while (n >= SBITMAP_ELT_BITS)
+    {
+      if (bmap->elms[i])
+       return false;
+      i++;
+      n -= SBITMAP_ELT_BITS;
+    }
+
+  /* The leftover bits.  */
+  if (n)
+    {
+      elm = bmap->elms[i];
+      elm &= ((1 << n) - 1);
+      return (elm == 0);
+    }
+
+  return true;
+}
+
+
+
 /* Zero all elements in a bitmap.  */
 
 void
 /* Zero all elements in a bitmap.  */
 
 void
-sbitmap_zero (bmap)
-     sbitmap bmap;
+sbitmap_zero (sbitmap bmap)
 {
 {
-  memset ((PTR) bmap->elms, 0, bmap->bytes);
+  memset (bmap->elms, 0, SBITMAP_SIZE_BYTES (bmap));
+  if (bmap->popcount)
+    memset (bmap->popcount, 0, bmap->size * sizeof (unsigned char));
 }
 
 /* Set all elements in a bitmap to ones.  */
 
 void
 }
 
 /* Set all elements in a bitmap to ones.  */
 
 void
-sbitmap_ones (bmap)
-     sbitmap bmap;
+sbitmap_ones (sbitmap bmap)
 {
   unsigned int last_bit;
 
 {
   unsigned int last_bit;
 
-  memset ((PTR) bmap->elms, -1, bmap->bytes);
+  memset (bmap->elms, -1, SBITMAP_SIZE_BYTES (bmap));
+  if (bmap->popcount)
+    memset (bmap->popcount, -1, bmap->size * sizeof (unsigned char));
 
   last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
   if (last_bit)
 
   last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
   if (last_bit)
-    bmap->elms[bmap->size - 1]
-      = (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+    {
+      bmap->elms[bmap->size - 1]
+       = (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+      if (bmap->popcount)
+       bmap->popcount[bmap->size - 1]
+         = do_popcount (bmap->elms[bmap->size - 1]);
+    }
 }
 
 /* Zero a vector of N_VECS bitmaps.  */
 
 void
 }
 
 /* Zero a vector of N_VECS bitmaps.  */
 
 void
-sbitmap_vector_zero (bmap, n_vecs)
-     sbitmap *bmap;
-     unsigned int n_vecs;
+sbitmap_vector_zero (sbitmap *bmap, unsigned int n_vecs)
 {
   unsigned int i;
 
 {
   unsigned int i;
 
@@ -148,9 +376,7 @@ sbitmap_vector_zero (bmap, n_vecs)
 /* Set a vector of N_VECS bitmaps to ones.  */
 
 void
 /* Set a vector of N_VECS bitmaps to ones.  */
 
 void
-sbitmap_vector_ones (bmap, n_vecs)
-     sbitmap *bmap;
-     unsigned int n_vecs;
+sbitmap_vector_ones (sbitmap *bmap, unsigned int n_vecs)
 {
   unsigned int i;
 
 {
   unsigned int i;
 
@@ -163,19 +389,20 @@ sbitmap_vector_ones (bmap, n_vecs)
    Returns true if any change is made.  */
 
 bool
    Returns true if any change is made.  */
 
 bool
-sbitmap_union_of_diff_cg (dst, a, b, c)
-     sbitmap dst, a, b, c;
+sbitmap_union_of_diff_cg (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
-  sbitmap_ptr cp = c->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr cp = c->elms;
   SBITMAP_ELT_TYPE changed = 0;
 
   SBITMAP_ELT_TYPE changed = 0;
 
+  gcc_assert (!dst->popcount);
+
   for (i = 0; i < n; i++)
     {
   for (i = 0; i < n; i++)
     {
-      SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & ~*cp++);
+      const SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & ~*cp++);
       changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
       changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
@@ -184,14 +411,16 @@ sbitmap_union_of_diff_cg (dst, a, b, c)
 }
 
 void
 }
 
 void
-sbitmap_union_of_diff (dst, a, b, c)
-     sbitmap dst, a, b, c;
+sbitmap_union_of_diff (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
-  sbitmap_ptr cp = c->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr cp = c->elms;
+
+  gcc_assert (!dst->popcount && !a->popcount
+             && !b->popcount && !c->popcount);
 
   for (i = 0; i < n; i++)
     *dstp++ = *ap++ | (*bp++ & ~*cp++);
 
   for (i = 0; i < n; i++)
     *dstp++ = *ap++ | (*bp++ & ~*cp++);
@@ -200,33 +429,41 @@ sbitmap_union_of_diff (dst, a, b, c)
 /* Set bitmap DST to the bitwise negation of the bitmap SRC.  */
 
 void
 /* Set bitmap DST to the bitwise negation of the bitmap SRC.  */
 
 void
-sbitmap_not (dst, src)
-     sbitmap dst, src;
+sbitmap_not (sbitmap dst, const_sbitmap src)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr srcp = src->elms;
+  const_sbitmap_ptr srcp = src->elms;
+  unsigned int last_bit;
+
+  gcc_assert (!dst->popcount);
 
   for (i = 0; i < n; i++)
     *dstp++ = ~*srcp++;
 
   for (i = 0; i < n; i++)
     *dstp++ = ~*srcp++;
+
+  /* Zero all bits past n_bits, by ANDing dst with sbitmap_ones.  */
+  last_bit = src->n_bits % SBITMAP_ELT_BITS;
+  if (last_bit)
+    dst->elms[n-1] = dst->elms[n-1]
+      & ((SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit));
 }
 
 /* Set the bits in DST to be the difference between the bits
    in A and the bits in B. i.e. dst = a & (~b).  */
 
 void
 }
 
 /* Set the bits in DST to be the difference between the bits
    in A and the bits in B. i.e. dst = a & (~b).  */
 
 void
-sbitmap_difference (dst, a, b)
-     sbitmap dst, a, b;
+sbitmap_difference (sbitmap dst, const_sbitmap a, const_sbitmap b)
 {
   unsigned int i, dst_size = dst->size;
   unsigned int min_size = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, dst_size = dst->size;
   unsigned int min_size = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
-  
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+
+  gcc_assert (!dst->popcount);
+
   /* A should be at least as large as DEST, to have a defined source.  */
   /* A should be at least as large as DEST, to have a defined source.  */
-  if (a->size < dst_size)
-    abort ();
+  gcc_assert (a->size >= dst_size);
   /* If minuend is smaller, we simply pretend it to be zero bits, i.e.
      only copy the subtrahend into dest.  */
   if (b->size < min_size)
   /* If minuend is smaller, we simply pretend it to be zero bits, i.e.
      only copy the subtrahend into dest.  */
   if (b->size < min_size)
@@ -240,23 +477,42 @@ sbitmap_difference (dst, a, b)
       *dstp++ = *ap++;
 }
 
       *dstp++ = *ap++;
 }
 
+/* Return true if there are any bits set in A are also set in B.
+   Return false otherwise.  */
+
+bool
+sbitmap_any_common_bits (const_sbitmap a, const_sbitmap b)
+{
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  unsigned int i, n;
+
+  n = MIN (a->size, b->size);
+  for (i = 0; i < n; i++)
+    if ((*ap++ & *bp++) != 0)
+      return true;
+
+  return false;
+}
+
 /* Set DST to be (A and B).
    Return nonzero if any change is made.  */
 
 bool
 /* Set DST to be (A and B).
    Return nonzero if any change is made.  */
 
 bool
-sbitmap_a_and_b_cg (dst, a, b)
-     sbitmap dst, a, b;
+sbitmap_a_and_b_cg (sbitmap dst, const_sbitmap a, const_sbitmap b)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
   SBITMAP_ELT_TYPE changed = 0;
 
   SBITMAP_ELT_TYPE changed = 0;
 
+  gcc_assert (!dst->popcount);
+
   for (i = 0; i < n; i++)
     {
   for (i = 0; i < n; i++)
     {
-      SBITMAP_ELT_TYPE tmp = *ap++ & *bp++;
-      changed = *dstp ^ tmp;
+      const SBITMAP_ELT_TYPE tmp = *ap++ & *bp++;
+      changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
 
       *dstp++ = tmp;
     }
 
@@ -264,35 +520,51 @@ sbitmap_a_and_b_cg (dst, a, b)
 }
 
 void
 }
 
 void
-sbitmap_a_and_b (dst, a, b)
-     sbitmap dst, a, b;
+sbitmap_a_and_b (sbitmap dst, const_sbitmap a, const_sbitmap b)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  bool has_popcount = dst->popcount != NULL;
+  unsigned char *popcountp = dst->popcount;
 
   for (i = 0; i < n; i++)
 
   for (i = 0; i < n; i++)
-    *dstp++ = *ap++ & *bp++;
+    {
+      const SBITMAP_ELT_TYPE tmp = *ap++ & *bp++;
+      if (has_popcount)
+       {
+         bool wordchanged = (*dstp ^ tmp) != 0;
+         if (wordchanged)
+           *popcountp = do_popcount (tmp);
+         popcountp++;
+       }
+      *dstp++ = tmp;
+    }
+#ifdef BITMAP_DEBUGGING
+  if (has_popcount)
+    sbitmap_verify_popcount (dst);
+#endif
 }
 
 /* Set DST to be (A xor B)).
    Return nonzero if any change is made.  */
 
 bool
 }
 
 /* Set DST to be (A xor B)).
    Return nonzero if any change is made.  */
 
 bool
-sbitmap_a_xor_b_cg (dst, a, b)
-     sbitmap dst, a, b;
+sbitmap_a_xor_b_cg (sbitmap dst, const_sbitmap a, const_sbitmap b)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
   SBITMAP_ELT_TYPE changed = 0;
 
   SBITMAP_ELT_TYPE changed = 0;
 
+  gcc_assert (!dst->popcount);
+
   for (i = 0; i < n; i++)
     {
   for (i = 0; i < n; i++)
     {
-      SBITMAP_ELT_TYPE tmp = *ap++ ^ *bp++;
-      changed = *dstp ^ tmp;
+      const SBITMAP_ELT_TYPE tmp = *ap++ ^ *bp++;
+      changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
 
       *dstp++ = tmp;
     }
 
@@ -300,35 +572,51 @@ sbitmap_a_xor_b_cg (dst, a, b)
 }
 
 void
 }
 
 void
-sbitmap_a_xor_b (dst, a, b)
-     sbitmap dst, a, b;
+sbitmap_a_xor_b (sbitmap dst, const_sbitmap a, const_sbitmap b)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  bool has_popcount = dst->popcount != NULL;
+  unsigned char *popcountp = dst->popcount;
 
   for (i = 0; i < n; i++)
 
   for (i = 0; i < n; i++)
-    *dstp++ = *ap++ ^ *bp++;
+    {
+      const SBITMAP_ELT_TYPE tmp = *ap++ ^ *bp++;
+      if (has_popcount)
+       {
+         bool wordchanged = (*dstp ^ tmp) != 0;
+         if (wordchanged)
+           *popcountp = do_popcount (tmp);
+         popcountp++;
+       }
+      *dstp++ = tmp;
+    }
+#ifdef BITMAP_DEBUGGING
+  if (has_popcount)
+    sbitmap_verify_popcount (dst);
+#endif
 }
 
 /* Set DST to be (A or B)).
    Return nonzero if any change is made.  */
 
 bool
 }
 
 /* Set DST to be (A or B)).
    Return nonzero if any change is made.  */
 
 bool
-sbitmap_a_or_b_cg (dst, a, b)
-     sbitmap dst, a, b;
+sbitmap_a_or_b_cg (sbitmap dst, const_sbitmap a, const_sbitmap b)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
   SBITMAP_ELT_TYPE changed = 0;
 
   SBITMAP_ELT_TYPE changed = 0;
 
+  gcc_assert (!dst->popcount);
+
   for (i = 0; i < n; i++)
     {
   for (i = 0; i < n; i++)
     {
-      SBITMAP_ELT_TYPE tmp = *ap++ | *bp++;
-      changed = *dstp ^ tmp;
+      const SBITMAP_ELT_TYPE tmp = *ap++ | *bp++;
+      changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
 
       *dstp++ = tmp;
     }
 
@@ -336,26 +624,40 @@ sbitmap_a_or_b_cg (dst, a, b)
 }
 
 void
 }
 
 void
-sbitmap_a_or_b (dst, a, b)
-     sbitmap dst, a, b;
+sbitmap_a_or_b (sbitmap dst, const_sbitmap a, const_sbitmap b)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  bool has_popcount = dst->popcount != NULL;
+  unsigned char *popcountp = dst->popcount;
 
   for (i = 0; i < n; i++)
 
   for (i = 0; i < n; i++)
-    *dstp++ = *ap++ | *bp++;
+    {
+      const SBITMAP_ELT_TYPE tmp = *ap++ | *bp++;
+      if (has_popcount)
+       {
+         bool wordchanged = (*dstp ^ tmp) != 0;
+         if (wordchanged)
+           *popcountp = do_popcount (tmp);
+         popcountp++;
+       }
+      *dstp++ = tmp;
+    }
+#ifdef BITMAP_DEBUGGING
+  if (has_popcount)
+    sbitmap_verify_popcount (dst);
+#endif
 }
 
 /* Return nonzero if A is a subset of B.  */
 
 bool
 }
 
 /* Return nonzero if A is a subset of B.  */
 
 bool
-sbitmap_a_subset_b_p (a, b)
-     sbitmap a, b;
+sbitmap_a_subset_b_p (const_sbitmap a, const_sbitmap b)
 {
   unsigned int i, n = a->size;
 {
   unsigned int i, n = a->size;
-  sbitmap_ptr ap, bp;
+  const_sbitmap_ptr ap, bp;
 
   for (ap = a->elms, bp = b->elms, i = 0; i < n; i++, ap++, bp++)
     if ((*ap | *bp) != *bp)
 
   for (ap = a->elms, bp = b->elms, i = 0; i < n; i++, ap++, bp++)
     if ((*ap | *bp) != *bp)
@@ -368,19 +670,20 @@ sbitmap_a_subset_b_p (a, b)
    Return nonzero if any change is made.  */
 
 bool
    Return nonzero if any change is made.  */
 
 bool
-sbitmap_a_or_b_and_c_cg (dst, a, b, c)
-     sbitmap dst, a, b, c;
+sbitmap_a_or_b_and_c_cg (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
-  sbitmap_ptr cp = c->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr cp = c->elms;
   SBITMAP_ELT_TYPE changed = 0;
 
   SBITMAP_ELT_TYPE changed = 0;
 
+  gcc_assert (!dst->popcount);
+
   for (i = 0; i < n; i++)
     {
   for (i = 0; i < n; i++)
     {
-      SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & *cp++);
+      const SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & *cp++);
       changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
       changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
@@ -389,14 +692,15 @@ sbitmap_a_or_b_and_c_cg (dst, a, b, c)
 }
 
 void
 }
 
 void
-sbitmap_a_or_b_and_c (dst, a, b, c)
-     sbitmap dst, a, b, c;
+sbitmap_a_or_b_and_c (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
-  sbitmap_ptr cp = c->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr cp = c->elms;
+
+  gcc_assert (!dst->popcount);
 
   for (i = 0; i < n; i++)
     *dstp++ = *ap++ | (*bp++ & *cp++);
 
   for (i = 0; i < n; i++)
     *dstp++ = *ap++ | (*bp++ & *cp++);
@@ -406,19 +710,20 @@ sbitmap_a_or_b_and_c (dst, a, b, c)
    Return nonzero if any change is made.  */
 
 bool
    Return nonzero if any change is made.  */
 
 bool
-sbitmap_a_and_b_or_c_cg (dst, a, b, c)
-     sbitmap dst, a, b, c;
+sbitmap_a_and_b_or_c_cg (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
-  sbitmap_ptr cp = c->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr cp = c->elms;
   SBITMAP_ELT_TYPE changed = 0;
 
   SBITMAP_ELT_TYPE changed = 0;
 
+  gcc_assert (!dst->popcount);
+
   for (i = 0; i < n; i++)
     {
   for (i = 0; i < n; i++)
     {
-      SBITMAP_ELT_TYPE tmp = *ap++ & (*bp++ | *cp++);
+      const SBITMAP_ELT_TYPE tmp = *ap++ & (*bp++ | *cp++);
       changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
       changed |= *dstp ^ tmp;
       *dstp++ = tmp;
     }
@@ -427,35 +732,43 @@ sbitmap_a_and_b_or_c_cg (dst, a, b, c)
 }
 
 void
 }
 
 void
-sbitmap_a_and_b_or_c (dst, a, b, c)
-     sbitmap dst, a, b, c;
+sbitmap_a_and_b_or_c (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
 {
   unsigned int i, n = dst->size;
   sbitmap_ptr dstp = dst->elms;
-  sbitmap_ptr ap = a->elms;
-  sbitmap_ptr bp = b->elms;
-  sbitmap_ptr cp = c->elms;
+  const_sbitmap_ptr ap = a->elms;
+  const_sbitmap_ptr bp = b->elms;
+  const_sbitmap_ptr cp = c->elms;
 
   for (i = 0; i < n; i++)
     *dstp++ = *ap++ & (*bp++ | *cp++);
 }
 
 #ifdef IN_GCC
 
   for (i = 0; i < n; i++)
     *dstp++ = *ap++ & (*bp++ | *cp++);
 }
 
 #ifdef IN_GCC
+/* FIXME: depends on basic-block.h, see comment at start of this file.
+
+   Ironically, the comments before the functions below suggest they do
+   dataflow using the "new flow graph structures", but that's the *old*
+   new data structures.  The functions receive basic block numbers and
+   use BASIC_BLOCK(idx) to get the basic block.  They should receive
+   the basic block directly,  *sigh*.  */
+
 /* Set the bitmap DST to the intersection of SRC of successors of
    block number BB, using the new flow graph structures.  */
 
 void
 /* Set the bitmap DST to the intersection of SRC of successors of
    block number BB, using the new flow graph structures.  */
 
 void
-sbitmap_intersection_of_succs (dst, src, bb)
-     sbitmap dst;
-     sbitmap *src;
-     int bb;
+sbitmap_intersection_of_succs (sbitmap dst, sbitmap *src, int bb)
 {
   basic_block b = BASIC_BLOCK (bb);
   unsigned int set_size = dst->size;
   edge e;
 {
   basic_block b = BASIC_BLOCK (bb);
   unsigned int set_size = dst->size;
   edge e;
+  unsigned ix;
+
+  gcc_assert (!dst->popcount);
 
 
-  for (e = b->succ; e != 0; e = e->succ_next)
+  for (e = NULL, ix = 0; ix < EDGE_COUNT (b->succs); ix++)
     {
     {
+      e = EDGE_SUCC (b, ix);
       if (e->dest == EXIT_BLOCK_PTR)
        continue;
 
       if (e->dest == EXIT_BLOCK_PTR)
        continue;
 
@@ -466,11 +779,12 @@ sbitmap_intersection_of_succs (dst, src, bb)
   if (e == 0)
     sbitmap_ones (dst);
   else
   if (e == 0)
     sbitmap_ones (dst);
   else
-    for (e = e->succ_next; e != 0; e = e->succ_next)
+    for (++ix; ix < EDGE_COUNT (b->succs); ix++)
       {
        unsigned int i;
        sbitmap_ptr p, r;
 
       {
        unsigned int i;
        sbitmap_ptr p, r;
 
+       e = EDGE_SUCC (b, ix);
        if (e->dest == EXIT_BLOCK_PTR)
          continue;
 
        if (e->dest == EXIT_BLOCK_PTR)
          continue;
 
@@ -485,17 +799,18 @@ sbitmap_intersection_of_succs (dst, src, bb)
    block number BB, using the new flow graph structures.  */
 
 void
    block number BB, using the new flow graph structures.  */
 
 void
-sbitmap_intersection_of_preds (dst, src, bb)
-     sbitmap dst;
-     sbitmap *src;
-     int bb;
+sbitmap_intersection_of_preds (sbitmap dst, sbitmap *src, int bb)
 {
   basic_block b = BASIC_BLOCK (bb);
   unsigned int set_size = dst->size;
   edge e;
 {
   basic_block b = BASIC_BLOCK (bb);
   unsigned int set_size = dst->size;
   edge e;
+  unsigned ix;
+
+  gcc_assert (!dst->popcount);
 
 
-  for (e = b->pred; e != 0; e = e->pred_next)
+  for (e = NULL, ix = 0; ix < EDGE_COUNT (b->preds); ix++)
     {
     {
+      e = EDGE_PRED (b, ix);
       if (e->src == ENTRY_BLOCK_PTR)
        continue;
 
       if (e->src == ENTRY_BLOCK_PTR)
        continue;
 
@@ -506,11 +821,12 @@ sbitmap_intersection_of_preds (dst, src, bb)
   if (e == 0)
     sbitmap_ones (dst);
   else
   if (e == 0)
     sbitmap_ones (dst);
   else
-    for (e = e->pred_next; e != 0; e = e->pred_next)
+    for (++ix; ix < EDGE_COUNT (b->preds); ix++)
       {
        unsigned int i;
        sbitmap_ptr p, r;
 
       {
        unsigned int i;
        sbitmap_ptr p, r;
 
+       e = EDGE_PRED (b, ix);
        if (e->src == ENTRY_BLOCK_PTR)
          continue;
 
        if (e->src == ENTRY_BLOCK_PTR)
          continue;
 
@@ -525,17 +841,18 @@ sbitmap_intersection_of_preds (dst, src, bb)
    block number BB, using the new flow graph structures.  */
 
 void
    block number BB, using the new flow graph structures.  */
 
 void
-sbitmap_union_of_succs (dst, src, bb)
-     sbitmap dst;
-     sbitmap *src;
-     int bb;
+sbitmap_union_of_succs (sbitmap dst, sbitmap *src, int bb)
 {
   basic_block b = BASIC_BLOCK (bb);
   unsigned int set_size = dst->size;
   edge e;
 {
   basic_block b = BASIC_BLOCK (bb);
   unsigned int set_size = dst->size;
   edge e;
+  unsigned ix;
 
 
-  for (e = b->succ; e != 0; e = e->succ_next)
+  gcc_assert (!dst->popcount);
+
+  for (ix = 0; ix < EDGE_COUNT (b->succs); ix++)
     {
     {
+      e = EDGE_SUCC (b, ix);
       if (e->dest == EXIT_BLOCK_PTR)
        continue;
 
       if (e->dest == EXIT_BLOCK_PTR)
        continue;
 
@@ -543,14 +860,15 @@ sbitmap_union_of_succs (dst, src, bb)
       break;
     }
 
       break;
     }
 
-  if (e == 0)
+  if (ix == EDGE_COUNT (b->succs))
     sbitmap_zero (dst);
   else
     sbitmap_zero (dst);
   else
-    for (e = e->succ_next; e != 0; e = e->succ_next)
+    for (ix++; ix < EDGE_COUNT (b->succs); ix++)
       {
        unsigned int i;
        sbitmap_ptr p, r;
 
       {
        unsigned int i;
        sbitmap_ptr p, r;
 
+       e = EDGE_SUCC (b, ix);
        if (e->dest == EXIT_BLOCK_PTR)
          continue;
 
        if (e->dest == EXIT_BLOCK_PTR)
          continue;
 
@@ -565,17 +883,18 @@ sbitmap_union_of_succs (dst, src, bb)
    block number BB, using the new flow graph structures.  */
 
 void
    block number BB, using the new flow graph structures.  */
 
 void
-sbitmap_union_of_preds (dst, src, bb)
-     sbitmap dst;
-     sbitmap *src;
-     int bb;
+sbitmap_union_of_preds (sbitmap dst, sbitmap *src, int bb)
 {
   basic_block b = BASIC_BLOCK (bb);
   unsigned int set_size = dst->size;
   edge e;
 {
   basic_block b = BASIC_BLOCK (bb);
   unsigned int set_size = dst->size;
   edge e;
+  unsigned ix;
+
+  gcc_assert (!dst->popcount);
 
 
-  for (e = b->pred; e != 0; e = e->pred_next)
+  for (ix = 0; ix < EDGE_COUNT (b->preds); ix++)
     {
     {
+      e = EDGE_PRED (b, ix);
       if (e->src== ENTRY_BLOCK_PTR)
        continue;
 
       if (e->src== ENTRY_BLOCK_PTR)
        continue;
 
@@ -583,14 +902,15 @@ sbitmap_union_of_preds (dst, src, bb)
       break;
     }
 
       break;
     }
 
-  if (e == 0)
+  if (ix == EDGE_COUNT (b->preds))
     sbitmap_zero (dst);
   else
     sbitmap_zero (dst);
   else
-    for (e = e->pred_next; e != 0; e = e->pred_next)
+    for (ix++; ix < EDGE_COUNT (b->preds); ix++)
       {
        unsigned int i;
        sbitmap_ptr p, r;
 
       {
        unsigned int i;
        sbitmap_ptr p, r;
 
+       e = EDGE_PRED (b, ix);
        if (e->src == ENTRY_BLOCK_PTR)
          continue;
 
        if (e->src == ENTRY_BLOCK_PTR)
          continue;
 
@@ -605,27 +925,27 @@ sbitmap_union_of_preds (dst, src, bb)
 /* Return number of first bit set in the bitmap, -1 if none.  */
 
 int
 /* Return number of first bit set in the bitmap, -1 if none.  */
 
 int
-sbitmap_first_set_bit (bmap)
-     sbitmap bmap;
+sbitmap_first_set_bit (const_sbitmap bmap)
 {
 {
-  unsigned int n;
+  unsigned int n = 0;
+  sbitmap_iterator sbi;
 
 
-  EXECUTE_IF_SET_IN_SBITMAP (bmap, 0, n, { return n; });
+  EXECUTE_IF_SET_IN_SBITMAP (bmap, 0, n, sbi)
+    return n;
   return -1;
 }
 
 /* Return number of last bit set in the bitmap, -1 if none.  */
 
 int
   return -1;
 }
 
 /* Return number of last bit set in the bitmap, -1 if none.  */
 
 int
-sbitmap_last_set_bit (bmap)
-     sbitmap bmap;
+sbitmap_last_set_bit (const_sbitmap bmap)
 {
   int i;
 {
   int i;
-  SBITMAP_ELT_TYPE *ptr = bmap->elms;
+  const SBITMAP_ELT_TYPE *const ptr = bmap->elms;
 
   for (i = bmap->size - 1; i >= 0; i--)
     {
 
   for (i = bmap->size - 1; i >= 0; i--)
     {
-      SBITMAP_ELT_TYPE word = ptr[i];
+      const SBITMAP_ELT_TYPE word = ptr[i];
 
       if (word != 0)
        {
 
       if (word != 0)
        {
@@ -648,9 +968,7 @@ sbitmap_last_set_bit (bmap)
 }
 
 void
 }
 
 void
-dump_sbitmap (file, bmap)
-     FILE *file;
-     sbitmap bmap;
+dump_sbitmap (FILE *file, const_sbitmap bmap)
 {
   unsigned int i, n, j;
   unsigned int set_size = bmap->size;
 {
   unsigned int i, n, j;
   unsigned int set_size = bmap->size;
@@ -671,9 +989,7 @@ dump_sbitmap (file, bmap)
 }
 
 void
 }
 
 void
-dump_sbitmap_file (file, bmap)
-     FILE *file;
-     sbitmap bmap;
+dump_sbitmap_file (FILE *file, const_sbitmap bmap)
 {
   unsigned int i, pos;
 
 {
   unsigned int i, pos;
 
@@ -695,19 +1011,15 @@ dump_sbitmap_file (file, bmap)
   fprintf (file, "}\n");
 }
 
   fprintf (file, "}\n");
 }
 
-void
-debug_sbitmap (bmap)
-     sbitmap bmap;
+DEBUG_FUNCTION void
+debug_sbitmap (const_sbitmap bmap)
 {
   dump_sbitmap_file (stderr, bmap);
 }
 
 void
 {
   dump_sbitmap_file (stderr, bmap);
 }
 
 void
-dump_sbitmap_vector (file, title, subtitle, bmaps, n_maps)
-     FILE *file;
-     const char *title, *subtitle;
-     sbitmap *bmaps;
-     int n_maps;
+dump_sbitmap_vector (FILE *file, const char *title, const char *subtitle,
+                    sbitmap *bmaps, int n_maps)
 {
   int bb;
 
 {
   int bb;
 
@@ -720,3 +1032,82 @@ dump_sbitmap_vector (file, title, subtitle, bmaps, n_maps)
 
   fprintf (file, "\n");
 }
 
   fprintf (file, "\n");
 }
+
+#if GCC_VERSION < 3400
+/* Table of number of set bits in a character, indexed by value of char.  */
+static const unsigned char popcount_table[] =
+{
+    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,
+    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,
+    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,
+    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,
+    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,
+    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,
+    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,
+    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,
+};
+
+/* Count the bits in an SBITMAP element A.  */
+
+static unsigned long
+sbitmap_elt_popcount (SBITMAP_ELT_TYPE a)
+{
+  unsigned long ret = 0;
+  unsigned i;
+
+  if (a == 0)
+    return 0;
+
+  /* Just do this the table way for now  */
+  for (i = 0; i < SBITMAP_ELT_BITS; i += 8)
+    ret += popcount_table[(a >> i) & 0xff];
+  return ret;
+}
+#endif
+
+/* Count the number of bits in SBITMAP a, up to bit MAXBIT.  */
+
+unsigned long
+sbitmap_popcount (const_sbitmap a, unsigned long maxbit)
+{
+  unsigned long count = 0;
+  unsigned ix;
+  unsigned int lastword;
+
+  if (maxbit == 0)
+    return 0;
+
+  if (maxbit >= a->n_bits)
+    maxbit = a->n_bits;
+
+  /* Count the bits in the full word.  */
+  lastword = MIN (a->size, SBITMAP_SET_SIZE (maxbit + 1) - 1);
+  for (ix = 0; ix < lastword; ix++)
+    {
+      if (a->popcount)
+       {
+         count += a->popcount[ix];
+#ifdef BITMAP_DEBUGGING
+         gcc_assert (a->popcount[ix] == do_popcount (a->elms[ix]));
+#endif
+       }
+      else
+       count += do_popcount (a->elms[ix]);
+    }
+
+  /* Count the remaining bits.  */
+  if (lastword < a->size)
+    {
+      unsigned int bitindex;
+      SBITMAP_ELT_TYPE theword = a->elms[lastword];
+
+      bitindex = maxbit % SBITMAP_ELT_BITS;
+      if (bitindex != 0)
+       {
+         theword &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - bitindex);
+         count += do_popcount (theword);
+       }
+    }
+  return count;
+}
+