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/IRBuilder.h" 12 #include "llvm/IR/LLVMContext.h" 13 #include "llvm/IR/Module.h" 14 #include "llvm/ProfileData/InstrProfReader.h" 15 #include "llvm/ProfileData/InstrProfWriter.h" 16 #include "llvm/Support/Compression.h" 17 #include "gtest/gtest.h" 18 #include <cstdarg> 19 20 using namespace llvm; 21 22 static ::testing::AssertionResult NoError(Error E) { 23 if (!E) 24 return ::testing::AssertionSuccess(); 25 return ::testing::AssertionFailure() << "error: " << toString(std::move(E)) 26 << "\n"; 27 } 28 29 static ::testing::AssertionResult ErrorEquals(instrprof_error Expected, 30 Error E) { 31 instrprof_error Found; 32 std::string FoundMsg; 33 handleAllErrors(std::move(E), [&](const InstrProfError &IPE) { 34 Found = IPE.get(); 35 FoundMsg = IPE.message(); 36 }); 37 if (Expected == Found) 38 return ::testing::AssertionSuccess(); 39 return ::testing::AssertionFailure() << "error: " << FoundMsg << "\n"; 40 } 41 42 namespace { 43 44 struct InstrProfTest : ::testing::Test { 45 InstrProfWriter Writer; 46 std::unique_ptr<IndexedInstrProfReader> Reader; 47 48 void SetUp() { Writer.setOutputSparse(false); } 49 50 void readProfile(std::unique_ptr<MemoryBuffer> Profile) { 51 auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile)); 52 ASSERT_TRUE(NoError(ReaderOrErr.takeError())); 53 Reader = std::move(ReaderOrErr.get()); 54 } 55 }; 56 57 struct SparseInstrProfTest : public InstrProfTest { 58 void SetUp() { Writer.setOutputSparse(true); } 59 }; 60 61 struct MaybeSparseInstrProfTest : public InstrProfTest, 62 public ::testing::WithParamInterface<bool> { 63 void SetUp() { Writer.setOutputSparse(GetParam()); } 64 }; 65 66 TEST_P(MaybeSparseInstrProfTest, write_and_read_empty_profile) { 67 auto Profile = Writer.writeBuffer(); 68 readProfile(std::move(Profile)); 69 ASSERT_TRUE(Reader->begin() == Reader->end()); 70 } 71 72 TEST_P(MaybeSparseInstrProfTest, write_and_read_one_function) { 73 InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4}); 74 NoError(Writer.addRecord(std::move(Record))); 75 auto Profile = Writer.writeBuffer(); 76 readProfile(std::move(Profile)); 77 78 auto I = Reader->begin(), E = Reader->end(); 79 ASSERT_TRUE(I != E); 80 ASSERT_EQ(StringRef("foo"), I->Name); 81 ASSERT_EQ(0x1234U, I->Hash); 82 ASSERT_EQ(4U, I->Counts.size()); 83 ASSERT_EQ(1U, I->Counts[0]); 84 ASSERT_EQ(2U, I->Counts[1]); 85 ASSERT_EQ(3U, I->Counts[2]); 86 ASSERT_EQ(4U, I->Counts[3]); 87 ASSERT_TRUE(++I == E); 88 } 89 90 TEST_P(MaybeSparseInstrProfTest, get_instr_prof_record) { 91 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 92 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 93 NoError(Writer.addRecord(std::move(Record1))); 94 NoError(Writer.addRecord(std::move(Record2))); 95 auto Profile = Writer.writeBuffer(); 96 readProfile(std::move(Profile)); 97 98 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234); 99 ASSERT_TRUE(NoError(R.takeError())); 100 ASSERT_EQ(2U, R->Counts.size()); 101 ASSERT_EQ(1U, R->Counts[0]); 102 ASSERT_EQ(2U, R->Counts[1]); 103 104 R = Reader->getInstrProfRecord("foo", 0x1235); 105 ASSERT_TRUE(NoError(R.takeError())); 106 ASSERT_EQ(2U, R->Counts.size()); 107 ASSERT_EQ(3U, R->Counts[0]); 108 ASSERT_EQ(4U, R->Counts[1]); 109 110 R = Reader->getInstrProfRecord("foo", 0x5678); 111 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.takeError())); 112 113 R = Reader->getInstrProfRecord("bar", 0x1234); 114 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.takeError())); 115 } 116 117 TEST_P(MaybeSparseInstrProfTest, get_function_counts) { 118 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 119 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 120 NoError(Writer.addRecord(std::move(Record1))); 121 NoError(Writer.addRecord(std::move(Record2))); 122 auto Profile = Writer.writeBuffer(); 123 readProfile(std::move(Profile)); 124 125 std::vector<uint64_t> Counts; 126 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts))); 127 ASSERT_EQ(2U, Counts.size()); 128 ASSERT_EQ(1U, Counts[0]); 129 ASSERT_EQ(2U, Counts[1]); 130 131 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts))); 132 ASSERT_EQ(2U, Counts.size()); 133 ASSERT_EQ(3U, Counts[0]); 134 ASSERT_EQ(4U, Counts[1]); 135 136 Error E1 = Reader->getFunctionCounts("foo", 0x5678, Counts); 137 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, std::move(E1))); 138 139 Error E2 = Reader->getFunctionCounts("bar", 0x1234, Counts); 140 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, std::move(E2))); 141 } 142 143 // Profile data is copied from general.proftext 144 TEST_F(InstrProfTest, get_profile_summary) { 145 InstrProfRecord Record1("func1", 0x1234, {97531}); 146 InstrProfRecord Record2("func2", 0x1234, {0, 0}); 147 InstrProfRecord Record3("func3", 0x1234, 148 {2305843009213693952, 1152921504606846976, 149 576460752303423488, 288230376151711744, 150 144115188075855872, 72057594037927936}); 151 InstrProfRecord Record4("func4", 0x1234, {0}); 152 NoError(Writer.addRecord(std::move(Record1))); 153 NoError(Writer.addRecord(std::move(Record2))); 154 NoError(Writer.addRecord(std::move(Record3))); 155 NoError(Writer.addRecord(std::move(Record4))); 156 auto Profile = Writer.writeBuffer(); 157 readProfile(std::move(Profile)); 158 159 auto VerifySummary = [](ProfileSummary &IPS) mutable { 160 ASSERT_EQ(ProfileSummary::PSK_Instr, IPS.getKind()); 161 ASSERT_EQ(2305843009213693952U, IPS.getMaxFunctionCount()); 162 ASSERT_EQ(2305843009213693952U, IPS.getMaxCount()); 163 ASSERT_EQ(10U, IPS.getNumCounts()); 164 ASSERT_EQ(4539628424389557499U, IPS.getTotalCount()); 165 std::vector<ProfileSummaryEntry> &Details = IPS.getDetailedSummary(); 166 uint32_t Cutoff = 800000; 167 auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) { 168 return PE.Cutoff == Cutoff; 169 }; 170 auto EightyPerc = std::find_if(Details.begin(), Details.end(), Predicate); 171 Cutoff = 900000; 172 auto NinetyPerc = std::find_if(Details.begin(), Details.end(), Predicate); 173 Cutoff = 950000; 174 auto NinetyFivePerc = 175 std::find_if(Details.begin(), Details.end(), Predicate); 176 Cutoff = 990000; 177 auto NinetyNinePerc = 178 std::find_if(Details.begin(), Details.end(), Predicate); 179 ASSERT_EQ(576460752303423488U, EightyPerc->MinCount); 180 ASSERT_EQ(288230376151711744U, NinetyPerc->MinCount); 181 ASSERT_EQ(288230376151711744U, NinetyFivePerc->MinCount); 182 ASSERT_EQ(72057594037927936U, NinetyNinePerc->MinCount); 183 }; 184 ProfileSummary &PS = Reader->getSummary(); 185 VerifySummary(PS); 186 187 // Test that conversion of summary to and from Metadata works. 188 LLVMContext Context; 189 Metadata *MD = PS.getMD(Context); 190 ASSERT_TRUE(MD); 191 ProfileSummary *PSFromMD = ProfileSummary::getFromMD(MD); 192 ASSERT_TRUE(PSFromMD); 193 VerifySummary(*PSFromMD); 194 delete PSFromMD; 195 196 // Test that summary can be attached to and read back from module. 197 Module M("my_module", Context); 198 M.setProfileSummary(MD); 199 MD = M.getProfileSummary(); 200 ASSERT_TRUE(MD); 201 PSFromMD = ProfileSummary::getFromMD(MD); 202 ASSERT_TRUE(PSFromMD); 203 VerifySummary(*PSFromMD); 204 delete PSFromMD; 205 } 206 207 TEST_F(InstrProfTest, test_writer_merge) { 208 InstrProfRecord Record1("func1", 0x1234, {42}); 209 NoError(Writer.addRecord(std::move(Record1))); 210 211 InstrProfWriter Writer2; 212 InstrProfRecord Record2("func2", 0x1234, {0, 0}); 213 NoError(Writer2.addRecord(std::move(Record2))); 214 215 NoError(Writer.mergeRecordsFromWriter(std::move(Writer2))); 216 217 auto Profile = Writer.writeBuffer(); 218 readProfile(std::move(Profile)); 219 220 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("func1", 0x1234); 221 ASSERT_TRUE(NoError(R.takeError())); 222 ASSERT_EQ(1U, R->Counts.size()); 223 ASSERT_EQ(42U, R->Counts[0]); 224 225 R = Reader->getInstrProfRecord("func2", 0x1234); 226 ASSERT_TRUE(NoError(R.takeError())); 227 ASSERT_EQ(2U, R->Counts.size()); 228 ASSERT_EQ(0U, R->Counts[0]); 229 ASSERT_EQ(0U, R->Counts[1]); 230 } 231 232 static const char callee1[] = "callee1"; 233 static const char callee2[] = "callee2"; 234 static const char callee3[] = "callee3"; 235 static const char callee4[] = "callee4"; 236 static const char callee5[] = "callee5"; 237 static const char callee6[] = "callee6"; 238 239 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) { 240 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 241 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 242 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 243 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 244 245 // 4 value sites. 246 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 247 InstrProfValueData VD0[] = { 248 {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}}; 249 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 250 // No value profile data at the second site. 251 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 252 InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}}; 253 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 254 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}}; 255 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 256 257 NoError(Writer.addRecord(std::move(Record1))); 258 NoError(Writer.addRecord(std::move(Record2))); 259 NoError(Writer.addRecord(std::move(Record3))); 260 NoError(Writer.addRecord(std::move(Record4))); 261 auto Profile = Writer.writeBuffer(); 262 readProfile(std::move(Profile)); 263 264 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 265 ASSERT_TRUE(NoError(R.takeError())); 266 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget)); 267 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 268 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 269 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 270 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 271 272 uint64_t TotalC; 273 std::unique_ptr<InstrProfValueData[]> VD = 274 R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC); 275 276 ASSERT_EQ(3U, VD[0].Count); 277 ASSERT_EQ(2U, VD[1].Count); 278 ASSERT_EQ(1U, VD[2].Count); 279 ASSERT_EQ(6U, TotalC); 280 281 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 282 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 283 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 284 } 285 286 TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) { 287 InstrProfRecord Record("caller", 0x1234, {1, 2}); 288 Record.reserveSites(IPVK_IndirectCallTarget, 1); 289 InstrProfValueData VD0[] = {{1000, 1}, {2000, 2}, {3000, 3}, {5000, 5}, 290 {4000, 4}, {6000, 6}}; 291 Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 6, nullptr); 292 NoError(Writer.addRecord(std::move(Record))); 293 auto Profile = Writer.writeBuffer(); 294 readProfile(std::move(Profile)); 295 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 296 ASSERT_TRUE(NoError(R.takeError())); 297 298 LLVMContext Ctx; 299 std::unique_ptr<Module> M(new Module("MyModule", Ctx)); 300 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), 301 /*isVarArg=*/false); 302 Function *F = 303 Function::Create(FTy, Function::ExternalLinkage, "caller", M.get()); 304 BasicBlock *BB = BasicBlock::Create(Ctx, "", F); 305 306 IRBuilder<> Builder(BB); 307 BasicBlock *TBB = BasicBlock::Create(Ctx, "", F); 308 BasicBlock *FBB = BasicBlock::Create(Ctx, "", F); 309 310 // Use branch instruction to annotate with value profile data for simplicity 311 Instruction *Inst = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB); 312 Instruction *Inst2 = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB); 313 annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0); 314 315 InstrProfValueData ValueData[5]; 316 uint32_t N; 317 uint64_t T; 318 bool Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5, 319 ValueData, N, T); 320 ASSERT_TRUE(Res); 321 ASSERT_EQ(3U, N); 322 ASSERT_EQ(21U, T); 323 // The result should be sorted already: 324 ASSERT_EQ(6000U, ValueData[0].Value); 325 ASSERT_EQ(6U, ValueData[0].Count); 326 ASSERT_EQ(5000U, ValueData[1].Value); 327 ASSERT_EQ(5U, ValueData[1].Count); 328 ASSERT_EQ(4000U, ValueData[2].Value); 329 ASSERT_EQ(4U, ValueData[2].Count); 330 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 1, ValueData, 331 N, T); 332 ASSERT_TRUE(Res); 333 ASSERT_EQ(1U, N); 334 ASSERT_EQ(21U, T); 335 336 Res = getValueProfDataFromInst(*Inst2, IPVK_IndirectCallTarget, 5, ValueData, 337 N, T); 338 ASSERT_FALSE(Res); 339 340 // Remove the MD_prof metadata 341 Inst->setMetadata(LLVMContext::MD_prof, 0); 342 // Annotate 5 records this time. 343 annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0, 5); 344 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5, 345 ValueData, N, T); 346 ASSERT_TRUE(Res); 347 ASSERT_EQ(5U, N); 348 ASSERT_EQ(21U, T); 349 ASSERT_EQ(6000U, ValueData[0].Value); 350 ASSERT_EQ(6U, ValueData[0].Count); 351 ASSERT_EQ(5000U, ValueData[1].Value); 352 ASSERT_EQ(5U, ValueData[1].Count); 353 ASSERT_EQ(4000U, ValueData[2].Value); 354 ASSERT_EQ(4U, ValueData[2].Count); 355 ASSERT_EQ(3000U, ValueData[3].Value); 356 ASSERT_EQ(3U, ValueData[3].Count); 357 ASSERT_EQ(2000U, ValueData[4].Value); 358 ASSERT_EQ(2U, ValueData[4].Count); 359 360 // Remove the MD_prof metadata 361 Inst->setMetadata(LLVMContext::MD_prof, 0); 362 // Annotate with 4 records. 363 InstrProfValueData VD0Sorted[] = {{1000, 6}, {2000, 5}, {3000, 4}, {4000, 3}, 364 {5000, 2}, {6000, 1}}; 365 annotateValueSite(*M, *Inst, makeArrayRef(VD0Sorted).slice(2), 10, 366 IPVK_IndirectCallTarget, 5); 367 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5, 368 ValueData, N, T); 369 ASSERT_TRUE(Res); 370 ASSERT_EQ(4U, N); 371 ASSERT_EQ(10U, T); 372 ASSERT_EQ(3000U, ValueData[0].Value); 373 ASSERT_EQ(4U, ValueData[0].Count); 374 ASSERT_EQ(4000U, ValueData[1].Value); 375 ASSERT_EQ(3U, ValueData[1].Count); 376 ASSERT_EQ(5000U, ValueData[2].Value); 377 ASSERT_EQ(2U, ValueData[2].Count); 378 ASSERT_EQ(6000U, ValueData[3].Value); 379 ASSERT_EQ(1U, ValueData[3].Count); 380 } 381 382 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) { 383 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 384 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 385 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 386 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 387 388 // 4 value sites. 389 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 390 InstrProfValueData VD0[] = { 391 {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}}; 392 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 393 // No value profile data at the second site. 394 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 395 InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}}; 396 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 397 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}}; 398 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 399 400 NoError(Writer.addRecord(std::move(Record1), 10)); 401 NoError(Writer.addRecord(std::move(Record2))); 402 NoError(Writer.addRecord(std::move(Record3))); 403 NoError(Writer.addRecord(std::move(Record4))); 404 auto Profile = Writer.writeBuffer(); 405 readProfile(std::move(Profile)); 406 407 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 408 ASSERT_TRUE(NoError(R.takeError())); 409 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget)); 410 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 411 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 412 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 413 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 414 415 uint64_t TotalC; 416 std::unique_ptr<InstrProfValueData[]> VD = 417 R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC); 418 ASSERT_EQ(30U, VD[0].Count); 419 ASSERT_EQ(20U, VD[1].Count); 420 ASSERT_EQ(10U, VD[2].Count); 421 ASSERT_EQ(60U, TotalC); 422 423 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 424 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 425 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 426 } 427 428 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) { 429 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 430 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 431 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 432 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 433 434 // 4 value sites. 435 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 436 InstrProfValueData VD0[] = { 437 {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}}; 438 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 439 // No value profile data at the second site. 440 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 441 InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}}; 442 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 443 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}}; 444 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 445 446 NoError(Writer.addRecord(std::move(Record1))); 447 NoError(Writer.addRecord(std::move(Record2))); 448 NoError(Writer.addRecord(std::move(Record3))); 449 NoError(Writer.addRecord(std::move(Record4))); 450 451 // Set big endian output. 452 Writer.setValueProfDataEndianness(support::big); 453 454 auto Profile = Writer.writeBuffer(); 455 readProfile(std::move(Profile)); 456 457 // Set big endian input. 458 Reader->setValueProfDataEndianness(support::big); 459 460 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 461 ASSERT_TRUE(NoError(R.takeError())); 462 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget)); 463 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 464 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 465 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 466 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 467 468 std::unique_ptr<InstrProfValueData[]> VD = 469 R->getValueForSite(IPVK_IndirectCallTarget, 0); 470 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 471 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 472 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 473 474 // Restore little endian default: 475 Writer.setValueProfDataEndianness(support::little); 476 } 477 478 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) { 479 static const char caller[] = "caller"; 480 InstrProfRecord Record11(caller, 0x1234, {1, 2}); 481 InstrProfRecord Record12(caller, 0x1234, {1, 2}); 482 InstrProfRecord Record2(callee1, 0x1235, {3, 4}); 483 InstrProfRecord Record3(callee2, 0x1235, {3, 4}); 484 InstrProfRecord Record4(callee3, 0x1235, {3, 4}); 485 InstrProfRecord Record5(callee3, 0x1235, {3, 4}); 486 InstrProfRecord Record6(callee4, 0x1235, {3, 5}); 487 488 // 5 value sites. 489 Record11.reserveSites(IPVK_IndirectCallTarget, 5); 490 InstrProfValueData VD0[] = {{uint64_t(callee1), 1}, 491 {uint64_t(callee2), 2}, 492 {uint64_t(callee3), 3}, 493 {uint64_t(callee4), 4}}; 494 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr); 495 496 // No value profile data at the second site. 497 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 498 499 InstrProfValueData VD2[] = { 500 {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; 501 Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); 502 503 InstrProfValueData VD3[] = {{uint64_t(callee1), 1}}; 504 Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 505 506 InstrProfValueData VD4[] = {{uint64_t(callee1), 1}, 507 {uint64_t(callee2), 2}, 508 {uint64_t(callee3), 3}}; 509 Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr); 510 511 // A different record for the same caller. 512 Record12.reserveSites(IPVK_IndirectCallTarget, 5); 513 InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}}; 514 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr); 515 516 // No value profile data at the second site. 517 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 518 519 InstrProfValueData VD22[] = { 520 {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}}; 521 Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr); 522 523 Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr); 524 525 InstrProfValueData VD42[] = {{uint64_t(callee1), 1}, 526 {uint64_t(callee2), 2}, 527 {uint64_t(callee3), 3}}; 528 Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr); 529 530 NoError(Writer.addRecord(std::move(Record11))); 531 // Merge profile data. 532 NoError(Writer.addRecord(std::move(Record12))); 533 534 NoError(Writer.addRecord(std::move(Record2))); 535 NoError(Writer.addRecord(std::move(Record3))); 536 NoError(Writer.addRecord(std::move(Record4))); 537 NoError(Writer.addRecord(std::move(Record5))); 538 NoError(Writer.addRecord(std::move(Record6))); 539 auto Profile = Writer.writeBuffer(); 540 readProfile(std::move(Profile)); 541 542 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 543 ASSERT_TRUE(NoError(R.takeError())); 544 ASSERT_EQ(5U, R->getNumValueSites(IPVK_IndirectCallTarget)); 545 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 546 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 547 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 548 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 549 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); 550 551 std::unique_ptr<InstrProfValueData[]> VD = 552 R->getValueForSite(IPVK_IndirectCallTarget, 0); 553 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2")); 554 ASSERT_EQ(7U, VD[0].Count); 555 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3")); 556 ASSERT_EQ(6U, VD[1].Count); 557 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4")); 558 ASSERT_EQ(4U, VD[2].Count); 559 ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1")); 560 ASSERT_EQ(1U, VD[3].Count); 561 562 std::unique_ptr<InstrProfValueData[]> VD_2( 563 R->getValueForSite(IPVK_IndirectCallTarget, 2)); 564 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3")); 565 ASSERT_EQ(6U, VD_2[0].Count); 566 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4")); 567 ASSERT_EQ(4U, VD_2[1].Count); 568 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2")); 569 ASSERT_EQ(3U, VD_2[2].Count); 570 ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1")); 571 ASSERT_EQ(1U, VD_2[3].Count); 572 573 std::unique_ptr<InstrProfValueData[]> VD_3( 574 R->getValueForSite(IPVK_IndirectCallTarget, 3)); 575 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1")); 576 ASSERT_EQ(1U, VD_3[0].Count); 577 578 std::unique_ptr<InstrProfValueData[]> VD_4( 579 R->getValueForSite(IPVK_IndirectCallTarget, 4)); 580 ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3")); 581 ASSERT_EQ(6U, VD_4[0].Count); 582 ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2")); 583 ASSERT_EQ(4U, VD_4[1].Count); 584 ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1")); 585 ASSERT_EQ(2U, VD_4[2].Count); 586 } 587 588 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1_saturation) { 589 static const char bar[] = "bar"; 590 591 const uint64_t Max = std::numeric_limits<uint64_t>::max(); 592 593 InstrProfRecord Record1("foo", 0x1234, {1}); 594 auto Result1 = Writer.addRecord(std::move(Record1)); 595 ASSERT_EQ(InstrProfError::take(std::move(Result1)), 596 instrprof_error::success); 597 598 // Verify counter overflow. 599 InstrProfRecord Record2("foo", 0x1234, {Max}); 600 auto Result2 = Writer.addRecord(std::move(Record2)); 601 ASSERT_EQ(InstrProfError::take(std::move(Result2)), 602 instrprof_error::counter_overflow); 603 604 InstrProfRecord Record3(bar, 0x9012, {8}); 605 auto Result3 = Writer.addRecord(std::move(Record3)); 606 ASSERT_EQ(InstrProfError::take(std::move(Result3)), 607 instrprof_error::success); 608 609 InstrProfRecord Record4("baz", 0x5678, {3, 4}); 610 Record4.reserveSites(IPVK_IndirectCallTarget, 1); 611 InstrProfValueData VD4[] = {{uint64_t(bar), 1}}; 612 Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr); 613 auto Result4 = Writer.addRecord(std::move(Record4)); 614 ASSERT_EQ(InstrProfError::take(std::move(Result4)), 615 instrprof_error::success); 616 617 // Verify value data counter overflow. 618 InstrProfRecord Record5("baz", 0x5678, {5, 6}); 619 Record5.reserveSites(IPVK_IndirectCallTarget, 1); 620 InstrProfValueData VD5[] = {{uint64_t(bar), Max}}; 621 Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr); 622 auto Result5 = Writer.addRecord(std::move(Record5)); 623 ASSERT_EQ(InstrProfError::take(std::move(Result5)), 624 instrprof_error::counter_overflow); 625 626 auto Profile = Writer.writeBuffer(); 627 readProfile(std::move(Profile)); 628 629 // Verify saturation of counts. 630 Expected<InstrProfRecord> ReadRecord1 = 631 Reader->getInstrProfRecord("foo", 0x1234); 632 ASSERT_TRUE(NoError(ReadRecord1.takeError())); 633 ASSERT_EQ(Max, ReadRecord1->Counts[0]); 634 635 Expected<InstrProfRecord> ReadRecord2 = 636 Reader->getInstrProfRecord("baz", 0x5678); 637 ASSERT_TRUE(bool(ReadRecord2)); 638 ASSERT_EQ(1U, ReadRecord2->getNumValueSites(IPVK_IndirectCallTarget)); 639 std::unique_ptr<InstrProfValueData[]> VD = 640 ReadRecord2->getValueForSite(IPVK_IndirectCallTarget, 0); 641 ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3)); 642 ASSERT_EQ(Max, VD[0].Count); 643 } 644 645 // This test tests that when there are too many values 646 // for a given site, the merged results are properly 647 // truncated. 648 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge_site_trunc) { 649 static const char caller[] = "caller"; 650 651 InstrProfRecord Record11(caller, 0x1234, {1, 2}); 652 InstrProfRecord Record12(caller, 0x1234, {1, 2}); 653 654 // 2 value sites. 655 Record11.reserveSites(IPVK_IndirectCallTarget, 2); 656 InstrProfValueData VD0[255]; 657 for (int I = 0; I < 255; I++) { 658 VD0[I].Value = 2 * I; 659 VD0[I].Count = 2 * I + 1000; 660 } 661 662 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr); 663 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 664 665 Record12.reserveSites(IPVK_IndirectCallTarget, 2); 666 InstrProfValueData VD1[255]; 667 for (int I = 0; I < 255; I++) { 668 VD1[I].Value = 2 * I + 1; 669 VD1[I].Count = 2 * I + 1001; 670 } 671 672 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr); 673 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 674 675 NoError(Writer.addRecord(std::move(Record11))); 676 // Merge profile data. 677 NoError(Writer.addRecord(std::move(Record12))); 678 679 auto Profile = Writer.writeBuffer(); 680 readProfile(std::move(Profile)); 681 682 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 683 ASSERT_TRUE(NoError(R.takeError())); 684 std::unique_ptr<InstrProfValueData[]> VD( 685 R->getValueForSite(IPVK_IndirectCallTarget, 0)); 686 ASSERT_EQ(2U, R->getNumValueSites(IPVK_IndirectCallTarget)); 687 ASSERT_EQ(255U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 688 for (unsigned I = 0; I < 255; I++) { 689 ASSERT_EQ(VD[I].Value, 509 - I); 690 ASSERT_EQ(VD[I].Count, 1509 - I); 691 } 692 } 693 694 static void addValueProfData(InstrProfRecord &Record) { 695 Record.reserveSites(IPVK_IndirectCallTarget, 5); 696 InstrProfValueData VD0[] = {{uint64_t(callee1), 400}, 697 {uint64_t(callee2), 1000}, 698 {uint64_t(callee3), 500}, 699 {uint64_t(callee4), 300}, 700 {uint64_t(callee5), 100}}; 701 Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 5, nullptr); 702 InstrProfValueData VD1[] = {{uint64_t(callee5), 800}, 703 {uint64_t(callee3), 1000}, 704 {uint64_t(callee2), 2500}, 705 {uint64_t(callee1), 1300}}; 706 Record.addValueData(IPVK_IndirectCallTarget, 1, VD1, 4, nullptr); 707 InstrProfValueData VD2[] = {{uint64_t(callee6), 800}, 708 {uint64_t(callee3), 1000}, 709 {uint64_t(callee4), 5500}}; 710 Record.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); 711 InstrProfValueData VD3[] = {{uint64_t(callee2), 1800}, 712 {uint64_t(callee3), 2000}}; 713 Record.addValueData(IPVK_IndirectCallTarget, 3, VD3, 2, nullptr); 714 Record.addValueData(IPVK_IndirectCallTarget, 4, nullptr, 0, nullptr); 715 } 716 717 TEST_P(MaybeSparseInstrProfTest, value_prof_data_read_write) { 718 InstrProfRecord SrcRecord("caller", 0x1234, {1ULL << 31, 2}); 719 addValueProfData(SrcRecord); 720 std::unique_ptr<ValueProfData> VPData = 721 ValueProfData::serializeFrom(SrcRecord); 722 723 InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2}); 724 VPData->deserializeTo(Record, nullptr); 725 726 // Now read data from Record and sanity check the data 727 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget)); 728 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 729 ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 730 ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 731 ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 732 ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); 733 734 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { 735 return VD1.Count > VD2.Count; 736 }; 737 std::unique_ptr<InstrProfValueData[]> VD_0( 738 Record.getValueForSite(IPVK_IndirectCallTarget, 0)); 739 std::sort(&VD_0[0], &VD_0[5], Cmp); 740 ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2")); 741 ASSERT_EQ(1000U, VD_0[0].Count); 742 ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3")); 743 ASSERT_EQ(500U, VD_0[1].Count); 744 ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1")); 745 ASSERT_EQ(400U, VD_0[2].Count); 746 ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4")); 747 ASSERT_EQ(300U, VD_0[3].Count); 748 ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5")); 749 ASSERT_EQ(100U, VD_0[4].Count); 750 751 std::unique_ptr<InstrProfValueData[]> VD_1( 752 Record.getValueForSite(IPVK_IndirectCallTarget, 1)); 753 std::sort(&VD_1[0], &VD_1[4], Cmp); 754 ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2")); 755 ASSERT_EQ(2500U, VD_1[0].Count); 756 ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1")); 757 ASSERT_EQ(1300U, VD_1[1].Count); 758 ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3")); 759 ASSERT_EQ(1000U, VD_1[2].Count); 760 ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5")); 761 ASSERT_EQ(800U, VD_1[3].Count); 762 763 std::unique_ptr<InstrProfValueData[]> VD_2( 764 Record.getValueForSite(IPVK_IndirectCallTarget, 2)); 765 std::sort(&VD_2[0], &VD_2[3], Cmp); 766 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4")); 767 ASSERT_EQ(5500U, VD_2[0].Count); 768 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3")); 769 ASSERT_EQ(1000U, VD_2[1].Count); 770 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6")); 771 ASSERT_EQ(800U, VD_2[2].Count); 772 773 std::unique_ptr<InstrProfValueData[]> VD_3( 774 Record.getValueForSite(IPVK_IndirectCallTarget, 3)); 775 std::sort(&VD_3[0], &VD_3[2], Cmp); 776 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3")); 777 ASSERT_EQ(2000U, VD_3[0].Count); 778 ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2")); 779 ASSERT_EQ(1800U, VD_3[1].Count); 780 } 781 782 TEST_P(MaybeSparseInstrProfTest, value_prof_data_read_write_mapping) { 783 784 InstrProfRecord SrcRecord("caller", 0x1234, {1ULL << 31, 2}); 785 addValueProfData(SrcRecord); 786 std::unique_ptr<ValueProfData> VPData = 787 ValueProfData::serializeFrom(SrcRecord); 788 789 InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2}); 790 InstrProfSymtab Symtab; 791 Symtab.mapAddress(uint64_t(callee1), 0x1000ULL); 792 Symtab.mapAddress(uint64_t(callee2), 0x2000ULL); 793 Symtab.mapAddress(uint64_t(callee3), 0x3000ULL); 794 Symtab.mapAddress(uint64_t(callee4), 0x4000ULL); 795 // Missing mapping for callee5 796 Symtab.finalizeSymtab(); 797 798 VPData->deserializeTo(Record, &Symtab.getAddrHashMap()); 799 800 // Now read data from Record and sanity check the data 801 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget)); 802 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 803 804 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { 805 return VD1.Count > VD2.Count; 806 }; 807 std::unique_ptr<InstrProfValueData[]> VD_0( 808 Record.getValueForSite(IPVK_IndirectCallTarget, 0)); 809 std::sort(&VD_0[0], &VD_0[5], Cmp); 810 ASSERT_EQ(VD_0[0].Value, 0x2000ULL); 811 ASSERT_EQ(1000U, VD_0[0].Count); 812 ASSERT_EQ(VD_0[1].Value, 0x3000ULL); 813 ASSERT_EQ(500U, VD_0[1].Count); 814 ASSERT_EQ(VD_0[2].Value, 0x1000ULL); 815 ASSERT_EQ(400U, VD_0[2].Count); 816 817 // callee5 does not have a mapped value -- default to 0. 818 ASSERT_EQ(VD_0[4].Value, 0ULL); 819 } 820 821 TEST_P(MaybeSparseInstrProfTest, get_max_function_count) { 822 InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2}); 823 InstrProfRecord Record2("bar", 0, {1ULL << 63}); 824 InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0}); 825 NoError(Writer.addRecord(std::move(Record1))); 826 NoError(Writer.addRecord(std::move(Record2))); 827 NoError(Writer.addRecord(std::move(Record3))); 828 auto Profile = Writer.writeBuffer(); 829 readProfile(std::move(Profile)); 830 831 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount()); 832 } 833 834 TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) { 835 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 836 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 837 NoError(Writer.addRecord(std::move(Record1), 3)); 838 NoError(Writer.addRecord(std::move(Record2), 5)); 839 auto Profile = Writer.writeBuffer(); 840 readProfile(std::move(Profile)); 841 842 std::vector<uint64_t> Counts; 843 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts))); 844 ASSERT_EQ(2U, Counts.size()); 845 ASSERT_EQ(3U, Counts[0]); 846 ASSERT_EQ(6U, Counts[1]); 847 848 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts))); 849 ASSERT_EQ(2U, Counts.size()); 850 ASSERT_EQ(15U, Counts[0]); 851 ASSERT_EQ(20U, Counts[1]); 852 } 853 854 // Testing symtab creator interface used by indexed profile reader. 855 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_test) { 856 std::vector<StringRef> FuncNames; 857 FuncNames.push_back("func1"); 858 FuncNames.push_back("func2"); 859 FuncNames.push_back("func3"); 860 FuncNames.push_back("bar1"); 861 FuncNames.push_back("bar2"); 862 FuncNames.push_back("bar3"); 863 InstrProfSymtab Symtab; 864 Symtab.create(FuncNames); 865 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); 866 ASSERT_EQ(StringRef("func1"), R); 867 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); 868 ASSERT_EQ(StringRef("func2"), R); 869 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); 870 ASSERT_EQ(StringRef("func3"), R); 871 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); 872 ASSERT_EQ(StringRef("bar1"), R); 873 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); 874 ASSERT_EQ(StringRef("bar2"), R); 875 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); 876 ASSERT_EQ(StringRef("bar3"), R); 877 878 // negative tests 879 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar4")); 880 ASSERT_EQ(StringRef(), R); 881 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("foo4")); 882 ASSERT_EQ(StringRef(), R); 883 884 // Now incrementally update the symtab 885 Symtab.addFuncName("blah_1"); 886 Symtab.addFuncName("blah_2"); 887 Symtab.addFuncName("blah_3"); 888 // Finalize it 889 Symtab.finalizeSymtab(); 890 891 // Check again 892 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1")); 893 ASSERT_EQ(StringRef("blah_1"), R); 894 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2")); 895 ASSERT_EQ(StringRef("blah_2"), R); 896 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3")); 897 ASSERT_EQ(StringRef("blah_3"), R); 898 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); 899 ASSERT_EQ(StringRef("func1"), R); 900 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); 901 ASSERT_EQ(StringRef("func2"), R); 902 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); 903 ASSERT_EQ(StringRef("func3"), R); 904 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); 905 ASSERT_EQ(StringRef("bar1"), R); 906 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); 907 ASSERT_EQ(StringRef("bar2"), R); 908 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); 909 ASSERT_EQ(StringRef("bar3"), R); 910 } 911 912 // Testing symtab creator interface used by value profile transformer. 913 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_module_test) { 914 LLVMContext Ctx; 915 std::unique_ptr<Module> M = llvm::make_unique<Module>("MyModule.cpp", Ctx); 916 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), 917 /*isVarArg=*/false); 918 Function::Create(FTy, Function::ExternalLinkage, "Gfoo", M.get()); 919 Function::Create(FTy, Function::ExternalLinkage, "Gblah", M.get()); 920 Function::Create(FTy, Function::ExternalLinkage, "Gbar", M.get()); 921 Function::Create(FTy, Function::InternalLinkage, "Ifoo", M.get()); 922 Function::Create(FTy, Function::InternalLinkage, "Iblah", M.get()); 923 Function::Create(FTy, Function::InternalLinkage, "Ibar", M.get()); 924 Function::Create(FTy, Function::PrivateLinkage, "Pfoo", M.get()); 925 Function::Create(FTy, Function::PrivateLinkage, "Pblah", M.get()); 926 Function::Create(FTy, Function::PrivateLinkage, "Pbar", M.get()); 927 Function::Create(FTy, Function::WeakODRLinkage, "Wfoo", M.get()); 928 Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get()); 929 Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get()); 930 931 InstrProfSymtab ProfSymtab; 932 ProfSymtab.create(*M); 933 934 StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar", 935 "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"}; 936 937 for (unsigned I = 0; I < sizeof(Funcs) / sizeof(*Funcs); I++) { 938 Function *F = M->getFunction(Funcs[I]); 939 ASSERT_TRUE(F != nullptr); 940 std::string PGOName = getPGOFuncName(*F); 941 uint64_t Key = IndexedInstrProf::ComputeHash(PGOName); 942 ASSERT_EQ(StringRef(PGOName), 943 ProfSymtab.getFuncName(Key)); 944 ASSERT_EQ(StringRef(Funcs[I]), ProfSymtab.getOrigFuncName(Key)); 945 } 946 } 947 948 // Testing symtab serialization and creator/deserialization interface 949 // used by coverage map reader, and raw profile reader. 950 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_compression_test) { 951 std::vector<std::string> FuncNames1; 952 std::vector<std::string> FuncNames2; 953 for (int I = 0; I < 3; I++) { 954 std::string str; 955 raw_string_ostream OS(str); 956 OS << "func_" << I; 957 FuncNames1.push_back(OS.str()); 958 str.clear(); 959 OS << "f oooooooooooooo_" << I; 960 FuncNames1.push_back(OS.str()); 961 str.clear(); 962 OS << "BAR_" << I; 963 FuncNames2.push_back(OS.str()); 964 str.clear(); 965 OS << "BlahblahBlahblahBar_" << I; 966 FuncNames2.push_back(OS.str()); 967 } 968 969 for (bool DoCompression : {false, true}) { 970 // Compressing: 971 std::string FuncNameStrings1; 972 NoError(collectPGOFuncNameStrings( 973 FuncNames1, (DoCompression && zlib::isAvailable()), FuncNameStrings1)); 974 975 // Compressing: 976 std::string FuncNameStrings2; 977 NoError(collectPGOFuncNameStrings( 978 FuncNames2, (DoCompression && zlib::isAvailable()), FuncNameStrings2)); 979 980 for (int Padding = 0; Padding < 2; Padding++) { 981 // Join with paddings : 982 std::string FuncNameStrings = FuncNameStrings1; 983 for (int P = 0; P < Padding; P++) { 984 FuncNameStrings.push_back('\0'); 985 } 986 FuncNameStrings += FuncNameStrings2; 987 988 // Now decompress: 989 InstrProfSymtab Symtab; 990 NoError(Symtab.create(StringRef(FuncNameStrings))); 991 992 // Now do the checks: 993 // First sampling some data points: 994 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[0])); 995 ASSERT_EQ(StringRef("func_0"), R); 996 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[1])); 997 ASSERT_EQ(StringRef("f oooooooooooooo_0"), R); 998 for (int I = 0; I < 3; I++) { 999 std::string N[4]; 1000 N[0] = FuncNames1[2 * I]; 1001 N[1] = FuncNames1[2 * I + 1]; 1002 N[2] = FuncNames2[2 * I]; 1003 N[3] = FuncNames2[2 * I + 1]; 1004 for (int J = 0; J < 4; J++) { 1005 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(N[J])); 1006 ASSERT_EQ(StringRef(N[J]), R); 1007 } 1008 } 1009 } 1010 } 1011 } 1012 1013 TEST_F(SparseInstrProfTest, preserve_no_records) { 1014 InstrProfRecord Record1("foo", 0x1234, {0}); 1015 InstrProfRecord Record2("bar", 0x4321, {0, 0}); 1016 InstrProfRecord Record3("bar", 0x4321, {0, 0, 0}); 1017 1018 NoError(Writer.addRecord(std::move(Record1))); 1019 NoError(Writer.addRecord(std::move(Record2))); 1020 NoError(Writer.addRecord(std::move(Record3))); 1021 auto Profile = Writer.writeBuffer(); 1022 readProfile(std::move(Profile)); 1023 1024 auto I = Reader->begin(), E = Reader->end(); 1025 ASSERT_TRUE(I == E); 1026 } 1027 1028 INSTANTIATE_TEST_CASE_P(MaybeSparse, MaybeSparseInstrProfTest, 1029 ::testing::Bool()); 1030 1031 } // end anonymous namespace 1032