171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin//===- llvm/unittest/ADT/ValueMapTest.cpp - ValueMap unit tests -*- C++ -*-===//
271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin//
371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin//                     The LLVM Compiler Infrastructure
471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin//
571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin// This file is distributed under the University of Illinois Open Source
671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin// License. See LICENSE.TXT for details.
771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin//
871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin//===----------------------------------------------------------------------===//
971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
1036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/ValueMap.h"
115a88dda4be791426ab4d20a6a6c9c65d66614a27Chandler Carruth#include "llvm/Config/llvm-config.h"
120b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Constants.h"
130b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Instructions.h"
140b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/LLVMContext.h"
1571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin#include "gtest/gtest.h"
1671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
1771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskinusing namespace llvm;
1871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
1971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskinnamespace {
2071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
2171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin// Test fixture
2271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate<typename T>
2371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskinclass ValueMapTest : public testing::Test {
2471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskinprotected:
2571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  Constant *ConstantV;
2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<BitCastInst> BitcastV;
2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  std::unique_ptr<BinaryOperator> AddV;
2871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
2971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMapTest() :
3071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
3171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))),
3271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    AddV(BinaryOperator::CreateAdd(ConstantV, ConstantV)) {
3371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
3471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin};
3571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
3671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin// Run everything on Value*, a subtype to make sure that casting works as
3771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin// expected, and a const subtype to make sure we cast const correctly.
3871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintypedef ::testing::Types<Value, Instruction, const Instruction> KeyTypes;
3971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST_CASE(ValueMapTest, KeyTypes);
4071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
4171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, Null) {
4271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int> VM1;
43cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  VM1[nullptr] = 7;
44cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(7, VM1.lookup(nullptr));
4571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
4671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
4771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, FollowsValue) {
4871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int> VM;
4971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->BitcastV.get()] = 7;
5071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
51cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->AddV.get()));
5271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->BitcastV->replaceAllUsesWith(this->AddV.get());
5371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(7, VM.lookup(this->AddV.get()));
54cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->BitcastV.get()));
5571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->AddV.reset();
56cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->AddV.get()));
57cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->BitcastV.get()));
5871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(0U, VM.size());
5971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
6071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
6171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, OperationsWork) {
6271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int> VM;
63a07cd90a2a13f86f7491d1fd58e71521936b086dChris Lattner  ValueMap<TypeParam*, int> VM2(16);  (void)VM2;
6471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  typename ValueMapConfig<TypeParam*>::ExtraData Data;
65a07cd90a2a13f86f7491d1fd58e71521936b086dChris Lattner  ValueMap<TypeParam*, int> VM3(Data, 16);  (void)VM3;
6671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_TRUE(VM.empty());
6771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
6871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->BitcastV.get()] = 7;
6971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
7071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // Find:
7171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  typename ValueMap<TypeParam*, int>::iterator I =
7271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    VM.find(this->BitcastV.get());
7371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ASSERT_TRUE(I != VM.end());
74e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach  EXPECT_EQ(this->BitcastV.get(), I->first);
7571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(7, I->second);
76e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach  EXPECT_TRUE(VM.find(this->AddV.get()) == VM.end());
7771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
7871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // Const find:
7971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  const ValueMap<TypeParam*, int> &CVM = VM;
8071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  typename ValueMap<TypeParam*, int>::const_iterator CI =
8171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    CVM.find(this->BitcastV.get());
8271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ASSERT_TRUE(CI != CVM.end());
83e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach  EXPECT_EQ(this->BitcastV.get(), CI->first);
8471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(7, CI->second);
8571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_TRUE(CVM.find(this->AddV.get()) == CVM.end());
8671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
8771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // Insert:
8871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult1 =
8971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    VM.insert(std::make_pair(this->AddV.get(), 3));
90e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach  EXPECT_EQ(this->AddV.get(), InsertResult1.first->first);
9171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(3, InsertResult1.first->second);
9271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_TRUE(InsertResult1.second);
93cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(1u, VM.count(this->AddV.get()));
9471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult2 =
9571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    VM.insert(std::make_pair(this->AddV.get(), 5));
96e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach  EXPECT_EQ(this->AddV.get(), InsertResult2.first->first);
9771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(3, InsertResult2.first->second);
9871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_FALSE(InsertResult2.second);
9971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
10071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // Erase:
10171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM.erase(InsertResult2.first);
1023732396fe1513c4d20661e65c538ce368f153557Bill Wendling  EXPECT_EQ(0U, VM.count(this->AddV.get()));
1033732396fe1513c4d20661e65c538ce368f153557Bill Wendling  EXPECT_EQ(1U, VM.count(this->BitcastV.get()));
10471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM.erase(this->BitcastV.get());
1053732396fe1513c4d20661e65c538ce368f153557Bill Wendling  EXPECT_EQ(0U, VM.count(this->BitcastV.get()));
10671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(0U, VM.size());
10771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
10871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // Range insert:
10971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  SmallVector<std::pair<Instruction*, int>, 2> Elems;
11071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  Elems.push_back(std::make_pair(this->AddV.get(), 1));
11171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  Elems.push_back(std::make_pair(this->BitcastV.get(), 2));
11271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM.insert(Elems.begin(), Elems.end());
11371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(1, VM.lookup(this->AddV.get()));
11471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(2, VM.lookup(this->BitcastV.get()));
11571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
11671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
11771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate<typename ExpectedType, typename VarType>
11871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskinvoid CompileAssertHasType(VarType) {
11936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  static_assert(std::is_same<ExpectedType, VarType>::value,
12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                "Not the same type");
12171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
12271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
12371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, Iteration) {
12471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int> VM;
12571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->BitcastV.get()] = 2;
12671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->AddV.get()] = 3;
12771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  size_t size = 0;
12871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  for (typename ValueMap<TypeParam*, int>::iterator I = VM.begin(), E = VM.end();
12971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin       I != E; ++I) {
13071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    ++size;
131a07cd90a2a13f86f7491d1fd58e71521936b086dChris Lattner    std::pair<TypeParam*, int> value = *I; (void)value;
13271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    CompileAssertHasType<TypeParam*>(I->first);
13371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    if (I->second == 2) {
134e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach      EXPECT_EQ(this->BitcastV.get(), I->first);
13571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin      I->second = 5;
13671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    } else if (I->second == 3) {
137e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach      EXPECT_EQ(this->AddV.get(), I->first);
13871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin      I->second = 6;
13971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    } else {
14071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin      ADD_FAILURE() << "Iterated through an extra value.";
14171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    }
14271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
14371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(2U, size);
14471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(5, VM[this->BitcastV.get()]);
14571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(6, VM[this->AddV.get()]);
14671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
14771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  size = 0;
14871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // Cast to const ValueMap to avoid a bug in DenseMap's iterators.
14971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  const ValueMap<TypeParam*, int>& CVM = VM;
15071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  for (typename ValueMap<TypeParam*, int>::const_iterator I = CVM.begin(),
15171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin         E = CVM.end(); I != E; ++I) {
15271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    ++size;
153a07cd90a2a13f86f7491d1fd58e71521936b086dChris Lattner    std::pair<TypeParam*, int> value = *I;  (void)value;
15471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    CompileAssertHasType<TypeParam*>(I->first);
15571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    if (I->second == 5) {
156e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach      EXPECT_EQ(this->BitcastV.get(), I->first);
15771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    } else if (I->second == 6) {
158e541528e351668fb5b6eebbd168aed73d7ff563bJim Grosbach      EXPECT_EQ(this->AddV.get(), I->first);
15971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    } else {
16071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin      ADD_FAILURE() << "Iterated through an extra value.";
16171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    }
16271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
16371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(2U, size);
16471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
16571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
16671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, DefaultCollisionBehavior) {
16771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // By default, we overwrite the old value with the replaced value.
16871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int> VM;
16971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->BitcastV.get()] = 7;
17071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->AddV.get()] = 9;
17171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->BitcastV->replaceAllUsesWith(this->AddV.get());
172cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->BitcastV.get()));
17371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(9, VM.lookup(this->AddV.get()));
17471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
17571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
17671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, ConfiguredCollisionBehavior) {
17771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // TODO: Implement this when someone needs it.
17871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
17971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
180cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinestemplate<typename KeyT, typename MutexT>
181cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstruct LockMutex : ValueMapConfig<KeyT, MutexT> {
18271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  struct ExtraData {
183cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    MutexT *M;
18471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    bool *CalledRAUW;
18571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    bool *CalledDeleted;
18671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  };
18771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) {
18871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    *Data.CalledRAUW = true;
18971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked.";
19071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
1914ab74cdc124af6b4f57c2d2d09548e01d64a1f34Jeffrey Yasskin  static void onDelete(const ExtraData &Data, KeyT Old) {
19271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    *Data.CalledDeleted = true;
19371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked.";
19471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
195cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  static MutexT *getMutex(const ExtraData &Data) { return Data.M; }
19671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin};
1979f756cf4e293e5ac75db4636f7ea45ee85123f25Dylan Noblesmith#if LLVM_ENABLE_THREADS
19871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, LocksMutex) {
19971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  sys::Mutex M(false);  // Not recursive.
20071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  bool CalledRAUW = false, CalledDeleted = false;
201cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  typedef LockMutex<TypeParam*, sys::Mutex> ConfigType;
202cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  typename ConfigType::ExtraData Data = {&M, &CalledRAUW, &CalledDeleted};
203cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ValueMap<TypeParam*, int, ConfigType> VM(Data);
20471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->BitcastV.get()] = 7;
20571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->BitcastV->replaceAllUsesWith(this->AddV.get());
20671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->AddV.reset();
20771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_TRUE(CalledRAUW);
20871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_TRUE(CalledDeleted);
20971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
210b83012a180dbd8d55672fd946ac9c6256cb00bceDuncan Sands#endif
21171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
21271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate<typename KeyT>
21371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskinstruct NoFollow : ValueMapConfig<KeyT> {
21471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  enum { FollowRAUW = false };
21571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin};
21671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
21771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, NoFollowRAUW) {
21871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int, NoFollow<TypeParam*> > VM;
21971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->BitcastV.get()] = 7;
22071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
221cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->AddV.get()));
22271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->BitcastV->replaceAllUsesWith(this->AddV.get());
22371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
22471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(0, VM.lookup(this->AddV.get()));
22571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->AddV.reset();
22671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
22771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(0, VM.lookup(this->AddV.get()));
22871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->BitcastV.reset();
22971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(0, VM.lookup(this->BitcastV.get()));
23071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(0, VM.lookup(this->AddV.get()));
23171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(0U, VM.size());
23271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
23371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
23471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate<typename KeyT>
23571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskinstruct CountOps : ValueMapConfig<KeyT> {
23671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  struct ExtraData {
23771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    int *Deletions;
23871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    int *RAUWs;
23971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  };
24071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
24171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) {
24271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    ++*Data.RAUWs;
24371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
2444ab74cdc124af6b4f57c2d2d09548e01d64a1f34Jeffrey Yasskin  static void onDelete(const ExtraData &Data, KeyT Old) {
24571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    ++*Data.Deletions;
24671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
24771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin};
24871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
24971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, CallsConfig) {
25071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  int Deletions = 0, RAUWs = 0;
25171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  typename CountOps<TypeParam*>::ExtraData Data = {&Deletions, &RAUWs};
25271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int, CountOps<TypeParam*> > VM(Data);
25371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->BitcastV.get()] = 7;
25471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->BitcastV->replaceAllUsesWith(this->AddV.get());
25571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(0, Deletions);
25671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(1, RAUWs);
25771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->AddV.reset();
25871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(1, Deletions);
25971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(1, RAUWs);
26071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->BitcastV.reset();
26171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(1, Deletions);
26271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  EXPECT_EQ(1, RAUWs);
26371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
26471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
26571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskintemplate<typename KeyT>
26671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskinstruct ModifyingConfig : ValueMapConfig<KeyT> {
26771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // We'll put a pointer here back to the ValueMap this key is in, so
26871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // that we can modify it (and clobber *this) before the ValueMap
26971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // tries to do the same modification.  In previous versions of
27071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // ValueMap, that exploded.
27171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  typedef ValueMap<KeyT, int, ModifyingConfig<KeyT> > **ExtraData;
27271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
27371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  static void onRAUW(ExtraData Map, KeyT Old, KeyT New) {
27471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    (*Map)->erase(Old);
27571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
2764ab74cdc124af6b4f57c2d2d09548e01d64a1f34Jeffrey Yasskin  static void onDelete(ExtraData Map, KeyT Old) {
27771a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin    (*Map)->erase(Old);
27871a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  }
27971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin};
28071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey YasskinTYPED_TEST(ValueMapTest, SurvivesModificationByConfig) {
28171a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int, ModifyingConfig<TypeParam*> > *MapAddress;
28271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  ValueMap<TypeParam*, int, ModifyingConfig<TypeParam*> > VM(&MapAddress);
28371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  MapAddress = &VM;
28471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  // Now the ModifyingConfig can modify the Map inside a callback.
28571a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->BitcastV.get()] = 7;
28671a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->BitcastV->replaceAllUsesWith(this->AddV.get());
287cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->BitcastV.get()));
288cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->AddV.get()));
28971a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  VM[this->AddV.get()] = 7;
29071a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin  this->AddV.reset();
291cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  EXPECT_EQ(0u, VM.count(this->AddV.get()));
29271a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
29371a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin
29471a5c22c2b635ea903c3ae7d2695ca649b38726fJeffrey Yasskin}
295