X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fbitmap.h;h=411443f360f41453288cd6da53dcba3c9c0b26a5;hb=5b48787beb73c16387bedb4c2f6e33270184c93a;hp=cac84c11fba4a4e0497f5f0e5e5f3f5fc1d997ed;hpb=5fecb0bfea1b6b84f342217bcbbd9b7f0aa6f616;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/bitmap.h b/gcc/bitmap.h index cac84c11fba..411443f360f 100644 --- a/gcc/bitmap.h +++ b/gcc/bitmap.h @@ -1,12 +1,12 @@ /* Functions to support general ended bitmaps. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 - Free Software Foundation, Inc. + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007, 2008, 2009, 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 -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 @@ -15,572 +15,583 @@ 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 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 +. */ #ifndef GCC_BITMAP_H #define GCC_BITMAP_H +#include "hashtab.h" +#include "statistics.h" +#include "obstack.h" /* Fundamental storage type for bitmap. */ -/* typedef unsigned HOST_WIDE_INT BITMAP_WORD; */ -/* #define nBITMAP_WORD_BITS HOST_BITS_PER_WIDE_INT */ typedef unsigned long BITMAP_WORD; -#define nBITMAP_WORD_BITS (CHAR_BIT * SIZEOF_LONG) -#define BITMAP_WORD_BITS (unsigned) nBITMAP_WORD_BITS +/* BITMAP_WORD_BITS needs to be unsigned, but cannot contain casts as + it is used in preprocessor directives -- hence the 1u. */ +#define BITMAP_WORD_BITS (CHAR_BIT * SIZEOF_LONG * 1u) /* Number of words to use for each element in the linked list. */ #ifndef BITMAP_ELEMENT_WORDS -#define BITMAP_ELEMENT_WORDS ((128 + nBITMAP_WORD_BITS - 1) / nBITMAP_WORD_BITS) +#define BITMAP_ELEMENT_WORDS ((128 + BITMAP_WORD_BITS - 1) / BITMAP_WORD_BITS) #endif -/* Number of bits in each actual element of a bitmap. We get slightly better - code for bit % BITMAP_ELEMENT_ALL_BITS and bit / BITMAP_ELEMENT_ALL_BITS if - bits is unsigned, assuming it is a power of 2. */ +/* Number of bits in each actual element of a bitmap. */ -#define BITMAP_ELEMENT_ALL_BITS \ - ((unsigned) (BITMAP_ELEMENT_WORDS * BITMAP_WORD_BITS)) +#define BITMAP_ELEMENT_ALL_BITS (BITMAP_ELEMENT_WORDS * BITMAP_WORD_BITS) + +/* Obstack for allocating bitmaps and elements from. */ +typedef struct GTY (()) bitmap_obstack { + struct bitmap_element_def *elements; + struct bitmap_head_def *heads; + struct obstack GTY ((skip)) obstack; +} bitmap_obstack; /* Bitmap set element. We use a linked list to hold only the bits that are set. This allows for use to grow the bitset dynamically without - having to realloc and copy a giant bit array. The `prev' field is - undefined for an element on the free list. */ + having to realloc and copy a giant bit array. -typedef struct bitmap_element_def GTY(()) -{ + The free list is implemented as a list of lists. There is one + outer list connected together by prev fields. Each element of that + outer is an inner list (that may consist only of the outer list + element) that are connected by the next fields. The prev pointer + is undefined for interior elements. This allows + bitmap_elt_clear_from to be implemented in unit time rather than + linear in the number of elements to be freed. */ + +typedef struct GTY(()) bitmap_element_def { struct bitmap_element_def *next; /* Next element. */ struct bitmap_element_def *prev; /* Previous element. */ unsigned int indx; /* regno/BITMAP_ELEMENT_ALL_BITS. */ BITMAP_WORD bits[BITMAP_ELEMENT_WORDS]; /* Bits that are set. */ } bitmap_element; -/* Head of bitmap linked list. */ -typedef struct bitmap_head_def GTY(()) { +struct bitmap_descriptor; +/* Head of bitmap linked list. gengtype ignores ifdefs, but for + statistics we need to add a bitmap descriptor pointer. As it is + not collected, we can just GTY((skip)) it. */ + +typedef struct GTY(()) bitmap_head_def { bitmap_element *first; /* First element in linked list. */ bitmap_element *current; /* Last element looked at. */ unsigned int indx; /* Index of last element looked at. */ - int using_obstack; /* Are we using an obstack or ggc for - allocation? */ + bitmap_obstack *obstack; /* Obstack to allocate elements from. + If NULL, then use GGC allocation. */ +#ifdef GATHER_STATISTICS + struct bitmap_descriptor GTY((skip)) *desc; +#endif } bitmap_head; -typedef struct bitmap_head_def *bitmap; - -/* Enumeration giving the various operations we support. */ -enum bitmap_bits { - BITMAP_AND, /* TO = FROM1 & FROM2 */ - BITMAP_AND_COMPL, /* TO = FROM1 & ~ FROM2 */ - BITMAP_IOR, /* TO = FROM1 | FROM2 */ - BITMAP_XOR, /* TO = FROM1 ^ FROM2 */ - BITMAP_IOR_COMPL /* TO = FROM1 | ~FROM2 */ -}; /* Global data */ extern bitmap_element bitmap_zero_bits; /* Zero bitmap element */ +extern bitmap_obstack bitmap_default_obstack; /* Default bitmap obstack */ /* Clear a bitmap by freeing up the linked list. */ extern void bitmap_clear (bitmap); /* Copy a bitmap to another bitmap. */ -extern void bitmap_copy (bitmap, bitmap); +extern void bitmap_copy (bitmap, const_bitmap); /* True if two bitmaps are identical. */ -extern int bitmap_equal_p (bitmap, bitmap); - -/* Perform an operation on two bitmaps, yielding a third. */ -extern int bitmap_operation (bitmap, bitmap, bitmap, enum bitmap_bits); - -/* `or' into one bitmap the `and' of a second bitmap witih the complement - of a third. */ -extern void bitmap_ior_and_compl (bitmap, bitmap, bitmap); - -/* Clear a single register in a register set. */ -extern void bitmap_clear_bit (bitmap, int); - -/* Set a single register in a register set. */ -extern void bitmap_set_bit (bitmap, int); +extern bool bitmap_equal_p (const_bitmap, const_bitmap); + +/* True if the bitmaps intersect (their AND is non-empty). */ +extern bool bitmap_intersect_p (const_bitmap, const_bitmap); + +/* True if the complement of the second intersects the first (their + AND_COMPL is non-empty). */ +extern bool bitmap_intersect_compl_p (const_bitmap, const_bitmap); + +/* True if MAP is an empty bitmap. */ +#define bitmap_empty_p(MAP) (!(MAP)->first) + +/* True if the bitmap has only a single bit set. */ +extern bool bitmap_single_bit_set_p (const_bitmap); + +/* Count the number of bits set in the bitmap. */ +extern unsigned long bitmap_count_bits (const_bitmap); + +/* Boolean operations on bitmaps. The _into variants are two operand + versions that modify the first source operand. The other variants + are three operand versions that to not destroy the source bitmaps. + The operations supported are &, & ~, |, ^. */ +extern void bitmap_and (bitmap, const_bitmap, const_bitmap); +extern void bitmap_and_into (bitmap, const_bitmap); +extern bool bitmap_and_compl (bitmap, const_bitmap, const_bitmap); +extern bool bitmap_and_compl_into (bitmap, const_bitmap); +#define bitmap_compl_and(DST, A, B) bitmap_and_compl (DST, B, A) +extern void bitmap_compl_and_into (bitmap, const_bitmap); +extern void bitmap_clear_range (bitmap, unsigned int, unsigned int); +extern void bitmap_set_range (bitmap, unsigned int, unsigned int); +extern bool bitmap_ior (bitmap, const_bitmap, const_bitmap); +extern bool bitmap_ior_into (bitmap, const_bitmap); +extern void bitmap_xor (bitmap, const_bitmap, const_bitmap); +extern void bitmap_xor_into (bitmap, const_bitmap); + +/* DST = A | (B & C). Return true if DST changes. */ +extern bool bitmap_ior_and_into (bitmap DST, const_bitmap B, const_bitmap C); +/* DST = A | (B & ~C). Return true if DST changes. */ +extern bool bitmap_ior_and_compl (bitmap DST, const_bitmap A, const_bitmap B, const_bitmap C); +/* A |= (B & ~C). Return true if A changes. */ +extern bool bitmap_ior_and_compl_into (bitmap DST, const_bitmap B, const_bitmap C); + +/* Clear a single bit in a bitmap. Return true if the bit changed. */ +extern bool bitmap_clear_bit (bitmap, int); + +/* Set a single bit in a bitmap. Return true if the bit changed. */ +extern bool bitmap_set_bit (bitmap, int); /* Return true if a register is set in a register set. */ extern int bitmap_bit_p (bitmap, int); /* Debug functions to print a bitmap linked list. */ -extern void debug_bitmap (bitmap); -extern void debug_bitmap_file (FILE *, bitmap); +extern void debug_bitmap (const_bitmap); +extern void debug_bitmap_file (FILE *, const_bitmap); /* Print a bitmap. */ -extern void bitmap_print (FILE *, bitmap, const char *, const char *); +extern void bitmap_print (FILE *, const_bitmap, const char *, const char *); + +/* Initialize and release a bitmap obstack. */ +extern void bitmap_obstack_initialize (bitmap_obstack *); +extern void bitmap_obstack_release (bitmap_obstack *); +extern void bitmap_register (bitmap MEM_STAT_DECL); +extern void dump_bitmap_statistics (void); -/* Initialize a bitmap header. If HEAD is NULL, a new header will be - allocated. USING_OBSTACK indicates how elements should be allocated. */ -extern bitmap bitmap_initialize (bitmap head, int using_obstack); +/* Initialize a bitmap header. OBSTACK indicates the bitmap obstack + to allocate from, NULL for GC'd bitmap. */ -/* Release all memory used by the bitmap obstack. */ -extern void bitmap_release_memory (void); +static inline void +bitmap_initialize_stat (bitmap head, bitmap_obstack *obstack MEM_STAT_DECL) +{ + head->first = head->current = NULL; + head->obstack = obstack; +#ifdef GATHER_STATISTICS + bitmap_register (head PASS_MEM_STAT); +#endif +} +#define bitmap_initialize(h,o) bitmap_initialize_stat (h,o MEM_STAT_INFO) + +/* Allocate and free bitmaps from obstack, malloc and gc'd memory. */ +extern bitmap bitmap_obstack_alloc_stat (bitmap_obstack *obstack MEM_STAT_DECL); +#define bitmap_obstack_alloc(t) bitmap_obstack_alloc_stat (t MEM_STAT_INFO) +extern bitmap bitmap_gc_alloc_stat (ALONE_MEM_STAT_DECL); +#define bitmap_gc_alloc() bitmap_gc_alloc_stat (ALONE_MEM_STAT_INFO) +extern void bitmap_obstack_free (bitmap); /* A few compatibility/functions macros for compatibility with sbitmaps */ #define dump_bitmap(file, bitmap) bitmap_print (file, bitmap, "", "\n") #define bitmap_zero(a) bitmap_clear (a) -#define bitmap_a_or_b(a,b,c) bitmap_operation (a, b, c, BITMAP_IOR) -#define bitmap_a_and_b(a,b,c) bitmap_operation (a, b, c, BITMAP_AND) -extern int bitmap_union_of_diff (bitmap, bitmap, bitmap, bitmap); -extern int bitmap_first_set_bit (bitmap); -extern int bitmap_last_set_bit (bitmap); +extern unsigned bitmap_first_set_bit (const_bitmap); +extern unsigned bitmap_last_set_bit (const_bitmap); -/* Allocate a bitmap with oballoc. */ -#define BITMAP_OBSTACK_ALLOC(OBSTACK) \ - bitmap_initialize (obstack_alloc (OBSTACK, sizeof (bitmap_head)), 1) +/* Compute bitmap hash (for purposes of hashing etc.) */ +extern hashval_t bitmap_hash(const_bitmap); -/* Allocate a bitmap with ggc_alloc. */ -#define BITMAP_GGC_ALLOC() \ - bitmap_initialize (NULL, 0) +/* Allocate a bitmap from a bit obstack. */ +#define BITMAP_ALLOC(OBSTACK) bitmap_obstack_alloc (OBSTACK) -/* Allocate a bitmap with xmalloc. */ -#define BITMAP_XMALLOC() \ - bitmap_initialize (xmalloc (sizeof (bitmap_head)), 1) +/* Allocate a gc'd bitmap. */ +#define BITMAP_GGC_ALLOC() bitmap_gc_alloc () /* Do any cleanup needed on a bitmap when it is no longer used. */ -#define BITMAP_FREE(BITMAP) \ -do { \ - if (BITMAP) \ - { \ - bitmap_clear (BITMAP); \ - (BITMAP) = 0; \ - } \ -} while (0) - -/* Do any cleanup needed on an xmalloced bitmap when it is no longer used. */ -#define BITMAP_XFREE(BITMAP) \ -do { \ - if (BITMAP) \ - { \ - bitmap_clear (BITMAP); \ - free (BITMAP); \ - (BITMAP) = 0; \ - } \ -} while (0) - -/* Do any one-time initializations needed for bitmaps. */ -#define BITMAP_INIT_ONCE() +#define BITMAP_FREE(BITMAP) \ + ((void) (bitmap_obstack_free ((bitmap) BITMAP), (BITMAP) = (bitmap) NULL)) /* Iterator for bitmaps. */ typedef struct { - /* Actual elements in the bitmaps. */ - bitmap_element *ptr1, *ptr2; - - /* Position of an actual word in the elements. */ - unsigned word; + /* Pointer to the current bitmap element. */ + bitmap_element *elt1; - /* Position of a bit corresponding to the start of word. */ - unsigned word_bit; + /* Pointer to 2nd bitmap element when two are involved. */ + bitmap_element *elt2; - /* Position of the actual bit. */ - unsigned bit; + /* Word within the current element. */ + unsigned word_no; /* Contents of the actually processed word. When finding next bit it is shifted right, so that the actual bit is always the least significant bit of ACTUAL. */ - BITMAP_WORD actual; + BITMAP_WORD bits; } bitmap_iterator; -/* Moves the iterator BI to the first set bit on or after the current - position in bitmap and returns the bit if available. The bit is - found in ACTUAL field only. */ +/* Initialize a single bitmap iterator. START_BIT is the first bit to + iterate from. */ -static inline unsigned -bmp_iter_common_next_1 (bitmap_iterator *bi) +static inline void +bmp_iter_set_init (bitmap_iterator *bi, const_bitmap map, + unsigned start_bit, unsigned *bit_no) { - while (!(bi->actual & 1)) + bi->elt1 = map->first; + bi->elt2 = NULL; + + /* Advance elt1 until it is not before the block containing start_bit. */ + while (1) { - bi->actual >>= 1; - bi->bit++; + if (!bi->elt1) + { + bi->elt1 = &bitmap_zero_bits; + break; + } + + if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS) + break; + bi->elt1 = bi->elt1->next; } - return bi->bit; + /* We might have gone past the start bit, so reinitialize it. */ + if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS) + start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS; + + /* Initialize for what is now start_bit. */ + bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; + bi->bits = bi->elt1->bits[bi->word_no]; + bi->bits >>= start_bit % BITMAP_WORD_BITS; + + /* If this word is zero, we must make sure we're not pointing at the + first bit, otherwise our incrementing to the next word boundary + will fail. It won't matter if this increment moves us into the + next word. */ + start_bit += !bi->bits; + + *bit_no = start_bit; } -/* Moves the iterator BI to the first set bit on or after the current - position in bitmap and returns the bit if available. */ +/* Initialize an iterator to iterate over the intersection of two + bitmaps. START_BIT is the bit to commence from. */ -static inline unsigned -bmp_iter_single_next_1 (bitmap_iterator *bi) +static inline void +bmp_iter_and_init (bitmap_iterator *bi, const_bitmap map1, const_bitmap map2, + unsigned start_bit, unsigned *bit_no) { - if (bi->actual) - return bmp_iter_common_next_1 (bi); - - bi->word++; - bi->word_bit += BITMAP_WORD_BITS; + bi->elt1 = map1->first; + bi->elt2 = map2->first; + /* Advance elt1 until it is not before the block containing + start_bit. */ while (1) { - for (; - bi->word < BITMAP_ELEMENT_WORDS; - bi->word++, bi->word_bit += BITMAP_WORD_BITS) + if (!bi->elt1) { - bi->actual = bi->ptr1->bits[bi->word]; - if (bi->actual) - { - bi->bit = bi->word_bit; - return bmp_iter_common_next_1 (bi); - } + bi->elt2 = NULL; + break; } - bi->ptr1 = bi->ptr1->next; - if (!bi->ptr1) - return 0; - - bi->word = 0; - bi->word_bit = bi->ptr1->indx * BITMAP_ELEMENT_ALL_BITS; + if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS) + break; + bi->elt1 = bi->elt1->next; } -} - -/* Initializes a bitmap iterator BI for looping over bits of bitmap - BMP, starting with bit MIN. Returns the first bit of BMP greater - or equal to MIN if there is any. */ - -static inline unsigned -bmp_iter_single_init (bitmap_iterator *bi, bitmap bmp, unsigned min) -{ - unsigned indx = min / BITMAP_ELEMENT_ALL_BITS; - for (bi->ptr1 = bmp->first; - bi->ptr1 && bi->ptr1->indx < indx; - bi->ptr1 = bi->ptr1->next) - continue; - - if (!bi->ptr1) + /* Advance elt2 until it is not before elt1. */ + while (1) { - /* To avoid warnings. */ - bi->word = 0; - bi->bit = 0; - bi->word_bit = 0; - bi->actual = 0; - bi->ptr2 = NULL; - return 0; + if (!bi->elt2) + { + bi->elt1 = bi->elt2 = &bitmap_zero_bits; + break; + } + + if (bi->elt2->indx >= bi->elt1->indx) + break; + bi->elt2 = bi->elt2->next; } - if (bi->ptr1->indx == indx) + /* If we're at the same index, then we have some intersecting bits. */ + if (bi->elt1->indx == bi->elt2->indx) { - unsigned bit_in_elt = min - BITMAP_ELEMENT_ALL_BITS * indx; - unsigned word_in_elt = bit_in_elt / BITMAP_WORD_BITS; - unsigned bit_in_word = bit_in_elt % BITMAP_WORD_BITS; - - bi->word = word_in_elt; - bi->word_bit = min - bit_in_word; - bi->bit = min; - bi->actual = bi->ptr1->bits[word_in_elt] >> bit_in_word; + /* We might have advanced beyond the start_bit, so reinitialize + for that. */ + if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS) + start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS; + + bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; + bi->bits = bi->elt1->bits[bi->word_no] & bi->elt2->bits[bi->word_no]; + bi->bits >>= start_bit % BITMAP_WORD_BITS; } else { - bi->word = 0; - bi->bit = bi->ptr1->indx * BITMAP_ELEMENT_ALL_BITS; - bi->word_bit = bi->bit; - bi->actual = bi->ptr1->bits[0]; + /* Otherwise we must immediately advance elt1, so initialize for + that. */ + bi->word_no = BITMAP_ELEMENT_WORDS - 1; + bi->bits = 0; } - return bmp_iter_single_next_1 (bi); -} + /* If this word is zero, we must make sure we're not pointing at the + first bit, otherwise our incrementing to the next word boundary + will fail. It won't matter if this increment moves us into the + next word. */ + start_bit += !bi->bits; -/* Returns true if all elements of the bitmap referred to by iterator BI - were processed. */ - -static inline bool -bmp_iter_end_p (bitmap_iterator bi) -{ - return bi.ptr1 == NULL; + *bit_no = start_bit; } -/* Moves the iterator BI to the next bit of bitmap and returns the bit - if available. */ +/* Initialize an iterator to iterate over the bits in MAP1 & ~MAP2. + */ -static inline unsigned -bmp_iter_single_next (bitmap_iterator *bi) +static inline void +bmp_iter_and_compl_init (bitmap_iterator *bi, const_bitmap map1, const_bitmap map2, + unsigned start_bit, unsigned *bit_no) { - bi->bit++; - bi->actual >>= 1; - return bmp_iter_single_next_1 (bi); -} - -/* Loop over all bits in BITMAP, starting with MIN and setting BITNUM to - the bit number. ITER is a bitmap iterator. */ - -#define EXECUTE_IF_SET_IN_BITMAP(BITMAP, MIN, BITNUM, ITER) \ - for ((BITNUM) = bmp_iter_single_init (&(ITER), (BITMAP), (MIN)); \ - !bmp_iter_end_p (ITER); \ - (BITNUM) = bmp_iter_single_next (&(ITER))) - -/* Moves the iterator BI to the first set bit on or after the current - position in difference of bitmaps and returns the bit if available. */ - -static inline unsigned -bmp_iter_and_not_next_1 (bitmap_iterator *bi) -{ - if (bi->actual) - return bmp_iter_common_next_1 (bi); - - bi->word++; - bi->word_bit += BITMAP_WORD_BITS; + bi->elt1 = map1->first; + bi->elt2 = map2->first; + /* Advance elt1 until it is not before the block containing start_bit. */ while (1) { - bitmap_element *snd; - - if (bi->ptr2 && bi->ptr2->indx == bi->ptr1->indx) - snd = bi->ptr2; - else - snd = &bitmap_zero_bits; - - for (; - bi->word < BITMAP_ELEMENT_WORDS; - bi->word++, bi->word_bit += BITMAP_WORD_BITS) + if (!bi->elt1) { - bi->actual = (bi->ptr1->bits[bi->word] - & ~snd->bits[bi->word]); - if (bi->actual) - { - bi->bit = bi->word_bit; - return bmp_iter_common_next_1 (bi); - } + bi->elt1 = &bitmap_zero_bits; + break; } - bi->ptr1 = bi->ptr1->next; - if (!bi->ptr1) - return 0; + if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS) + break; + bi->elt1 = bi->elt1->next; + } - while (bi->ptr2 - && bi->ptr2->indx < bi->ptr1->indx) - bi->ptr2 = bi->ptr2->next; + /* Advance elt2 until it is not before elt1. */ + while (bi->elt2 && bi->elt2->indx < bi->elt1->indx) + bi->elt2 = bi->elt2->next; - bi->word = 0; - bi->word_bit = bi->ptr1->indx * BITMAP_ELEMENT_ALL_BITS; - } + /* We might have advanced beyond the start_bit, so reinitialize for + that. */ + if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS) + start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS; + + bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; + bi->bits = bi->elt1->bits[bi->word_no]; + if (bi->elt2 && bi->elt1->indx == bi->elt2->indx) + bi->bits &= ~bi->elt2->bits[bi->word_no]; + bi->bits >>= start_bit % BITMAP_WORD_BITS; + + /* If this word is zero, we must make sure we're not pointing at the + first bit, otherwise our incrementing to the next word boundary + will fail. It won't matter if this increment moves us into the + next word. */ + start_bit += !bi->bits; + + *bit_no = start_bit; } -/* Initializes a bitmap iterator BI for looping over bits of bitmap - BMP1 &~ BMP2, starting with bit MIN. Returns the first bit of - BMP1 &~ BMP2 greater or equal to MIN if there is any. */ +/* Advance to the next bit in BI. We don't advance to the next + nonzero bit yet. */ -static inline unsigned -bmp_iter_and_not_init (bitmap_iterator *bi, bitmap bmp1, bitmap bmp2, - unsigned min) +static inline void +bmp_iter_next (bitmap_iterator *bi, unsigned *bit_no) { - unsigned indx = min / BITMAP_ELEMENT_ALL_BITS; + bi->bits >>= 1; + *bit_no += 1; +} - for (bi->ptr1 = bmp1->first; - bi->ptr1 && bi->ptr1->indx < indx; - bi->ptr1 = bi->ptr1->next) - continue; +/* Advance to first set bit in BI. */ - if (!bi->ptr1) +static inline void +bmp_iter_next_bit (bitmap_iterator * bi, unsigned *bit_no) +{ +#if (GCC_VERSION >= 3004) + { + unsigned int n = __builtin_ctzl (bi->bits); + gcc_assert (sizeof (unsigned long) == sizeof (BITMAP_WORD)); + bi->bits >>= n; + *bit_no += n; + } +#else + while (!(bi->bits & 1)) { - /* To avoid warnings. */ - bi->word = 0; - bi->bit = 0; - bi->word_bit = 0; - bi->actual = 0; - bi->ptr2 = NULL; - return 0; + bi->bits >>= 1; + *bit_no += 1; } +#endif +} - for (bi->ptr2 = bmp2->first; - bi->ptr2 && bi->ptr2->indx < bi->ptr1->indx; - bi->ptr2 = bi->ptr2->next) - continue; +/* Advance to the next nonzero bit of a single bitmap, we will have + already advanced past the just iterated bit. Return true if there + is a bit to iterate. */ - if (bi->ptr1->indx == indx) - { - unsigned bit_in_elt = min - BITMAP_ELEMENT_ALL_BITS * indx; - unsigned word_in_elt = bit_in_elt / BITMAP_WORD_BITS; - unsigned bit_in_word = bit_in_elt % BITMAP_WORD_BITS; - - bi->word = word_in_elt; - bi->word_bit = min - bit_in_word; - bi->bit = min; - - if (bi->ptr2 && bi->ptr2->indx == indx) - bi->actual = (bi->ptr1->bits[word_in_elt] - & ~bi->ptr2->bits[word_in_elt]) >> bit_in_word; - else - bi->actual = bi->ptr1->bits[word_in_elt] >> bit_in_word; - } - else +static inline bool +bmp_iter_set (bitmap_iterator *bi, unsigned *bit_no) +{ + /* If our current word is nonzero, it contains the bit we want. */ + if (bi->bits) { - bi->word = 0; - bi->bit = bi->ptr1->indx * BITMAP_ELEMENT_ALL_BITS; - bi->word_bit = bi->bit; - - if (bi->ptr2 && bi->ptr2->indx == bi->ptr1->indx) - bi->actual = (bi->ptr1->bits[0] & ~bi->ptr2->bits[0]); - else - bi->actual = bi->ptr1->bits[0]; + next_bit: + bmp_iter_next_bit (bi, bit_no); + return true; } - return bmp_iter_and_not_next_1 (bi); -} + /* Round up to the word boundary. We might have just iterated past + the end of the last word, hence the -1. It is not possible for + bit_no to point at the beginning of the now last word. */ + *bit_no = ((*bit_no + BITMAP_WORD_BITS - 1) + / BITMAP_WORD_BITS * BITMAP_WORD_BITS); + bi->word_no++; -/* Moves the iterator BI to the next bit of difference of bitmaps and returns - the bit if available. */ + while (1) + { + /* Find the next nonzero word in this elt. */ + while (bi->word_no != BITMAP_ELEMENT_WORDS) + { + bi->bits = bi->elt1->bits[bi->word_no]; + if (bi->bits) + goto next_bit; + *bit_no += BITMAP_WORD_BITS; + bi->word_no++; + } -static inline unsigned -bmp_iter_and_not_next (bitmap_iterator *bi) -{ - bi->bit++; - bi->actual >>= 1; - return bmp_iter_and_not_next_1 (bi); + /* Advance to the next element. */ + bi->elt1 = bi->elt1->next; + if (!bi->elt1) + return false; + *bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS; + bi->word_no = 0; + } } -/* Loop over all bits in BMP1 and BMP2, starting with MIN, setting - BITNUM to the bit number for all bits that are set in the first bitmap - and not set in the second. ITER is a bitmap iterator. */ +/* Advance to the next nonzero bit of an intersecting pair of + bitmaps. We will have already advanced past the just iterated bit. + Return true if there is a bit to iterate. */ -#define EXECUTE_IF_AND_COMPL_IN_BITMAP(BMP1, BMP2, MIN, BITNUM, ITER) \ - for ((BITNUM) = bmp_iter_and_not_init (&(ITER), (BMP1), (BMP2), (MIN)); \ - !bmp_iter_end_p (ITER); \ - (BITNUM) = bmp_iter_and_not_next (&(ITER))) - -/* Moves the iterator BI to the first set bit on or after the current - position in intersection of bitmaps and returns the bit if available. */ - -static inline unsigned -bmp_iter_and_next_1 (bitmap_iterator *bi) +static inline bool +bmp_iter_and (bitmap_iterator *bi, unsigned *bit_no) { - if (bi->actual) - return bmp_iter_common_next_1 (bi); + /* If our current word is nonzero, it contains the bit we want. */ + if (bi->bits) + { + next_bit: + bmp_iter_next_bit (bi, bit_no); + return true; + } - bi->word++; - bi->word_bit += BITMAP_WORD_BITS; + /* Round up to the word boundary. We might have just iterated past + the end of the last word, hence the -1. It is not possible for + bit_no to point at the beginning of the now last word. */ + *bit_no = ((*bit_no + BITMAP_WORD_BITS - 1) + / BITMAP_WORD_BITS * BITMAP_WORD_BITS); + bi->word_no++; while (1) { - for (; - bi->word < BITMAP_ELEMENT_WORDS; - bi->word++, bi->word_bit += BITMAP_WORD_BITS) + /* Find the next nonzero word in this elt. */ + while (bi->word_no != BITMAP_ELEMENT_WORDS) { - bi->actual = (bi->ptr1->bits[bi->word] - & bi->ptr2->bits[bi->word]); - if (bi->actual) - { - bi->bit = bi->word_bit; - return bmp_iter_common_next_1 (bi); - } + bi->bits = bi->elt1->bits[bi->word_no] & bi->elt2->bits[bi->word_no]; + if (bi->bits) + goto next_bit; + *bit_no += BITMAP_WORD_BITS; + bi->word_no++; } + /* Advance to the next identical element. */ do { - bi->ptr1 = bi->ptr1->next; - if (!bi->ptr1) - return 0; + /* Advance elt1 while it is less than elt2. We always want + to advance one elt. */ + do + { + bi->elt1 = bi->elt1->next; + if (!bi->elt1) + return false; + } + while (bi->elt1->indx < bi->elt2->indx); - while (bi->ptr2->indx < bi->ptr1->indx) + /* Advance elt2 to be no less than elt1. This might not + advance. */ + while (bi->elt2->indx < bi->elt1->indx) { - bi->ptr2 = bi->ptr2->next; - if (!bi->ptr2) - { - bi->ptr1 = NULL; - return 0; - } + bi->elt2 = bi->elt2->next; + if (!bi->elt2) + return false; } } - while (bi->ptr1->indx != bi->ptr2->indx); + while (bi->elt1->indx != bi->elt2->indx); - bi->word = 0; - bi->word_bit = bi->ptr1->indx * BITMAP_ELEMENT_ALL_BITS; + *bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS; + bi->word_no = 0; } } -/* Initializes a bitmap iterator BI for looping over bits of bitmap - BMP1 & BMP2, starting with bit MIN. Returns the first bit of - BMP1 & BMP2 greater or equal to MIN if there is any. */ +/* Advance to the next nonzero bit in the intersection of + complemented bitmaps. We will have already advanced past the just + iterated bit. */ -static inline unsigned -bmp_iter_and_init (bitmap_iterator *bi, bitmap bmp1, bitmap bmp2, - unsigned min) +static inline bool +bmp_iter_and_compl (bitmap_iterator *bi, unsigned *bit_no) { - unsigned indx = min / BITMAP_ELEMENT_ALL_BITS; - - for (bi->ptr1 = bmp1->first; - bi->ptr1 && bi->ptr1->indx < indx; - bi->ptr1 = bi->ptr1->next) - continue; - - if (!bi->ptr1) - goto empty; + /* If our current word is nonzero, it contains the bit we want. */ + if (bi->bits) + { + next_bit: + bmp_iter_next_bit (bi, bit_no); + return true; + } - bi->ptr2 = bmp2->first; - if (!bi->ptr2) - goto empty; + /* Round up to the word boundary. We might have just iterated past + the end of the last word, hence the -1. It is not possible for + bit_no to point at the beginning of the now last word. */ + *bit_no = ((*bit_no + BITMAP_WORD_BITS - 1) + / BITMAP_WORD_BITS * BITMAP_WORD_BITS); + bi->word_no++; while (1) { - while (bi->ptr2->indx < bi->ptr1->indx) + /* Find the next nonzero word in this elt. */ + while (bi->word_no != BITMAP_ELEMENT_WORDS) { - bi->ptr2 = bi->ptr2->next; - if (!bi->ptr2) - goto empty; + bi->bits = bi->elt1->bits[bi->word_no]; + if (bi->elt2 && bi->elt2->indx == bi->elt1->indx) + bi->bits &= ~bi->elt2->bits[bi->word_no]; + if (bi->bits) + goto next_bit; + *bit_no += BITMAP_WORD_BITS; + bi->word_no++; } - if (bi->ptr1->indx == bi->ptr2->indx) - break; - - bi->ptr1 = bi->ptr1->next; - if (!bi->ptr1) - goto empty; - } - - if (bi->ptr1->indx == indx) - { - unsigned bit_in_elt = min - BITMAP_ELEMENT_ALL_BITS * indx; - unsigned word_in_elt = bit_in_elt / BITMAP_WORD_BITS; - unsigned bit_in_word = bit_in_elt % BITMAP_WORD_BITS; - - bi->word = word_in_elt; - bi->word_bit = min - bit_in_word; - bi->bit = min; + /* Advance to the next element of elt1. */ + bi->elt1 = bi->elt1->next; + if (!bi->elt1) + return false; - bi->actual = (bi->ptr1->bits[word_in_elt] - & bi->ptr2->bits[word_in_elt]) >> bit_in_word; - } - else - { - bi->word = 0; - bi->bit = bi->ptr1->indx * BITMAP_ELEMENT_ALL_BITS; - bi->word_bit = bi->bit; + /* Advance elt2 until it is no less than elt1. */ + while (bi->elt2 && bi->elt2->indx < bi->elt1->indx) + bi->elt2 = bi->elt2->next; - bi->actual = (bi->ptr1->bits[0] & bi->ptr2->bits[0]); + *bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS; + bi->word_no = 0; } - - return bmp_iter_and_next_1 (bi); - -empty: - /* To avoid warnings. */ - bi->word = 0; - bi->bit = 0; - bi->word_bit = 0; - bi->actual = 0; - bi->ptr1 = NULL; - bi->ptr2 = NULL; - return 0; -} - -/* Moves the iterator BI to the next bit of intersection of bitmaps and returns - the bit if available. */ - -static inline unsigned -bmp_iter_and_next (bitmap_iterator *bi) -{ - bi->bit++; - bi->actual >>= 1; - return bmp_iter_and_next_1 (bi); } -/* Loop over all bits in BMP1 and BMP2, starting with MIN, setting - BITNUM to the bit number for all bits that are set in both bitmaps. - ITER is a bitmap iterator. */ +/* Loop over all bits set in BITMAP, starting with MIN and setting + BITNUM to the bit number. ITER is a bitmap iterator. BITNUM + should be treated as a read-only variable as it contains loop + state. */ -#define EXECUTE_IF_AND_IN_BITMAP(BMP1, BMP2, MIN, BITNUM, ITER) \ - for ((BITNUM) = bmp_iter_and_init (&(ITER), (BMP1), (BMP2), (MIN)); \ - !bmp_iter_end_p (ITER); \ - (BITNUM) = bmp_iter_and_next (&(ITER))) +#define EXECUTE_IF_SET_IN_BITMAP(BITMAP, MIN, BITNUM, ITER) \ + for (bmp_iter_set_init (&(ITER), (BITMAP), (MIN), &(BITNUM)); \ + bmp_iter_set (&(ITER), &(BITNUM)); \ + bmp_iter_next (&(ITER), &(BITNUM))) + +/* Loop over all the bits set in BITMAP1 & BITMAP2, starting with MIN + and setting BITNUM to the bit number. ITER is a bitmap iterator. + BITNUM should be treated as a read-only variable as it contains + loop state. */ + +#define EXECUTE_IF_AND_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, ITER) \ + for (bmp_iter_and_init (&(ITER), (BITMAP1), (BITMAP2), (MIN), \ + &(BITNUM)); \ + bmp_iter_and (&(ITER), &(BITNUM)); \ + bmp_iter_next (&(ITER), &(BITNUM))) + +/* Loop over all the bits set in BITMAP1 & ~BITMAP2, starting with MIN + and setting BITNUM to the bit number. ITER is a bitmap iterator. + BITNUM should be treated as a read-only variable as it contains + loop state. */ + +#define EXECUTE_IF_AND_COMPL_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, ITER) \ + for (bmp_iter_and_compl_init (&(ITER), (BITMAP1), (BITMAP2), (MIN), \ + &(BITNUM)); \ + bmp_iter_and_compl (&(ITER), &(BITNUM)); \ + bmp_iter_next (&(ITER), &(BITNUM))) #endif /* GCC_BITMAP_H */