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