llvm.org GIT mirror llvm / 5e2cfa2
Add support for DenseMap/DenseSet count and find using const pointers Summary: Similar to SmallPtrSet, this makes find and count work with both const referneces and const pointers. Reviewers: dblaikie Subscribers: llvm-commits, mzolotukhin Differential Revision: https://reviews.llvm.org/D30713 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297424 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Berlin 3 years ago
6 changed file(s) with 53 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
5252 template
5353 typename BucketT>
5454 class DenseMapBase : public DebugEpochBase {
55 template
56 using const_arg_type_t = typename const_pointer_or_const_ref::type;
57
5558 public:
5659 typedef unsigned size_type;
5760 typedef KeyT key_type;
118121 }
119122
120123 /// Return 1 if the specified key is in the map, 0 otherwise.
121 size_type count(const KeyT &Val) const {
124 size_type count(const_arg_type_t Val) const {
122125 const BucketT *TheBucket;
123126 return LookupBucketFor(Val, TheBucket) ? 1 : 0;
124127 }
125128
126 iterator find(const KeyT &Val) {
129 iterator find(const_arg_type_t Val) {
127130 BucketT *TheBucket;
128131 if (LookupBucketFor(Val, TheBucket))
129132 return iterator(TheBucket, getBucketsEnd(), *this, true);
130133 return end();
131134 }
132 const_iterator find(const KeyT &Val) const {
135 const_iterator find(const_arg_type_t Val) const {
133136 const BucketT *TheBucket;
134137 if (LookupBucketFor(Val, TheBucket))
135138 return const_iterator(TheBucket, getBucketsEnd(), *this, true);
158161
159162 /// lookup - Return the entry for the specified key, or a default
160163 /// constructed value if no such entry exists.
161 ValueT lookup(const KeyT &Val) const {
164 ValueT lookup(const_arg_type_t Val) const {
162165 const BucketT *TheBucket;
163166 if (LookupBucketFor(Val, TheBucket))
164167 return TheBucket->getSecond();
4747 static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
4848 "DenseMap buckets unexpectedly large!");
4949 MapTy TheMap;
50 template
51 using const_arg_type_t = typename const_pointer_or_const_ref::type;
5052
5153 public:
5254 typedef ValueT key_type;
7779 }
7880
7981 /// Return 1 if the specified key is in the set, 0 otherwise.
80 size_type count(const ValueT &V) const {
82 size_type count(const_arg_type_t V) const {
8183 return TheMap.count(V);
8284 }
8385
153155 const_iterator begin() const { return ConstIterator(TheMap.begin()); }
154156 const_iterator end() const { return ConstIterator(TheMap.end()); }
155157
156 iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); }
157 const_iterator find(const ValueT &V) const {
158 iterator find(const_arg_type_t V) { return Iterator(TheMap.find(V)); }
159 const_iterator find(const_arg_type_t V) const {
158160 return ConstIterator(TheMap.find(V));
159161 }
160162
9494 typedef const typename std::remove_pointer::type *type;
9595 };
9696
97 template
98 struct const_pointer_or_const_ref {
99 using type = const T &;
100 };
101 template
102 struct const_pointer_or_const_ref<
103 T, typename std::enable_if::value>::type> {
104 using type = typename add_const_past_pointer::type;
105 };
97106 }
98107
99108 // If the compiler supports detecting whether a class is final, define
36563656
36573657 namespace {
36583658 struct CSEDenseMapInfo {
3659 static bool canHandle(Instruction *I) {
3659 static bool canHandle(const Instruction *I) {
36603660 return isa(I) || isa(I) ||
36613661 isa(I) || isa(I);
36623662 }
36663666 static inline Instruction *getTombstoneKey() {
36673667 return DenseMapInfo::getTombstoneKey();
36683668 }
3669 static unsigned getHashValue(Instruction *I) {
3669 static unsigned getHashValue(const Instruction *I) {
36703670 assert(canHandle(I) && "Unknown instruction!");
36713671 return hash_combine(I->getOpcode(), hash_combine_range(I->value_op_begin(),
36723672 I->value_op_end()));
36733673 }
3674 static bool isEqual(Instruction *LHS, Instruction *RHS) {
3674 static bool isEqual(const Instruction *LHS, const Instruction *RHS) {
36753675 if (LHS == getEmptyKey() || RHS == getEmptyKey() ||
36763676 LHS == getTombstoneKey() || RHS == getTombstoneKey())
36773677 return LHS == RHS;
579579 EXPECT_EQ(Try1.first, Try2.first);
580580 EXPECT_NE(nullptr, P);
581581 }
582 }
582
583 TEST(DenseMapCustomTest, ConstTest) {
584 // Test that const pointers work okay for count and find, even when the
585 // underlying map is a non-const pointer.
586 DenseMap Map;
587 int A;
588 int *B = &A;
589 const int *C = &A;
590 Map.insert({B, 0});
591 EXPECT_EQ(Map.count(B), 1u);
592 EXPECT_EQ(Map.count(C), 1u);
593 EXPECT_NE(Map.find(B), Map.end());
594 EXPECT_NE(Map.find(C), Map.end());
595 }
596 }
184184 EXPECT_EQ(0, CountCopyAndMove::Copy);
185185 }
186186 }
187 }
187 TEST(DenseSetCustomTest, ConstTest) {
188 // Test that const pointers work okay for count and find, even when the
189 // underlying map is a non-const pointer.
190 DenseSet Map;
191 int A;
192 int *B = &A;
193 const int *C = &A;
194 Map.insert(B);
195 EXPECT_EQ(Map.count(B), 1u);
196 EXPECT_EQ(Map.count(C), 1u);
197 EXPECT_NE(Map.find(B), Map.end());
198 EXPECT_NE(Map.find(C), Map.end());
199 }
200 }