Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / unittests / ProfileData / InstrProfTest.cpp
blobf26f244afc5378ed0a327e204ef7c47ed7e85f4b
1 //===- unittest/ProfileData/InstrProfTest.cpp -------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/IR/Function.h"
10 #include "llvm/IR/IRBuilder.h"
11 #include "llvm/IR/LLVMContext.h"
12 #include "llvm/IR/Module.h"
13 #include "llvm/ProfileData/InstrProfReader.h"
14 #include "llvm/ProfileData/InstrProfWriter.h"
15 #include "llvm/ProfileData/MemProf.h"
16 #include "llvm/ProfileData/MemProfData.inc"
17 #include "llvm/Support/Compression.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/Testing/Support/Error.h"
20 #include "gtest/gtest.h"
21 #include <cstdarg>
23 using namespace llvm;
24 using ::testing::EndsWith;
25 using ::testing::IsSubsetOf;
26 using ::testing::SizeIs;
27 using ::testing::UnorderedElementsAre;
29 [[nodiscard]] static ::testing::AssertionResult
30 ErrorEquals(instrprof_error Expected, Error E) {
31 instrprof_error Found;
32 std::string FoundMsg;
33 handleAllErrors(std::move(E), [&](const InstrProfError &IPE) {
34 Found = IPE.get();
35 FoundMsg = IPE.message();
36 });
37 if (Expected == Found)
38 return ::testing::AssertionSuccess();
39 return ::testing::AssertionFailure() << "error: " << FoundMsg << "\n";
42 namespace llvm {
43 bool operator==(const TemporalProfTraceTy &lhs,
44 const TemporalProfTraceTy &rhs) {
45 return lhs.Weight == rhs.Weight &&
46 lhs.FunctionNameRefs == rhs.FunctionNameRefs;
48 } // end namespace llvm
50 namespace {
52 struct InstrProfTest : ::testing::Test {
53 InstrProfWriter Writer;
54 std::unique_ptr<IndexedInstrProfReader> Reader;
56 void SetUp() override { Writer.setOutputSparse(false); }
58 void readProfile(std::unique_ptr<MemoryBuffer> Profile,
59 std::unique_ptr<MemoryBuffer> Remapping = nullptr) {
60 auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile),
61 std::move(Remapping));
62 EXPECT_THAT_ERROR(ReaderOrErr.takeError(), Succeeded());
63 Reader = std::move(ReaderOrErr.get());
67 struct SparseInstrProfTest : public InstrProfTest {
68 void SetUp() override { Writer.setOutputSparse(true); }
71 struct MaybeSparseInstrProfTest : public InstrProfTest,
72 public ::testing::WithParamInterface<bool> {
73 void SetUp() override { Writer.setOutputSparse(GetParam()); }
76 TEST_P(MaybeSparseInstrProfTest, write_and_read_empty_profile) {
77 auto Profile = Writer.writeBuffer();
78 readProfile(std::move(Profile));
79 ASSERT_TRUE(Reader->begin() == Reader->end());
82 static const auto Err = [](Error E) {
83 consumeError(std::move(E));
84 FAIL();
87 TEST_P(MaybeSparseInstrProfTest, write_and_read_one_function) {
88 Writer.addRecord({"foo", 0x1234, {1, 2, 3, 4}}, Err);
89 auto Profile = Writer.writeBuffer();
90 readProfile(std::move(Profile));
92 auto I = Reader->begin(), E = Reader->end();
93 ASSERT_TRUE(I != E);
94 ASSERT_EQ(StringRef("foo"), I->Name);
95 ASSERT_EQ(0x1234U, I->Hash);
96 ASSERT_EQ(4U, I->Counts.size());
97 ASSERT_EQ(1U, I->Counts[0]);
98 ASSERT_EQ(2U, I->Counts[1]);
99 ASSERT_EQ(3U, I->Counts[2]);
100 ASSERT_EQ(4U, I->Counts[3]);
101 ASSERT_TRUE(++I == E);
104 TEST_P(MaybeSparseInstrProfTest, get_instr_prof_record) {
105 Writer.addRecord({"foo", 0x1234, {1, 2}}, Err);
106 Writer.addRecord({"foo", 0x1235, {3, 4}}, Err);
107 auto Profile = Writer.writeBuffer();
108 readProfile(std::move(Profile));
110 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234);
111 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
112 ASSERT_EQ(2U, R->Counts.size());
113 ASSERT_EQ(1U, R->Counts[0]);
114 ASSERT_EQ(2U, R->Counts[1]);
116 R = Reader->getInstrProfRecord("foo", 0x1235);
117 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
118 ASSERT_EQ(2U, R->Counts.size());
119 ASSERT_EQ(3U, R->Counts[0]);
120 ASSERT_EQ(4U, R->Counts[1]);
122 R = Reader->getInstrProfRecord("foo", 0x5678);
123 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.takeError()));
125 R = Reader->getInstrProfRecord("bar", 0x1234);
126 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.takeError()));
129 TEST_P(MaybeSparseInstrProfTest, get_function_counts) {
130 Writer.addRecord({"foo", 0x1234, {1, 2}}, Err);
131 Writer.addRecord({"foo", 0x1235, {3, 4}}, Err);
132 auto Profile = Writer.writeBuffer();
133 readProfile(std::move(Profile));
135 std::vector<uint64_t> Counts;
136 EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1234, Counts),
137 Succeeded());
138 ASSERT_EQ(2U, Counts.size());
139 ASSERT_EQ(1U, Counts[0]);
140 ASSERT_EQ(2U, Counts[1]);
142 EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1235, Counts),
143 Succeeded());
144 ASSERT_EQ(2U, Counts.size());
145 ASSERT_EQ(3U, Counts[0]);
146 ASSERT_EQ(4U, Counts[1]);
148 Error E1 = Reader->getFunctionCounts("foo", 0x5678, Counts);
149 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, std::move(E1)));
151 Error E2 = Reader->getFunctionCounts("bar", 0x1234, Counts);
152 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, std::move(E2)));
155 // Profile data is copied from general.proftext
156 TEST_F(InstrProfTest, get_profile_summary) {
157 Writer.addRecord({"func1", 0x1234, {97531}}, Err);
158 Writer.addRecord({"func2", 0x1234, {0, 0}}, Err);
159 Writer.addRecord(
160 {"func3",
161 0x1234,
162 {2305843009213693952, 1152921504606846976, 576460752303423488,
163 288230376151711744, 144115188075855872, 72057594037927936}},
164 Err);
165 Writer.addRecord({"func4", 0x1234, {0}}, Err);
166 auto Profile = Writer.writeBuffer();
167 readProfile(std::move(Profile));
169 auto VerifySummary = [](ProfileSummary &IPS) mutable {
170 ASSERT_EQ(ProfileSummary::PSK_Instr, IPS.getKind());
171 ASSERT_EQ(2305843009213693952U, IPS.getMaxFunctionCount());
172 ASSERT_EQ(2305843009213693952U, IPS.getMaxCount());
173 ASSERT_EQ(10U, IPS.getNumCounts());
174 ASSERT_EQ(4539628424389557499U, IPS.getTotalCount());
175 const std::vector<ProfileSummaryEntry> &Details = IPS.getDetailedSummary();
176 uint32_t Cutoff = 800000;
177 auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) {
178 return PE.Cutoff == Cutoff;
180 auto EightyPerc = find_if(Details, Predicate);
181 Cutoff = 900000;
182 auto NinetyPerc = find_if(Details, Predicate);
183 Cutoff = 950000;
184 auto NinetyFivePerc = find_if(Details, Predicate);
185 Cutoff = 990000;
186 auto NinetyNinePerc = find_if(Details, Predicate);
187 ASSERT_EQ(576460752303423488U, EightyPerc->MinCount);
188 ASSERT_EQ(288230376151711744U, NinetyPerc->MinCount);
189 ASSERT_EQ(288230376151711744U, NinetyFivePerc->MinCount);
190 ASSERT_EQ(72057594037927936U, NinetyNinePerc->MinCount);
192 ProfileSummary &PS = Reader->getSummary(/* IsCS */ false);
193 VerifySummary(PS);
195 // Test that conversion of summary to and from Metadata works.
196 LLVMContext Context;
197 Metadata *MD = PS.getMD(Context);
198 ASSERT_TRUE(MD);
199 ProfileSummary *PSFromMD = ProfileSummary::getFromMD(MD);
200 ASSERT_TRUE(PSFromMD);
201 VerifySummary(*PSFromMD);
202 delete PSFromMD;
204 // Test that summary can be attached to and read back from module.
205 Module M("my_module", Context);
206 M.setProfileSummary(MD, ProfileSummary::PSK_Instr);
207 MD = M.getProfileSummary(/* IsCS */ false);
208 ASSERT_TRUE(MD);
209 PSFromMD = ProfileSummary::getFromMD(MD);
210 ASSERT_TRUE(PSFromMD);
211 VerifySummary(*PSFromMD);
212 delete PSFromMD;
215 TEST_F(InstrProfTest, test_writer_merge) {
216 Writer.addRecord({"func1", 0x1234, {42}}, Err);
218 InstrProfWriter Writer2;
219 Writer2.addRecord({"func2", 0x1234, {0, 0}}, Err);
221 Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
223 auto Profile = Writer.writeBuffer();
224 readProfile(std::move(Profile));
226 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("func1", 0x1234);
227 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
228 ASSERT_EQ(1U, R->Counts.size());
229 ASSERT_EQ(42U, R->Counts[0]);
231 R = Reader->getInstrProfRecord("func2", 0x1234);
232 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
233 ASSERT_EQ(2U, R->Counts.size());
234 ASSERT_EQ(0U, R->Counts[0]);
235 ASSERT_EQ(0U, R->Counts[1]);
238 TEST_F(InstrProfTest, test_merge_temporal_prof_traces_truncated) {
239 uint64_t ReservoirSize = 10;
240 uint64_t MaxTraceLength = 2;
241 InstrProfWriter Writer(/*Sparse=*/false, ReservoirSize, MaxTraceLength);
242 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::TemporalProfile),
243 Succeeded());
245 TemporalProfTraceTy LargeTrace, SmallTrace;
246 LargeTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("foo"),
247 IndexedInstrProf::ComputeHash("bar"),
248 IndexedInstrProf::ComputeHash("goo")};
249 SmallTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("foo"),
250 IndexedInstrProf::ComputeHash("bar")};
252 SmallVector<TemporalProfTraceTy, 4> Traces = {LargeTrace, SmallTrace};
253 Writer.addTemporalProfileTraces(Traces, 2);
255 auto Profile = Writer.writeBuffer();
256 readProfile(std::move(Profile));
258 ASSERT_TRUE(Reader->hasTemporalProfile());
259 EXPECT_EQ(Reader->getTemporalProfTraceStreamSize(), 2U);
260 EXPECT_THAT(Reader->getTemporalProfTraces(),
261 UnorderedElementsAre(SmallTrace, SmallTrace));
264 TEST_F(InstrProfTest, test_merge_traces_from_writer) {
265 uint64_t ReservoirSize = 10;
266 uint64_t MaxTraceLength = 10;
267 InstrProfWriter Writer(/*Sparse=*/false, ReservoirSize, MaxTraceLength);
268 InstrProfWriter Writer2(/*Sparse=*/false, ReservoirSize, MaxTraceLength);
269 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::TemporalProfile),
270 Succeeded());
271 ASSERT_THAT_ERROR(Writer2.mergeProfileKind(InstrProfKind::TemporalProfile),
272 Succeeded());
274 TemporalProfTraceTy FooTrace, BarTrace;
275 FooTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("foo")};
276 BarTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("bar")};
278 SmallVector<TemporalProfTraceTy, 4> Traces1({FooTrace}), Traces2({BarTrace});
279 Writer.addTemporalProfileTraces(Traces1, 1);
280 Writer2.addTemporalProfileTraces(Traces2, 1);
281 Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
283 auto Profile = Writer.writeBuffer();
284 readProfile(std::move(Profile));
286 ASSERT_TRUE(Reader->hasTemporalProfile());
287 EXPECT_EQ(Reader->getTemporalProfTraceStreamSize(), 2U);
288 EXPECT_THAT(Reader->getTemporalProfTraces(),
289 UnorderedElementsAre(FooTrace, BarTrace));
292 TEST_F(InstrProfTest, test_merge_traces_sampled) {
293 uint64_t ReservoirSize = 3;
294 uint64_t MaxTraceLength = 10;
295 InstrProfWriter Writer(/*Sparse=*/false, ReservoirSize, MaxTraceLength);
296 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::TemporalProfile),
297 Succeeded());
299 TemporalProfTraceTy FooTrace, BarTrace, GooTrace;
300 FooTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("foo")};
301 BarTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("bar")};
302 GooTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("Goo")};
304 // Add some sampled traces
305 SmallVector<TemporalProfTraceTy, 4> SampledTraces = {FooTrace, BarTrace,
306 GooTrace};
307 Writer.addTemporalProfileTraces(SampledTraces, 5);
308 // Add some unsampled traces
309 SmallVector<TemporalProfTraceTy, 4> UnsampledTraces = {BarTrace, GooTrace};
310 Writer.addTemporalProfileTraces(UnsampledTraces, 2);
311 UnsampledTraces = {FooTrace};
312 Writer.addTemporalProfileTraces(UnsampledTraces, 1);
314 auto Profile = Writer.writeBuffer();
315 readProfile(std::move(Profile));
317 ASSERT_TRUE(Reader->hasTemporalProfile());
318 EXPECT_EQ(Reader->getTemporalProfTraceStreamSize(), 8U);
319 // Check that we have a subset of all the traces we added
320 EXPECT_THAT(Reader->getTemporalProfTraces(), SizeIs(ReservoirSize));
321 EXPECT_THAT(
322 Reader->getTemporalProfTraces(),
323 IsSubsetOf({FooTrace, BarTrace, GooTrace, BarTrace, GooTrace, FooTrace}));
326 using ::llvm::memprof::IndexedMemProfRecord;
327 using ::llvm::memprof::MemInfoBlock;
328 using FrameIdMapTy =
329 llvm::DenseMap<::llvm::memprof::FrameId, ::llvm::memprof::Frame>;
331 static FrameIdMapTy getFrameMapping() {
332 FrameIdMapTy Mapping;
333 Mapping.insert({0, {0x123, 1, 2, false}});
334 Mapping.insert({1, {0x345, 3, 4, true}});
335 Mapping.insert({2, {0x125, 5, 6, false}});
336 Mapping.insert({3, {0x567, 7, 8, true}});
337 Mapping.insert({4, {0x124, 5, 6, false}});
338 Mapping.insert({5, {0x789, 8, 9, true}});
339 return Mapping;
342 IndexedMemProfRecord makeRecord(
343 std::initializer_list<std::initializer_list<::llvm::memprof::FrameId>>
344 AllocFrames,
345 std::initializer_list<std::initializer_list<::llvm::memprof::FrameId>>
346 CallSiteFrames,
347 const MemInfoBlock &Block = MemInfoBlock()) {
348 llvm::memprof::IndexedMemProfRecord MR;
349 for (const auto &Frames : AllocFrames)
350 MR.AllocSites.emplace_back(Frames, Block);
351 for (const auto &Frames : CallSiteFrames)
352 MR.CallSites.push_back(Frames);
353 return MR;
356 MATCHER_P(EqualsRecord, Want, "") {
357 const memprof::MemProfRecord &Got = arg;
359 auto PrintAndFail = [&]() {
360 std::string Buffer;
361 llvm::raw_string_ostream OS(Buffer);
362 OS << "Want:\n";
363 Want.print(OS);
364 OS << "Got:\n";
365 Got.print(OS);
366 OS.flush();
367 *result_listener << "MemProf Record differs!\n" << Buffer;
368 return false;
371 if (Want.AllocSites.size() != Got.AllocSites.size())
372 return PrintAndFail();
373 if (Want.CallSites.size() != Got.CallSites.size())
374 return PrintAndFail();
376 for (size_t I = 0; I < Got.AllocSites.size(); I++) {
377 if (Want.AllocSites[I].Info != Got.AllocSites[I].Info)
378 return PrintAndFail();
379 if (Want.AllocSites[I].CallStack != Got.AllocSites[I].CallStack)
380 return PrintAndFail();
383 for (size_t I = 0; I < Got.CallSites.size(); I++) {
384 if (Want.CallSites[I] != Got.CallSites[I])
385 return PrintAndFail();
387 return true;
390 TEST_F(InstrProfTest, test_memprof) {
391 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::MemProf),
392 Succeeded());
394 const IndexedMemProfRecord IndexedMR = makeRecord(
395 /*AllocFrames=*/
397 {0, 1},
398 {2, 3},
400 /*CallSiteFrames=*/{
401 {4, 5},
403 const FrameIdMapTy IdToFrameMap = getFrameMapping();
404 for (const auto &I : IdToFrameMap) {
405 Writer.addMemProfFrame(I.first, I.getSecond(), Err);
407 Writer.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
409 auto Profile = Writer.writeBuffer();
410 readProfile(std::move(Profile));
412 auto RecordOr = Reader->getMemProfRecord(0x9999);
413 ASSERT_THAT_ERROR(RecordOr.takeError(), Succeeded());
414 const memprof::MemProfRecord &Record = RecordOr.get();
416 memprof::FrameId LastUnmappedFrameId = 0;
417 bool HasFrameMappingError = false;
418 auto IdToFrameCallback = [&](const memprof::FrameId Id) {
419 auto Iter = IdToFrameMap.find(Id);
420 if (Iter == IdToFrameMap.end()) {
421 LastUnmappedFrameId = Id;
422 HasFrameMappingError = true;
423 return memprof::Frame(0, 0, 0, false);
425 return Iter->second;
428 const memprof::MemProfRecord WantRecord(IndexedMR, IdToFrameCallback);
429 ASSERT_FALSE(HasFrameMappingError)
430 << "could not map frame id: " << LastUnmappedFrameId;
431 EXPECT_THAT(WantRecord, EqualsRecord(Record));
434 TEST_F(InstrProfTest, test_memprof_getrecord_error) {
435 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::MemProf),
436 Succeeded());
438 const IndexedMemProfRecord IndexedMR = makeRecord(
439 /*AllocFrames=*/
441 {0, 1},
442 {2, 3},
444 /*CallSiteFrames=*/{
445 {4, 5},
447 // We skip adding the frame mappings here unlike the test_memprof unit test
448 // above to exercise the failure path when getMemProfRecord is invoked.
449 Writer.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
451 auto Profile = Writer.writeBuffer();
452 readProfile(std::move(Profile));
454 // Missing frames give a hash_mismatch error.
455 auto RecordOr = Reader->getMemProfRecord(0x9999);
456 ASSERT_TRUE(
457 ErrorEquals(instrprof_error::hash_mismatch, RecordOr.takeError()));
459 // Missing functions give a unknown_function error.
460 RecordOr = Reader->getMemProfRecord(0x1111);
461 ASSERT_TRUE(
462 ErrorEquals(instrprof_error::unknown_function, RecordOr.takeError()));
465 TEST_F(InstrProfTest, test_memprof_merge) {
466 Writer.addRecord({"func1", 0x1234, {42}}, Err);
468 InstrProfWriter Writer2;
469 ASSERT_THAT_ERROR(Writer2.mergeProfileKind(InstrProfKind::MemProf),
470 Succeeded());
472 const IndexedMemProfRecord IndexedMR = makeRecord(
473 /*AllocFrames=*/
475 {0, 1},
476 {2, 3},
478 /*CallSiteFrames=*/{
479 {4, 5},
482 const FrameIdMapTy IdToFrameMap = getFrameMapping();
483 for (const auto &I : IdToFrameMap) {
484 Writer.addMemProfFrame(I.first, I.getSecond(), Err);
486 Writer2.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
488 ASSERT_THAT_ERROR(Writer.mergeProfileKind(Writer2.getProfileKind()),
489 Succeeded());
490 Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
492 auto Profile = Writer.writeBuffer();
493 readProfile(std::move(Profile));
495 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("func1", 0x1234);
496 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
497 ASSERT_EQ(1U, R->Counts.size());
498 ASSERT_EQ(42U, R->Counts[0]);
500 auto RecordOr = Reader->getMemProfRecord(0x9999);
501 ASSERT_THAT_ERROR(RecordOr.takeError(), Succeeded());
502 const memprof::MemProfRecord &Record = RecordOr.get();
504 memprof::FrameId LastUnmappedFrameId = 0;
505 bool HasFrameMappingError = false;
507 auto IdToFrameCallback = [&](const memprof::FrameId Id) {
508 auto Iter = IdToFrameMap.find(Id);
509 if (Iter == IdToFrameMap.end()) {
510 LastUnmappedFrameId = Id;
511 HasFrameMappingError = true;
512 return memprof::Frame(0, 0, 0, false);
514 return Iter->second;
517 const memprof::MemProfRecord WantRecord(IndexedMR, IdToFrameCallback);
518 ASSERT_FALSE(HasFrameMappingError)
519 << "could not map frame id: " << LastUnmappedFrameId;
520 EXPECT_THAT(WantRecord, EqualsRecord(Record));
523 TEST_F(InstrProfTest, test_irpgo_function_name) {
524 LLVMContext Ctx;
525 auto M = std::make_unique<Module>("MyModule.cpp", Ctx);
526 // Use Mach-O mangling so that non-private symbols get a `_` prefix.
527 M->setDataLayout(DataLayout("m:o"));
528 auto *FTy = FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false);
530 std::vector<std::tuple<StringRef, Function::LinkageTypes, StringRef>> Data;
531 Data.emplace_back("ExternalFoo", Function::ExternalLinkage, "_ExternalFoo");
532 Data.emplace_back("InternalFoo", Function::InternalLinkage,
533 "MyModule.cpp;_InternalFoo");
534 Data.emplace_back("PrivateFoo", Function::PrivateLinkage,
535 "MyModule.cpp;l_PrivateFoo");
536 Data.emplace_back("WeakODRFoo", Function::WeakODRLinkage, "_WeakODRFoo");
537 // Test Objective-C symbols
538 Data.emplace_back("\01-[C dynamicFoo:]", Function::ExternalLinkage,
539 "-[C dynamicFoo:]");
540 Data.emplace_back("-<C directFoo:>", Function::ExternalLinkage,
541 "_-<C directFoo:>");
542 Data.emplace_back("\01-[C internalFoo:]", Function::InternalLinkage,
543 "MyModule.cpp;-[C internalFoo:]");
545 for (auto &[Name, Linkage, ExpectedIRPGOFuncName] : Data)
546 Function::Create(FTy, Linkage, Name, M.get());
548 for (auto &[Name, Linkage, ExpectedIRPGOFuncName] : Data) {
549 auto *F = M->getFunction(Name);
550 auto IRPGOFuncName = getIRPGOFuncName(*F);
551 EXPECT_EQ(IRPGOFuncName, ExpectedIRPGOFuncName);
553 auto [Filename, ParsedIRPGOFuncName] =
554 getParsedIRPGOFuncName(IRPGOFuncName);
555 StringRef ExpectedParsedIRPGOFuncName = IRPGOFuncName;
556 if (ExpectedParsedIRPGOFuncName.consume_front("MyModule.cpp;")) {
557 EXPECT_EQ(Filename, "MyModule.cpp");
558 } else {
559 EXPECT_EQ(Filename, "");
561 EXPECT_EQ(ParsedIRPGOFuncName, ExpectedParsedIRPGOFuncName);
565 TEST_F(InstrProfTest, test_pgo_function_name) {
566 LLVMContext Ctx;
567 auto M = std::make_unique<Module>("MyModule.cpp", Ctx);
568 auto *FTy = FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false);
570 std::vector<std::tuple<StringRef, Function::LinkageTypes, StringRef>> Data;
571 Data.emplace_back("ExternalFoo", Function::ExternalLinkage, "ExternalFoo");
572 Data.emplace_back("InternalFoo", Function::InternalLinkage,
573 "MyModule.cpp:InternalFoo");
574 Data.emplace_back("PrivateFoo", Function::PrivateLinkage,
575 "MyModule.cpp:PrivateFoo");
576 Data.emplace_back("WeakODRFoo", Function::WeakODRLinkage, "WeakODRFoo");
577 // Test Objective-C symbols
578 Data.emplace_back("\01-[C externalFoo:]", Function::ExternalLinkage,
579 "-[C externalFoo:]");
580 Data.emplace_back("\01-[C internalFoo:]", Function::InternalLinkage,
581 "MyModule.cpp:-[C internalFoo:]");
583 for (auto &[Name, Linkage, ExpectedPGOFuncName] : Data)
584 Function::Create(FTy, Linkage, Name, M.get());
586 for (auto &[Name, Linkage, ExpectedPGOFuncName] : Data) {
587 auto *F = M->getFunction(Name);
588 EXPECT_EQ(getPGOFuncName(*F), ExpectedPGOFuncName);
592 TEST_F(InstrProfTest, test_irpgo_read_deprecated_names) {
593 LLVMContext Ctx;
594 auto M = std::make_unique<Module>("MyModule.cpp", Ctx);
595 // Use Mach-O mangling so that non-private symbols get a `_` prefix.
596 M->setDataLayout(DataLayout("m:o"));
597 auto *FTy = FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false);
598 auto *InternalFooF =
599 Function::Create(FTy, Function::InternalLinkage, "InternalFoo", M.get());
600 auto *ExternalFooF =
601 Function::Create(FTy, Function::ExternalLinkage, "ExternalFoo", M.get());
603 auto *InternalBarF =
604 Function::Create(FTy, Function::InternalLinkage, "InternalBar", M.get());
605 auto *ExternalBarF =
606 Function::Create(FTy, Function::ExternalLinkage, "ExternalBar", M.get());
608 Writer.addRecord({getIRPGOFuncName(*InternalFooF), 0x1234, {1}}, Err);
609 Writer.addRecord({getIRPGOFuncName(*ExternalFooF), 0x5678, {1}}, Err);
610 // Write a record with a deprecated name
611 Writer.addRecord({getPGOFuncName(*InternalBarF), 0x1111, {2}}, Err);
612 Writer.addRecord({getPGOFuncName(*ExternalBarF), 0x2222, {2}}, Err);
614 auto Profile = Writer.writeBuffer();
615 readProfile(std::move(Profile));
617 EXPECT_THAT_EXPECTED(
618 Reader->getInstrProfRecord(getIRPGOFuncName(*InternalFooF), 0x1234,
619 getPGOFuncName(*InternalFooF)),
620 Succeeded());
621 EXPECT_THAT_EXPECTED(
622 Reader->getInstrProfRecord(getIRPGOFuncName(*ExternalFooF), 0x5678,
623 getPGOFuncName(*ExternalFooF)),
624 Succeeded());
625 // Ensure we can still read this old record name
626 EXPECT_THAT_EXPECTED(
627 Reader->getInstrProfRecord(getIRPGOFuncName(*InternalBarF), 0x1111,
628 getPGOFuncName(*InternalBarF)),
629 Succeeded());
630 EXPECT_THAT_EXPECTED(
631 Reader->getInstrProfRecord(getIRPGOFuncName(*ExternalBarF), 0x2222,
632 getPGOFuncName(*ExternalBarF)),
633 Succeeded());
636 static const char callee1[] = "callee1";
637 static const char callee2[] = "callee2";
638 static const char callee3[] = "callee3";
639 static const char callee4[] = "callee4";
640 static const char callee5[] = "callee5";
641 static const char callee6[] = "callee6";
643 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) {
644 NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
646 // 4 value sites.
647 Record1.reserveSites(IPVK_IndirectCallTarget, 4);
648 InstrProfValueData VD0[] = {
649 {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}};
650 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
651 // No value profile data at the second site.
652 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
653 InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}};
654 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
655 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
656 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
658 Writer.addRecord(std::move(Record1), Err);
659 Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
660 Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
661 Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
662 auto Profile = Writer.writeBuffer();
663 readProfile(std::move(Profile));
665 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
666 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
667 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
668 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
669 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
670 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
671 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
673 uint64_t TotalC;
674 std::unique_ptr<InstrProfValueData[]> VD =
675 R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);
677 ASSERT_EQ(3U, VD[0].Count);
678 ASSERT_EQ(2U, VD[1].Count);
679 ASSERT_EQ(1U, VD[2].Count);
680 ASSERT_EQ(6U, TotalC);
682 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
683 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
684 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
687 TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
688 NamedInstrProfRecord Record("caller", 0x1234, {1, 2});
689 Record.reserveSites(IPVK_IndirectCallTarget, 1);
690 InstrProfValueData VD0[] = {{1000, 1}, {2000, 2}, {3000, 3}, {5000, 5},
691 {4000, 4}, {6000, 6}};
692 Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 6, nullptr);
693 Writer.addRecord(std::move(Record), Err);
694 auto Profile = Writer.writeBuffer();
695 readProfile(std::move(Profile));
696 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
697 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
699 LLVMContext Ctx;
700 std::unique_ptr<Module> M(new Module("MyModule", Ctx));
701 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
702 /*isVarArg=*/false);
703 Function *F =
704 Function::Create(FTy, Function::ExternalLinkage, "caller", M.get());
705 BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
707 IRBuilder<> Builder(BB);
708 BasicBlock *TBB = BasicBlock::Create(Ctx, "", F);
709 BasicBlock *FBB = BasicBlock::Create(Ctx, "", F);
711 // Use branch instruction to annotate with value profile data for simplicity
712 Instruction *Inst = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
713 Instruction *Inst2 = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
714 annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0);
716 InstrProfValueData ValueData[5];
717 uint32_t N;
718 uint64_t T;
719 bool Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
720 ValueData, N, T);
721 ASSERT_TRUE(Res);
722 ASSERT_EQ(3U, N);
723 ASSERT_EQ(21U, T);
724 // The result should be sorted already:
725 ASSERT_EQ(6000U, ValueData[0].Value);
726 ASSERT_EQ(6U, ValueData[0].Count);
727 ASSERT_EQ(5000U, ValueData[1].Value);
728 ASSERT_EQ(5U, ValueData[1].Count);
729 ASSERT_EQ(4000U, ValueData[2].Value);
730 ASSERT_EQ(4U, ValueData[2].Count);
731 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 1, ValueData,
732 N, T);
733 ASSERT_TRUE(Res);
734 ASSERT_EQ(1U, N);
735 ASSERT_EQ(21U, T);
737 Res = getValueProfDataFromInst(*Inst2, IPVK_IndirectCallTarget, 5, ValueData,
738 N, T);
739 ASSERT_FALSE(Res);
741 // Remove the MD_prof metadata
742 Inst->setMetadata(LLVMContext::MD_prof, 0);
743 // Annotate 5 records this time.
744 annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0, 5);
745 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
746 ValueData, N, T);
747 ASSERT_TRUE(Res);
748 ASSERT_EQ(5U, N);
749 ASSERT_EQ(21U, T);
750 ASSERT_EQ(6000U, ValueData[0].Value);
751 ASSERT_EQ(6U, ValueData[0].Count);
752 ASSERT_EQ(5000U, ValueData[1].Value);
753 ASSERT_EQ(5U, ValueData[1].Count);
754 ASSERT_EQ(4000U, ValueData[2].Value);
755 ASSERT_EQ(4U, ValueData[2].Count);
756 ASSERT_EQ(3000U, ValueData[3].Value);
757 ASSERT_EQ(3U, ValueData[3].Count);
758 ASSERT_EQ(2000U, ValueData[4].Value);
759 ASSERT_EQ(2U, ValueData[4].Count);
761 // Remove the MD_prof metadata
762 Inst->setMetadata(LLVMContext::MD_prof, 0);
763 // Annotate with 4 records.
764 InstrProfValueData VD0Sorted[] = {{1000, 6}, {2000, 5}, {3000, 4}, {4000, 3},
765 {5000, 2}, {6000, 1}};
766 annotateValueSite(*M, *Inst, ArrayRef(VD0Sorted).slice(2), 10,
767 IPVK_IndirectCallTarget, 5);
768 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
769 ValueData, N, T);
770 ASSERT_TRUE(Res);
771 ASSERT_EQ(4U, N);
772 ASSERT_EQ(10U, T);
773 ASSERT_EQ(3000U, ValueData[0].Value);
774 ASSERT_EQ(4U, ValueData[0].Count);
775 ASSERT_EQ(4000U, ValueData[1].Value);
776 ASSERT_EQ(3U, ValueData[1].Count);
777 ASSERT_EQ(5000U, ValueData[2].Value);
778 ASSERT_EQ(2U, ValueData[2].Count);
779 ASSERT_EQ(6000U, ValueData[3].Value);
780 ASSERT_EQ(1U, ValueData[3].Count);
783 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) {
784 NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
786 // 4 value sites.
787 Record1.reserveSites(IPVK_IndirectCallTarget, 4);
788 InstrProfValueData VD0[] = {
789 {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}};
790 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
791 // No value profile data at the second site.
792 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
793 InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}};
794 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
795 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
796 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
798 Writer.addRecord(std::move(Record1), 10, Err);
799 Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
800 Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
801 Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
802 auto Profile = Writer.writeBuffer();
803 readProfile(std::move(Profile));
805 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
806 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
807 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
808 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
809 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
810 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
811 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
813 uint64_t TotalC;
814 std::unique_ptr<InstrProfValueData[]> VD =
815 R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);
816 ASSERT_EQ(30U, VD[0].Count);
817 ASSERT_EQ(20U, VD[1].Count);
818 ASSERT_EQ(10U, VD[2].Count);
819 ASSERT_EQ(60U, TotalC);
821 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
822 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
823 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
826 TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) {
827 NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
829 // 4 value sites.
830 Record1.reserveSites(IPVK_IndirectCallTarget, 4);
831 InstrProfValueData VD0[] = {
832 {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}};
833 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
834 // No value profile data at the second site.
835 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
836 InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}};
837 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
838 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
839 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
841 Writer.addRecord(std::move(Record1), Err);
842 Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
843 Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
844 Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
846 // Set big endian output.
847 Writer.setValueProfDataEndianness(llvm::endianness::big);
849 auto Profile = Writer.writeBuffer();
850 readProfile(std::move(Profile));
852 // Set big endian input.
853 Reader->setValueProfDataEndianness(llvm::endianness::big);
855 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
856 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
857 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
858 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
859 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
860 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
861 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
863 std::unique_ptr<InstrProfValueData[]> VD =
864 R->getValueForSite(IPVK_IndirectCallTarget, 0);
865 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
866 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
867 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
869 // Restore little endian default:
870 Writer.setValueProfDataEndianness(llvm::endianness::little);
873 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) {
874 static const char caller[] = "caller";
875 NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
876 NamedInstrProfRecord Record12(caller, 0x1234, {1, 2});
878 // 5 value sites.
879 Record11.reserveSites(IPVK_IndirectCallTarget, 5);
880 InstrProfValueData VD0[] = {{uint64_t(callee1), 1},
881 {uint64_t(callee2), 2},
882 {uint64_t(callee3), 3},
883 {uint64_t(callee4), 4}};
884 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr);
886 // No value profile data at the second site.
887 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
889 InstrProfValueData VD2[] = {
890 {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}};
891 Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
893 InstrProfValueData VD3[] = {{uint64_t(callee1), 1}};
894 Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
896 InstrProfValueData VD4[] = {{uint64_t(callee1), 1},
897 {uint64_t(callee2), 2},
898 {uint64_t(callee3), 3}};
899 Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr);
901 // A different record for the same caller.
902 Record12.reserveSites(IPVK_IndirectCallTarget, 5);
903 InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}};
904 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr);
906 // No value profile data at the second site.
907 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
909 InstrProfValueData VD22[] = {
910 {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}};
911 Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr);
913 Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr);
915 InstrProfValueData VD42[] = {{uint64_t(callee1), 1},
916 {uint64_t(callee2), 2},
917 {uint64_t(callee3), 3}};
918 Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr);
920 Writer.addRecord(std::move(Record11), Err);
921 // Merge profile data.
922 Writer.addRecord(std::move(Record12), Err);
924 Writer.addRecord({callee1, 0x1235, {3, 4}}, Err);
925 Writer.addRecord({callee2, 0x1235, {3, 4}}, Err);
926 Writer.addRecord({callee3, 0x1235, {3, 4}}, Err);
927 Writer.addRecord({callee3, 0x1235, {3, 4}}, Err);
928 Writer.addRecord({callee4, 0x1235, {3, 5}}, Err);
929 auto Profile = Writer.writeBuffer();
930 readProfile(std::move(Profile));
932 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
933 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
934 ASSERT_EQ(5U, R->getNumValueSites(IPVK_IndirectCallTarget));
935 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
936 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
937 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
938 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
939 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
941 std::unique_ptr<InstrProfValueData[]> VD =
942 R->getValueForSite(IPVK_IndirectCallTarget, 0);
943 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2"));
944 ASSERT_EQ(7U, VD[0].Count);
945 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3"));
946 ASSERT_EQ(6U, VD[1].Count);
947 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4"));
948 ASSERT_EQ(4U, VD[2].Count);
949 ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1"));
950 ASSERT_EQ(1U, VD[3].Count);
952 std::unique_ptr<InstrProfValueData[]> VD_2(
953 R->getValueForSite(IPVK_IndirectCallTarget, 2));
954 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3"));
955 ASSERT_EQ(6U, VD_2[0].Count);
956 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4"));
957 ASSERT_EQ(4U, VD_2[1].Count);
958 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2"));
959 ASSERT_EQ(3U, VD_2[2].Count);
960 ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1"));
961 ASSERT_EQ(1U, VD_2[3].Count);
963 std::unique_ptr<InstrProfValueData[]> VD_3(
964 R->getValueForSite(IPVK_IndirectCallTarget, 3));
965 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1"));
966 ASSERT_EQ(1U, VD_3[0].Count);
968 std::unique_ptr<InstrProfValueData[]> VD_4(
969 R->getValueForSite(IPVK_IndirectCallTarget, 4));
970 ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3"));
971 ASSERT_EQ(6U, VD_4[0].Count);
972 ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2"));
973 ASSERT_EQ(4U, VD_4[1].Count);
974 ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1"));
975 ASSERT_EQ(2U, VD_4[2].Count);
978 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1_saturation) {
979 static const char bar[] = "bar";
981 const uint64_t MaxValCount = std::numeric_limits<uint64_t>::max();
982 const uint64_t MaxEdgeCount = getInstrMaxCountValue();
984 instrprof_error Result;
985 auto Err = [&](Error E) {
986 Result = std::get<0>(InstrProfError::take(std::move(E)));
988 Result = instrprof_error::success;
989 Writer.addRecord({"foo", 0x1234, {1}}, Err);
990 ASSERT_EQ(Result, instrprof_error::success);
992 // Verify counter overflow.
993 Result = instrprof_error::success;
994 Writer.addRecord({"foo", 0x1234, {MaxEdgeCount}}, Err);
995 ASSERT_EQ(Result, instrprof_error::counter_overflow);
997 Result = instrprof_error::success;
998 Writer.addRecord({bar, 0x9012, {8}}, Err);
999 ASSERT_EQ(Result, instrprof_error::success);
1001 NamedInstrProfRecord Record4("baz", 0x5678, {3, 4});
1002 Record4.reserveSites(IPVK_IndirectCallTarget, 1);
1003 InstrProfValueData VD4[] = {{uint64_t(bar), 1}};
1004 Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
1005 Result = instrprof_error::success;
1006 Writer.addRecord(std::move(Record4), Err);
1007 ASSERT_EQ(Result, instrprof_error::success);
1009 // Verify value data counter overflow.
1010 NamedInstrProfRecord Record5("baz", 0x5678, {5, 6});
1011 Record5.reserveSites(IPVK_IndirectCallTarget, 1);
1012 InstrProfValueData VD5[] = {{uint64_t(bar), MaxValCount}};
1013 Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
1014 Result = instrprof_error::success;
1015 Writer.addRecord(std::move(Record5), Err);
1016 ASSERT_EQ(Result, instrprof_error::counter_overflow);
1018 auto Profile = Writer.writeBuffer();
1019 readProfile(std::move(Profile));
1021 // Verify saturation of counts.
1022 Expected<InstrProfRecord> ReadRecord1 =
1023 Reader->getInstrProfRecord("foo", 0x1234);
1024 EXPECT_THAT_ERROR(ReadRecord1.takeError(), Succeeded());
1025 ASSERT_EQ(MaxEdgeCount, ReadRecord1->Counts[0]);
1027 Expected<InstrProfRecord> ReadRecord2 =
1028 Reader->getInstrProfRecord("baz", 0x5678);
1029 ASSERT_TRUE(bool(ReadRecord2));
1030 ASSERT_EQ(1U, ReadRecord2->getNumValueSites(IPVK_IndirectCallTarget));
1031 std::unique_ptr<InstrProfValueData[]> VD =
1032 ReadRecord2->getValueForSite(IPVK_IndirectCallTarget, 0);
1033 ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3));
1034 ASSERT_EQ(MaxValCount, VD[0].Count);
1037 // This test tests that when there are too many values
1038 // for a given site, the merged results are properly
1039 // truncated.
1040 TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge_site_trunc) {
1041 static const char caller[] = "caller";
1043 NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
1044 NamedInstrProfRecord Record12(caller, 0x1234, {1, 2});
1046 // 2 value sites.
1047 Record11.reserveSites(IPVK_IndirectCallTarget, 2);
1048 InstrProfValueData VD0[255];
1049 for (int I = 0; I < 255; I++) {
1050 VD0[I].Value = 2 * I;
1051 VD0[I].Count = 2 * I + 1000;
1054 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr);
1055 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
1057 Record12.reserveSites(IPVK_IndirectCallTarget, 2);
1058 InstrProfValueData VD1[255];
1059 for (int I = 0; I < 255; I++) {
1060 VD1[I].Value = 2 * I + 1;
1061 VD1[I].Count = 2 * I + 1001;
1064 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr);
1065 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
1067 Writer.addRecord(std::move(Record11), Err);
1068 // Merge profile data.
1069 Writer.addRecord(std::move(Record12), Err);
1071 auto Profile = Writer.writeBuffer();
1072 readProfile(std::move(Profile));
1074 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
1075 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
1076 std::unique_ptr<InstrProfValueData[]> VD(
1077 R->getValueForSite(IPVK_IndirectCallTarget, 0));
1078 ASSERT_EQ(2U, R->getNumValueSites(IPVK_IndirectCallTarget));
1079 ASSERT_EQ(255U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
1080 for (unsigned I = 0; I < 255; I++) {
1081 ASSERT_EQ(VD[I].Value, 509 - I);
1082 ASSERT_EQ(VD[I].Count, 1509 - I);
1086 static void addValueProfData(InstrProfRecord &Record) {
1087 Record.reserveSites(IPVK_IndirectCallTarget, 5);
1088 InstrProfValueData VD0[] = {{uint64_t(callee1), 400},
1089 {uint64_t(callee2), 1000},
1090 {uint64_t(callee3), 500},
1091 {uint64_t(callee4), 300},
1092 {uint64_t(callee5), 100}};
1093 Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 5, nullptr);
1094 InstrProfValueData VD1[] = {{uint64_t(callee5), 800},
1095 {uint64_t(callee3), 1000},
1096 {uint64_t(callee2), 2500},
1097 {uint64_t(callee1), 1300}};
1098 Record.addValueData(IPVK_IndirectCallTarget, 1, VD1, 4, nullptr);
1099 InstrProfValueData VD2[] = {{uint64_t(callee6), 800},
1100 {uint64_t(callee3), 1000},
1101 {uint64_t(callee4), 5500}};
1102 Record.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
1103 InstrProfValueData VD3[] = {{uint64_t(callee2), 1800},
1104 {uint64_t(callee3), 2000}};
1105 Record.addValueData(IPVK_IndirectCallTarget, 3, VD3, 2, nullptr);
1106 Record.addValueData(IPVK_IndirectCallTarget, 4, nullptr, 0, nullptr);
1109 TEST_P(MaybeSparseInstrProfTest, value_prof_data_read_write) {
1110 InstrProfRecord SrcRecord({1ULL << 31, 2});
1111 addValueProfData(SrcRecord);
1112 std::unique_ptr<ValueProfData> VPData =
1113 ValueProfData::serializeFrom(SrcRecord);
1115 InstrProfRecord Record({1ULL << 31, 2});
1116 VPData->deserializeTo(Record, nullptr);
1118 // Now read data from Record and sanity check the data
1119 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
1120 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
1121 ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
1122 ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
1123 ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
1124 ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
1126 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
1127 return VD1.Count > VD2.Count;
1129 std::unique_ptr<InstrProfValueData[]> VD_0(
1130 Record.getValueForSite(IPVK_IndirectCallTarget, 0));
1131 llvm::sort(&VD_0[0], &VD_0[5], Cmp);
1132 ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2"));
1133 ASSERT_EQ(1000U, VD_0[0].Count);
1134 ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3"));
1135 ASSERT_EQ(500U, VD_0[1].Count);
1136 ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1"));
1137 ASSERT_EQ(400U, VD_0[2].Count);
1138 ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4"));
1139 ASSERT_EQ(300U, VD_0[3].Count);
1140 ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5"));
1141 ASSERT_EQ(100U, VD_0[4].Count);
1143 std::unique_ptr<InstrProfValueData[]> VD_1(
1144 Record.getValueForSite(IPVK_IndirectCallTarget, 1));
1145 llvm::sort(&VD_1[0], &VD_1[4], Cmp);
1146 ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2"));
1147 ASSERT_EQ(2500U, VD_1[0].Count);
1148 ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1"));
1149 ASSERT_EQ(1300U, VD_1[1].Count);
1150 ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3"));
1151 ASSERT_EQ(1000U, VD_1[2].Count);
1152 ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5"));
1153 ASSERT_EQ(800U, VD_1[3].Count);
1155 std::unique_ptr<InstrProfValueData[]> VD_2(
1156 Record.getValueForSite(IPVK_IndirectCallTarget, 2));
1157 llvm::sort(&VD_2[0], &VD_2[3], Cmp);
1158 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4"));
1159 ASSERT_EQ(5500U, VD_2[0].Count);
1160 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3"));
1161 ASSERT_EQ(1000U, VD_2[1].Count);
1162 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6"));
1163 ASSERT_EQ(800U, VD_2[2].Count);
1165 std::unique_ptr<InstrProfValueData[]> VD_3(
1166 Record.getValueForSite(IPVK_IndirectCallTarget, 3));
1167 llvm::sort(&VD_3[0], &VD_3[2], Cmp);
1168 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3"));
1169 ASSERT_EQ(2000U, VD_3[0].Count);
1170 ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2"));
1171 ASSERT_EQ(1800U, VD_3[1].Count);
1174 TEST_P(MaybeSparseInstrProfTest, value_prof_data_read_write_mapping) {
1176 NamedInstrProfRecord SrcRecord("caller", 0x1234, {1ULL << 31, 2});
1177 addValueProfData(SrcRecord);
1178 std::unique_ptr<ValueProfData> VPData =
1179 ValueProfData::serializeFrom(SrcRecord);
1181 NamedInstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
1182 InstrProfSymtab Symtab;
1183 Symtab.mapAddress(uint64_t(callee1), 0x1000ULL);
1184 Symtab.mapAddress(uint64_t(callee2), 0x2000ULL);
1185 Symtab.mapAddress(uint64_t(callee3), 0x3000ULL);
1186 Symtab.mapAddress(uint64_t(callee4), 0x4000ULL);
1187 // Missing mapping for callee5
1189 VPData->deserializeTo(Record, &Symtab);
1191 // Now read data from Record and sanity check the data
1192 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
1193 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
1195 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
1196 return VD1.Count > VD2.Count;
1198 std::unique_ptr<InstrProfValueData[]> VD_0(
1199 Record.getValueForSite(IPVK_IndirectCallTarget, 0));
1200 llvm::sort(&VD_0[0], &VD_0[5], Cmp);
1201 ASSERT_EQ(VD_0[0].Value, 0x2000ULL);
1202 ASSERT_EQ(1000U, VD_0[0].Count);
1203 ASSERT_EQ(VD_0[1].Value, 0x3000ULL);
1204 ASSERT_EQ(500U, VD_0[1].Count);
1205 ASSERT_EQ(VD_0[2].Value, 0x1000ULL);
1206 ASSERT_EQ(400U, VD_0[2].Count);
1208 // callee5 does not have a mapped value -- default to 0.
1209 ASSERT_EQ(VD_0[4].Value, 0ULL);
1212 TEST_P(MaybeSparseInstrProfTest, get_max_function_count) {
1213 Writer.addRecord({"foo", 0x1234, {1ULL << 31, 2}}, Err);
1214 Writer.addRecord({"bar", 0, {1ULL << 63}}, Err);
1215 Writer.addRecord({"baz", 0x5678, {0, 0, 0, 0}}, Err);
1216 auto Profile = Writer.writeBuffer();
1217 readProfile(std::move(Profile));
1219 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount(/* IsCS */ false));
1222 TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) {
1223 Writer.addRecord({"foo", 0x1234, {1, 2}}, 3, Err);
1224 Writer.addRecord({"foo", 0x1235, {3, 4}}, 5, Err);
1225 auto Profile = Writer.writeBuffer();
1226 readProfile(std::move(Profile));
1228 std::vector<uint64_t> Counts;
1229 EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1234, Counts),
1230 Succeeded());
1231 ASSERT_EQ(2U, Counts.size());
1232 ASSERT_EQ(3U, Counts[0]);
1233 ASSERT_EQ(6U, Counts[1]);
1235 EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1235, Counts),
1236 Succeeded());
1237 ASSERT_EQ(2U, Counts.size());
1238 ASSERT_EQ(15U, Counts[0]);
1239 ASSERT_EQ(20U, Counts[1]);
1242 // Testing symtab creator interface used by indexed profile reader.
1243 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_test) {
1244 std::vector<StringRef> FuncNames;
1245 FuncNames.push_back("func1");
1246 FuncNames.push_back("func2");
1247 FuncNames.push_back("func3");
1248 FuncNames.push_back("bar1");
1249 FuncNames.push_back("bar2");
1250 FuncNames.push_back("bar3");
1251 InstrProfSymtab Symtab;
1252 EXPECT_THAT_ERROR(Symtab.create(FuncNames), Succeeded());
1253 StringRef R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func1"));
1254 ASSERT_EQ(StringRef("func1"), R);
1255 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func2"));
1256 ASSERT_EQ(StringRef("func2"), R);
1257 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func3"));
1258 ASSERT_EQ(StringRef("func3"), R);
1259 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar1"));
1260 ASSERT_EQ(StringRef("bar1"), R);
1261 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar2"));
1262 ASSERT_EQ(StringRef("bar2"), R);
1263 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar3"));
1264 ASSERT_EQ(StringRef("bar3"), R);
1266 // negative tests
1267 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar4"));
1268 ASSERT_EQ(StringRef(), R);
1269 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("foo4"));
1270 ASSERT_EQ(StringRef(), R);
1272 // Now incrementally update the symtab
1273 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_1"), Succeeded());
1274 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_2"), Succeeded());
1275 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_3"), Succeeded());
1277 // Check again
1278 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("blah_1"));
1279 ASSERT_EQ(StringRef("blah_1"), R);
1280 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("blah_2"));
1281 ASSERT_EQ(StringRef("blah_2"), R);
1282 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("blah_3"));
1283 ASSERT_EQ(StringRef("blah_3"), R);
1284 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func1"));
1285 ASSERT_EQ(StringRef("func1"), R);
1286 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func2"));
1287 ASSERT_EQ(StringRef("func2"), R);
1288 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func3"));
1289 ASSERT_EQ(StringRef("func3"), R);
1290 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar1"));
1291 ASSERT_EQ(StringRef("bar1"), R);
1292 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar2"));
1293 ASSERT_EQ(StringRef("bar2"), R);
1294 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar3"));
1295 ASSERT_EQ(StringRef("bar3"), R);
1298 // Test that we get an error when creating a bogus symtab.
1299 TEST_P(MaybeSparseInstrProfTest, instr_prof_bogus_symtab_empty_func_name) {
1300 InstrProfSymtab Symtab;
1301 EXPECT_TRUE(ErrorEquals(instrprof_error::malformed, Symtab.addFuncName("")));
1304 // Testing symtab creator interface used by value profile transformer.
1305 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_module_test) {
1306 LLVMContext Ctx;
1307 std::unique_ptr<Module> M = std::make_unique<Module>("MyModule.cpp", Ctx);
1308 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
1309 /*isVarArg=*/false);
1310 Function::Create(FTy, Function::ExternalLinkage, "Gfoo", M.get());
1311 Function::Create(FTy, Function::ExternalLinkage, "Gblah", M.get());
1312 Function::Create(FTy, Function::ExternalLinkage, "Gbar", M.get());
1313 Function::Create(FTy, Function::InternalLinkage, "Ifoo", M.get());
1314 Function::Create(FTy, Function::InternalLinkage, "Iblah", M.get());
1315 Function::Create(FTy, Function::InternalLinkage, "Ibar", M.get());
1316 Function::Create(FTy, Function::PrivateLinkage, "Pfoo", M.get());
1317 Function::Create(FTy, Function::PrivateLinkage, "Pblah", M.get());
1318 Function::Create(FTy, Function::PrivateLinkage, "Pbar", M.get());
1319 Function::Create(FTy, Function::WeakODRLinkage, "Wfoo", M.get());
1320 Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get());
1321 Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get());
1323 InstrProfSymtab ProfSymtab;
1324 EXPECT_THAT_ERROR(ProfSymtab.create(*M), Succeeded());
1326 StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar",
1327 "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"};
1329 for (unsigned I = 0; I < std::size(Funcs); I++) {
1330 Function *F = M->getFunction(Funcs[I]);
1332 std::string IRPGOName = getIRPGOFuncName(*F);
1333 auto IRPGOFuncName =
1334 ProfSymtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(IRPGOName));
1335 EXPECT_EQ(StringRef(IRPGOName), IRPGOFuncName);
1336 EXPECT_EQ(StringRef(Funcs[I]),
1337 getParsedIRPGOFuncName(IRPGOFuncName).second);
1338 // Ensure we can still read this old record name.
1339 std::string PGOName = getPGOFuncName(*F);
1340 auto PGOFuncName =
1341 ProfSymtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(PGOName));
1342 EXPECT_EQ(StringRef(PGOName), PGOFuncName);
1343 EXPECT_THAT(PGOFuncName.str(), EndsWith(Funcs[I].str()));
1347 // Testing symtab serialization and creator/deserialization interface
1348 // used by coverage map reader, and raw profile reader.
1349 TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_compression_test) {
1350 std::vector<std::string> FuncNames1;
1351 std::vector<std::string> FuncNames2;
1352 for (int I = 0; I < 3; I++) {
1353 std::string str;
1354 raw_string_ostream OS(str);
1355 OS << "func_" << I;
1356 FuncNames1.push_back(OS.str());
1357 str.clear();
1358 OS << "f oooooooooooooo_" << I;
1359 FuncNames1.push_back(OS.str());
1360 str.clear();
1361 OS << "BAR_" << I;
1362 FuncNames2.push_back(OS.str());
1363 str.clear();
1364 OS << "BlahblahBlahblahBar_" << I;
1365 FuncNames2.push_back(OS.str());
1368 for (bool DoCompression : {false, true}) {
1369 // Compressing:
1370 std::string FuncNameStrings1;
1371 EXPECT_THAT_ERROR(collectGlobalObjectNameStrings(
1372 FuncNames1,
1373 (DoCompression && compression::zlib::isAvailable()),
1374 FuncNameStrings1),
1375 Succeeded());
1377 // Compressing:
1378 std::string FuncNameStrings2;
1379 EXPECT_THAT_ERROR(collectGlobalObjectNameStrings(
1380 FuncNames2,
1381 (DoCompression && compression::zlib::isAvailable()),
1382 FuncNameStrings2),
1383 Succeeded());
1385 for (int Padding = 0; Padding < 2; Padding++) {
1386 // Join with paddings :
1387 std::string FuncNameStrings = FuncNameStrings1;
1388 for (int P = 0; P < Padding; P++) {
1389 FuncNameStrings.push_back('\0');
1391 FuncNameStrings += FuncNameStrings2;
1393 // Now decompress:
1394 InstrProfSymtab Symtab;
1395 EXPECT_THAT_ERROR(Symtab.create(StringRef(FuncNameStrings)), Succeeded());
1397 // Now do the checks:
1398 // First sampling some data points:
1399 StringRef R =
1400 Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(FuncNames1[0]));
1401 ASSERT_EQ(StringRef("func_0"), R);
1402 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(FuncNames1[1]));
1403 ASSERT_EQ(StringRef("f oooooooooooooo_0"), R);
1404 for (int I = 0; I < 3; I++) {
1405 std::string N[4];
1406 N[0] = FuncNames1[2 * I];
1407 N[1] = FuncNames1[2 * I + 1];
1408 N[2] = FuncNames2[2 * I];
1409 N[3] = FuncNames2[2 * I + 1];
1410 for (int J = 0; J < 4; J++) {
1411 StringRef R =
1412 Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(N[J]));
1413 ASSERT_EQ(StringRef(N[J]), R);
1420 TEST_P(MaybeSparseInstrProfTest, remapping_test) {
1421 Writer.addRecord({"_Z3fooi", 0x1234, {1, 2, 3, 4}}, Err);
1422 Writer.addRecord({"file:_Z3barf", 0x567, {5, 6, 7}}, Err);
1423 auto Profile = Writer.writeBuffer();
1424 readProfile(std::move(Profile), llvm::MemoryBuffer::getMemBuffer(R"(
1425 type i l
1426 name 3bar 4quux
1427 )"));
1429 std::vector<uint64_t> Counts;
1430 for (StringRef FooName : {"_Z3fooi", "_Z3fool"}) {
1431 EXPECT_THAT_ERROR(Reader->getFunctionCounts(FooName, 0x1234, Counts),
1432 Succeeded());
1433 ASSERT_EQ(4u, Counts.size());
1434 EXPECT_EQ(1u, Counts[0]);
1435 EXPECT_EQ(2u, Counts[1]);
1436 EXPECT_EQ(3u, Counts[2]);
1437 EXPECT_EQ(4u, Counts[3]);
1440 for (StringRef BarName : {"file:_Z3barf", "file:_Z4quuxf"}) {
1441 EXPECT_THAT_ERROR(Reader->getFunctionCounts(BarName, 0x567, Counts),
1442 Succeeded());
1443 ASSERT_EQ(3u, Counts.size());
1444 EXPECT_EQ(5u, Counts[0]);
1445 EXPECT_EQ(6u, Counts[1]);
1446 EXPECT_EQ(7u, Counts[2]);
1449 for (StringRef BadName : {"_Z3foof", "_Z4quuxi", "_Z3barl", "", "_ZZZ",
1450 "_Z3barf", "otherfile:_Z4quuxf"}) {
1451 EXPECT_THAT_ERROR(Reader->getFunctionCounts(BadName, 0x1234, Counts),
1452 Failed());
1453 EXPECT_THAT_ERROR(Reader->getFunctionCounts(BadName, 0x567, Counts),
1454 Failed());
1458 TEST_F(SparseInstrProfTest, preserve_no_records) {
1459 Writer.addRecord({"foo", 0x1234, {0}}, Err);
1460 Writer.addRecord({"bar", 0x4321, {0, 0}}, Err);
1461 Writer.addRecord({"baz", 0x4321, {0, 0, 0}}, Err);
1463 auto Profile = Writer.writeBuffer();
1464 readProfile(std::move(Profile));
1466 auto I = Reader->begin(), E = Reader->end();
1467 ASSERT_TRUE(I == E);
1470 INSTANTIATE_TEST_SUITE_P(MaybeSparse, MaybeSparseInstrProfTest,
1471 ::testing::Bool());
1473 #if defined(_LP64) && defined(EXPENSIVE_CHECKS)
1474 TEST(ProfileReaderTest, ReadsLargeFiles) {
1475 const size_t LargeSize = 1ULL << 32; // 4GB
1477 auto RawProfile = WritableMemoryBuffer::getNewUninitMemBuffer(LargeSize);
1478 if (!RawProfile)
1479 GTEST_SKIP();
1480 auto RawProfileReaderOrErr = InstrProfReader::create(std::move(RawProfile));
1481 ASSERT_TRUE(
1482 std::get<0>(InstrProfError::take(RawProfileReaderOrErr.takeError())) ==
1483 instrprof_error::unrecognized_format);
1485 auto IndexedProfile = WritableMemoryBuffer::getNewUninitMemBuffer(LargeSize);
1486 if (!IndexedProfile)
1487 GTEST_SKIP();
1488 auto IndexedReaderOrErr =
1489 IndexedInstrProfReader::create(std::move(IndexedProfile), nullptr);
1490 ASSERT_TRUE(
1491 std::get<0>(InstrProfError::take(IndexedReaderOrErr.takeError())) ==
1492 instrprof_error::bad_magic);
1494 #endif
1496 } // end anonymous namespace