1 //===- llvm/unittest/ADT/ValueMapTest.cpp - ValueMap unit tests -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/ADT/ValueMap.h"
11 #include "llvm/Constants.h"
12 #include "llvm/Instructions.h"
13 #include "llvm/LLVMContext.h"
14 #include "llvm/ADT/OwningPtr.h"
15 #include "llvm/Config/config.h"
17 #include "gtest/gtest.h"
25 class ValueMapTest
: public testing::Test
{
28 OwningPtr
<BitCastInst
> BitcastV
;
29 OwningPtr
<BinaryOperator
> AddV
;
32 ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
33 BitcastV(new BitCastInst(ConstantV
, Type::getInt32Ty(getGlobalContext()))),
34 AddV(BinaryOperator::CreateAdd(ConstantV
, ConstantV
)) {
38 // Run everything on Value*, a subtype to make sure that casting works as
39 // expected, and a const subtype to make sure we cast const correctly.
40 typedef ::testing::Types
<Value
, Instruction
, const Instruction
> KeyTypes
;
41 TYPED_TEST_CASE(ValueMapTest
, KeyTypes
);
43 TYPED_TEST(ValueMapTest
, Null
) {
44 ValueMap
<TypeParam
*, int> VM1
;
46 EXPECT_EQ(7, VM1
.lookup(NULL
));
49 TYPED_TEST(ValueMapTest
, FollowsValue
) {
50 ValueMap
<TypeParam
*, int> VM
;
51 VM
[this->BitcastV
.get()] = 7;
52 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
53 EXPECT_EQ(0, VM
.count(this->AddV
.get()));
54 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
55 EXPECT_EQ(7, VM
.lookup(this->AddV
.get()));
56 EXPECT_EQ(0, VM
.count(this->BitcastV
.get()));
58 EXPECT_EQ(0, VM
.count(this->AddV
.get()));
59 EXPECT_EQ(0, VM
.count(this->BitcastV
.get()));
60 EXPECT_EQ(0U, VM
.size());
63 TYPED_TEST(ValueMapTest
, OperationsWork
) {
64 ValueMap
<TypeParam
*, int> VM
;
65 ValueMap
<TypeParam
*, int> VM2(16); (void)VM2
;
66 typename ValueMapConfig
<TypeParam
*>::ExtraData Data
;
67 ValueMap
<TypeParam
*, int> VM3(Data
, 16); (void)VM3
;
68 EXPECT_TRUE(VM
.empty());
70 VM
[this->BitcastV
.get()] = 7;
73 typename ValueMap
<TypeParam
*, int>::iterator I
=
74 VM
.find(this->BitcastV
.get());
75 ASSERT_TRUE(I
!= VM
.end());
76 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
77 EXPECT_EQ(7, I
->second
);
78 EXPECT_TRUE(VM
.find(this->AddV
.get()) == VM
.end());
81 const ValueMap
<TypeParam
*, int> &CVM
= VM
;
82 typename ValueMap
<TypeParam
*, int>::const_iterator CI
=
83 CVM
.find(this->BitcastV
.get());
84 ASSERT_TRUE(CI
!= CVM
.end());
85 EXPECT_EQ(this->BitcastV
.get(), CI
->first
);
86 EXPECT_EQ(7, CI
->second
);
87 EXPECT_TRUE(CVM
.find(this->AddV
.get()) == CVM
.end());
90 std::pair
<typename ValueMap
<TypeParam
*, int>::iterator
, bool> InsertResult1
=
91 VM
.insert(std::make_pair(this->AddV
.get(), 3));
92 EXPECT_EQ(this->AddV
.get(), InsertResult1
.first
->first
);
93 EXPECT_EQ(3, InsertResult1
.first
->second
);
94 EXPECT_TRUE(InsertResult1
.second
);
95 EXPECT_EQ(true, VM
.count(this->AddV
.get()));
96 std::pair
<typename ValueMap
<TypeParam
*, int>::iterator
, bool> InsertResult2
=
97 VM
.insert(std::make_pair(this->AddV
.get(), 5));
98 EXPECT_EQ(this->AddV
.get(), InsertResult2
.first
->first
);
99 EXPECT_EQ(3, InsertResult2
.first
->second
);
100 EXPECT_FALSE(InsertResult2
.second
);
103 VM
.erase(InsertResult2
.first
);
104 EXPECT_EQ(0U, VM
.count(this->AddV
.get()));
105 EXPECT_EQ(1U, VM
.count(this->BitcastV
.get()));
106 VM
.erase(this->BitcastV
.get());
107 EXPECT_EQ(0U, VM
.count(this->BitcastV
.get()));
108 EXPECT_EQ(0U, VM
.size());
111 SmallVector
<std::pair
<Instruction
*, int>, 2> Elems
;
112 Elems
.push_back(std::make_pair(this->AddV
.get(), 1));
113 Elems
.push_back(std::make_pair(this->BitcastV
.get(), 2));
114 VM
.insert(Elems
.begin(), Elems
.end());
115 EXPECT_EQ(1, VM
.lookup(this->AddV
.get()));
116 EXPECT_EQ(2, VM
.lookup(this->BitcastV
.get()));
119 template<typename ExpectedType
, typename VarType
>
120 void CompileAssertHasType(VarType
) {
121 typedef char assert[is_same
<ExpectedType
, VarType
>::value
? 1 : -1];
124 TYPED_TEST(ValueMapTest
, Iteration
) {
125 ValueMap
<TypeParam
*, int> VM
;
126 VM
[this->BitcastV
.get()] = 2;
127 VM
[this->AddV
.get()] = 3;
129 for (typename ValueMap
<TypeParam
*, int>::iterator I
= VM
.begin(), E
= VM
.end();
132 std::pair
<TypeParam
*, int> value
= *I
; (void)value
;
133 CompileAssertHasType
<TypeParam
*>(I
->first
);
134 if (I
->second
== 2) {
135 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
137 } else if (I
->second
== 3) {
138 EXPECT_EQ(this->AddV
.get(), I
->first
);
141 ADD_FAILURE() << "Iterated through an extra value.";
145 EXPECT_EQ(5, VM
[this->BitcastV
.get()]);
146 EXPECT_EQ(6, VM
[this->AddV
.get()]);
149 // Cast to const ValueMap to avoid a bug in DenseMap's iterators.
150 const ValueMap
<TypeParam
*, int>& CVM
= VM
;
151 for (typename ValueMap
<TypeParam
*, int>::const_iterator I
= CVM
.begin(),
152 E
= CVM
.end(); I
!= E
; ++I
) {
154 std::pair
<TypeParam
*, int> value
= *I
; (void)value
;
155 CompileAssertHasType
<TypeParam
*>(I
->first
);
156 if (I
->second
== 5) {
157 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
158 } else if (I
->second
== 6) {
159 EXPECT_EQ(this->AddV
.get(), I
->first
);
161 ADD_FAILURE() << "Iterated through an extra value.";
167 TYPED_TEST(ValueMapTest
, DefaultCollisionBehavior
) {
168 // By default, we overwrite the old value with the replaced value.
169 ValueMap
<TypeParam
*, int> VM
;
170 VM
[this->BitcastV
.get()] = 7;
171 VM
[this->AddV
.get()] = 9;
172 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
173 EXPECT_EQ(0, VM
.count(this->BitcastV
.get()));
174 EXPECT_EQ(9, VM
.lookup(this->AddV
.get()));
177 TYPED_TEST(ValueMapTest
, ConfiguredCollisionBehavior
) {
178 // TODO: Implement this when someone needs it.
181 template<typename KeyT
>
182 struct LockMutex
: ValueMapConfig
<KeyT
> {
188 static void onRAUW(const ExtraData
&Data
, KeyT Old
, KeyT New
) {
189 *Data
.CalledRAUW
= true;
190 EXPECT_FALSE(Data
.M
->tryacquire()) << "Mutex should already be locked.";
192 static void onDelete(const ExtraData
&Data
, KeyT Old
) {
193 *Data
.CalledDeleted
= true;
194 EXPECT_FALSE(Data
.M
->tryacquire()) << "Mutex should already be locked.";
196 static sys::Mutex
*getMutex(const ExtraData
&Data
) { return Data
.M
; }
199 TYPED_TEST(ValueMapTest
, LocksMutex
) {
200 sys::Mutex
M(false); // Not recursive.
201 bool CalledRAUW
= false, CalledDeleted
= false;
202 typename LockMutex
<TypeParam
*>::ExtraData Data
=
203 {&M
, &CalledRAUW
, &CalledDeleted
};
204 ValueMap
<TypeParam
*, int, LockMutex
<TypeParam
*> > VM(Data
);
205 VM
[this->BitcastV
.get()] = 7;
206 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
208 EXPECT_TRUE(CalledRAUW
);
209 EXPECT_TRUE(CalledDeleted
);
213 template<typename KeyT
>
214 struct NoFollow
: ValueMapConfig
<KeyT
> {
215 enum { FollowRAUW
= false };
218 TYPED_TEST(ValueMapTest
, NoFollowRAUW
) {
219 ValueMap
<TypeParam
*, int, NoFollow
<TypeParam
*> > VM
;
220 VM
[this->BitcastV
.get()] = 7;
221 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
222 EXPECT_EQ(0, VM
.count(this->AddV
.get()));
223 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
224 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
225 EXPECT_EQ(0, VM
.lookup(this->AddV
.get()));
227 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
228 EXPECT_EQ(0, VM
.lookup(this->AddV
.get()));
229 this->BitcastV
.reset();
230 EXPECT_EQ(0, VM
.lookup(this->BitcastV
.get()));
231 EXPECT_EQ(0, VM
.lookup(this->AddV
.get()));
232 EXPECT_EQ(0U, VM
.size());
235 template<typename KeyT
>
236 struct CountOps
: ValueMapConfig
<KeyT
> {
242 static void onRAUW(const ExtraData
&Data
, KeyT Old
, KeyT New
) {
245 static void onDelete(const ExtraData
&Data
, KeyT Old
) {
250 TYPED_TEST(ValueMapTest
, CallsConfig
) {
251 int Deletions
= 0, RAUWs
= 0;
252 typename CountOps
<TypeParam
*>::ExtraData Data
= {&Deletions
, &RAUWs
};
253 ValueMap
<TypeParam
*, int, CountOps
<TypeParam
*> > VM(Data
);
254 VM
[this->BitcastV
.get()] = 7;
255 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
256 EXPECT_EQ(0, Deletions
);
259 EXPECT_EQ(1, Deletions
);
261 this->BitcastV
.reset();
262 EXPECT_EQ(1, Deletions
);
266 template<typename KeyT
>
267 struct ModifyingConfig
: ValueMapConfig
<KeyT
> {
268 // We'll put a pointer here back to the ValueMap this key is in, so
269 // that we can modify it (and clobber *this) before the ValueMap
270 // tries to do the same modification. In previous versions of
271 // ValueMap, that exploded.
272 typedef ValueMap
<KeyT
, int, ModifyingConfig
<KeyT
> > **ExtraData
;
274 static void onRAUW(ExtraData Map
, KeyT Old
, KeyT New
) {
277 static void onDelete(ExtraData Map
, KeyT Old
) {
281 TYPED_TEST(ValueMapTest
, SurvivesModificationByConfig
) {
282 ValueMap
<TypeParam
*, int, ModifyingConfig
<TypeParam
*> > *MapAddress
;
283 ValueMap
<TypeParam
*, int, ModifyingConfig
<TypeParam
*> > VM(&MapAddress
);
285 // Now the ModifyingConfig can modify the Map inside a callback.
286 VM
[this->BitcastV
.get()] = 7;
287 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
288 EXPECT_FALSE(VM
.count(this->BitcastV
.get()));
289 EXPECT_FALSE(VM
.count(this->AddV
.get()));
290 VM
[this->AddV
.get()] = 7;
292 EXPECT_FALSE(VM
.count(this->AddV
.get()));