diff options
Diffstat (limited to 'llvm/unittests/CGData')
-rw-r--r-- | llvm/unittests/CGData/CMakeLists.txt | 2 | ||||
-rw-r--r-- | llvm/unittests/CGData/StableFunctionMapRecordTest.cpp | 127 | ||||
-rw-r--r-- | llvm/unittests/CGData/StableFunctionMapTest.cpp | 153 |
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 |