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