//===- subzero/src/IceBitVector.h - Inline bit vector. ----------*- C++ -*-===// // // The Subzero Code Generator // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// \brief Defines and implements a bit vector classes. /// /// SmallBitVector is a drop in replacement for llvm::SmallBitVector. It uses /// inline storage, at the expense of limited, static size. /// /// BitVector is a allocator aware version of llvm::BitVector. Its /// implementation was copied ipsis literis from llvm. /// //===----------------------------------------------------------------------===// #ifndef SUBZERO_SRC_ICEBITVECTOR_H #define SUBZERO_SRC_ICEBITVECTOR_H #include "IceMemory.h" #include "IceOperand.h" #include "llvm/Support/MathExtras.h" #include #include #include #include #include #include namespace Ice { class SmallBitVector { public: using ElementType = uint64_t; static constexpr SizeT BitIndexSize = 6; // log2(NumBitsPerPos); static constexpr SizeT NumBitsPerPos = sizeof(ElementType) * CHAR_BIT; static_assert(1 << BitIndexSize == NumBitsPerPos, "Invalid BitIndexSize."); SmallBitVector(const SmallBitVector &BV) { *this = BV; } SmallBitVector &operator=(const SmallBitVector &BV) { if (&BV != this) { resize(BV.size()); memcpy(Bits, BV.Bits, sizeof(Bits)); } return *this; } SmallBitVector() { reset(); } explicit SmallBitVector(SizeT S) : SmallBitVector() { assert(S <= MaxBits); resize(S); } class Reference { Reference() = delete; public: Reference(const Reference &) = default; Reference &operator=(const Reference &Rhs) { return *this = (bool)Rhs; } Reference &operator=(bool t) { if (t) { *Data |= _1 << Bit; } else { *Data &= ~(_1 << Bit); } return *this; } operator bool() const { return (*Data & (_1 << Bit)) != 0; } private: friend class SmallBitVector; Reference(ElementType *D, SizeT B) : Data(D), Bit(B) { assert(B < NumBitsPerPos); } ElementType *const Data; const SizeT Bit; }; Reference operator[](unsigned Idx) { assert(Idx < size()); return Reference(Bits + (Idx >> BitIndexSize), Idx & ((_1 << BitIndexSize) - 1)); } bool operator[](unsigned Idx) const { assert(Idx < size()); return Bits[Idx >> BitIndexSize] & (_1 << (Idx & ((_1 << BitIndexSize) - 1))); } int find_first() const { return find_first<0>(); } int find_next(unsigned Prev) const { return find_next<0>(Prev); } bool any() const { for (SizeT i = 0; i < BitsElements; ++i) { if (Bits[i]) { return true; } } return false; } SizeT size() const { return Size; } void resize(SizeT Size) { assert(Size <= MaxBits); this->Size = Size; } void reserve(SizeT Size) { assert(Size <= MaxBits); (void)Size; } void set(unsigned Idx) { (*this)[Idx] = true; } void set() { for (SizeT ii = 0; ii < size(); ++ii) { (*this)[ii] = true; } } SizeT count() const { SizeT Count = 0; for (SizeT i = 0; i < BitsElements; ++i) { Count += llvm::countPopulation(Bits[i]); } return Count; } SmallBitVector operator&(const SmallBitVector &Rhs) const { assert(size() == Rhs.size()); SmallBitVector Ret(std::max(size(), Rhs.size())); for (SizeT i = 0; i < BitsElements; ++i) { Ret.Bits[i] = Bits[i] & Rhs.Bits[i]; } return Ret; } SmallBitVector operator~() const { SmallBitVector Ret = *this; Ret.invert<0>(); return Ret; } SmallBitVector &operator|=(const SmallBitVector &Rhs) { assert(size() == Rhs.size()); resize(std::max(size(), Rhs.size())); for (SizeT i = 0; i < BitsElements; ++i) { Bits[i] |= Rhs.Bits[i]; } return *this; } SmallBitVector operator|(const SmallBitVector &Rhs) const { assert(size() == Rhs.size()); SmallBitVector Ret(std::max(size(), Rhs.size())); for (SizeT i = 0; i < BitsElements; ++i) { Ret.Bits[i] = Bits[i] | Rhs.Bits[i]; } return Ret; } void reset() { memset(Bits, 0, sizeof(Bits)); } void reset(const SmallBitVector &Mask) { for (const auto V : RegNumBVIter(Mask)) { (*this)[unsigned(V)] = false; } } private: // _1 is the constant 1 of type ElementType. static constexpr ElementType _1 = ElementType(1); static constexpr SizeT BitsElements = 2; ElementType Bits[BitsElements]; // MaxBits is defined here because it needs Bits to be defined. static constexpr SizeT MaxBits = sizeof(SmallBitVector::Bits) * CHAR_BIT; static_assert(sizeof(SmallBitVector::Bits) == 16, "Bits must be 16 bytes wide."); SizeT Size = 0; template typename std::enable_if::type find_first() const { return -1; } template typename std::enable_if < Pos::type find_first() const { if (Bits[Pos] != 0) { return NumBitsPerPos * Pos + llvm::countTrailingZeros(Bits[Pos]); } return find_first(); } template typename std::enable_if::type find_next(unsigned) const { return -1; } template typename std::enable_if < Pos::type find_next(unsigned Prev) const { if (Prev + 1 < (Pos + 1) * NumBitsPerPos) { const ElementType Mask = (ElementType(1) << ((Prev + 1) - Pos * NumBitsPerPos)) - 1; const ElementType B = Bits[Pos] & ~Mask; if (B != 0) { return NumBitsPerPos * Pos + llvm::countTrailingZeros(B); } Prev = (1 + Pos) * NumBitsPerPos - 1; } return find_next(Prev); } template typename std::enable_if::type invert() {} template typename std::enable_if < Pos::type invert() { if (size() < Pos * NumBitsPerPos) { Bits[Pos] = 0; } else if ((Pos + 1) * NumBitsPerPos < size()) { Bits[Pos] ^= ~ElementType(0); } else { const ElementType Mask = (ElementType(1) << (size() - (Pos * NumBitsPerPos))) - 1; Bits[Pos] ^= Mask; } invert(); } }; template