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