Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 36 additions & 53 deletions llvm/include/llvm/ADT/PackedVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,53 +20,6 @@

namespace llvm {

template <typename T, unsigned BitNum, typename BitVectorTy, bool isSigned>
class PackedVectorBase;

// This won't be necessary if we can specialize members without specializing
// the parent template.
template <typename T, unsigned BitNum, typename BitVectorTy>
class PackedVectorBase<T, BitNum, BitVectorTy, false> {
protected:
static T getValue(const BitVectorTy &Bits, unsigned Idx) {
T val = T();
for (unsigned i = 0; i != BitNum; ++i)
val = T(val | ((Bits[(Idx * BitNum) + i] ? 1UL : 0UL) << i));
return val;
}

static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
assert((val >> BitNum) == 0 && "value is too big");
for (unsigned i = 0; i != BitNum; ++i)
Bits[(Idx * BitNum) + i] = val & (T(1) << i);
}
};

template <typename T, unsigned BitNum, typename BitVectorTy>
class PackedVectorBase<T, BitNum, BitVectorTy, true> {
protected:
static T getValue(const BitVectorTy &Bits, unsigned Idx) {
T val = T();
for (unsigned i = 0; i != BitNum - 1; ++i)
val = T(val | ((Bits[(Idx * BitNum) + i] ? 1UL : 0UL) << i));
if (Bits[(Idx * BitNum) + BitNum - 1])
val = ~val;
return val;
}

static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
if (val < 0) {
val = ~val;
Bits.set((Idx * BitNum) + BitNum - 1);
} else {
Bits.reset((Idx * BitNum) + BitNum - 1);
}
assert((val >> (BitNum - 1)) == 0 && "value is too big");
for (unsigned i = 0; i != BitNum - 1; ++i)
Bits[(Idx * BitNum) + i] = val & (T(1) << i);
}
};

/// Store a vector of values using a specific number of bits for each
/// value. Both signed and unsigned types can be used, e.g
/// @code
Expand All @@ -75,16 +28,46 @@ class PackedVectorBase<T, BitNum, BitVectorTy, true> {
/// will create a vector accepting values -2, -1, 0, 1. Any other value will hit
/// an assertion.
template <typename T, unsigned BitNum, typename BitVectorTy = BitVector>
class PackedVector
: public PackedVectorBase<T, BitNum, BitVectorTy,
std::numeric_limits<T>::is_signed> {
class PackedVector {
BitVectorTy Bits;
// Keep track of the number of elements on our own.
// We always maintain Bits.size() == NumElements * BitNum.
// Used to avoid an integer division in size().
unsigned NumElements = 0;
using base = PackedVectorBase<T, BitNum, BitVectorTy,
std::numeric_limits<T>::is_signed>;

static T getValue(const BitVectorTy &Bits, unsigned Idx) {
if constexpr (std::numeric_limits<T>::is_signed) {
T val = T();
for (unsigned i = 0; i != BitNum - 1; ++i)
val = T(val | ((Bits[(Idx * BitNum) + i] ? 1UL : 0UL) << i));
if (Bits[(Idx * BitNum) + BitNum - 1])
val = ~val;
return val;
} else {
T val = T();
for (unsigned i = 0; i != BitNum; ++i)
val = T(val | ((Bits[(Idx * BitNum) + i] ? 1UL : 0UL) << i));
return val;
}
}

static void setValue(BitVectorTy &Bits, unsigned Idx, T val) {
if constexpr (std::numeric_limits<T>::is_signed) {
if (val < 0) {
val = ~val;
Bits.set((Idx * BitNum) + BitNum - 1);
} else {
Bits.reset((Idx * BitNum) + BitNum - 1);
}
assert((val >> (BitNum - 1)) == 0 && "value is too big");
for (unsigned i = 0; i != BitNum - 1; ++i)
Bits[(Idx * BitNum) + i] = val & (T(1) << i);
} else {
assert((val >> BitNum) == 0 && "value is too big");
for (unsigned i = 0; i != BitNum; ++i)
Bits[(Idx * BitNum) + i] = val & (T(1) << i);
}
}

public:
class reference {
Expand Down Expand Up @@ -135,7 +118,7 @@ class PackedVector

reference operator[](unsigned Idx) { return reference(*this, Idx); }

T operator[](unsigned Idx) const { return base::getValue(Bits, Idx); }
T operator[](unsigned Idx) const { return getValue(Bits, Idx); }

bool operator==(const PackedVector &RHS) const { return Bits == RHS.Bits; }

Expand Down