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