aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/CGData
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/unittests/CGData')
-rw-r--r--llvm/unittests/CGData/CMakeLists.txt2
-rw-r--r--llvm/unittests/CGData/StableFunctionMapRecordTest.cpp127
-rw-r--r--llvm/unittests/CGData/StableFunctionMapTest.cpp153
3 files changed, 282 insertions, 0 deletions
diff --git a/llvm/unittests/CGData/CMakeLists.txt b/llvm/unittests/CGData/CMakeLists.txt
index 792b323..0bdb9e1 100644
--- a/llvm/unittests/CGData/CMakeLists.txt
+++ b/llvm/unittests/CGData/CMakeLists.txt
@@ -9,6 +9,8 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(CGDataTests
OutlinedHashTreeRecordTest.cpp
OutlinedHashTreeTest.cpp
+ StableFunctionMapRecordTest.cpp
+ StableFunctionMapTest.cpp
)
target_link_libraries(CGDataTests PRIVATE LLVMTestingSupport)
diff --git a/llvm/unittests/CGData/StableFunctionMapRecordTest.cpp b/llvm/unittests/CGData/StableFunctionMapRecordTest.cpp
new file mode 100644
index 0000000..f5c9afe
--- /dev/null
+++ b/llvm/unittests/CGData/StableFunctionMapRecordTest.cpp
@@ -0,0 +1,127 @@
+//===- StableFunctionMapRecordTest.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/StableFunctionMapRecord.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(StableFunctionMapRecordTest, Print) {
+ StableFunctionMapRecord MapRecord;
+ StableFunction Func1{1, "Func1", "Mod1", 2, {{{0, 1}, 3}}};
+ MapRecord.FunctionMap->insert(Func1);
+
+ const char *ExpectedMapStr = R"(---
+- Hash: 1
+ FunctionName: Func1
+ ModuleName: Mod1
+ InstCount: 2
+ IndexOperandHashes:
+ - InstIndex: 0
+ OpndIndex: 1
+ OpndHash: 3
+...
+)";
+ std::string MapDump;
+ raw_string_ostream OS(MapDump);
+ MapRecord.print(OS);
+ EXPECT_EQ(ExpectedMapStr, MapDump);
+}
+
+TEST(StableFunctionMapRecordTest, Stable) {
+ StableFunction Func1{1, "Func2", "Mod1", 1, {}};
+ StableFunction Func2{1, "Func3", "Mod1", 1, {}};
+ StableFunction Func3{1, "Func1", "Mod2", 1, {}};
+ StableFunction Func4{2, "Func4", "Mod3", 1, {}};
+
+ StableFunctionMapRecord MapRecord1;
+ MapRecord1.FunctionMap->insert(Func1);
+ MapRecord1.FunctionMap->insert(Func2);
+ MapRecord1.FunctionMap->insert(Func3);
+ MapRecord1.FunctionMap->insert(Func4);
+
+ StableFunctionMapRecord MapRecord2;
+ MapRecord2.FunctionMap->insert(Func4);
+ MapRecord2.FunctionMap->insert(Func3);
+ MapRecord2.FunctionMap->insert(Func2);
+ MapRecord2.FunctionMap->insert(Func1);
+
+ // Output is sorted by hash (1 < 2), module name (Mod1 < Mod2), and function
+ // name (Func2 < Func3).
+ std::string MapDump1;
+ raw_string_ostream OS1(MapDump1);
+ MapRecord1.print(OS1);
+ std::string MapDump2;
+ raw_string_ostream OS2(MapDump2);
+ MapRecord2.print(OS2);
+ EXPECT_EQ(MapDump1, MapDump2);
+}
+
+TEST(StableFunctionMapRecordTest, Serialize) {
+ StableFunctionMapRecord MapRecord1;
+ StableFunction Func1{1, "Func1", "Mod1", 2, {{{0, 1}, 3}, {{1, 2}, 4}}};
+ StableFunction Func2{2, "Func2", "Mod1", 3, {{{0, 1}, 2}}};
+ StableFunction Func3{2, "Func3", "Mod1", 3, {{{0, 1}, 3}}};
+ MapRecord1.FunctionMap->insert(Func1);
+ MapRecord1.FunctionMap->insert(Func2);
+ MapRecord1.FunctionMap->insert(Func3);
+
+ // Serialize and deserialize the map.
+ SmallVector<char> Out;
+ raw_svector_ostream OS(Out);
+ MapRecord1.serialize(OS);
+
+ StableFunctionMapRecord MapRecord2;
+ const uint8_t *Data = reinterpret_cast<const uint8_t *>(Out.data());
+ MapRecord2.deserialize(Data);
+
+ // Two maps should be identical.
+ std::string MapDump1;
+ raw_string_ostream OS1(MapDump1);
+ MapRecord1.print(OS1);
+ std::string MapDump2;
+ raw_string_ostream OS2(MapDump2);
+ MapRecord2.print(OS2);
+
+ EXPECT_EQ(MapDump1, MapDump2);
+}
+
+TEST(StableFunctionMapRecordTest, SerializeYAML) {
+ StableFunctionMapRecord MapRecord1;
+ StableFunction Func1{1, "Func1", "Mod1", 2, {{{0, 1}, 3}, {{1, 2}, 4}}};
+ StableFunction Func2{2, "Func2", "Mod1", 3, {{{0, 1}, 2}}};
+ StableFunction Func3{2, "Func3", "Mod1", 3, {{{0, 1}, 3}}};
+ MapRecord1.FunctionMap->insert(Func1);
+ MapRecord1.FunctionMap->insert(Func2);
+ MapRecord1.FunctionMap->insert(Func3);
+
+ // Serialize and deserialize the map in a YAML format.
+ std::string Out;
+ raw_string_ostream OS(Out);
+ yaml::Output YOS(OS);
+ MapRecord1.serializeYAML(YOS);
+
+ StableFunctionMapRecord MapRecord2;
+ yaml::Input YIS(StringRef(Out.data(), Out.size()));
+ MapRecord2.deserializeYAML(YIS);
+
+ // Two maps should be identical.
+ std::string MapDump1;
+ raw_string_ostream OS1(MapDump1);
+ MapRecord1.print(OS1);
+ std::string MapDump2;
+ raw_string_ostream OS2(MapDump2);
+ MapRecord2.print(OS2);
+
+ EXPECT_EQ(MapDump1, MapDump2);
+}
+
+} // end namespace
diff --git a/llvm/unittests/CGData/StableFunctionMapTest.cpp b/llvm/unittests/CGData/StableFunctionMapTest.cpp
new file mode 100644
index 0000000..839b997
--- /dev/null
+++ b/llvm/unittests/CGData/StableFunctionMapTest.cpp
@@ -0,0 +1,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