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, makeArrayRef(VD0Sorted).slice(2), 10, 334 IPVK_IndirectCallTarget, 5); 335 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5, 336 ValueData, N, T); 337 ASSERT_TRUE(Res); 338 ASSERT_EQ(4U, N); 339 ASSERT_EQ(10U, T); 340 ASSERT_EQ(3000U, ValueData[0].Value); 341 ASSERT_EQ(4U, ValueData[0].Count); 342 ASSERT_EQ(4000U, ValueData[1].Value); 343 ASSERT_EQ(3U, ValueData[1].Count); 344 ASSERT_EQ(5000U, ValueData[2].Value); 345 ASSERT_EQ(2U, ValueData[2].Count); 346 ASSERT_EQ(6000U, ValueData[3].Value); 347 ASSERT_EQ(1U, ValueData[3].Count); 348 } 349 350 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) { 351 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 352 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 353 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 354 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 355 356 // 4 value sites. 357 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 358 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, 359 {(uint64_t) "callee2", 2}, 360 {(uint64_t) "callee3", 3}}; 361 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 362 // No value profile data at the second site. 363 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 364 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, 365 {(uint64_t) "callee2", 2}}; 366 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 367 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; 368 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 369 370 Writer.addRecord(std::move(Record1), 10); 371 Writer.addRecord(std::move(Record2)); 372 Writer.addRecord(std::move(Record3)); 373 Writer.addRecord(std::move(Record4)); 374 auto Profile = Writer.writeBuffer(); 375 readProfile(std::move(Profile)); 376 377 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 378 ASSERT_TRUE(NoError(R.getError())); 379 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget)); 380 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 381 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 382 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 383 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 384 385 uint64_t TotalC; 386 std::unique_ptr<InstrProfValueData[]> VD = 387 R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC); 388 ASSERT_EQ(30U, VD[0].Count); 389 ASSERT_EQ(20U, VD[1].Count); 390 ASSERT_EQ(10U, VD[2].Count); 391 ASSERT_EQ(60U, TotalC); 392 393 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 394 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 395 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 396 } 397 398 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) { 399 InstrProfRecord Record1("caller", 0x1234, {1, 2}); 400 InstrProfRecord Record2("callee1", 0x1235, {3, 4}); 401 InstrProfRecord Record3("callee2", 0x1235, {3, 4}); 402 InstrProfRecord Record4("callee3", 0x1235, {3, 4}); 403 404 // 4 value sites. 405 Record1.reserveSites(IPVK_IndirectCallTarget, 4); 406 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1}, 407 {(uint64_t) "callee2", 2}, 408 {(uint64_t) "callee3", 3}}; 409 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); 410 // No value profile data at the second site. 411 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 412 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}, 413 {(uint64_t) "callee2", 2}}; 414 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); 415 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}}; 416 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 417 418 Writer.addRecord(std::move(Record1)); 419 Writer.addRecord(std::move(Record2)); 420 Writer.addRecord(std::move(Record3)); 421 Writer.addRecord(std::move(Record4)); 422 423 // Set big endian output. 424 Writer.setValueProfDataEndianness(support::big); 425 426 auto Profile = Writer.writeBuffer(); 427 readProfile(std::move(Profile)); 428 429 // Set big endian input. 430 Reader->setValueProfDataEndianness(support::big); 431 432 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 433 ASSERT_TRUE(NoError(R.getError())); 434 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget)); 435 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 436 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 437 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 438 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 439 440 std::unique_ptr<InstrProfValueData[]> VD = 441 R->getValueForSite(IPVK_IndirectCallTarget, 0); 442 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); 443 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); 444 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); 445 446 // Restore little endian default: 447 Writer.setValueProfDataEndianness(support::little); 448 } 449 450 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) { 451 static const char caller[] = "caller"; 452 static const char callee1[] = "callee1"; 453 static const char callee2[] = "callee2"; 454 static const char callee3[] = "callee3"; 455 static const char callee4[] = "callee4"; 456 457 InstrProfRecord Record11(caller, 0x1234, {1, 2}); 458 InstrProfRecord Record12(caller, 0x1234, {1, 2}); 459 InstrProfRecord Record2(callee1, 0x1235, {3, 4}); 460 InstrProfRecord Record3(callee2, 0x1235, {3, 4}); 461 InstrProfRecord Record4(callee3, 0x1235, {3, 4}); 462 InstrProfRecord Record5(callee3, 0x1235, {3, 4}); 463 InstrProfRecord Record6(callee4, 0x1235, {3, 5}); 464 465 // 5 value sites. 466 Record11.reserveSites(IPVK_IndirectCallTarget, 5); 467 InstrProfValueData VD0[] = {{uint64_t(callee1), 1}, 468 {uint64_t(callee2), 2}, 469 {uint64_t(callee3), 3}, 470 {uint64_t(callee4), 4}}; 471 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr); 472 473 // No value profile data at the second site. 474 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 475 476 InstrProfValueData VD2[] = { 477 {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; 478 Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); 479 480 InstrProfValueData VD3[] = {{uint64_t(callee1), 1}}; 481 Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); 482 483 InstrProfValueData VD4[] = {{uint64_t(callee1), 1}, 484 {uint64_t(callee2), 2}, 485 {uint64_t(callee3), 3}}; 486 Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr); 487 488 // A differnt record for the same caller. 489 Record12.reserveSites(IPVK_IndirectCallTarget, 5); 490 InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}}; 491 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr); 492 493 // No value profile data at the second site. 494 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 495 496 InstrProfValueData VD22[] = { 497 {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}}; 498 Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr); 499 500 Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr); 501 502 InstrProfValueData VD42[] = {{uint64_t(callee1), 1}, 503 {uint64_t(callee2), 2}, 504 {uint64_t(callee3), 3}}; 505 Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr); 506 507 Writer.addRecord(std::move(Record11)); 508 // Merge profile data. 509 Writer.addRecord(std::move(Record12)); 510 511 Writer.addRecord(std::move(Record2)); 512 Writer.addRecord(std::move(Record3)); 513 Writer.addRecord(std::move(Record4)); 514 Writer.addRecord(std::move(Record5)); 515 Writer.addRecord(std::move(Record6)); 516 auto Profile = Writer.writeBuffer(); 517 readProfile(std::move(Profile)); 518 519 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 520 ASSERT_TRUE(NoError(R.getError())); 521 ASSERT_EQ(5U, R->getNumValueSites(IPVK_IndirectCallTarget)); 522 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 523 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 524 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 525 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 526 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); 527 528 std::unique_ptr<InstrProfValueData[]> VD = 529 R->getValueForSite(IPVK_IndirectCallTarget, 0); 530 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2")); 531 ASSERT_EQ(7U, VD[0].Count); 532 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3")); 533 ASSERT_EQ(6U, VD[1].Count); 534 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4")); 535 ASSERT_EQ(4U, VD[2].Count); 536 ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1")); 537 ASSERT_EQ(1U, VD[3].Count); 538 539 std::unique_ptr<InstrProfValueData[]> VD_2( 540 R->getValueForSite(IPVK_IndirectCallTarget, 2)); 541 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3")); 542 ASSERT_EQ(6U, VD_2[0].Count); 543 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4")); 544 ASSERT_EQ(4U, VD_2[1].Count); 545 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2")); 546 ASSERT_EQ(3U, VD_2[2].Count); 547 ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1")); 548 ASSERT_EQ(1U, VD_2[3].Count); 549 550 std::unique_ptr<InstrProfValueData[]> VD_3( 551 R->getValueForSite(IPVK_IndirectCallTarget, 3)); 552 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1")); 553 ASSERT_EQ(1U, VD_3[0].Count); 554 555 std::unique_ptr<InstrProfValueData[]> VD_4( 556 R->getValueForSite(IPVK_IndirectCallTarget, 4)); 557 ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3")); 558 ASSERT_EQ(6U, VD_4[0].Count); 559 ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2")); 560 ASSERT_EQ(4U, VD_4[1].Count); 561 ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1")); 562 ASSERT_EQ(2U, VD_4[2].Count); 563 } 564 565 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1_saturation) { 566 static const char bar[] = "bar"; 567 568 const uint64_t Max = std::numeric_limits<uint64_t>::max(); 569 570 InstrProfRecord Record1("foo", 0x1234, {1}); 571 auto Result1 = Writer.addRecord(std::move(Record1)); 572 ASSERT_EQ(Result1, instrprof_error::success); 573 574 // Verify counter overflow. 575 InstrProfRecord Record2("foo", 0x1234, {Max}); 576 auto Result2 = Writer.addRecord(std::move(Record2)); 577 ASSERT_EQ(Result2, instrprof_error::counter_overflow); 578 579 InstrProfRecord Record3(bar, 0x9012, {8}); 580 auto Result3 = Writer.addRecord(std::move(Record3)); 581 ASSERT_EQ(Result3, instrprof_error::success); 582 583 InstrProfRecord Record4("baz", 0x5678, {3, 4}); 584 Record4.reserveSites(IPVK_IndirectCallTarget, 1); 585 InstrProfValueData VD4[] = {{uint64_t(bar), 1}}; 586 Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr); 587 auto Result4 = Writer.addRecord(std::move(Record4)); 588 ASSERT_EQ(Result4, instrprof_error::success); 589 590 // Verify value data counter overflow. 591 InstrProfRecord Record5("baz", 0x5678, {5, 6}); 592 Record5.reserveSites(IPVK_IndirectCallTarget, 1); 593 InstrProfValueData VD5[] = {{uint64_t(bar), Max}}; 594 Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr); 595 auto Result5 = Writer.addRecord(std::move(Record5)); 596 ASSERT_EQ(Result5, instrprof_error::counter_overflow); 597 598 auto Profile = Writer.writeBuffer(); 599 readProfile(std::move(Profile)); 600 601 // Verify saturation of counts. 602 ErrorOr<InstrProfRecord> ReadRecord1 = 603 Reader->getInstrProfRecord("foo", 0x1234); 604 ASSERT_TRUE(NoError(ReadRecord1.getError())); 605 ASSERT_EQ(Max, ReadRecord1->Counts[0]); 606 607 ErrorOr<InstrProfRecord> ReadRecord2 = 608 Reader->getInstrProfRecord("baz", 0x5678); 609 ASSERT_EQ(1U, ReadRecord2->getNumValueSites(IPVK_IndirectCallTarget)); 610 std::unique_ptr<InstrProfValueData[]> VD = 611 ReadRecord2->getValueForSite(IPVK_IndirectCallTarget, 0); 612 ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3)); 613 ASSERT_EQ(Max, VD[0].Count); 614 } 615 616 // This test tests that when there are too many values 617 // for a given site, the merged results are properly 618 // truncated. 619 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge_site_trunc) { 620 static const char caller[] = "caller"; 621 622 InstrProfRecord Record11(caller, 0x1234, {1, 2}); 623 InstrProfRecord Record12(caller, 0x1234, {1, 2}); 624 625 // 2 value sites. 626 Record11.reserveSites(IPVK_IndirectCallTarget, 2); 627 InstrProfValueData VD0[255]; 628 for (int I = 0; I < 255; I++) { 629 VD0[I].Value = 2 * I; 630 VD0[I].Count = 2 * I + 1000; 631 } 632 633 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr); 634 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 635 636 Record12.reserveSites(IPVK_IndirectCallTarget, 2); 637 InstrProfValueData VD1[255]; 638 for (int I = 0; I < 255; I++) { 639 VD1[I].Value = 2 * I + 1; 640 VD1[I].Count = 2 * I + 1001; 641 } 642 643 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr); 644 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); 645 646 Writer.addRecord(std::move(Record11)); 647 // Merge profile data. 648 Writer.addRecord(std::move(Record12)); 649 650 auto Profile = Writer.writeBuffer(); 651 readProfile(std::move(Profile)); 652 653 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); 654 ASSERT_TRUE(NoError(R.getError())); 655 std::unique_ptr<InstrProfValueData[]> VD( 656 R->getValueForSite(IPVK_IndirectCallTarget, 0)); 657 ASSERT_EQ(2U, R->getNumValueSites(IPVK_IndirectCallTarget)); 658 ASSERT_EQ(255U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 659 for (unsigned I = 0; I < 255; I++) { 660 ASSERT_EQ(VD[I].Value, 509 - I); 661 ASSERT_EQ(VD[I].Count, 1509 - I); 662 } 663 } 664 665 // Synthesize runtime value profile data. 666 ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]}, 667 {{uint64_t("callee2"), 1000}, &Site1Values[2]}, 668 {{uint64_t("callee3"), 500}, &Site1Values[3]}, 669 {{uint64_t("callee4"), 300}, &Site1Values[4]}, 670 {{uint64_t("callee5"), 100}, nullptr}}; 671 672 ValueProfNode Site2Values[4] = {{{uint64_t("callee5"), 800}, &Site2Values[1]}, 673 {{uint64_t("callee3"), 1000}, &Site2Values[2]}, 674 {{uint64_t("callee2"), 2500}, &Site2Values[3]}, 675 {{uint64_t("callee1"), 1300}, nullptr}}; 676 677 ValueProfNode Site3Values[3] = {{{uint64_t("callee6"), 800}, &Site3Values[1]}, 678 {{uint64_t("callee3"), 1000}, &Site3Values[2]}, 679 {{uint64_t("callee4"), 5500}, nullptr}}; 680 681 ValueProfNode Site4Values[2] = {{{uint64_t("callee2"), 1800}, &Site4Values[1]}, 682 {{uint64_t("callee3"), 2000}, nullptr}}; 683 684 static ValueProfNode *ValueProfNodes[5] = {&Site1Values[0], &Site2Values[0], 685 &Site3Values[0], &Site4Values[0], 686 nullptr}; 687 688 static uint16_t NumValueSites[IPVK_Last + 1] = {5}; 689 TEST_P(MaybeSparseInstrProfTest, runtime_value_prof_data_read_write) { 690 ValueProfRuntimeRecord RTRecord; 691 initializeValueProfRuntimeRecord(&RTRecord, &NumValueSites[0], 692 &ValueProfNodes[0]); 693 694 ValueProfData *VPData = serializeValueProfDataFromRT(&RTRecord, nullptr); 695 696 InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2}); 697 698 VPData->deserializeTo(Record, nullptr); 699 700 // Now read data from Record and sanity check the data 701 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget)); 702 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); 703 ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); 704 ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); 705 ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); 706 ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); 707 708 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { 709 return VD1.Count > VD2.Count; 710 }; 711 std::unique_ptr<InstrProfValueData[]> VD_0( 712 Record.getValueForSite(IPVK_IndirectCallTarget, 0)); 713 std::sort(&VD_0[0], &VD_0[5], Cmp); 714 ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2")); 715 ASSERT_EQ(1000U, VD_0[0].Count); 716 ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3")); 717 ASSERT_EQ(500U, VD_0[1].Count); 718 ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1")); 719 ASSERT_EQ(400U, VD_0[2].Count); 720 ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4")); 721 ASSERT_EQ(300U, VD_0[3].Count); 722 ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5")); 723 ASSERT_EQ(100U, VD_0[4].Count); 724 725 std::unique_ptr<InstrProfValueData[]> VD_1( 726 Record.getValueForSite(IPVK_IndirectCallTarget, 1)); 727 std::sort(&VD_1[0], &VD_1[4], Cmp); 728 ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2")); 729 ASSERT_EQ(2500U, VD_1[0].Count); 730 ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1")); 731 ASSERT_EQ(1300U, VD_1[1].Count); 732 ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3")); 733 ASSERT_EQ(1000U, VD_1[2].Count); 734 ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5")); 735 ASSERT_EQ(800U, VD_1[3].Count); 736 737 std::unique_ptr<InstrProfValueData[]> VD_2( 738 Record.getValueForSite(IPVK_IndirectCallTarget, 2)); 739 std::sort(&VD_2[0], &VD_2[3], Cmp); 740 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4")); 741 ASSERT_EQ(5500U, VD_2[0].Count); 742 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3")); 743 ASSERT_EQ(1000U, VD_2[1].Count); 744 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6")); 745 ASSERT_EQ(800U, VD_2[2].Count); 746 747 std::unique_ptr<InstrProfValueData[]> VD_3( 748 Record.getValueForSite(IPVK_IndirectCallTarget, 3)); 749 std::sort(&VD_3[0], &VD_3[2], Cmp); 750 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3")); 751 ASSERT_EQ(2000U, VD_3[0].Count); 752 ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2")); 753 ASSERT_EQ(1800U, VD_3[1].Count); 754 755 finalizeValueProfRuntimeRecord(&RTRecord); 756 free(VPData); 757 } 758 759 TEST_P(MaybeSparseInstrProfTest, get_max_function_count) { 760 InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2}); 761 InstrProfRecord Record2("bar", 0, {1ULL << 63}); 762 InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0}); 763 Writer.addRecord(std::move(Record1)); 764 Writer.addRecord(std::move(Record2)); 765 Writer.addRecord(std::move(Record3)); 766 auto Profile = Writer.writeBuffer(); 767 readProfile(std::move(Profile)); 768 769 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount()); 770 } 771 772 TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) { 773 InstrProfRecord Record1("foo", 0x1234, {1, 2}); 774 InstrProfRecord Record2("foo", 0x1235, {3, 4}); 775 Writer.addRecord(std::move(Record1), 3); 776 Writer.addRecord(std::move(Record2), 5); 777 auto Profile = Writer.writeBuffer(); 778 readProfile(std::move(Profile)); 779 780 std::vector<uint64_t> Counts; 781 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts))); 782 ASSERT_EQ(2U, Counts.size()); 783 ASSERT_EQ(3U, Counts[0]); 784 ASSERT_EQ(6U, Counts[1]); 785 786 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts))); 787 ASSERT_EQ(2U, Counts.size()); 788 ASSERT_EQ(15U, Counts[0]); 789 ASSERT_EQ(20U, Counts[1]); 790 } 791 792 // Testing symtab creator interface used by indexed profile reader. 793 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_test) { 794 std::vector<StringRef> FuncNames; 795 FuncNames.push_back("func1"); 796 FuncNames.push_back("func2"); 797 FuncNames.push_back("func3"); 798 FuncNames.push_back("bar1"); 799 FuncNames.push_back("bar2"); 800 FuncNames.push_back("bar3"); 801 InstrProfSymtab Symtab; 802 Symtab.create(FuncNames); 803 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); 804 ASSERT_EQ(StringRef("func1"), R); 805 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); 806 ASSERT_EQ(StringRef("func2"), R); 807 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); 808 ASSERT_EQ(StringRef("func3"), R); 809 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); 810 ASSERT_EQ(StringRef("bar1"), R); 811 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); 812 ASSERT_EQ(StringRef("bar2"), R); 813 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); 814 ASSERT_EQ(StringRef("bar3"), R); 815 816 // negative tests 817 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar4")); 818 ASSERT_EQ(StringRef(), R); 819 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("foo4")); 820 ASSERT_EQ(StringRef(), R); 821 822 // Now incrementally update the symtab 823 Symtab.addFuncName("blah_1"); 824 Symtab.addFuncName("blah_2"); 825 Symtab.addFuncName("blah_3"); 826 // Finalize it 827 Symtab.finalizeSymtab(); 828 829 // Check again 830 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1")); 831 ASSERT_EQ(StringRef("blah_1"), R); 832 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2")); 833 ASSERT_EQ(StringRef("blah_2"), R); 834 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3")); 835 ASSERT_EQ(StringRef("blah_3"), R); 836 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); 837 ASSERT_EQ(StringRef("func1"), R); 838 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); 839 ASSERT_EQ(StringRef("func2"), R); 840 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); 841 ASSERT_EQ(StringRef("func3"), R); 842 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); 843 ASSERT_EQ(StringRef("bar1"), R); 844 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); 845 ASSERT_EQ(StringRef("bar2"), R); 846 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); 847 ASSERT_EQ(StringRef("bar3"), R); 848 } 849 850 // Testing symtab creator interface used by value profile transformer. 851 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_module_test) { 852 LLVMContext Ctx; 853 std::unique_ptr<Module> M = llvm::make_unique<Module>("MyModule.cpp", Ctx); 854 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), 855 /*isVarArg=*/false); 856 Function::Create(FTy, Function::ExternalLinkage, "Gfoo", M.get()); 857 Function::Create(FTy, Function::ExternalLinkage, "Gblah", M.get()); 858 Function::Create(FTy, Function::ExternalLinkage, "Gbar", M.get()); 859 Function::Create(FTy, Function::InternalLinkage, "Ifoo", M.get()); 860 Function::Create(FTy, Function::InternalLinkage, "Iblah", M.get()); 861 Function::Create(FTy, Function::InternalLinkage, "Ibar", M.get()); 862 Function::Create(FTy, Function::PrivateLinkage, "Pfoo", M.get()); 863 Function::Create(FTy, Function::PrivateLinkage, "Pblah", M.get()); 864 Function::Create(FTy, Function::PrivateLinkage, "Pbar", M.get()); 865 Function::Create(FTy, Function::WeakODRLinkage, "Wfoo", M.get()); 866 Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get()); 867 Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get()); 868 869 InstrProfSymtab ProfSymtab; 870 ProfSymtab.create(*M); 871 872 StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar", 873 "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"}; 874 875 for (unsigned I = 0; I < sizeof(Funcs) / sizeof(*Funcs); I++) { 876 Function *F = M->getFunction(Funcs[I]); 877 ASSERT_TRUE(F != nullptr); 878 std::string PGOName = getPGOFuncName(*F); 879 uint64_t Key = IndexedInstrProf::ComputeHash(PGOName); 880 ASSERT_EQ(StringRef(PGOName), 881 ProfSymtab.getFuncName(Key)); 882 ASSERT_EQ(StringRef(Funcs[I]), ProfSymtab.getOrigFuncName(Key)); 883 } 884 } 885 886 // Testing symtab serialization and creator/deserialization interface 887 // used by coverage map reader, and raw profile reader. 888 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_compression_test) { 889 std::vector<std::string> FuncNames1; 890 std::vector<std::string> FuncNames2; 891 for (int I = 0; I < 3; I++) { 892 std::string str; 893 raw_string_ostream OS(str); 894 OS << "func_" << I; 895 FuncNames1.push_back(OS.str()); 896 str.clear(); 897 OS << "f oooooooooooooo_" << I; 898 FuncNames1.push_back(OS.str()); 899 str.clear(); 900 OS << "BAR_" << I; 901 FuncNames2.push_back(OS.str()); 902 str.clear(); 903 OS << "BlahblahBlahblahBar_" << I; 904 FuncNames2.push_back(OS.str()); 905 } 906 907 for (bool DoCompression : {false, true}) { 908 // Compressing: 909 std::string FuncNameStrings1; 910 collectPGOFuncNameStrings( 911 FuncNames1, (DoCompression && zlib::isAvailable()), FuncNameStrings1); 912 913 // Compressing: 914 std::string FuncNameStrings2; 915 collectPGOFuncNameStrings( 916 FuncNames2, (DoCompression && zlib::isAvailable()), FuncNameStrings2); 917 918 for (int Padding = 0; Padding < 2; Padding++) { 919 // Join with paddings : 920 std::string FuncNameStrings = FuncNameStrings1; 921 for (int P = 0; P < Padding; P++) { 922 FuncNameStrings.push_back('\0'); 923 } 924 FuncNameStrings += FuncNameStrings2; 925 926 // Now decompress: 927 InstrProfSymtab Symtab; 928 Symtab.create(StringRef(FuncNameStrings)); 929 930 // Now do the checks: 931 // First sampling some data points: 932 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[0])); 933 ASSERT_EQ(StringRef("func_0"), R); 934 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[1])); 935 ASSERT_EQ(StringRef("f oooooooooooooo_0"), R); 936 for (int I = 0; I < 3; I++) { 937 std::string N[4]; 938 N[0] = FuncNames1[2 * I]; 939 N[1] = FuncNames1[2 * I + 1]; 940 N[2] = FuncNames2[2 * I]; 941 N[3] = FuncNames2[2 * I + 1]; 942 for (int J = 0; J < 4; J++) { 943 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(N[J])); 944 ASSERT_EQ(StringRef(N[J]), R); 945 } 946 } 947 } 948 } 949 } 950 951 TEST_F(SparseInstrProfTest, preserve_no_records) { 952 InstrProfRecord Record1("foo", 0x1234, {0}); 953 InstrProfRecord Record2("bar", 0x4321, {0, 0}); 954 InstrProfRecord Record3("bar", 0x4321, {0, 0, 0}); 955 956 Writer.addRecord(std::move(Record1)); 957 Writer.addRecord(std::move(Record2)); 958 Writer.addRecord(std::move(Record3)); 959 auto Profile = Writer.writeBuffer(); 960 readProfile(std::move(Profile)); 961 962 auto I = Reader->begin(), E = Reader->end(); 963 ASSERT_TRUE(I == E); 964 } 965 966 INSTANTIATE_TEST_CASE_P(MaybeSparse, MaybeSparseInstrProfTest, 967 ::testing::Bool()); 968 969 } // end anonymous namespace 970