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/IR/ValueMap.h"
11 #include "llvm/Config/llvm-config.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/LLVMContext.h"
15 #include "gtest/gtest.h"
23 class ValueMapTest
: public testing::Test
{
27 std::unique_ptr
<BitCastInst
> BitcastV
;
28 std::unique_ptr
<BinaryOperator
> AddV
;
31 : ConstantV(ConstantInt::get(Type::getInt32Ty(Context
), 0)),
32 BitcastV(new BitCastInst(ConstantV
, Type::getInt32Ty(Context
))),
33 AddV(BinaryOperator::CreateAdd(ConstantV
, ConstantV
)) {}
36 // Run everything on Value*, a subtype to make sure that casting works as
37 // expected, and a const subtype to make sure we cast const correctly.
38 typedef ::testing::Types
<Value
, Instruction
, const Instruction
> KeyTypes
;
39 TYPED_TEST_CASE(ValueMapTest
, KeyTypes
);
41 TYPED_TEST(ValueMapTest
, Null
) {
42 ValueMap
<TypeParam
*, int> VM1
;
44 EXPECT_EQ(7, VM1
.lookup(nullptr));
47 TYPED_TEST(ValueMapTest
, FollowsValue
) {
48 ValueMap
<TypeParam
*, int> VM
;
49 VM
[this->BitcastV
.get()] = 7;
50 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
51 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));
52 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
53 EXPECT_EQ(7, VM
.lookup(this->AddV
.get()));
54 EXPECT_EQ(0u, VM
.count(this->BitcastV
.get()));
56 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));
57 EXPECT_EQ(0u, VM
.count(this->BitcastV
.get()));
58 EXPECT_EQ(0U, VM
.size());
61 TYPED_TEST(ValueMapTest
, OperationsWork
) {
62 ValueMap
<TypeParam
*, int> VM
;
63 ValueMap
<TypeParam
*, int> VM2(16); (void)VM2
;
64 typename ValueMapConfig
<TypeParam
*>::ExtraData Data
;
65 ValueMap
<TypeParam
*, int> VM3(Data
, 16); (void)VM3
;
66 EXPECT_TRUE(VM
.empty());
68 VM
[this->BitcastV
.get()] = 7;
71 typename ValueMap
<TypeParam
*, int>::iterator I
=
72 VM
.find(this->BitcastV
.get());
73 ASSERT_TRUE(I
!= VM
.end());
74 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
75 EXPECT_EQ(7, I
->second
);
76 EXPECT_TRUE(VM
.find(this->AddV
.get()) == VM
.end());
79 const ValueMap
<TypeParam
*, int> &CVM
= VM
;
80 typename ValueMap
<TypeParam
*, int>::const_iterator CI
=
81 CVM
.find(this->BitcastV
.get());
82 ASSERT_TRUE(CI
!= CVM
.end());
83 EXPECT_EQ(this->BitcastV
.get(), CI
->first
);
84 EXPECT_EQ(7, CI
->second
);
85 EXPECT_TRUE(CVM
.find(this->AddV
.get()) == CVM
.end());
88 std::pair
<typename ValueMap
<TypeParam
*, int>::iterator
, bool> InsertResult1
=
89 VM
.insert(std::make_pair(this->AddV
.get(), 3));
90 EXPECT_EQ(this->AddV
.get(), InsertResult1
.first
->first
);
91 EXPECT_EQ(3, InsertResult1
.first
->second
);
92 EXPECT_TRUE(InsertResult1
.second
);
93 EXPECT_EQ(1u, VM
.count(this->AddV
.get()));
94 std::pair
<typename ValueMap
<TypeParam
*, int>::iterator
, bool> InsertResult2
=
95 VM
.insert(std::make_pair(this->AddV
.get(), 5));
96 EXPECT_EQ(this->AddV
.get(), InsertResult2
.first
->first
);
97 EXPECT_EQ(3, InsertResult2
.first
->second
);
98 EXPECT_FALSE(InsertResult2
.second
);
101 VM
.erase(InsertResult2
.first
);
102 EXPECT_EQ(0U, VM
.count(this->AddV
.get()));
103 EXPECT_EQ(1U, VM
.count(this->BitcastV
.get()));
104 VM
.erase(this->BitcastV
.get());
105 EXPECT_EQ(0U, VM
.count(this->BitcastV
.get()));
106 EXPECT_EQ(0U, VM
.size());
109 SmallVector
<std::pair
<Instruction
*, int>, 2> Elems
;
110 Elems
.push_back(std::make_pair(this->AddV
.get(), 1));
111 Elems
.push_back(std::make_pair(this->BitcastV
.get(), 2));
112 VM
.insert(Elems
.begin(), Elems
.end());
113 EXPECT_EQ(1, VM
.lookup(this->AddV
.get()));
114 EXPECT_EQ(2, VM
.lookup(this->BitcastV
.get()));
117 template<typename ExpectedType
, typename VarType
>
118 void CompileAssertHasType(VarType
) {
119 static_assert(std::is_same
<ExpectedType
, VarType
>::value
,
120 "Not the same type");
123 TYPED_TEST(ValueMapTest
, Iteration
) {
124 ValueMap
<TypeParam
*, int> VM
;
125 VM
[this->BitcastV
.get()] = 2;
126 VM
[this->AddV
.get()] = 3;
128 for (typename ValueMap
<TypeParam
*, int>::iterator I
= VM
.begin(), E
= VM
.end();
131 std::pair
<TypeParam
*, int> value
= *I
; (void)value
;
132 CompileAssertHasType
<TypeParam
*>(I
->first
);
133 if (I
->second
== 2) {
134 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
136 } else if (I
->second
== 3) {
137 EXPECT_EQ(this->AddV
.get(), I
->first
);
140 ADD_FAILURE() << "Iterated through an extra value.";
144 EXPECT_EQ(5, VM
[this->BitcastV
.get()]);
145 EXPECT_EQ(6, VM
[this->AddV
.get()]);
148 // Cast to const ValueMap to avoid a bug in DenseMap's iterators.
149 const ValueMap
<TypeParam
*, int>& CVM
= VM
;
150 for (typename ValueMap
<TypeParam
*, int>::const_iterator I
= CVM
.begin(),
151 E
= CVM
.end(); I
!= E
; ++I
) {
153 std::pair
<TypeParam
*, int> value
= *I
; (void)value
;
154 CompileAssertHasType
<TypeParam
*>(I
->first
);
155 if (I
->second
== 5) {
156 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
157 } else if (I
->second
== 6) {
158 EXPECT_EQ(this->AddV
.get(), I
->first
);
160 ADD_FAILURE() << "Iterated through an extra value.";
166 TYPED_TEST(ValueMapTest
, DefaultCollisionBehavior
) {
167 // By default, we overwrite the old value with the replaced value.
168 ValueMap
<TypeParam
*, int> VM
;
169 VM
[this->BitcastV
.get()] = 7;
170 VM
[this->AddV
.get()] = 9;
171 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
172 EXPECT_EQ(0u, VM
.count(this->BitcastV
.get()));
173 EXPECT_EQ(9, VM
.lookup(this->AddV
.get()));
176 TYPED_TEST(ValueMapTest
, ConfiguredCollisionBehavior
) {
177 // TODO: Implement this when someone needs it.
180 template<typename KeyT
, typename MutexT
>
181 struct LockMutex
: ValueMapConfig
<KeyT
, MutexT
> {
187 static void onRAUW(const ExtraData
&Data
, KeyT Old
, KeyT New
) {
188 *Data
.CalledRAUW
= true;
189 EXPECT_FALSE(Data
.M
->try_lock()) << "Mutex should already be locked.";
191 static void onDelete(const ExtraData
&Data
, KeyT Old
) {
192 *Data
.CalledDeleted
= true;
193 EXPECT_FALSE(Data
.M
->try_lock()) << "Mutex should already be locked.";
195 static MutexT
*getMutex(const ExtraData
&Data
) { return Data
.M
; }
197 // FIXME: These tests started failing on Windows.
198 #if LLVM_ENABLE_THREADS && !defined(LLVM_ON_WIN32)
199 TYPED_TEST(ValueMapTest
, LocksMutex
) {
200 sys::Mutex
M(false); // Not recursive.
201 bool CalledRAUW
= false, CalledDeleted
= false;
202 typedef LockMutex
<TypeParam
*, sys::Mutex
> ConfigType
;
203 typename
ConfigType::ExtraData Data
= {&M
, &CalledRAUW
, &CalledDeleted
};
204 ValueMap
<TypeParam
*, int, ConfigType
> 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(0u, 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_EQ(0u, VM
.count(this->BitcastV
.get()));
289 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));
290 VM
[this->AddV
.get()] = 7;
292 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));