1 //===- llvm/unittest/ADT/ValueMapTest.cpp - ValueMap unit tests -*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/ValueMap.h"
10 #include "llvm/Config/llvm-config.h"
11 #include "llvm/IR/Constants.h"
12 #include "llvm/IR/Instructions.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "gtest/gtest.h"
22 class ValueMapTest
: public testing::Test
{
26 std::unique_ptr
<BitCastInst
> BitcastV
;
27 std::unique_ptr
<BinaryOperator
> AddV
;
30 : ConstantV(ConstantInt::get(Type::getInt32Ty(Context
), 0)),
31 BitcastV(new BitCastInst(ConstantV
, Type::getInt32Ty(Context
))),
32 AddV(BinaryOperator::CreateAdd(ConstantV
, ConstantV
)) {}
35 // Run everything on Value*, a subtype to make sure that casting works as
36 // expected, and a const subtype to make sure we cast const correctly.
37 typedef ::testing::Types
<Value
, Instruction
, const Instruction
> KeyTypes
;
38 TYPED_TEST_SUITE(ValueMapTest
, KeyTypes
, );
40 TYPED_TEST(ValueMapTest
, Null
) {
41 ValueMap
<TypeParam
*, int> VM1
;
43 EXPECT_EQ(7, VM1
.lookup(nullptr));
46 TYPED_TEST(ValueMapTest
, FollowsValue
) {
47 ValueMap
<TypeParam
*, int> VM
;
48 VM
[this->BitcastV
.get()] = 7;
49 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
50 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));
51 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
52 EXPECT_EQ(7, VM
.lookup(this->AddV
.get()));
53 EXPECT_EQ(0u, VM
.count(this->BitcastV
.get()));
55 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));
56 EXPECT_EQ(0u, VM
.count(this->BitcastV
.get()));
57 EXPECT_EQ(0U, VM
.size());
60 TYPED_TEST(ValueMapTest
, OperationsWork
) {
61 ValueMap
<TypeParam
*, int> VM
;
62 ValueMap
<TypeParam
*, int> VM2(16); (void)VM2
;
63 typename ValueMapConfig
<TypeParam
*>::ExtraData Data
;
64 ValueMap
<TypeParam
*, int> VM3(Data
, 16); (void)VM3
;
65 EXPECT_TRUE(VM
.empty());
67 VM
[this->BitcastV
.get()] = 7;
70 typename ValueMap
<TypeParam
*, int>::iterator I
=
71 VM
.find(this->BitcastV
.get());
72 ASSERT_TRUE(I
!= VM
.end());
73 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
74 EXPECT_EQ(7, I
->second
);
75 EXPECT_TRUE(VM
.find(this->AddV
.get()) == VM
.end());
78 const ValueMap
<TypeParam
*, int> &CVM
= VM
;
79 typename ValueMap
<TypeParam
*, int>::const_iterator CI
=
80 CVM
.find(this->BitcastV
.get());
81 ASSERT_TRUE(CI
!= CVM
.end());
82 EXPECT_EQ(this->BitcastV
.get(), CI
->first
);
83 EXPECT_EQ(7, CI
->second
);
84 EXPECT_TRUE(CVM
.find(this->AddV
.get()) == CVM
.end());
87 std::pair
<typename ValueMap
<TypeParam
*, int>::iterator
, bool> InsertResult1
=
88 VM
.insert(std::make_pair(this->AddV
.get(), 3));
89 EXPECT_EQ(this->AddV
.get(), InsertResult1
.first
->first
);
90 EXPECT_EQ(3, InsertResult1
.first
->second
);
91 EXPECT_TRUE(InsertResult1
.second
);
92 EXPECT_EQ(1u, VM
.count(this->AddV
.get()));
93 std::pair
<typename ValueMap
<TypeParam
*, int>::iterator
, bool> InsertResult2
=
94 VM
.insert(std::make_pair(this->AddV
.get(), 5));
95 EXPECT_EQ(this->AddV
.get(), InsertResult2
.first
->first
);
96 EXPECT_EQ(3, InsertResult2
.first
->second
);
97 EXPECT_FALSE(InsertResult2
.second
);
100 VM
.erase(InsertResult2
.first
);
101 EXPECT_EQ(0U, VM
.count(this->AddV
.get()));
102 EXPECT_EQ(1U, VM
.count(this->BitcastV
.get()));
103 VM
.erase(this->BitcastV
.get());
104 EXPECT_EQ(0U, VM
.count(this->BitcastV
.get()));
105 EXPECT_EQ(0U, VM
.size());
108 SmallVector
<std::pair
<Instruction
*, int>, 2> Elems
;
109 Elems
.push_back(std::make_pair(this->AddV
.get(), 1));
110 Elems
.push_back(std::make_pair(this->BitcastV
.get(), 2));
111 VM
.insert(Elems
.begin(), Elems
.end());
112 EXPECT_EQ(1, VM
.lookup(this->AddV
.get()));
113 EXPECT_EQ(2, VM
.lookup(this->BitcastV
.get()));
116 template<typename ExpectedType
, typename VarType
>
117 void CompileAssertHasType(VarType
) {
118 static_assert(std::is_same
<ExpectedType
, VarType
>::value
,
119 "Not the same type");
122 TYPED_TEST(ValueMapTest
, Iteration
) {
123 ValueMap
<TypeParam
*, int> VM
;
124 VM
[this->BitcastV
.get()] = 2;
125 VM
[this->AddV
.get()] = 3;
127 for (typename ValueMap
<TypeParam
*, int>::iterator I
= VM
.begin(), E
= VM
.end();
130 std::pair
<TypeParam
*, int> value
= *I
; (void)value
;
131 CompileAssertHasType
<TypeParam
*>(I
->first
);
132 if (I
->second
== 2) {
133 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
135 } else if (I
->second
== 3) {
136 EXPECT_EQ(this->AddV
.get(), I
->first
);
139 ADD_FAILURE() << "Iterated through an extra value.";
143 EXPECT_EQ(5, VM
[this->BitcastV
.get()]);
144 EXPECT_EQ(6, VM
[this->AddV
.get()]);
147 // Cast to const ValueMap to avoid a bug in DenseMap's iterators.
148 const ValueMap
<TypeParam
*, int>& CVM
= VM
;
149 for (typename ValueMap
<TypeParam
*, int>::const_iterator I
= CVM
.begin(),
150 E
= CVM
.end(); I
!= E
; ++I
) {
152 std::pair
<TypeParam
*, int> value
= *I
; (void)value
;
153 CompileAssertHasType
<TypeParam
*>(I
->first
);
154 if (I
->second
== 5) {
155 EXPECT_EQ(this->BitcastV
.get(), I
->first
);
156 } else if (I
->second
== 6) {
157 EXPECT_EQ(this->AddV
.get(), I
->first
);
159 ADD_FAILURE() << "Iterated through an extra value.";
165 TYPED_TEST(ValueMapTest
, DefaultCollisionBehavior
) {
166 // By default, we overwrite the old value with the replaced value.
167 ValueMap
<TypeParam
*, int> VM
;
168 VM
[this->BitcastV
.get()] = 7;
169 VM
[this->AddV
.get()] = 9;
170 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
171 EXPECT_EQ(0u, VM
.count(this->BitcastV
.get()));
172 EXPECT_EQ(9, VM
.lookup(this->AddV
.get()));
175 TYPED_TEST(ValueMapTest
, ConfiguredCollisionBehavior
) {
176 // TODO: Implement this when someone needs it.
179 template<typename KeyT
, typename MutexT
>
180 struct LockMutex
: ValueMapConfig
<KeyT
, MutexT
> {
186 static void onRAUW(const ExtraData
&Data
, KeyT Old
, KeyT New
) {
187 *Data
.CalledRAUW
= true;
188 EXPECT_FALSE(Data
.M
->try_lock()) << "Mutex should already be locked.";
190 static void onDelete(const ExtraData
&Data
, KeyT Old
) {
191 *Data
.CalledDeleted
= true;
192 EXPECT_FALSE(Data
.M
->try_lock()) << "Mutex should already be locked.";
194 static MutexT
*getMutex(const ExtraData
&Data
) { return Data
.M
; }
196 // FIXME: These tests started failing on Windows.
197 #if LLVM_ENABLE_THREADS && !defined(_WIN32)
198 TYPED_TEST(ValueMapTest
, LocksMutex
) {
200 bool CalledRAUW
= false, CalledDeleted
= false;
201 typedef LockMutex
<TypeParam
*, std::mutex
> ConfigType
;
202 typename
ConfigType::ExtraData Data
= {&M
, &CalledRAUW
, &CalledDeleted
};
203 ValueMap
<TypeParam
*, int, ConfigType
> VM(Data
);
204 VM
[this->BitcastV
.get()] = 7;
205 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
207 EXPECT_TRUE(CalledRAUW
);
208 EXPECT_TRUE(CalledDeleted
);
212 template<typename KeyT
>
213 struct NoFollow
: ValueMapConfig
<KeyT
> {
214 enum { FollowRAUW
= false };
217 TYPED_TEST(ValueMapTest
, NoFollowRAUW
) {
218 ValueMap
<TypeParam
*, int, NoFollow
<TypeParam
*> > VM
;
219 VM
[this->BitcastV
.get()] = 7;
220 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
221 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));
222 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
223 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
224 EXPECT_EQ(0, VM
.lookup(this->AddV
.get()));
226 EXPECT_EQ(7, VM
.lookup(this->BitcastV
.get()));
227 EXPECT_EQ(0, VM
.lookup(this->AddV
.get()));
228 this->BitcastV
.reset();
229 EXPECT_EQ(0, VM
.lookup(this->BitcastV
.get()));
230 EXPECT_EQ(0, VM
.lookup(this->AddV
.get()));
231 EXPECT_EQ(0U, VM
.size());
234 template<typename KeyT
>
235 struct CountOps
: ValueMapConfig
<KeyT
> {
241 static void onRAUW(const ExtraData
&Data
, KeyT Old
, KeyT New
) {
244 static void onDelete(const ExtraData
&Data
, KeyT Old
) {
249 TYPED_TEST(ValueMapTest
, CallsConfig
) {
250 int Deletions
= 0, RAUWs
= 0;
251 typename CountOps
<TypeParam
*>::ExtraData Data
= {&Deletions
, &RAUWs
};
252 ValueMap
<TypeParam
*, int, CountOps
<TypeParam
*> > VM(Data
);
253 VM
[this->BitcastV
.get()] = 7;
254 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
255 EXPECT_EQ(0, Deletions
);
258 EXPECT_EQ(1, Deletions
);
260 this->BitcastV
.reset();
261 EXPECT_EQ(1, Deletions
);
265 template<typename KeyT
>
266 struct ModifyingConfig
: ValueMapConfig
<KeyT
> {
267 // We'll put a pointer here back to the ValueMap this key is in, so
268 // that we can modify it (and clobber *this) before the ValueMap
269 // tries to do the same modification. In previous versions of
270 // ValueMap, that exploded.
271 typedef ValueMap
<KeyT
, int, ModifyingConfig
<KeyT
> > **ExtraData
;
273 static void onRAUW(ExtraData Map
, KeyT Old
, KeyT New
) {
276 static void onDelete(ExtraData Map
, KeyT Old
) {
280 TYPED_TEST(ValueMapTest
, SurvivesModificationByConfig
) {
281 ValueMap
<TypeParam
*, int, ModifyingConfig
<TypeParam
*> > *MapAddress
;
282 ValueMap
<TypeParam
*, int, ModifyingConfig
<TypeParam
*> > VM(&MapAddress
);
284 // Now the ModifyingConfig can modify the Map inside a callback.
285 VM
[this->BitcastV
.get()] = 7;
286 this->BitcastV
->replaceAllUsesWith(this->AddV
.get());
287 EXPECT_EQ(0u, VM
.count(this->BitcastV
.get()));
288 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));
289 VM
[this->AddV
.get()] = 7;
291 EXPECT_EQ(0u, VM
.count(this->AddV
.get()));