1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
//===- StableFunctionMapTest.cpp ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/CGData/StableFunctionMap.h"
#include "gmock/gmock-matchers.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
using testing::Contains;
using testing::Key;
using testing::Not;
using testing::Pair;
using testing::SizeIs;
TEST(StableFunctionMap, Name) {
StableFunctionMap Map;
EXPECT_TRUE(Map.empty());
EXPECT_TRUE(Map.getNames().empty());
unsigned ID1 = Map.getIdOrCreateForName("Func1");
unsigned ID2 = Map.getIdOrCreateForName("Func2");
unsigned ID3 = Map.getIdOrCreateForName("Func1");
EXPECT_THAT(Map.getNames(), SizeIs(2));
// The different names should return different IDs.
EXPECT_NE(ID1, ID2);
// The same name should return the same ID.
EXPECT_EQ(ID1, ID3);
// The IDs should be valid.
EXPECT_EQ(*Map.getNameForId(ID1), "Func1");
EXPECT_EQ(*Map.getNameForId(ID2), "Func2");
}
TEST(StableFunctionMap, Insert) {
StableFunctionMap Map;
StableFunction Func1{1, "Func1", "Mod1", 2, {{{0, 1}, 3}}};
StableFunction Func2{1, "Func2", "Mod1", 2, {{{0, 1}, 2}}};
Map.insert(Func1);
Map.insert(Func2);
// We only have a unique hash, 1
EXPECT_THAT(Map, SizeIs(1));
// We have two functions with the same hash which are potentially mergeable.
EXPECT_EQ(Map.size(StableFunctionMap::SizeType::TotalFunctionCount), 2u);
EXPECT_EQ(Map.size(StableFunctionMap::SizeType::MergeableFunctionCount), 2u);
}
TEST(StableFunctionMap, InsertEntry) {
StableFunctionMap Map;
unsigned ID1 = Map.getIdOrCreateForName("Func1");
unsigned ID2 = Map.getIdOrCreateForName("Mod1");
unsigned ID3 = Map.getIdOrCreateForName("Func2");
// Create a function entry and insert it into the map.
auto IndexOperandHashMap1 = std::make_unique<IndexOperandHashMapType>();
IndexOperandHashMap1->try_emplace({1, 1}, 3);
auto FuncEntry1 = std::make_unique<StableFunctionEntry>(
1, ID1, ID2, 2, std::move(IndexOperandHashMap1));
Map.insert(std::move(FuncEntry1));
// Create another function entry and insert it into the map.
auto IndexOperandHashMap2 = std::make_unique<IndexOperandHashMapType>();
IndexOperandHashMap2->try_emplace({0, 1}, 2);
auto FuncEntry2 = std::make_unique<StableFunctionEntry>(
1, ID3, ID2, 2, std::move(IndexOperandHashMap2));
Map.insert(std::move(FuncEntry2));
// We only have a unique hash, 1
EXPECT_THAT(Map, SizeIs(1));
// We have two functions with the same hash which are potentially mergeable.
EXPECT_EQ(Map.size(StableFunctionMap::SizeType::TotalFunctionCount), 2u);
}
TEST(StableFunctionMap, Merge) {
StableFunctionMap Map1;
StableFunction Func1{1, "Func1", "Mod1", 2, {{{0, 1}, 3}}};
StableFunction Func2{1, "Func2", "Mod1", 2, {{{0, 1}, 2}}};
StableFunction Func3{2, "Func3", "Mod1", 2, {{{1, 1}, 2}}};
Map1.insert(Func1);
Map1.insert(Func2);
Map1.insert(Func3);
StableFunctionMap Map2;
StableFunction Func4{1, "Func4", "Mod2", 2, {{{0, 1}, 4}}};
StableFunction Func5{2, "Func5", "Mod2", 2, {{{1, 1}, 5}}};
StableFunction Func6{3, "Func6", "Mod2", 2, {{{1, 1}, 6}}};
Map2.insert(Func4);
Map2.insert(Func5);
Map2.insert(Func6);
// Merge two maps.
Map1.merge(Map2);
// We only have two unique hashes, 1, 2 and 3
EXPECT_THAT(Map1, SizeIs(3));
// We have total 6 functions.
EXPECT_EQ(Map1.size(StableFunctionMap::SizeType::TotalFunctionCount), 6u);
// We have 5 mergeable functions. Func6 only has a unique hash, 3.
EXPECT_EQ(Map1.size(StableFunctionMap::SizeType::MergeableFunctionCount), 5u);
}
TEST(StableFunctionMap, Finalize1) {
StableFunctionMap Map;
StableFunction Func1{1, "Func1", "Mod1", 2, {{{0, 1}, 3}}};
StableFunction Func2{1, "Func2", "Mod2", 3, {{{0, 1}, 2}}};
Map.insert(Func1);
Map.insert(Func2);
// Instruction count is mis-matched, so they're not mergeable.
Map.finalize();
EXPECT_TRUE(Map.empty());
}
TEST(StableFunctionMap, Finalize2) {
StableFunctionMap Map;
StableFunction Func1{1, "Func1", "Mod1", 2, {{{0, 1}, 3}}};
StableFunction Func2{1, "Func2", "Mod2", 2, {{{0, 1}, 2}, {{1, 1}, 1}}};
Map.insert(Func1);
Map.insert(Func2);
// Operand map size is mis-matched, so they're not mergeable.
Map.finalize();
EXPECT_TRUE(Map.empty());
}
TEST(StableFunctionMap, Finalize3) {
StableFunctionMap Map;
StableFunction Func1{1, "Func1", "Mod1", 2, {{{0, 1}, 3}, {{1, 1}, 1}}};
StableFunction Func2{1, "Func2", "Mod2", 2, {{{0, 1}, 2}, {{1, 1}, 1}}};
Map.insert(Func1);
Map.insert(Func2);
// The same operand entry is removed, which is redundant.
Map.finalize();
auto &M = Map.getFunctionMap();
EXPECT_THAT(M, SizeIs(1));
auto &FuncEntries = M.begin()->second;
for (auto &FuncEntry : FuncEntries) {
EXPECT_THAT(*FuncEntry->IndexOperandHashMap, SizeIs(1));
ASSERT_THAT(*FuncEntry->IndexOperandHashMap,
Not(Contains(Key(Pair(1, 1)))));
}
}
} // end namespace
|