1 //===- unittest/ProfileData/InstrProfTest.cpp -------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/IR/Function.h" 11 #include "llvm/IR/LLVMContext.h" 12 #include "llvm/IR/Module.h" 13 #include "llvm/ProfileData/InstrProfReader.h" 14 #include "llvm/ProfileData/InstrProfWriter.h" 15 #include "llvm/Support/Compression.h" 16 #include "gtest/gtest.h" 17 #include <cstdarg> 18 19 using namespace llvm; 20 21 static ::testing::AssertionResult NoError(std::error_code EC) { 22 if (!EC) 23 return ::testing::AssertionSuccess(); 24 return ::testing::AssertionFailure() << "error " << EC.value() 25 << ": " << EC.message(); 26 } 27 28 static ::testing::AssertionResult ErrorEquals(std::error_code Expected, 29 std::error_code Found) { 30 if (Expected == Found) 31 return ::testing::AssertionSuccess(); 32 return ::testing::AssertionFailure() << "error " << Found.value() 33 << ": " << Found.message(); 34 } 35 36 namespace { 37 38 struct InstrProfTest : ::testing::Test { 39 InstrProfWriter Writer; 40 std::unique_ptr<IndexedInstrProfReader> Reader; 41 42 void SetUp() { Writer.setOutputSparse(false); } 43 44 void readProfile(std::unique_ptr<MemoryBuffer> Profile) { 45 auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile)); 46 ASSERT_TRUE(NoError(ReaderOrErr.getError())); 47 Reader = std::move(ReaderOrErr.get()); 48 } 49 }; 50 51 struct SparseInstrProfTest : public InstrProfTest { 52 void SetUp() { Writer.setOutputSparse(true); } 53 }; 54 55 struct MaybeSparseInstrProfTest : public InstrProfTest, 56 public ::testing::WithParamInterface<bool> { 57 void SetUp() { 58 Writer.setOutputSparse(GetParam()); 59 } 60 }; 61 62 TEST_P(MaybeSparseInstrProfTest, write_and_read_empty_profile) { 63 auto Profile = Writer.writeBuffer(); 64 readProfile(std::move(Profile)); 65 ASSERT_TRUE(Reader->begin() == Reader->end()); 66 } 67 68 TEST_P(MaybeSparseInstrProfTest, write_and_read_one_function) { 69 InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4}); 70 Writer.addRecord(std::move(Record)); 71 auto Profile = Writer.writeBuffer(); 72 readProfile(std::move(Profile)); 73 74 auto I = Reader->begin(), E = Reader->end(); 75 ASSERT_TRUE(I != E); 76 ASSERT_EQ(StringRef("foo"), I->Name); 77 ASSERT_EQ(0x1234U, I->Hash); 78 ASSERT_EQ(4U, I->Counts.size()); 79 ASSERT_EQ(1U, I->Counts[0]); 80 ASSERT_EQ(2U, I->Counts[1]); 81 ASSERT_EQ(3U, I->Counts[2]); 82 ASSERT_EQ(4U, I->Counts[3]); 83 ASSERT_TRUE(++I == E); 84 } 85 86 TEST_P(MaybeSparseInstrProfTest, get_instr_prof_record) { 87 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 88 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 89 Writer.addRecord(std::move(Record1)); 90 Writer.addRecord(std::move(Record2)); 91 auto Profile = Writer.writeBuffer(); 92 readProfile(std::move(Profile)); 93 94 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234); 95 ASSERT_TRUE(NoError(R.getError())); 96 ASSERT_EQ(2U, R.get().Counts.size()); 97 ASSERT_EQ(1U, R.get().Counts[0]); 98 ASSERT_EQ(2U, R.get().Counts[1]); 99 100 R = Reader->getInstrProfRecord("foo", 0x1235); 101 ASSERT_TRUE(NoError(R.getError())); 102 ASSERT_EQ(2U, R.get().Counts.size()); 103 ASSERT_EQ(3U, R.get().Counts[0]); 104 ASSERT_EQ(4U, R.get().Counts[1]); 105 106 R = Reader->getInstrProfRecord("foo", 0x5678); 107 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.getError())); 108 109 R = Reader->getInstrProfRecord("bar", 0x1234); 110 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.getError())); 111 } 112 113 TEST_P(MaybeSparseInstrProfTest, get_function_counts) { 114 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 115 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 116 Writer.addRecord(std::move(Record1)); 117 Writer.addRecord(std::move(Record2)); 118 auto Profile = Writer.writeBuffer(); 119 readProfile(std::move(Profile)); 120 121 std::vector<uint64_t> Counts; 122 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts))); 123 ASSERT_EQ(2U, Counts.size()); 124 ASSERT_EQ(1U, Counts[0]); 125 ASSERT_EQ(2U, Counts[1]); 126 127 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts))); 128 ASSERT_EQ(2U, Counts.size()); 129 ASSERT_EQ(3U, Counts[0]); 130 ASSERT_EQ(4U, Counts[1]); 131 132 std::error_code EC; 133 EC = Reader->getFunctionCounts("foo", 0x5678, Counts); 134 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, EC)); 135 136 EC = Reader->getFunctionCounts("bar", 0x1234, Counts); 137 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, EC)); 138 } 139 140 // Profile data is copied from general.proftext 141 TEST_F(InstrProfTest, get_profile_summary) { 142 InstrProfRecord Record1("func1", 0x1234, {97531}); 143 InstrProfRecord Record2("func2", 0x1234, {0, 0}); 144 InstrProfRecord Record3("func3", 0x1234, 145 {2305843009213693952, 1152921504606846976, 146 576460752303423488, 288230376151711744, 147 144115188075855872, 72057594037927936}); 148 InstrProfRecord Record4("func4", 0x1234, {0}); 149 Writer.addRecord(std::move(Record1)); 150 Writer.addRecord(std::move(Record2)); 151 Writer.addRecord(std::move(Record3)); 152 Writer.addRecord(std::move(Record4)); 153 auto Profile = Writer.writeBuffer(); 154 readProfile(std::move(Profile)); 155 156 ProfileSummary &PS = Reader->getSummary(); 157 ASSERT_EQ(2305843009213693952U, PS.getMaxFunctionCount()); 158 ASSERT_EQ(2305843009213693952U, PS.getMaxBlockCount()); 159 ASSERT_EQ(10U, PS.getNumBlocks()); 160 ASSERT_EQ(4539628424389557499U, PS.getTotalCount()); 161 std::vector<ProfileSummaryEntry> &Details = PS.getDetailedSummary(); 162 uint32_t Cutoff = 800000; 163 auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) { 164 return PE.Cutoff == Cutoff; 165 }; 166 auto EightyPerc = std::find_if(Details.begin(), Details.end(), Predicate); 167 Cutoff = 900000; 168 auto NinetyPerc = std::find_if(Details.begin(), Details.end(), Predicate); 169 Cutoff = 950000; 170 auto NinetyFivePerc = std::find_if(Details.begin(), Details.end(), Predicate); 171 Cutoff = 990000; 172 auto NinetyNinePerc = std::find_if(Details.begin(), Details.end(), Predicate); 173 ASSERT_EQ(576460752303423488U, EightyPerc->MinBlockCount); 174 ASSERT_EQ(288230376151711744U, NinetyPerc->MinBlockCount); 175 ASSERT_EQ(288230376151711744U, NinetyFivePerc->MinBlockCount); 176 ASSERT_EQ(72057594037927936U, NinetyNinePerc->MinBlockCount); 177 } 178 179 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) { 180 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 181 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 182 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 183 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 184 185 // 4 value sites. 186 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 187 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, 188 {(uint64_t) "callee2", 2}, 189 {(uint64_t) "callee3", 3}}; 190 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 191 // No value profile data at the second site. 192 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 193 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, 194 {(uint64_t) "callee2", 2}}; 195 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 196 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; 197 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 198 199 Writer.addRecord(std::move(Record1)); 200 Writer.addRecord(std::move(Record2)); 201 Writer.addRecord(std::move(Record3)); 202 Writer.addRecord(std::move(Record4)); 203 auto Profile = Writer.writeBuffer(); 204 readProfile(std::move(Profile)); 205 206 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 207 ASSERT_TRUE(NoError(R.getError())); 208 ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 209 ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 210 ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 211 ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 212 ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 213 214 uint64_t TotalC; 215 std::unique_ptr<InstrProfValueData[]> VD = 216 R.get().getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC); 217 218 ASSERT_EQ(3U, VD[0].Count); 219 ASSERT_EQ(2U, VD[1].Count); 220 ASSERT_EQ(1U, VD[2].Count); 221 ASSERT_EQ(6U, TotalC); 222 223 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 224 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 225 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 226 } 227 228 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) { 229 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 230 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 231 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 232 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 233 234 // 4 value sites. 235 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 236 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, 237 {(uint64_t) "callee2", 2}, 238 {(uint64_t) "callee3", 3}}; 239 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 240 // No value profile data at the second site. 241 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 242 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, 243 {(uint64_t) "callee2", 2}}; 244 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 245 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; 246 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 247 248 Writer.addRecord(std::move(Record1), 10); 249 Writer.addRecord(std::move(Record2)); 250 Writer.addRecord(std::move(Record3)); 251 Writer.addRecord(std::move(Record4)); 252 auto Profile = Writer.writeBuffer(); 253 readProfile(std::move(Profile)); 254 255 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 256 ASSERT_TRUE(NoError(R.getError())); 257 ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 258 ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 259 ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 260 ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 261 ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 262 263 uint64_t TotalC; 264 std::unique_ptr<InstrProfValueData[]> VD = 265 R.get().getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC); 266 ASSERT_EQ(30U, VD[0].Count); 267 ASSERT_EQ(20U, VD[1].Count); 268 ASSERT_EQ(10U, VD[2].Count); 269 ASSERT_EQ(60U, TotalC); 270 271 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 272 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 273 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 274 } 275 276 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) { 277 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 278 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 279 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 280 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 281 282 // 4 value sites. 283 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 284 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, 285 {(uint64_t) "callee2", 2}, 286 {(uint64_t) "callee3", 3}}; 287 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 288 // No value profile data at the second site. 289 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 290 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, 291 {(uint64_t) "callee2", 2}}; 292 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 293 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; 294 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 295 296 Writer.addRecord(std::move(Record1)); 297 Writer.addRecord(std::move(Record2)); 298 Writer.addRecord(std::move(Record3)); 299 Writer.addRecord(std::move(Record4)); 300 301 // Set big endian output. 302 Writer.setValueProfDataEndianness(support::big); 303 304 auto Profile = Writer.writeBuffer(); 305 readProfile(std::move(Profile)); 306 307 // Set big endian input. 308 Reader->setValueProfDataEndianness(support::big); 309 310 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 311 ASSERT_TRUE(NoError(R.getError())); 312 ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 313 ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 314 ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 315 ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 316 ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 317 318 std::unique_ptr<InstrProfValueData[]> VD = 319 R.get().getValueForSite(IPVK_IndirectCallTarget, 0); 320 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 321 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 322 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 323 324 // Restore little endian default: 325 Writer.setValueProfDataEndianness(support::little); 326 } 327 328 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) { 329 static const char caller[] = "caller"; 330 static const char callee1[] = "callee1"; 331 static const char callee2[] = "callee2"; 332 static const char callee3[] = "callee3"; 333 static const char callee4[] = "callee4"; 334 335 InstrProfRecord Record11(caller, 0x1234, {1, 2}); 336 InstrProfRecord Record12(caller, 0x1234, {1, 2}); 337 InstrProfRecord Record2(callee1, 0x1235, {3, 4}); 338 InstrProfRecord Record3(callee2, 0x1235, {3, 4}); 339 InstrProfRecord Record4(callee3, 0x1235, {3, 4}); 340 InstrProfRecord Record5(callee3, 0x1235, {3, 4}); 341 InstrProfRecord Record6(callee4, 0x1235, {3, 5}); 342 343 // 5 value sites. 344 Record11.reserveSites(IPVK_IndirectCallTarget, 5); 345 InstrProfValueData VD0[] = {{uint64_t(callee1), 1}, 346 {uint64_t(callee2), 2}, 347 {uint64_t(callee3), 3}, 348 {uint64_t(callee4), 4}}; 349 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr); 350 351 // No value profile data at the second site. 352 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 353 354 InstrProfValueData VD2[] = { 355 {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; 356 Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); 357 358 InstrProfValueData VD3[] = {{uint64_t(callee1), 1}}; 359 Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 360 361 InstrProfValueData VD4[] = {{uint64_t(callee1), 1}, 362 {uint64_t(callee2), 2}, 363 {uint64_t(callee3), 3}}; 364 Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr); 365 366 // A differnt record for the same caller. 367 Record12.reserveSites(IPVK_IndirectCallTarget, 5); 368 InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}}; 369 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr); 370 371 // No value profile data at the second site. 372 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 373 374 InstrProfValueData VD22[] = { 375 {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}}; 376 Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr); 377 378 Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr); 379 380 InstrProfValueData VD42[] = {{uint64_t(callee1), 1}, 381 {uint64_t(callee2), 2}, 382 {uint64_t(callee3), 3}}; 383 Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr); 384 385 Writer.addRecord(std::move(Record11)); 386 // Merge profile data. 387 Writer.addRecord(std::move(Record12)); 388 389 Writer.addRecord(std::move(Record2)); 390 Writer.addRecord(std::move(Record3)); 391 Writer.addRecord(std::move(Record4)); 392 Writer.addRecord(std::move(Record5)); 393 Writer.addRecord(std::move(Record6)); 394 auto Profile = Writer.writeBuffer(); 395 readProfile(std::move(Profile)); 396 397 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 398 ASSERT_TRUE(NoError(R.getError())); 399 ASSERT_EQ(5U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 400 ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 401 ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 402 ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 403 ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 404 ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); 405 406 std::unique_ptr<InstrProfValueData[]> VD = 407 R.get().getValueForSite(IPVK_IndirectCallTarget, 0); 408 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2")); 409 ASSERT_EQ(7U, VD[0].Count); 410 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3")); 411 ASSERT_EQ(6U, VD[1].Count); 412 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4")); 413 ASSERT_EQ(4U, VD[2].Count); 414 ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1")); 415 ASSERT_EQ(1U, VD[3].Count); 416 417 std::unique_ptr<InstrProfValueData[]> VD_2( 418 R.get().getValueForSite(IPVK_IndirectCallTarget, 2)); 419 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3")); 420 ASSERT_EQ(6U, VD_2[0].Count); 421 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4")); 422 ASSERT_EQ(4U, VD_2[1].Count); 423 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2")); 424 ASSERT_EQ(3U, VD_2[2].Count); 425 ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1")); 426 ASSERT_EQ(1U, VD_2[3].Count); 427 428 std::unique_ptr<InstrProfValueData[]> VD_3( 429 R.get().getValueForSite(IPVK_IndirectCallTarget, 3)); 430 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1")); 431 ASSERT_EQ(1U, VD_3[0].Count); 432 433 std::unique_ptr<InstrProfValueData[]> VD_4( 434 R.get().getValueForSite(IPVK_IndirectCallTarget, 4)); 435 ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3")); 436 ASSERT_EQ(6U, VD_4[0].Count); 437 ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2")); 438 ASSERT_EQ(4U, VD_4[1].Count); 439 ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1")); 440 ASSERT_EQ(2U, VD_4[2].Count); 441 } 442 443 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1_saturation) { 444 static const char bar[] = "bar"; 445 446 const uint64_t Max = std::numeric_limits<uint64_t>::max(); 447 448 InstrProfRecord Record1("foo", 0x1234, {1}); 449 auto Result1 = Writer.addRecord(std::move(Record1)); 450 ASSERT_EQ(Result1, instrprof_error::success); 451 452 // Verify counter overflow. 453 InstrProfRecord Record2("foo", 0x1234, {Max}); 454 auto Result2 = Writer.addRecord(std::move(Record2)); 455 ASSERT_EQ(Result2, instrprof_error::counter_overflow); 456 457 InstrProfRecord Record3(bar, 0x9012, {8}); 458 auto Result3 = Writer.addRecord(std::move(Record3)); 459 ASSERT_EQ(Result3, instrprof_error::success); 460 461 InstrProfRecord Record4("baz", 0x5678, {3, 4}); 462 Record4.reserveSites(IPVK_IndirectCallTarget, 1); 463 InstrProfValueData VD4[] = {{uint64_t(bar), 1}}; 464 Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr); 465 auto Result4 = Writer.addRecord(std::move(Record4)); 466 ASSERT_EQ(Result4, instrprof_error::success); 467 468 // Verify value data counter overflow. 469 InstrProfRecord Record5("baz", 0x5678, {5, 6}); 470 Record5.reserveSites(IPVK_IndirectCallTarget, 1); 471 InstrProfValueData VD5[] = {{uint64_t(bar), Max}}; 472 Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr); 473 auto Result5 = Writer.addRecord(std::move(Record5)); 474 ASSERT_EQ(Result5, instrprof_error::counter_overflow); 475 476 auto Profile = Writer.writeBuffer(); 477 readProfile(std::move(Profile)); 478 479 // Verify saturation of counts. 480 ErrorOr<InstrProfRecord> ReadRecord1 = 481 Reader->getInstrProfRecord("foo", 0x1234); 482 ASSERT_TRUE(NoError(ReadRecord1.getError())); 483 ASSERT_EQ(Max, ReadRecord1.get().Counts[0]); 484 485 ErrorOr<InstrProfRecord> ReadRecord2 = 486 Reader->getInstrProfRecord("baz", 0x5678); 487 ASSERT_EQ(1U, ReadRecord2.get().getNumValueSites(IPVK_IndirectCallTarget)); 488 std::unique_ptr<InstrProfValueData[]> VD = 489 ReadRecord2.get().getValueForSite(IPVK_IndirectCallTarget, 0); 490 ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3)); 491 ASSERT_EQ(Max, VD[0].Count); 492 } 493 494 // This test tests that when there are too many values 495 // for a given site, the merged results are properly 496 // truncated. 497 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge_site_trunc) { 498 static const char caller[] = "caller"; 499 500 InstrProfRecord Record11(caller, 0x1234, {1, 2}); 501 InstrProfRecord Record12(caller, 0x1234, {1, 2}); 502 503 // 2 value sites. 504 Record11.reserveSites(IPVK_IndirectCallTarget, 2); 505 InstrProfValueData VD0[255]; 506 for (int I = 0; I < 255; I++) { 507 VD0[I].Value = 2 * I; 508 VD0[I].Count = 2 * I + 1000; 509 } 510 511 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr); 512 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 513 514 Record12.reserveSites(IPVK_IndirectCallTarget, 2); 515 InstrProfValueData VD1[255]; 516 for (int I = 0; I < 255; I++) { 517 VD1[I].Value = 2 * I + 1; 518 VD1[I].Count = 2 * I + 1001; 519 } 520 521 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr); 522 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 523 524 Writer.addRecord(std::move(Record11)); 525 // Merge profile data. 526 Writer.addRecord(std::move(Record12)); 527 528 auto Profile = Writer.writeBuffer(); 529 readProfile(std::move(Profile)); 530 531 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 532 ASSERT_TRUE(NoError(R.getError())); 533 std::unique_ptr<InstrProfValueData[]> VD( 534 R.get().getValueForSite(IPVK_IndirectCallTarget, 0)); 535 ASSERT_EQ(2U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); 536 ASSERT_EQ(255U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 537 for (unsigned I = 0; I < 255; I++) { 538 ASSERT_EQ(VD[I].Value, 509 - I); 539 ASSERT_EQ(VD[I].Count, 1509 - I); 540 } 541 } 542 543 // Synthesize runtime value profile data. 544 ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]}, 545 {{uint64_t("callee2"), 1000}, &Site1Values[2]}, 546 {{uint64_t("callee3"), 500}, &Site1Values[3]}, 547 {{uint64_t("callee4"), 300}, &Site1Values[4]}, 548 {{uint64_t("callee5"), 100}, nullptr}}; 549 550 ValueProfNode Site2Values[4] = {{{uint64_t("callee5"), 800}, &Site2Values[1]}, 551 {{uint64_t("callee3"), 1000}, &Site2Values[2]}, 552 {{uint64_t("callee2"), 2500}, &Site2Values[3]}, 553 {{uint64_t("callee1"), 1300}, nullptr}}; 554 555 ValueProfNode Site3Values[3] = {{{uint64_t("callee6"), 800}, &Site3Values[1]}, 556 {{uint64_t("callee3"), 1000}, &Site3Values[2]}, 557 {{uint64_t("callee4"), 5500}, nullptr}}; 558 559 ValueProfNode Site4Values[2] = {{{uint64_t("callee2"), 1800}, &Site4Values[1]}, 560 {{uint64_t("callee3"), 2000}, nullptr}}; 561 562 static ValueProfNode *ValueProfNodes[5] = {&Site1Values[0], &Site2Values[0], 563 &Site3Values[0], &Site4Values[0], 564 nullptr}; 565 566 static uint16_t NumValueSites[IPVK_Last + 1] = {5}; 567 TEST_P(MaybeSparseInstrProfTest, runtime_value_prof_data_read_write) { 568 ValueProfRuntimeRecord RTRecord; 569 initializeValueProfRuntimeRecord(&RTRecord, &NumValueSites[0], 570 &ValueProfNodes[0]); 571 572 ValueProfData *VPData = serializeValueProfDataFromRT(&RTRecord, nullptr); 573 574 InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2}); 575 576 VPData->deserializeTo(Record, nullptr); 577 578 // Now read data from Record and sanity check the data 579 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget)); 580 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 581 ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 582 ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 583 ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 584 ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); 585 586 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { 587 return VD1.Count > VD2.Count; 588 }; 589 std::unique_ptr<InstrProfValueData[]> VD_0( 590 Record.getValueForSite(IPVK_IndirectCallTarget, 0)); 591 std::sort(&VD_0[0], &VD_0[5], Cmp); 592 ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2")); 593 ASSERT_EQ(1000U, VD_0[0].Count); 594 ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3")); 595 ASSERT_EQ(500U, VD_0[1].Count); 596 ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1")); 597 ASSERT_EQ(400U, VD_0[2].Count); 598 ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4")); 599 ASSERT_EQ(300U, VD_0[3].Count); 600 ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5")); 601 ASSERT_EQ(100U, VD_0[4].Count); 602 603 std::unique_ptr<InstrProfValueData[]> VD_1( 604 Record.getValueForSite(IPVK_IndirectCallTarget, 1)); 605 std::sort(&VD_1[0], &VD_1[4], Cmp); 606 ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2")); 607 ASSERT_EQ(2500U, VD_1[0].Count); 608 ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1")); 609 ASSERT_EQ(1300U, VD_1[1].Count); 610 ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3")); 611 ASSERT_EQ(1000U, VD_1[2].Count); 612 ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5")); 613 ASSERT_EQ(800U, VD_1[3].Count); 614 615 std::unique_ptr<InstrProfValueData[]> VD_2( 616 Record.getValueForSite(IPVK_IndirectCallTarget, 2)); 617 std::sort(&VD_2[0], &VD_2[3], Cmp); 618 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4")); 619 ASSERT_EQ(5500U, VD_2[0].Count); 620 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3")); 621 ASSERT_EQ(1000U, VD_2[1].Count); 622 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6")); 623 ASSERT_EQ(800U, VD_2[2].Count); 624 625 std::unique_ptr<InstrProfValueData[]> VD_3( 626 Record.getValueForSite(IPVK_IndirectCallTarget, 3)); 627 std::sort(&VD_3[0], &VD_3[2], Cmp); 628 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3")); 629 ASSERT_EQ(2000U, VD_3[0].Count); 630 ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2")); 631 ASSERT_EQ(1800U, VD_3[1].Count); 632 633 finalizeValueProfRuntimeRecord(&RTRecord); 634 free(VPData); 635 } 636 637 TEST_P(MaybeSparseInstrProfTest, get_max_function_count) { 638 InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2}); 639 InstrProfRecord Record2("bar", 0, {1ULL << 63}); 640 InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0}); 641 Writer.addRecord(std::move(Record1)); 642 Writer.addRecord(std::move(Record2)); 643 Writer.addRecord(std::move(Record3)); 644 auto Profile = Writer.writeBuffer(); 645 readProfile(std::move(Profile)); 646 647 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount()); 648 } 649 650 TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) { 651 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 652 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 653 Writer.addRecord(std::move(Record1), 3); 654 Writer.addRecord(std::move(Record2), 5); 655 auto Profile = Writer.writeBuffer(); 656 readProfile(std::move(Profile)); 657 658 std::vector<uint64_t> Counts; 659 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts))); 660 ASSERT_EQ(2U, Counts.size()); 661 ASSERT_EQ(3U, Counts[0]); 662 ASSERT_EQ(6U, Counts[1]); 663 664 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts))); 665 ASSERT_EQ(2U, Counts.size()); 666 ASSERT_EQ(15U, Counts[0]); 667 ASSERT_EQ(20U, Counts[1]); 668 } 669 670 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_test) { 671 std::vector<StringRef> FuncNames; 672 FuncNames.push_back("func1"); 673 FuncNames.push_back("func2"); 674 FuncNames.push_back("func3"); 675 FuncNames.push_back("bar1"); 676 FuncNames.push_back("bar2"); 677 FuncNames.push_back("bar3"); 678 InstrProfSymtab Symtab; 679 Symtab.create(FuncNames); 680 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); 681 ASSERT_EQ(StringRef("func1"), R); 682 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); 683 ASSERT_EQ(StringRef("func2"), R); 684 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); 685 ASSERT_EQ(StringRef("func3"), R); 686 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); 687 ASSERT_EQ(StringRef("bar1"), R); 688 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); 689 ASSERT_EQ(StringRef("bar2"), R); 690 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); 691 ASSERT_EQ(StringRef("bar3"), R); 692 693 // Now incrementally update the symtab 694 Symtab.addFuncName("blah_1"); 695 Symtab.addFuncName("blah_2"); 696 Symtab.addFuncName("blah_3"); 697 // Finalize it 698 Symtab.finalizeSymtab(); 699 700 // Check again 701 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1")); 702 ASSERT_EQ(StringRef("blah_1"), R); 703 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2")); 704 ASSERT_EQ(StringRef("blah_2"), R); 705 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3")); 706 ASSERT_EQ(StringRef("blah_3"), R); 707 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); 708 ASSERT_EQ(StringRef("func1"), R); 709 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); 710 ASSERT_EQ(StringRef("func2"), R); 711 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); 712 ASSERT_EQ(StringRef("func3"), R); 713 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); 714 ASSERT_EQ(StringRef("bar1"), R); 715 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); 716 ASSERT_EQ(StringRef("bar2"), R); 717 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); 718 ASSERT_EQ(StringRef("bar3"), R); 719 } 720 721 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_module_test) { 722 LLVMContext Ctx; 723 std::unique_ptr<Module> M = llvm::make_unique<Module>("MyModule.cpp", Ctx); 724 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), 725 /*isVarArg=*/false); 726 Function::Create(FTy, Function::ExternalLinkage, "Gfoo", M.get()); 727 Function::Create(FTy, Function::ExternalLinkage, "Gblah", M.get()); 728 Function::Create(FTy, Function::ExternalLinkage, "Gbar", M.get()); 729 Function::Create(FTy, Function::InternalLinkage, "Ifoo", M.get()); 730 Function::Create(FTy, Function::InternalLinkage, "Iblah", M.get()); 731 Function::Create(FTy, Function::InternalLinkage, "Ibar", M.get()); 732 Function::Create(FTy, Function::PrivateLinkage, "Pfoo", M.get()); 733 Function::Create(FTy, Function::PrivateLinkage, "Pblah", M.get()); 734 Function::Create(FTy, Function::PrivateLinkage, "Pbar", M.get()); 735 Function::Create(FTy, Function::WeakODRLinkage, "Wfoo", M.get()); 736 Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get()); 737 Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get()); 738 739 InstrProfSymtab ProfSymtab; 740 ProfSymtab.create(*(M.get())); 741 742 StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar", 743 "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"}; 744 745 for (unsigned I = 0; I < sizeof(Funcs) / sizeof(*Funcs); I++) { 746 Function *F = M->getFunction(Funcs[I]); 747 ASSERT_TRUE(F != nullptr); 748 std::string PGOName = getPGOFuncName(*F); 749 uint64_t Key = IndexedInstrProf::ComputeHash(PGOName); 750 ASSERT_EQ(StringRef(PGOName), 751 ProfSymtab.getFuncName(Key)); 752 ASSERT_EQ(StringRef(Funcs[I]), ProfSymtab.getOrigFuncName(Key)); 753 } 754 } 755 756 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_compression_test) { 757 std::vector<std::string> FuncNames1; 758 std::vector<std::string> FuncNames2; 759 for (int I = 0; I < 128; I++) { 760 std::string str; 761 raw_string_ostream OS(str); 762 OS << "func_" << I; 763 FuncNames1.push_back(OS.str()); 764 str.clear(); 765 OS << "fooooooooooooooo_" << I; 766 FuncNames1.push_back(OS.str()); 767 str.clear(); 768 OS << "BAR_" << I; 769 FuncNames2.push_back(OS.str()); 770 str.clear(); 771 OS << "BlahblahBlahblahBar_" << I; 772 FuncNames2.push_back(OS.str()); 773 } 774 775 for (bool DoCompression : {false, true}) { 776 // Compressing: 777 std::string FuncNameStrings1; 778 collectPGOFuncNameStrings( 779 FuncNames1, (DoCompression && zlib::isAvailable()), FuncNameStrings1); 780 781 // Compressing: 782 std::string FuncNameStrings2; 783 collectPGOFuncNameStrings( 784 FuncNames2, (DoCompression && zlib::isAvailable()), FuncNameStrings2); 785 786 for (int Padding = 0; Padding < 3; Padding++) { 787 // Join with paddings: 788 std::string FuncNameStrings = FuncNameStrings1; 789 for (int P = 0; P < Padding; P++) { 790 FuncNameStrings.push_back('\0'); 791 } 792 FuncNameStrings += FuncNameStrings2; 793 794 // Now decompress: 795 InstrProfSymtab Symtab; 796 Symtab.create(StringRef(FuncNameStrings)); 797 798 // Now do the checks: 799 // First sampling some data points: 800 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[0])); 801 ASSERT_EQ(StringRef("func_0"), R); 802 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[1])); 803 ASSERT_EQ(StringRef("fooooooooooooooo_0"), R); 804 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames2[100])); 805 ASSERT_EQ(StringRef("BAR_50"), R); 806 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames2[101])); 807 ASSERT_EQ(StringRef("BlahblahBlahblahBar_50"), R); 808 for (int I = 0; I < 128; I++) { 809 std::string N[4]; 810 N[0] = FuncNames1[2 * I]; 811 N[1] = FuncNames1[2 * I + 1]; 812 N[2] = FuncNames2[2 * I]; 813 N[3] = FuncNames2[2 * I + 1]; 814 for (int J = 0; J < 4; J++) { 815 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(N[J])); 816 ASSERT_EQ(StringRef(N[J]), R); 817 } 818 } 819 } 820 } 821 } 822 823 TEST_F(SparseInstrProfTest, preserve_no_records) { 824 InstrProfRecord Record1("foo", 0x1234, {0}); 825 InstrProfRecord Record2("bar", 0x4321, {0, 0}); 826 InstrProfRecord Record3("bar", 0x4321, {0, 0, 0}); 827 828 Writer.addRecord(std::move(Record1)); 829 Writer.addRecord(std::move(Record2)); 830 Writer.addRecord(std::move(Record3)); 831 auto Profile = Writer.writeBuffer(); 832 readProfile(std::move(Profile)); 833 834 auto I = Reader->begin(), E = Reader->end(); 835 ASSERT_TRUE(I == E); 836 } 837 838 INSTANTIATE_TEST_CASE_P(MaybeSparse, MaybeSparseInstrProfTest, 839 ::testing::Bool()); 840 841 } // end anonymous namespace 842