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