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