summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPete Cooper <peter_cooper@apple.com>2012-10-23 18:47:35 +0000
committerPete Cooper <peter_cooper@apple.com>2012-10-23 18:47:35 +0000
commit8ba353da398116cc8b294c3e7a2f9467f3c61b14 (patch)
tree72a4564ab0de42970064b406ca28047e5cc60643
parent5bed7b4fad0da8db2b8af33709f18c261c547ec4 (diff)
downloadbcm5719-llvm-8ba353da398116cc8b294c3e7a2f9467f3c61b14.tar.gz
bcm5719-llvm-8ba353da398116cc8b294c3e7a2f9467f3c61b14.zip
Fixed bug in SmallDenseMap where it wouldn't leave enough space for an empty bucket if the number of values was exactly equal to the small capacity. This led to an infinite loop when finding a non-existent element
llvm-svn: 166492
-rw-r--r--llvm/include/llvm/ADT/DenseMap.h4
-rw-r--r--llvm/unittests/ADT/DenseMapTest.cpp33
2 files changed, 35 insertions, 2 deletions
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index cbcf7892c97..0ae54f42926 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -826,11 +826,11 @@ public:
}
void grow(unsigned AtLeast) {
- if (AtLeast > InlineBuckets)
+ if (AtLeast >= InlineBuckets)
AtLeast = std::max<unsigned>(64, NextPowerOf2(AtLeast));
if (Small) {
- if (AtLeast <= InlineBuckets)
+ if (AtLeast < InlineBuckets)
return; // Nothing to do.
// First move the inline buckets into a temporary storage.
diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index 75e7006434a..15eb6988f66 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -330,4 +330,37 @@ TEST(DenseMapCustomTest, FindAsTest) {
EXPECT_TRUE(map.find_as("d") == map.end());
}
+struct ContiguousDenseMapInfo {
+ static inline unsigned getEmptyKey() { return ~0; }
+ static inline unsigned getTombstoneKey() { return ~0U - 1; }
+ static unsigned getHashValue(const unsigned& Val) { return Val; }
+ static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Test that filling a small dense map with exactly the number of elements in
+// the map grows to have enough space for an empty bucket.
+TEST(DenseMapCustomTest, SmallDenseMapGrowTest) {
+ SmallDenseMap<unsigned, unsigned, 32, ContiguousDenseMapInfo> map;
+ // Add some number of elements, then delete a few to leave us some tombstones.
+ // If we just filled the map with 32 elements we'd grow because of not enough
+ // tombstones which masks the issue here.
+ for (unsigned i = 0; i < 20; ++i)
+ map[i] = i + 1;
+ for (unsigned i = 0; i < 10; ++i)
+ map.erase(i);
+ for (unsigned i = 20; i < 32; ++i)
+ map[i] = i + 1;
+
+ // Size tests
+ EXPECT_EQ(22u, map.size());
+
+ // Try to find an element which doesn't exist. There was a bug in
+ // SmallDenseMap which led to a map with num elements == small capacity not
+ // having an empty bucket any more. Finding an element not in the map would
+ // therefore never terminate.
+ EXPECT_TRUE(map.find(32) == map.end());
+}
+
}
OpenPOWER on IntegriCloud