[llvm] d110c3a - [ADT] Support BitVector as a key in DenseSet/Map
Alexandre Ganea via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 14 07:25:57 PST 2020
Author: Alexandre Ganea
Date: 2020-02-14T10:24:22-05:00
New Revision: d110c3a9f5253c4d94c10299c61fbbb33edab7db
URL: https://github.com/llvm/llvm-project/commit/d110c3a9f5253c4d94c10299c61fbbb33edab7db
DIFF: https://github.com/llvm/llvm-project/commit/d110c3a9f5253c4d94c10299c61fbbb33edab7db.diff
LOG: [ADT] Support BitVector as a key in DenseSet/Map
This patch adds DenseMapInfo<> support for BitVector and SmallBitVector.
This is part of https://reviews.llvm.org/D71775, where a BitVector is used as a thread affinity mask.
Added:
Modified:
llvm/include/llvm/ADT/BitVector.h
llvm/include/llvm/ADT/SmallBitVector.h
llvm/unittests/ADT/BitVectorTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/BitVector.h b/llvm/include/llvm/ADT/BitVector.h
index 5284be8c4a02..02e01effc0fc 100644
--- a/llvm/include/llvm/ADT/BitVector.h
+++ b/llvm/include/llvm/ADT/BitVector.h
@@ -14,6 +14,7 @@
#define LLVM_ADT_BITVECTOR_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
@@ -719,6 +720,14 @@ class BitVector {
if (this == &RHS) return *this;
Size = RHS.size();
+
+ // Handle tombstone when the BitVector is a key of a DenseHash.
+ if (RHS.isInvalid()) {
+ std::free(Bits.data());
+ Bits = None;
+ return *this;
+ }
+
unsigned RHSWords = NumBitWords(Size);
if (Size <= getBitCapacity()) {
if (Size)
@@ -758,6 +767,14 @@ class BitVector {
std::swap(Size, RHS.Size);
}
+ void invalid() {
+ assert(!Size && Bits.empty());
+ Size = (unsigned)-1;
+ }
+ bool isInvalid() const { return Size == (unsigned)-1; }
+
+ ArrayRef<BitWord> getData() const { return Bits; }
+
//===--------------------------------------------------------------------===//
// Portable bit mask operations.
//===--------------------------------------------------------------------===//
@@ -932,6 +949,23 @@ inline size_t capacity_in_bytes(const BitVector &X) {
return X.getMemorySize();
}
+template <> struct DenseMapInfo<BitVector> {
+ static inline BitVector getEmptyKey() { return BitVector(); }
+ static inline BitVector getTombstoneKey() {
+ BitVector V;
+ V.invalid();
+ return V;
+ }
+ static unsigned getHashValue(const BitVector &V) {
+ return DenseMapInfo<std::pair<unsigned, ArrayRef<uintptr_t>>>::getHashValue(
+ std::make_pair(V.size(), V.getData()));
+ }
+ static bool isEqual(const BitVector &LHS, const BitVector &RHS) {
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return LHS.isInvalid() == RHS.isInvalid();
+ return LHS == RHS;
+ }
+};
} // end namespace llvm
namespace std {
diff --git a/llvm/include/llvm/ADT/SmallBitVector.h b/llvm/include/llvm/ADT/SmallBitVector.h
index 61375c008022..b7367d68bdae 100644
--- a/llvm/include/llvm/ADT/SmallBitVector.h
+++ b/llvm/include/llvm/ADT/SmallBitVector.h
@@ -662,6 +662,16 @@ class SmallBitVector {
getPointer()->clearBitsNotInMask(Mask, MaskWords);
}
+ void invalid() {
+ assert(empty());
+ X = (uintptr_t)-1;
+ }
+ bool isInvalid() const { return X == (uintptr_t)-1; }
+
+ ArrayRef<uintptr_t> getData() const {
+ return isSmall() ? makeArrayRef(X) : getPointer()->getData();
+ }
+
private:
template <bool AddBits, bool InvertMask>
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
@@ -699,6 +709,23 @@ operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) {
return Result;
}
+template <> struct DenseMapInfo<SmallBitVector> {
+ static inline SmallBitVector getEmptyKey() { return SmallBitVector(); }
+ static inline SmallBitVector getTombstoneKey() {
+ SmallBitVector V;
+ V.invalid();
+ return V;
+ }
+ static unsigned getHashValue(const SmallBitVector &V) {
+ return DenseMapInfo<std::pair<unsigned, ArrayRef<uintptr_t>>>::getHashValue(
+ std::make_pair(V.size(), V.getData()));
+ }
+ static bool isEqual(const SmallBitVector &LHS, const SmallBitVector &RHS) {
+ if (LHS.isInvalid() || RHS.isInvalid())
+ return LHS.isInvalid() == RHS.isInvalid();
+ return LHS == RHS;
+ }
+};
} // end namespace llvm
namespace std {
diff --git a/llvm/unittests/ADT/BitVectorTest.cpp b/llvm/unittests/ADT/BitVectorTest.cpp
index 5d3830972a62..3fa81846b135 100644
--- a/llvm/unittests/ADT/BitVectorTest.cpp
+++ b/llvm/unittests/ADT/BitVectorTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallBitVector.h"
#include "gtest/gtest.h"
@@ -1149,4 +1150,38 @@ TYPED_TEST(BitVectorTest, PushBack) {
EXPECT_EQ(213U, Vec.size());
EXPECT_EQ(102U, Vec.count());
}
+
+TYPED_TEST(BitVectorTest, DenseSet) {
+ DenseSet<TypeParam> Set;
+ TypeParam A(10, true);
+ auto I = Set.insert(A);
+ EXPECT_EQ(true, I.second);
+
+ TypeParam B(5, true);
+ I = Set.insert(B);
+ EXPECT_EQ(true, I.second);
+
+ TypeParam C(20, false);
+ C.set(19);
+ I = Set.insert(C);
+ EXPECT_EQ(true, I.second);
+
+ TypeParam D;
+ EXPECT_DEATH(Set.insert(D),
+ "Empty/Tombstone value shouldn't be inserted into map!");
+
+ EXPECT_EQ(3U, Set.size());
+ EXPECT_EQ(1U, Set.count(A));
+ EXPECT_EQ(1U, Set.count(B));
+ EXPECT_EQ(1U, Set.count(C));
+
+ EXPECT_EQ(true, Set.erase(B));
+ EXPECT_EQ(2U, Set.size());
+
+ EXPECT_EQ(true, Set.erase(C));
+ EXPECT_EQ(1U, Set.size());
+
+ EXPECT_EQ(true, Set.erase(A));
+ EXPECT_EQ(0U, Set.size());
}
+} // namespace
More information about the llvm-commits
mailing list