Unused bits in the last unit are now cleared
authorSebastian Hack <hack@ipd.info.uni-karlsruhe.de>
Thu, 21 Apr 2005 15:08:31 +0000 (15:08 +0000)
committerSebastian Hack <hack@ipd.info.uni-karlsruhe.de>
Thu, 21 Apr 2005 15:08:31 +0000 (15:08 +0000)
[r5731]

ir/adt/bitset.h
ir/adt/bitset_ia32.h
ir/adt/bitset_std.h

index 5d86c23..096e19c 100644 (file)
@@ -16,6 +16,8 @@
 #include "firm_config.h"
 #include "bitfiddle.h"
 
+typedef unsigned int bitset_pos_t;
+
 #include "bitset_std.h"
 
 /*
 */
 
 typedef struct _bitset_t {
-       unsigned long units;
-       unsigned long *data;
+       bitset_pos_t units;
+  bitset_pos_t highest_bit;
+       bitset_unit_t *data;
 } bitset_t;
 
-#define BS_UNIT_SIZE sizeof(unsigned long)
+#define BS_UNIT_SIZE sizeof(bitset_unit_t)
 #define BS_UNIT_SIZE_BITS (BS_UNIT_SIZE * 8)
 #define BS_UNIT_MASK (BS_UNIT_SIZE_BITS - 1)
 
@@ -52,15 +55,28 @@ typedef struct _bitset_t {
  * @param units The number of units that are allocated for the bitset.
  * @return A pointer to the initialized bitset.
  */
-static INLINE bitset_t *_bitset_prepare(void *area, unsigned long highest_bit)
+static INLINE bitset_t *_bitset_prepare(void *area, bitset_pos_t highest_bit)
 {
        bitset_t *ptr = area;
        memset(area, 0, _bitset_overall_size(sizeof(bitset_t), highest_bit));
        ptr->units = _bitset_units(highest_bit);
+  ptr->highest_bit = highest_bit;
        ptr->data = _bitset_data_ptr(area, sizeof(bitset_t), highest_bit);
        return ptr;
 }
 
+/**
+ * Mask out all bits, which are only there, because the number
+ * of bits in the set didn't match a unit size boundary.
+ * @param bs The bitset.
+ * @return The masked bitset.
+ */
+static INLINE bitset_t *_bitset_mask_highest(bitset_t *bs)
+{
+  bs->data[bs->units - 1] &= (bs->highest_bit & BS_UNIT_MASK) - 1;
+  return bs;
+}
+
 /**
  * Get the capacity of the bitset in bits.
  * @param bs The bitset.
@@ -68,6 +84,13 @@ static INLINE bitset_t *_bitset_prepare(void *area, unsigned long highest_bit)
  */
 #define bitset_capacity(bs) ((bs)->units * BS_UNIT_SIZE_BITS)
 
+/**
+ * Get the highest bit which can be stored in the bitset.
+ * @param bs The bitset.
+ * @return The highest bit which can be set or cleared.
+ */
+#define bistet_highest_bit(bs)  ((bs)->highest_bit)
+
 /**
  * Allocate a bitset on an obstack.
  * @param obst The obstack.
@@ -107,9 +130,10 @@ static INLINE bitset_t *_bitset_prepare(void *area, unsigned long highest_bit)
  * @param bit The bit.
  * @return A pointer to the unit containing the bit.
  */
-static INLINE unsigned long *_bitset_get_unit(const bitset_t *bs, unsigned long bit)
+static INLINE bitset_unit_t *_bitset_get_unit(const bitset_t *bs, bitset_pos_t bit)
 {
-       assert(bit < bs->units * BS_UNIT_SIZE_BITS && "Bit too large");
+       /* assert(bit < bs->units * BS_UNIT_SIZE_BITS && "Bit too large"); */
+  assert(bit <= bs->highest_bit && "Bit to large");
        return bs->data + bit / BS_UNIT_SIZE_BITS;
 }
 
@@ -118,9 +142,9 @@ static INLINE unsigned long *_bitset_get_unit(const bitset_t *bs, unsigned long
  * @param bs The bitset.
  * @param bit The bit to set.
  */
-static INLINE void bitset_set(bitset_t *bs, unsigned long bit)
+static INLINE void bitset_set(bitset_t *bs, bitset_pos_t bit)
 {
-       unsigned long *unit = _bitset_get_unit(bs, bit);
+       bitset_unit_t *unit = _bitset_get_unit(bs, bit);
        _bitset_inside_set(unit, bit & BS_UNIT_MASK);
 }
 
@@ -129,15 +153,21 @@ static INLINE void bitset_set(bitset_t *bs, unsigned long bit)
  * @param bs The bitset.
  * @param bit The bit to clear.
  */
-static INLINE void bitset_clear(bitset_t *bs, unsigned long bit)
+static INLINE void bitset_clear(bitset_t *bs, bitset_pos_t bit)
 {
-       unsigned long *unit = _bitset_get_unit(bs, bit);
+       bitset_unit_t *unit = _bitset_get_unit(bs, bit);
        _bitset_inside_clear(unit, bit & BS_UNIT_MASK);
 }
 
-static INLINE int bitset_is_set(const bitset_t *bs, unsigned long bit)
+/**
+ * Check, if a bit is set.
+ * @param bs The bitset.
+ * @param bit The bit to check for.
+ * @return 1, if the bit was set, 0 if not.
+ */
+static INLINE int bitset_is_set(const bitset_t *bs, bitset_pos_t bit)
 {
-       unsigned long *unit = _bitset_get_unit(bs, bit);
+       bitset_unit_t *unit = _bitset_get_unit(bs, bit);
        return _bitset_inside_is_set(unit, bit & BS_UNIT_MASK);
 }
 
@@ -146,9 +176,9 @@ static INLINE int bitset_is_set(const bitset_t *bs, unsigned long bit)
  * @param bs The bitset.
  * @param bit The bit to flip.
  */
-static INLINE void bitset_flip(bitset_t *bs, unsigned long bit)
+static INLINE void bitset_flip(bitset_t *bs, bitset_pos_t bit)
 {
-       unsigned long *unit = _bitset_get_unit(bs, bit);
+       bitset_unit_t *unit = _bitset_get_unit(bs, bit);
        _bitset_inside_flip(unit, bit & BS_UNIT_MASK);
 }
 
@@ -160,13 +190,13 @@ static INLINE void bitset_flip(bitset_t *bs, unsigned long bit)
  */
 static INLINE bitset_t *bitset_copy(bitset_t *tgt, const bitset_t *src)
 {
-       unsigned long tu = tgt->units;
-       unsigned long su = src->units;
-       unsigned long min_units = tu < su ? tu : su;
+       bitset_pos_t tu = tgt->units;
+       bitset_pos_t su = src->units;
+       bitset_pos_t min_units = tu < su ? tu : su;
        memcpy(tgt->data, src->data, min_units * BS_UNIT_SIZE);
        if(tu > min_units)
                memset(tgt->data + min_units, 0, BS_UNIT_SIZE * (tu - min_units));
-       return tgt;
+       return _bitset_mask_highest(tgt);
 }
 
 /**
@@ -174,13 +204,13 @@ static INLINE bitset_t *bitset_copy(bitset_t *tgt, const bitset_t *src)
  * @param bs The bitset.
  * @return The smallest bit set in the bitset.
  */
-static INLINE unsigned long bitset_min(const bitset_t *bs)
+static INLINE bitset_pos_t bitset_min(const bitset_t *bs)
 {
-       unsigned long i, ofs = 0;
+       bitset_pos_t i, ofs = 0;
 
        for(i = 0; i < bs->units; ++i) {
-               unsigned long *unit = &bs->data[i];
-               unsigned long pos = _bitset_inside_ntz(unit);
+               bitset_unit_t *unit = &bs->data[i];
+               bitset_pos_t pos = _bitset_inside_ntz(unit);
                if(pos > 0)
                        return ofs + pos;
                ofs += BS_UNIT_SIZE_BITS;
@@ -194,13 +224,13 @@ static INLINE unsigned long bitset_min(const bitset_t *bs)
  * @param bs The bitset.
  * @return The greatest bit set in the bitset.
  */
-static INLINE unsigned long bitset_max(const bitset_t *bs)
+static INLINE bitset_pos_t bitset_max(const bitset_t *bs)
 {
-       unsigned long i, max = 0, ofs = 0;
+       bitset_pos_t i, max = 0, ofs = 0;
 
        for(i = 0; i < bs->units; ++i) {
-               unsigned long *unit = &bs->data[i];
-               unsigned long pos = _bitset_inside_nlz(unit);
+               bitset_unit_t *unit = &bs->data[i];
+               bitset_pos_t pos = _bitset_inside_nlz(unit);
                if(pos > 0)
                        max = ofs + pos;
                ofs += BS_UNIT_SIZE_BITS;
@@ -217,30 +247,30 @@ static INLINE unsigned long bitset_max(const bitset_t *bs)
  * @return The next set bit from pos on, or -1, if no set bit was found
  * after pos.
  */
-static INLINE unsigned long _bitset_next(const bitset_t *bs,
-               unsigned long pos, int set)
+static INLINE bitset_pos_t _bitset_next(const bitset_t *bs,
+               bitset_pos_t pos, int set)
 {
-       unsigned long unit_number = pos / BS_UNIT_SIZE_BITS;
+       bitset_pos_t unit_number = pos / BS_UNIT_SIZE_BITS;
 
        if(unit_number >= bs->units)
                return -1;
 
        {
-               unsigned long bit_in_unit = pos & BS_UNIT_MASK;
-               unsigned long in_unit_mask = (1 << bit_in_unit) - 1;
+               bitset_pos_t bit_in_unit = pos & BS_UNIT_MASK;
+               bitset_pos_t in_unit_mask = (1 << bit_in_unit) - 1;
 
                /*
                 * Mask out the bits smaller than pos in the current unit.
                 * We are only interested in bits set higher than pos.
                 */
-               unsigned long curr_unit = bs->data[unit_number];
+               bitset_unit_t curr_unit = bs->data[unit_number];
 
                /*
                 * Find the next bit set in the unit.
                 * Mind that this function returns 0, if the unit is -1 and
                 * counts the bits from 1 on.
                 */
-               unsigned long next_in_this_unit =
+               bitset_pos_t next_in_this_unit =
                        _bitset_inside_ntz_value((set ? curr_unit : ~curr_unit) & ~in_unit_mask);
 
                /* If there is a bit set in the current unit, exit. */
@@ -249,10 +279,10 @@ static INLINE unsigned long _bitset_next(const bitset_t *bs,
 
                /* Else search for set bits in the next units. */
                else {
-                       unsigned long i;
+                       bitset_pos_t i;
                        for(i = unit_number + 1; i < bs->units; ++i) {
-                               unsigned long data = bs->data[i];
-                               unsigned long first_set =
+                               bitset_unit_t data = bs->data[i];
+                               bitset_pos_t first_set =
                                        _bitset_inside_ntz_value(set ? data : ~data);
 
                                if(first_set < BS_UNIT_SIZE_BITS)
@@ -285,10 +315,10 @@ static INLINE unsigned long _bitset_next(const bitset_t *bs,
  * @param bs The bitset.
  * @return The number of bits set in the bitset.
  */
-static INLINE unsigned long bitset_popcnt(const bitset_t *bs)
+static INLINE bitset_pos_t bitset_popcnt(const bitset_t *bs)
 {
-       unsigned long i, pop = 0;
-       unsigned long *unit;
+       bitset_pos_t i, pop = 0;
+       bitset_unit_t *unit;
 
        for(i = 0, unit = bs->data; i < bs->units; ++i, ++unit)
                pop += _bitset_inside_pop(unit);
@@ -301,9 +331,10 @@ static INLINE unsigned long bitset_popcnt(const bitset_t *bs)
  * This sets all bits to zero.
  * @param bs The bitset.
  */
-static INLINE void bitset_clear_all(bitset_t *bs)
+static INLINE bitset_t *bitset_clear_all(bitset_t *bs)
 {
        memset(bs->data, 0, BS_UNIT_SIZE * bs->units);
+  return bs;
 }
 
 /**
@@ -311,11 +342,10 @@ static INLINE void bitset_clear_all(bitset_t *bs)
  * This sets all bits to one.
  * @param bs The bitset.
  */
-static INLINE void bitset_set_all(bitset_t *bs)
+static INLINE bitset_t *bitset_set_all(bitset_t *bs)
 {
-       //TODO is this correct (last unit)?
-       //TODO is -1 correct == all bits equal 1
        memset(bs->data, -1, BS_UNIT_SIZE * bs->units);
+  return bs;
 }
 
 /**
@@ -327,12 +357,12 @@ static INLINE void bitset_set_all(bitset_t *bs)
  */
 static INLINE int bitset_contains(const bitset_t *lhs, const bitset_t *rhs)
 {
-       unsigned long n = lhs->units < rhs->units ? lhs->units : rhs->units;
-       unsigned long i;
+       bitset_pos_t n = lhs->units < rhs->units ? lhs->units : rhs->units;
+       bitset_pos_t i;
 
        for(i = 0; i < n; ++i) {
-               unsigned long lu = lhs->data[i];
-               unsigned long ru = rhs->data[i];
+               bitset_unit_t lu = lhs->data[i];
+               bitset_unit_t ru = rhs->data[i];
 
                if((lu | ru) & ~ru)
                        return 0;
@@ -373,11 +403,11 @@ static INLINE void bitset_fprint(FILE *file, const bitset_t *bs)
 
 static INLINE void bitset_debug_fprint(FILE *file, const bitset_t *bs)
 {
-       unsigned long i;
+       bitset_pos_t i;
 
-       fprintf(file, "%lu:", bs->units);
+       fprintf(file, "%u:", bs->units);
        for(i = 0; i < bs->units; ++i)
-               fprintf(file, " %0lx", bs->data[i]);
+               fprintf(file, " " BITSET_UNIT_FMT, bs->data[i]);
 }
 
 /*
@@ -387,13 +417,13 @@ static INLINE void bitset_debug_fprint(FILE *file, const bitset_t *bs)
 #define BINARY_OP(op) \
 static INLINE bitset_t *bitset_ ## op(bitset_t *tgt, const bitset_t *src) \
 { \
-       unsigned long i; \
-       unsigned long n = tgt->units > src->units ? src->units : tgt->units; \
+       bitset_pos_t i; \
+       bitset_pos_t n = tgt->units > src->units ? src->units : tgt->units; \
        for(i = 0; i < n; i += _BITSET_BINOP_UNITS_INC) \
                _bitset_inside_binop_ ## op(&tgt->data[i], &src->data[i]); \
        if(n < tgt->units) \
                _bitset_clear_rest(&tgt->data[i], tgt->units - i); \
-       return tgt; \
+       return _bitset_mask_highest(tgt); \
 }
 
 /*
index 934a3a5..515e4d9 100644 (file)
@@ -2,6 +2,9 @@
 #ifndef _BITSET_IA32_H
 #define _BITSET_IA32_H
 
+typedef unsigned int bitset_unit_t;
+#define BITSET_UNIT_FMT "%0x"
+
 #undef _bitset_inside_clear
 #undef _bitset_inside_set
 #undef _bitset_inside_flip
@@ -25,7 +28,7 @@
 #define _bitset_inside_ntz(unit) _bitset_ia32_inside_ntz(unit)
 #define _bitset_inside_ntz_value(unit) _bitset_ia32_inside_ntz_value(unit)
 
-static INLINE int _bitset_ia32_inside_is_set(unsigned long *unit, unsigned bit)
+static INLINE int _bitset_ia32_inside_is_set(bitset_unit_t *unit, unsigned bit)
 {
        int res = 0;
        __asm__("mov $0,%0\n\tbtl %1,%2\n\tadc $0,%0"
@@ -35,20 +38,20 @@ static INLINE int _bitset_ia32_inside_is_set(unsigned long *unit, unsigned bit)
        return res;
 }
 
-static INLINE unsigned _bitset_ia32_inside_nlz(unsigned long *unit)
+static INLINE unsigned _bitset_ia32_inside_nlz(bitset_unit_t *unit)
 {
        unsigned res = 0;
        __asm__("bsrl %1,%0" :"=r" (res) :"m" (unit));
        return *unit == 0 ? 32 : res;
 }
 
-static INLINE unsigned _bitset_ia32_inside_ntz(unsigned long *unit) {
+static INLINE unsigned _bitset_ia32_inside_ntz(bitset_unit_t *unit) {
        unsigned res = 0;
        __asm__("bsfl %1,%0" :"=r" (res) :"m" (unit));
        return *unit == 0 ? 32 : res;
 }
 
-static INLINE unsigned _bitset_ia32_inside_ntz_value(unsigned long unit) {
+static INLINE unsigned _bitset_ia32_inside_ntz_value(bitset_unit_t unit) {
        unsigned res = 0;
        __asm__("bsfl %1,%0" :"=r" (res) :"rm" (unit));
        return unit == 0 ? 32 : res;
@@ -83,8 +86,8 @@ static INLINE unsigned _bitset_ia32_inside_ntz_value(unsigned long unit) {
 #define _bitset_data_ptr(data,bitset_base_size,highest_bit) \
   _bitset_sse_data_ptr(data, bitset_base_size, highest_bit)
 
-static INLINE unsigned long *_bitset_sse_data_ptr(void *data, size_t bitset_base_size,
-               unsigned long highest_bit)
+static INLINE bitset_unit_t *_bitset_sse_data_ptr(void *data, size_t bitset_base_size,
+               bitset_pos_t highest_bit)
 {
        ptrdiff_t diff;
        char *units = data;
@@ -92,7 +95,7 @@ static INLINE unsigned long *_bitset_sse_data_ptr(void *data, size_t bitset_base
        diff = (units - (char *) 0) + bitset_base_size;
        diff = round_up2(diff, 16);
        units = (char *) 0 + diff;
-       return (unsigned long *) units;
+       return (bitset_unit_t *) units;
 }
 
 #define _BITSET_BINOP_UNITS_INC 4
@@ -102,7 +105,7 @@ static INLINE unsigned long *_bitset_sse_data_ptr(void *data, size_t bitset_base
 #define _bitset_inside_binop_xor(tgt,src) _bitset_sse_inside_binop_xor(tgt,src)
 
 #define _BITSET_SSE_BINOP(name) \
-static INLINE void _bitset_sse_inside_binop_ ## name(unsigned long *tgt, unsigned long *src) \
+static INLINE void _bitset_sse_inside_binop_ ## name(bitset_unit_t *tgt, bitset_unit_t *src) \
 { \
        __m128i src_op = _mm_load_si128((__m128i *) src); \
        __m128i tgt_op = _mm_load_si128((__m128i *) tgt); \
@@ -111,7 +114,7 @@ static INLINE void _bitset_sse_inside_binop_ ## name(unsigned long *tgt, unsigne
 }
 
 
-static INLINE void _bitset_sse_inside_binop_with_zero_and(unsigned long *tgt)
+static INLINE void _bitset_sse_inside_binop_with_zero_and(bitset_unit_t *tgt)
 {
        tgt[0] = 0;
        tgt[1] = 0;
@@ -119,7 +122,7 @@ static INLINE void _bitset_sse_inside_binop_with_zero_and(unsigned long *tgt)
        tgt[3] = 0;
 }
 
-static INLINE void _bitset_sse_inside_binop_andnot(unsigned long *tgt, unsigned long *src)
+static INLINE void _bitset_sse_inside_binop_andnot(bitset_unit_t *tgt, bitset_unit_t *src)
 {
        __m128i src_op = _mm_load_si128((void *) src);
        __m128i tgt_op = _mm_load_si128((void *) tgt);
index 2253c27..7183e87 100644 (file)
@@ -1,4 +1,10 @@
 
+/** Use ordinary ints as unit types. */
+typedef unsigned int bitset_unit_t;
+
+#define BITSET_UNIT_FMT "%0x"
+#define BITSET_UNIT_ALL_ONE ((unsigned int) -1)
+
 /**
  * Units needed for a given highest bit.
  * This implementation always allocates units in a multiple of 16 bytes.
@@ -26,7 +32,7 @@
  * @param hightest_bit The highest bit that will occur in the bitset.
  */
 #define _bitset_data_ptr(data,bitset_base_size,highest_bit) \
-       ((unsigned long *) ((char *) data + bitset_base_size))
+       ((bitset_unit_t *) ((char *) data + bitset_base_size))
 
 
 /**
  * @return The Number of leading zeroes.
  */
 #define _bitset_inside_ntz(unit_ptr) _bitset_std_inside_ntz(unit_ptr)
-static INLINE int _bitset_std_inside_ntz(unsigned long *unit_ptr)
+static INLINE bitset_pos_t _bitset_std_inside_ntz(bitset_unit_t *unit_ptr)
 {
        unsigned long data = *unit_ptr;
-       return 32 - nlz(~data & (data - 1));
+       return 32 - (bitset_pos_t) nlz(~data & (data - 1));
 }
 
 /**