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