Commit 10cfe14d authored by Matthias Braun's avatar Matthias Braun
Browse files

rework bitset to use raw_bitset

[r27293]
parent 66752b5a
This diff is collapsed.
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief intel 80x86 implementation of bitsets
* @version $Id$
*/
#ifndef _BITSET_IA32_H
#define _BITSET_IA32_H
#undef _bitset_inside_clear
#undef _bitset_inside_set
#undef _bitset_inside_flip
#define _bitset_inside_set(unit, bit) \
__asm__ __volatile__( "btsl %1,%0" :"=m" (*unit) : "Ir" (bit) : "cc")
#define _bitset_inside_clear(unit, bit) \
__asm__ __volatile__( "btrl %1,%0" :"=m" (*unit) : "Ir" (bit) : "cc")
#define _bitset_inside_flip(unit, bit) \
__asm__ __volatile__( "btcl %1,%0" :"=m" (*unit) : "Ir" (bit) : "cc")
#undef _bitset_inside_is_set
#undef _bitset_inside_nlz
#undef _bitset_inside_ntz
#undef _bitset_inside_ntz_value
#define _bitset_inside_is_set(unit, bit) _bitset_ia32_inside_is_set(unit, bit)
#define _bitset_inside_nlz(unit) _bitset_ia32_inside_nlz(unit)
#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(bitset_unit_t *unit, unsigned bit)
{
int res;
__asm__("bt %2, %1\n\t"
"rcl $1, %0\n\t"
"and $1, %0"
: "=r" (res)
: "m" (*unit), "Ir" (bit)
: "cc");
return res;
}
static inline unsigned _bitset_ia32_inside_nlz(bitset_unit_t *unit)
{
unsigned res;
__asm__("bsr %1, %0\n\t"
"cmovz %2, %0\n\t"
"neg %0\n\t"
"add $31, %0"
: "=&r" (res)
: "m" (*unit), "r" (-1)
: "cc");
return res;
}
static inline unsigned _bitset_ia32_inside_ntz(bitset_unit_t *unit) {
unsigned res;
__asm__("bsfl %1, %0\n\t"
"cmovz %2, %0\n\t"
: "=&r" (res)
: "m" (*unit), "r" (32)
: "cc");
return res;
}
static inline unsigned _bitset_ia32_inside_ntz_value(bitset_unit_t unit) {
unsigned res;
__asm__("bsfl %1, %0\n\t"
"cmovz %2, %0\n\t"
: "=&r" (res)
: "r" (unit), "r" (32)
: "cc");
return res;
}
#endif
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief ANSI-C compliant implementation of bitsets
* @version $Id$
*/
#ifndef FIRM_ADT_BITSET_STD_H
#define FIRM_ADT_BITSET_STD_H
#include "bitfiddle.h"
/** 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)
/**
* Clear some units from a certain address on.
* @param addr The address from where to clear.
* @param n The number of units to set to 0.
*/
#define _bitset_inside_clear_units(addr,n) \
memset(addr, 0, n * BS_UNIT_SIZE)
/**
* Set a bit in a unit.
* @param unit A pointer to the unit.
* @param bit which bit to set.
*/
#define _bitset_inside_set(unit_ptr,bit) (*unit_ptr) |= (1 << (bit))
/**
* Clear a bit in a unit.
* @param unit A pointer to the unit.
* @param bit which bit to set.
*/
#define _bitset_inside_clear(unit_ptr,bit) (*unit_ptr) &= ~(1 << (bit))
/**
* Flip a bit in a unit.
* @param unit A pointer to the unit.
* @param bit which bit to set.
*/
#define _bitset_inside_flip(unit_ptr,bit) (*unit_ptr) ^= (1 << (bit))
/**
* Flip a whole unit.
* @param unit_ptr The pointer to the unit.
*/
#define _bitset_inside_flip_unit(unit_ptr) (*unit_ptr) = ~(*unit_ptr)
/**
* Count the number of leading zeroes in a unit.
* @param unit A pointer to the unit.
* @return The Number of leading zeroes.
*/
#define _bitset_inside_nlz(unit_ptr) (nlz(*unit_ptr))
/**
* Count the number of trailing zeroes in a unit.
* @param unit A pointer to the unit.
* @return The Number of leading zeroes.
*/
#define _bitset_inside_ntz(unit_ptr) _bitset_std_inside_ntz(unit_ptr)
static inline unsigned _bitset_std_inside_ntz(bitset_unit_t *unit_ptr)
{
unsigned long data = *unit_ptr;
return 32 - (unsigned) nlz(~data & (data - 1));
}
/**
* Count the number of trailing zeroes in a unit (whereas the unit is no
* pointer but a value).
* @param unit A unit.
* @return The Number of leading zeroes.
*/
#define _bitset_inside_ntz_value(unit) (32 - nlz(~(unit) & ((unit) - 1)))
/**
* test if a bit is set in a unit.
* @param unit_ptr The pointer to the unit.
* @param bit The bit to check.
* @return 1, if the bit is set, 0 otherise.
*/
#define _bitset_inside_is_set(unit_ptr,bit) \
(((*unit_ptr) & (1 << (bit))) != 0)
/**
* count the number of bits set in a unit.
* @param unit_ptr The pointer to a unit.
* @return The number of bits set in the unit.
*/
#define _bitset_inside_pop(unit_ptr) (popcount(*unit_ptr))
#define _BITSET_BINOP_UNITS_INC 1
#define _bitset_inside_binop_and(tgt,src) ((*tgt) &= (*src))
#define _bitset_inside_binop_andnot(tgt,src) ((*tgt) &= ~(*src))
#define _bitset_inside_binop_or(tgt,src) ((*tgt) |= (*src))
#define _bitset_inside_binop_xor(tgt,src) ((*tgt) ^= (*src))
#endif
......@@ -19,39 +19,35 @@
/**
* @file
* @brief helper functions for working with raw bitsets
* @brief raw bitsets (low-level bitset operations)
* @date 15.10.2004
* @author Matthias Braun
* @version $Id$
* @brief
* Raw bitsets are constructed from unsigned int arrays. Additional information
* like the size of the bitset or the used memory are not stored for
* efficiency reasons.
*
* Raw bitsets are constructed from unsigned int arrays. Additional
* information like the size of the bitset or the used memory are not
* stored for (memory) efficiency reasons.
*
* These bitsets need less space than bitset_t and their representation
* as int arrays allows having constant bitsets in the ro data segment.
* They should for smaller bitset, whose length is known through other means
* (a typical usage case is a set of cpu registers)
*
* The bitset is built as an array of unsigned integers. It is assumed that
* exactly 32 bits may be put into each element of the array. If there are
* remaining bits, then they should be 0
* The bitset is built as an array of unsigned integers. The unused bits
* must be zero.
*/
#ifndef FIRM_ADT_RAW_BITSET_H
#define FIRM_ADT_RAW_BITSET_H
#include <assert.h>
#include "bitset.h"
#include <stdbool.h>
#include "bitfiddle.h"
#include "obst.h"
/** The base type for raw bitsets. */
typedef unsigned int rawbs_base_t;
#define BITS_PER_ELEM (sizeof(rawbs_base_t) * 8)
#define BITSET_SIZE_ELEMS(size_bits) ((size_bits)/BITS_PER_ELEM + 1)
#define BITSET_SIZE_BYTES(size_bits) (BITSET_SIZE_ELEMS(size_bits) * sizeof(rawbs_base_t))
#define BITSET_ELEM(bitset,pos) bitset[pos / BITS_PER_ELEM]
#define BITS_PER_ELEM (sizeof(unsigned) * 8)
#define BITSET_SIZE_ELEMS(size_bits) ((size_bits)/BITS_PER_ELEM + 1)
#define BITSET_SIZE_BYTES(size_bits) (BITSET_SIZE_ELEMS(size_bits) * sizeof(unsigned))
#define BITSET_ELEM(bitset,pos) bitset[pos / BITS_PER_ELEM]
/**
* Allocate an empty raw bitset on the heap.
......@@ -60,9 +56,10 @@ typedef unsigned int rawbs_base_t;
*
* @return the new bitset
*/
static inline unsigned *rbitset_malloc(unsigned size) {
unsigned size_bytes = BITSET_SIZE_BYTES(size);
unsigned *res = xmalloc(size_bytes);
static inline unsigned *rbitset_malloc(unsigned size)
{
unsigned size_bytes = BITSET_SIZE_BYTES(size);
unsigned *res = xmalloc(size_bytes);
memset(res, 0, size_bytes);
return res;
......@@ -89,10 +86,11 @@ do { \
*
* @return the new bitset
*/
static inline unsigned *rbitset_obstack_alloc(struct obstack *obst, unsigned size)
static inline unsigned *rbitset_obstack_alloc(struct obstack *obst,
unsigned size)
{
unsigned size_bytes = BITSET_SIZE_BYTES(size);
unsigned *res = obstack_alloc(obst, size_bytes);
unsigned size_bytes = BITSET_SIZE_BYTES(size);
unsigned *res = obstack_alloc(obst, size_bytes);
memset(res, 0, size_bytes);
return res;
......@@ -107,10 +105,11 @@ static inline unsigned *rbitset_obstack_alloc(struct obstack *obst, unsigned siz
*
* @return the new bitset
*/
static inline unsigned *rbitset_w_size_obstack_alloc(struct obstack *obst, unsigned size)
static inline unsigned *rbitset_w_size_obstack_alloc(struct obstack *obst,
unsigned size)
{
unsigned size_bytes = BITSET_SIZE_BYTES(size);
unsigned *res = obstack_alloc(obst, size_bytes + sizeof(unsigned));
unsigned size_bytes = BITSET_SIZE_BYTES(size);
unsigned *res = obstack_alloc(obst, size_bytes + sizeof(unsigned));
*res = size;
++res;
memset(res, 0, size_bytes);
......@@ -133,8 +132,8 @@ static inline unsigned *rbitset_w_size_obstack_alloc(struct obstack *obst, unsig
static inline unsigned *rbitset_duplicate_obstack_alloc(struct obstack *obst,
const unsigned *old_bitset, unsigned size)
{
unsigned size_bytes = BITSET_SIZE_BYTES(size);
unsigned *res = obstack_alloc(obst, size_bytes);
unsigned size_bytes = BITSET_SIZE_BYTES(size);
unsigned *res = obstack_alloc(obst, size_bytes);
memcpy(res, old_bitset, size_bytes);
return res;
......@@ -143,16 +142,17 @@ static inline unsigned *rbitset_duplicate_obstack_alloc(struct obstack *obst,
/**
* Check if a bitset is empty, ie all bits cleared.
*/
static inline int rbitset_is_empty(unsigned *bitset, unsigned size)
static inline bool rbitset_is_empty(const unsigned *bitset, unsigned size)
{
unsigned n = BITSET_SIZE_ELEMS(size);
unsigned i;
unsigned n = BITSET_SIZE_ELEMS(size);
for (i = 0; i < n; ++i) {
if (bitset[i] != 0)
return 0;
if (bitset[i] != 0) {
return false;
}
}
return 1;
return true;
}
/**
......@@ -166,6 +166,26 @@ static inline void rbitset_set(unsigned *bitset, unsigned pos)
BITSET_ELEM(bitset,pos) |= 1 << (pos % BITS_PER_ELEM);
}
/**
* Flip a bit at position pos. A zero bit becomes one, a one bit becomes zero.
*
* @param bitset the bitset
* @param pos position of the bit to be flipped
*/
static inline void rbitset_flip(unsigned *bitset, unsigned pos)
{
BITSET_ELEM(bitset, pos) ^= 1 << (pos % BITS_PER_ELEM);
}
static inline unsigned rbitset_last_mask_(unsigned size)
{
unsigned p;
if (size == 0)
return 0;
p = size % BITS_PER_ELEM;
return p == 0 ? ~0u : (1u << p)-1u;
}
/**
* Set all bits in a given bitset.
*
......@@ -174,10 +194,14 @@ static inline void rbitset_set(unsigned *bitset, unsigned pos)
*/
static inline void rbitset_set_all(unsigned *bitset, unsigned size)
{
unsigned size_bytes = BITSET_SIZE_BYTES(size);
memset(bitset, ~0, size_bytes);
}
unsigned i;
unsigned n = BITSET_SIZE_ELEMS(size);
for (i = 0; i < n-1; ++i) {
bitset[i] = ~0u;
}
bitset[i] = rbitset_last_mask_(size);
}
/**
* Clear a bit at position pos.
......@@ -202,13 +226,29 @@ static inline void rbitset_clear_all(unsigned *bitset, unsigned size)
memset(bitset, 0, size_bytes);
}
/**
* Flip all bits in a given bitset.
*
* @param bitset the bitset
* @param size number of bits in the bitset
*/
static inline void rbitset_flip_all(unsigned *bitset, unsigned size)
{
unsigned pos;
unsigned n = BITSET_SIZE_ELEMS(size);
for (pos = 0; pos < n-1; ++pos) {
bitset[pos] ^= ~0u;
}
bitset[pos] ^= rbitset_last_mask_(size);
}
/**
* Check if a bit is set at position pos.
*
* @param bitset the bitset
* @param pos the position of the bit to check
*/
static inline int rbitset_is_set(const unsigned *bitset, unsigned pos)
static inline bool rbitset_is_set(const unsigned *bitset, unsigned pos)
{
return BITSET_ELEM(bitset, pos) & (1 << (pos % BITS_PER_ELEM));
}
......@@ -217,16 +257,16 @@ static inline int rbitset_is_set(const unsigned *bitset, unsigned pos)
* Calculate the number of set bits (number of elements).
*
* @param bitset the bitset
* @param size size of the bitset
* @param size size of the bitset in bits
*/
static inline unsigned rbitset_popcount(const unsigned *bitset, unsigned size)
{
unsigned pos;
unsigned n = BITSET_SIZE_ELEMS(size);
unsigned i;
unsigned n = BITSET_SIZE_ELEMS(size);
unsigned res = 0;
for (pos = 0; pos < n; ++pos) {
res += popcount(bitset[pos]);
for (i = 0; i < n; ++i) {
res += popcount(bitset[i]);
}
return res;
......@@ -245,14 +285,15 @@ static inline unsigned rbitset_popcount(const unsigned *bitset, unsigned size)
* @note Does NOT check the size of the bitset, so ensure that a bit
* will be found or use a sentinel bit!
*/
static inline unsigned rbitset_next(const unsigned *bitset, unsigned pos, int set)
static inline unsigned rbitset_next(const unsigned *bitset, unsigned pos,
bool set)
{
unsigned p;
unsigned elem_pos = pos / BITS_PER_ELEM;
unsigned bit_pos = pos % BITS_PER_ELEM;
unsigned elem = bitset[elem_pos];
unsigned mask = 0;
unsigned mask = set ? 0 : ~0u;
/*
* Mask out the bits smaller than pos in the current unit.
......@@ -260,8 +301,6 @@ static inline unsigned rbitset_next(const unsigned *bitset, unsigned pos, int se
*/
unsigned in_elem_mask = (1 << bit_pos) - 1;
if (!set)
mask = ~mask;
elem ^= mask;
p = ntz(elem & ~in_elem_mask);
......@@ -282,12 +321,68 @@ static inline unsigned rbitset_next(const unsigned *bitset, unsigned pos, int se
}
}
/**
* Returns the position of the next bit starting from (and including)
* a given position.
*
* @param bitset a bitset
* @param pos the first position to check
* @param last first position that is not checked anymore
* @param set if 0 search for unset bit, else for set bit
*
* @return the first position where a matched bit was found.
* (unsigned)-1 if no bit was found.
*/
static inline unsigned rbitset_next_max(const unsigned *bitset, unsigned pos,
unsigned last, bool set)
{
unsigned p;
unsigned elem_pos = pos / BITS_PER_ELEM;
unsigned bit_pos = pos % BITS_PER_ELEM;
unsigned elem = bitset[elem_pos];
unsigned mask = set ? 0 : ~0u;
unsigned res = (unsigned)-1;
/*
* Mask out the bits smaller than pos in the current unit.
* We are only interested in bits set higher than pos.
*/
unsigned in_elem_mask = (1 << bit_pos) - 1;
assert(pos < last);
elem ^= mask;
p = ntz(elem & ~in_elem_mask);
/* If there is a bit set in the current elem, exit. */
if (p < BITS_PER_ELEM) {
res = elem_pos * BITS_PER_ELEM + p;
} else {
unsigned n = BITSET_SIZE_ELEMS(last);
/* Else search for set bits in the next units. */
for (elem_pos++; elem_pos < n; elem_pos++) {
elem = bitset[elem_pos] ^ mask;
p = ntz(elem);
if (p < BITS_PER_ELEM) {
res = elem_pos * BITS_PER_ELEM + p;
break;
}
}
}
if (res >= last)
res = (unsigned)-1;
return res;
}
/**
* Inplace Intersection of two sets.
*
* @param dst the destination bitset and first operand
* @param src the second bitset
* @param size size of both bitsets
* @param size size of both bitsets in bits
*/
static inline void rbitset_and(unsigned *dst, const unsigned *src, unsigned size)
{
......@@ -303,7 +398,7 @@ static inline void rbitset_and(unsigned *dst, const unsigned *src, unsigned size
*
* @param dst the destination bitset and first operand
* @param src the second bitset
* @param size size of both bitsets
* @param size size of both bitsets in bits
*/
static inline void rbitset_or(unsigned *dst, const unsigned *src, unsigned size)
{
......@@ -319,7 +414,7 @@ static inline void rbitset_or(unsigned *dst, const unsigned *src, unsigned size)
*
* @param dst the destination bitset and first operand
* @param src the second bitset
* @param size size of both bitsets
* @param size size of both bitsets in bits
*/
static inline void rbitset_andnot(unsigned *dst, const unsigned *src, unsigned size)
{
......@@ -335,7 +430,7 @@ static inline void rbitset_andnot(unsigned *dst, const unsigned *src, unsigned s
*
* @param dst the destination bitset and first operand
* @param src the second bitset
* @param size size of both bitsets
* @param size size of both bitsets in bits
*/
static inline void rbitset_xor(unsigned *dst, const unsigned *src, unsigned size)
{
......@@ -346,17 +441,75 @@ static inline void rbitset_xor(unsigned *dst, const unsigned *src, unsigned size
}
}
/**
* Set bits in a range to zero or one
* @param bitset the bitset
* @param from first bit to set
* @param to last bit (the first bit which is not set anymore)
* @param val wether to set to 1 or 0
*/
static inline void rbitset_set_range(unsigned *bitset, unsigned from,
unsigned to, bool val)
{
assert(from < to);
/*
* A small example (for cleaning bits in the same unit).
* from = 7
* to = 19
* do_set = 0
* result: xxxxxxx000000000000xxxxxxxxxxxxx
* from_unit_mask: 00000001111111111111111111111111
* to_unit_mask: 11111111111111111110000000000000
* scale: 01234567890123456789012345678901
* 1 2 3
*/
unsigned from_bit = from % BITS_PER_ELEM;
unsigned from_pos = from / BITS_PER_ELEM;
unsigned from_unit_mask = ~((1 << from_bit) - 1);
unsigned to_bit = to % BITS_PER_ELEM;
unsigned to_pos = to / BITS_PER_ELEM;
unsigned to_unit_mask = (1 << to_bit) - 1;
/* do we want to set the bits in the range? */
if (val) {
if (from_pos == to_pos) {
BITSET_ELEM(bitset, from_pos) |= from_unit_mask & to_unit_mask;
} else {
unsigned i;
BITSET_ELEM(bitset, from_pos) |= from_unit_mask;
BITSET_ELEM(bitset, to_pos) |= to_unit_mask;
for (i = from_pos + 1; i < to_pos; ++i)
BITSET_ELEM(bitset, i) = ~0u;
}
} else {
/* ... or clear them? */
if (from_pos == to_pos) {
BITSET_ELEM(bitset, from_pos) &= ~(from_unit_mask & to_unit_mask);
} else {
unsigned i;
BITSET_ELEM(bitset, from_pos) &= ~from_unit_mask;
BITSET_ELEM(bitset, to_pos) &= ~to_unit_mask;
for (i = from_pos + 1; i < to_pos; ++i)
BITSET_ELEM(bitset, i) = 0;
}
}
}
/**
* Returns 1 of two bitsets are equal.
*
* @param bitset1 the first bitset
* @param bitset2 the second bitset
* @param size size of both bitsets
* @param size size of both bitsets in bits
*/