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