[ADT] Add a reserve() method to DenseSet as well as an insert() for R-value

Recommit 278600 with some fixes to make the test more robust.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278604 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mehdi Amini 2016-08-13 20:42:19 +00:00
parent 80f0510b4f
commit 568382ff0e
2 changed files with 81 additions and 1 deletions

View File

@ -58,6 +58,10 @@ public:
/// the Size of the set.
void resize(size_t Size) { TheMap.resize(Size); }
/// Grow the DenseSet so that it can contain at least \p NumEntries items
/// before resizing again.
void reserve(size_t Size) { TheMap.reserve(Size); }
void clear() {
TheMap.clear();
}
@ -151,7 +155,12 @@ public:
std::pair<iterator, bool> insert(const ValueT &V) {
detail::DenseSetEmpty Empty;
return TheMap.insert(std::make_pair(V, Empty));
return TheMap.try_emplace(V, Empty);
}
std::pair<iterator, bool> insert(ValueT &&V) {
detail::DenseSetEmpty Empty;
return TheMap.try_emplace(std::move(V), Empty);
}
/// Alternative version of insert that uses a different (and possibly less

View File

@ -65,4 +65,75 @@ TEST(DenseSetCustomTest, FindAsTest) {
EXPECT_TRUE(set.find_as("d") == set.end());
}
// Simple class that counts how many moves and copy happens when growing a map
struct CountCopyAndMove {
static int Move;
static int Copy;
int Value;
CountCopyAndMove(int Value) : Value(Value) {}
CountCopyAndMove(const CountCopyAndMove &RHS) {
Value = RHS.Value;
Copy++;
}
CountCopyAndMove &operator=(const CountCopyAndMove &RHS) {
Value = RHS.Value;
Copy++;
return *this;
}
CountCopyAndMove(CountCopyAndMove &&RHS) {
Value = RHS.Value;
Move++;
}
CountCopyAndMove &operator=(const CountCopyAndMove &&RHS) {
Value = RHS.Value;
Move++;
return *this;
}
};
int CountCopyAndMove::Copy = 0;
int CountCopyAndMove::Move = 0;
} // anonymous namespace
namespace llvm {
// Specialization required to insert a CountCopyAndMove into a DenseSet.
template <> struct DenseMapInfo<CountCopyAndMove> {
static inline CountCopyAndMove getEmptyKey() { return CountCopyAndMove(-1); };
static inline CountCopyAndMove getTombstoneKey() {
return CountCopyAndMove(-2);
};
static unsigned getHashValue(const CountCopyAndMove &Val) {
return Val.Value;
}
static bool isEqual(const CountCopyAndMove &LHS,
const CountCopyAndMove &RHS) {
return LHS.Value == RHS.Value;
}
};
}
namespace {
// Make sure reserve actually gives us enough buckets to insert N items
// without increasing allocation size.
TEST(DenseSetCustomTest, ReserveTest) {
// Test a few different size, 48 is *not* a random choice: we need a value
// that is 2/3 of a power of two to stress the grow() condition, and the power
// of two has to be at least 64 because of minimum size allocation in the
// DenseMa. 66 is a value just above the 64 default init.
for (auto Size : {1, 2, 48, 66}) {
DenseSet<CountCopyAndMove> Set;
Set.reserve(Size);
unsigned MemorySize = Set.getMemorySize();
CountCopyAndMove::Copy = 0;
CountCopyAndMove::Move = 0;
for (int i = 0; i < Size; ++i)
Set.insert(CountCopyAndMove(i));
// Check that we didn't grow
EXPECT_EQ(MemorySize, Set.getMemorySize());
// Check that move was called the expected number of times
EXPECT_EQ(Size, CountCopyAndMove::Move);
// Check that no copy occured
EXPECT_EQ(0, CountCopyAndMove::Copy);
}
}
}