[llvm-shlib] Fix the version naming style of libLLVM for Windows (#85710)
[llvm-project.git] / llvm / unittests / ProfileData / InstrProfTest.cpp
blob8ffb68de7a2d204351b783f57bdf4877e91fe3fe
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 InstrProfReaderWriterTest
72 : public InstrProfTest,
73 public ::testing::WithParamInterface<
74 std::tuple<bool, uint64_t, llvm::endianness>> {
75 void SetUp() override { Writer.setOutputSparse(std::get<0>(GetParam())); }
76 void TearDown() override {
77 // Reset writer value profile data endianness after each test case. Note
78 // it's not necessary to reset reader value profile endianness for each test
79 // case. Each test case creates a new reader; at reader initialization time,
80 // it uses the endianness from hash table object (which is little by
81 // default).
82 Writer.setValueProfDataEndianness(llvm::endianness::little);
85 uint64_t getProfWeight() const { return std::get<1>(GetParam()); }
87 llvm::endianness getEndianness() const { return std::get<2>(GetParam()); }
90 struct MaybeSparseInstrProfTest : public InstrProfTest,
91 public ::testing::WithParamInterface<bool> {
92 void SetUp() override { Writer.setOutputSparse(GetParam()); }
95 TEST_P(MaybeSparseInstrProfTest, write_and_read_empty_profile) {
96 auto Profile = Writer.writeBuffer();
97 readProfile(std::move(Profile));
98 ASSERT_TRUE(Reader->begin() == Reader->end());
101 static const auto Err = [](Error E) {
102 consumeError(std::move(E));
103 FAIL();
106 TEST_P(MaybeSparseInstrProfTest, write_and_read_one_function) {
107 Writer.addRecord({"foo", 0x1234, {1, 2, 3, 4}}, Err);
108 auto Profile = Writer.writeBuffer();
109 readProfile(std::move(Profile));
111 auto I = Reader->begin(), E = Reader->end();
112 ASSERT_TRUE(I != E);
113 ASSERT_EQ(StringRef("foo"), I->Name);
114 ASSERT_EQ(0x1234U, I->Hash);
115 ASSERT_EQ(4U, I->Counts.size());
116 ASSERT_EQ(1U, I->Counts[0]);
117 ASSERT_EQ(2U, I->Counts[1]);
118 ASSERT_EQ(3U, I->Counts[2]);
119 ASSERT_EQ(4U, I->Counts[3]);
120 ASSERT_TRUE(++I == E);
123 TEST_P(MaybeSparseInstrProfTest, get_instr_prof_record) {
124 Writer.addRecord({"foo", 0x1234, {1, 2}}, Err);
125 Writer.addRecord({"foo", 0x1235, {3, 4}}, Err);
126 auto Profile = Writer.writeBuffer();
127 readProfile(std::move(Profile));
129 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234);
130 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
131 ASSERT_EQ(2U, R->Counts.size());
132 ASSERT_EQ(1U, R->Counts[0]);
133 ASSERT_EQ(2U, R->Counts[1]);
135 R = Reader->getInstrProfRecord("foo", 0x1235);
136 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
137 ASSERT_EQ(2U, R->Counts.size());
138 ASSERT_EQ(3U, R->Counts[0]);
139 ASSERT_EQ(4U, R->Counts[1]);
141 R = Reader->getInstrProfRecord("foo", 0x5678);
142 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.takeError()));
144 R = Reader->getInstrProfRecord("bar", 0x1234);
145 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.takeError()));
148 TEST_P(MaybeSparseInstrProfTest, get_function_counts) {
149 Writer.addRecord({"foo", 0x1234, {1, 2}}, Err);
150 Writer.addRecord({"foo", 0x1235, {3, 4}}, Err);
151 auto Profile = Writer.writeBuffer();
152 readProfile(std::move(Profile));
154 std::vector<uint64_t> Counts;
155 EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1234, Counts),
156 Succeeded());
157 ASSERT_EQ(2U, Counts.size());
158 ASSERT_EQ(1U, Counts[0]);
159 ASSERT_EQ(2U, Counts[1]);
161 EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1235, Counts),
162 Succeeded());
163 ASSERT_EQ(2U, Counts.size());
164 ASSERT_EQ(3U, Counts[0]);
165 ASSERT_EQ(4U, Counts[1]);
167 Error E1 = Reader->getFunctionCounts("foo", 0x5678, Counts);
168 ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, std::move(E1)));
170 Error E2 = Reader->getFunctionCounts("bar", 0x1234, Counts);
171 ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, std::move(E2)));
174 // Profile data is copied from general.proftext
175 TEST_F(InstrProfTest, get_profile_summary) {
176 Writer.addRecord({"func1", 0x1234, {97531}}, Err);
177 Writer.addRecord({"func2", 0x1234, {0, 0}}, Err);
178 Writer.addRecord(
179 {"func3",
180 0x1234,
181 {2305843009213693952, 1152921504606846976, 576460752303423488,
182 288230376151711744, 144115188075855872, 72057594037927936}},
183 Err);
184 Writer.addRecord({"func4", 0x1234, {0}}, Err);
185 auto Profile = Writer.writeBuffer();
186 readProfile(std::move(Profile));
188 auto VerifySummary = [](ProfileSummary &IPS) mutable {
189 ASSERT_EQ(ProfileSummary::PSK_Instr, IPS.getKind());
190 ASSERT_EQ(2305843009213693952U, IPS.getMaxFunctionCount());
191 ASSERT_EQ(2305843009213693952U, IPS.getMaxCount());
192 ASSERT_EQ(10U, IPS.getNumCounts());
193 ASSERT_EQ(4539628424389557499U, IPS.getTotalCount());
194 const std::vector<ProfileSummaryEntry> &Details = IPS.getDetailedSummary();
195 uint32_t Cutoff = 800000;
196 auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) {
197 return PE.Cutoff == Cutoff;
199 auto EightyPerc = find_if(Details, Predicate);
200 Cutoff = 900000;
201 auto NinetyPerc = find_if(Details, Predicate);
202 Cutoff = 950000;
203 auto NinetyFivePerc = find_if(Details, Predicate);
204 Cutoff = 990000;
205 auto NinetyNinePerc = find_if(Details, Predicate);
206 ASSERT_EQ(576460752303423488U, EightyPerc->MinCount);
207 ASSERT_EQ(288230376151711744U, NinetyPerc->MinCount);
208 ASSERT_EQ(288230376151711744U, NinetyFivePerc->MinCount);
209 ASSERT_EQ(72057594037927936U, NinetyNinePerc->MinCount);
211 ProfileSummary &PS = Reader->getSummary(/* IsCS */ false);
212 VerifySummary(PS);
214 // Test that conversion of summary to and from Metadata works.
215 LLVMContext Context;
216 Metadata *MD = PS.getMD(Context);
217 ASSERT_TRUE(MD);
218 ProfileSummary *PSFromMD = ProfileSummary::getFromMD(MD);
219 ASSERT_TRUE(PSFromMD);
220 VerifySummary(*PSFromMD);
221 delete PSFromMD;
223 // Test that summary can be attached to and read back from module.
224 Module M("my_module", Context);
225 M.setProfileSummary(MD, ProfileSummary::PSK_Instr);
226 MD = M.getProfileSummary(/* IsCS */ false);
227 ASSERT_TRUE(MD);
228 PSFromMD = ProfileSummary::getFromMD(MD);
229 ASSERT_TRUE(PSFromMD);
230 VerifySummary(*PSFromMD);
231 delete PSFromMD;
234 TEST_F(InstrProfTest, test_writer_merge) {
235 Writer.addRecord({"func1", 0x1234, {42}}, Err);
237 InstrProfWriter Writer2;
238 Writer2.addRecord({"func2", 0x1234, {0, 0}}, Err);
240 Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
242 auto Profile = Writer.writeBuffer();
243 readProfile(std::move(Profile));
245 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("func1", 0x1234);
246 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
247 ASSERT_EQ(1U, R->Counts.size());
248 ASSERT_EQ(42U, R->Counts[0]);
250 R = Reader->getInstrProfRecord("func2", 0x1234);
251 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
252 ASSERT_EQ(2U, R->Counts.size());
253 ASSERT_EQ(0U, R->Counts[0]);
254 ASSERT_EQ(0U, R->Counts[1]);
257 TEST_F(InstrProfTest, test_merge_temporal_prof_traces_truncated) {
258 uint64_t ReservoirSize = 10;
259 uint64_t MaxTraceLength = 2;
260 InstrProfWriter Writer(/*Sparse=*/false, ReservoirSize, MaxTraceLength);
261 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::TemporalProfile),
262 Succeeded());
264 TemporalProfTraceTy LargeTrace, SmallTrace;
265 LargeTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("foo"),
266 IndexedInstrProf::ComputeHash("bar"),
267 IndexedInstrProf::ComputeHash("goo")};
268 SmallTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("foo"),
269 IndexedInstrProf::ComputeHash("bar")};
271 SmallVector<TemporalProfTraceTy, 4> Traces = {LargeTrace, SmallTrace};
272 Writer.addTemporalProfileTraces(Traces, 2);
274 auto Profile = Writer.writeBuffer();
275 readProfile(std::move(Profile));
277 ASSERT_TRUE(Reader->hasTemporalProfile());
278 EXPECT_EQ(Reader->getTemporalProfTraceStreamSize(), 2U);
279 EXPECT_THAT(Reader->getTemporalProfTraces(),
280 UnorderedElementsAre(SmallTrace, SmallTrace));
283 TEST_F(InstrProfTest, test_merge_traces_from_writer) {
284 uint64_t ReservoirSize = 10;
285 uint64_t MaxTraceLength = 10;
286 InstrProfWriter Writer(/*Sparse=*/false, ReservoirSize, MaxTraceLength);
287 InstrProfWriter Writer2(/*Sparse=*/false, ReservoirSize, MaxTraceLength);
288 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::TemporalProfile),
289 Succeeded());
290 ASSERT_THAT_ERROR(Writer2.mergeProfileKind(InstrProfKind::TemporalProfile),
291 Succeeded());
293 TemporalProfTraceTy FooTrace, BarTrace;
294 FooTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("foo")};
295 BarTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("bar")};
297 SmallVector<TemporalProfTraceTy, 4> Traces1({FooTrace}), Traces2({BarTrace});
298 Writer.addTemporalProfileTraces(Traces1, 1);
299 Writer2.addTemporalProfileTraces(Traces2, 1);
300 Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
302 auto Profile = Writer.writeBuffer();
303 readProfile(std::move(Profile));
305 ASSERT_TRUE(Reader->hasTemporalProfile());
306 EXPECT_EQ(Reader->getTemporalProfTraceStreamSize(), 2U);
307 EXPECT_THAT(Reader->getTemporalProfTraces(),
308 UnorderedElementsAre(FooTrace, BarTrace));
311 TEST_F(InstrProfTest, test_merge_traces_sampled) {
312 uint64_t ReservoirSize = 3;
313 uint64_t MaxTraceLength = 10;
314 InstrProfWriter Writer(/*Sparse=*/false, ReservoirSize, MaxTraceLength);
315 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::TemporalProfile),
316 Succeeded());
318 TemporalProfTraceTy FooTrace, BarTrace, GooTrace;
319 FooTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("foo")};
320 BarTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("bar")};
321 GooTrace.FunctionNameRefs = {IndexedInstrProf::ComputeHash("Goo")};
323 // Add some sampled traces
324 SmallVector<TemporalProfTraceTy, 4> SampledTraces = {FooTrace, BarTrace,
325 GooTrace};
326 Writer.addTemporalProfileTraces(SampledTraces, 5);
327 // Add some unsampled traces
328 SmallVector<TemporalProfTraceTy, 4> UnsampledTraces = {BarTrace, GooTrace};
329 Writer.addTemporalProfileTraces(UnsampledTraces, 2);
330 UnsampledTraces = {FooTrace};
331 Writer.addTemporalProfileTraces(UnsampledTraces, 1);
333 auto Profile = Writer.writeBuffer();
334 readProfile(std::move(Profile));
336 ASSERT_TRUE(Reader->hasTemporalProfile());
337 EXPECT_EQ(Reader->getTemporalProfTraceStreamSize(), 8U);
338 // Check that we have a subset of all the traces we added
339 EXPECT_THAT(Reader->getTemporalProfTraces(), SizeIs(ReservoirSize));
340 EXPECT_THAT(
341 Reader->getTemporalProfTraces(),
342 IsSubsetOf({FooTrace, BarTrace, GooTrace, BarTrace, GooTrace, FooTrace}));
345 using ::llvm::memprof::IndexedMemProfRecord;
346 using ::llvm::memprof::MemInfoBlock;
347 using FrameIdMapTy =
348 llvm::DenseMap<::llvm::memprof::FrameId, ::llvm::memprof::Frame>;
350 static FrameIdMapTy getFrameMapping() {
351 FrameIdMapTy Mapping;
352 Mapping.insert({0, {0x123, 1, 2, false}});
353 Mapping.insert({1, {0x345, 3, 4, true}});
354 Mapping.insert({2, {0x125, 5, 6, false}});
355 Mapping.insert({3, {0x567, 7, 8, true}});
356 Mapping.insert({4, {0x124, 5, 6, false}});
357 Mapping.insert({5, {0x789, 8, 9, true}});
358 return Mapping;
361 IndexedMemProfRecord makeRecord(
362 std::initializer_list<std::initializer_list<::llvm::memprof::FrameId>>
363 AllocFrames,
364 std::initializer_list<std::initializer_list<::llvm::memprof::FrameId>>
365 CallSiteFrames,
366 const MemInfoBlock &Block = MemInfoBlock()) {
367 llvm::memprof::IndexedMemProfRecord MR;
368 for (const auto &Frames : AllocFrames)
369 MR.AllocSites.emplace_back(Frames, Block);
370 for (const auto &Frames : CallSiteFrames)
371 MR.CallSites.push_back(Frames);
372 return MR;
375 MATCHER_P(EqualsRecord, Want, "") {
376 const memprof::MemProfRecord &Got = arg;
378 auto PrintAndFail = [&]() {
379 std::string Buffer;
380 llvm::raw_string_ostream OS(Buffer);
381 OS << "Want:\n";
382 Want.print(OS);
383 OS << "Got:\n";
384 Got.print(OS);
385 OS.flush();
386 *result_listener << "MemProf Record differs!\n" << Buffer;
387 return false;
390 if (Want.AllocSites.size() != Got.AllocSites.size())
391 return PrintAndFail();
392 if (Want.CallSites.size() != Got.CallSites.size())
393 return PrintAndFail();
395 for (size_t I = 0; I < Got.AllocSites.size(); I++) {
396 if (Want.AllocSites[I].Info != Got.AllocSites[I].Info)
397 return PrintAndFail();
398 if (Want.AllocSites[I].CallStack != Got.AllocSites[I].CallStack)
399 return PrintAndFail();
402 for (size_t I = 0; I < Got.CallSites.size(); I++) {
403 if (Want.CallSites[I] != Got.CallSites[I])
404 return PrintAndFail();
406 return true;
409 TEST_F(InstrProfTest, test_memprof) {
410 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::MemProf),
411 Succeeded());
413 const IndexedMemProfRecord IndexedMR = makeRecord(
414 /*AllocFrames=*/
416 {0, 1},
417 {2, 3},
419 /*CallSiteFrames=*/{
420 {4, 5},
422 const FrameIdMapTy IdToFrameMap = getFrameMapping();
423 for (const auto &I : IdToFrameMap) {
424 Writer.addMemProfFrame(I.first, I.getSecond(), Err);
426 Writer.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
428 auto Profile = Writer.writeBuffer();
429 readProfile(std::move(Profile));
431 auto RecordOr = Reader->getMemProfRecord(0x9999);
432 ASSERT_THAT_ERROR(RecordOr.takeError(), Succeeded());
433 const memprof::MemProfRecord &Record = RecordOr.get();
435 memprof::FrameId LastUnmappedFrameId = 0;
436 bool HasFrameMappingError = false;
437 auto IdToFrameCallback = [&](const memprof::FrameId Id) {
438 auto Iter = IdToFrameMap.find(Id);
439 if (Iter == IdToFrameMap.end()) {
440 LastUnmappedFrameId = Id;
441 HasFrameMappingError = true;
442 return memprof::Frame(0, 0, 0, false);
444 return Iter->second;
447 const memprof::MemProfRecord WantRecord(IndexedMR, IdToFrameCallback);
448 ASSERT_FALSE(HasFrameMappingError)
449 << "could not map frame id: " << LastUnmappedFrameId;
450 EXPECT_THAT(WantRecord, EqualsRecord(Record));
453 TEST_F(InstrProfTest, test_memprof_getrecord_error) {
454 ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::MemProf),
455 Succeeded());
457 const IndexedMemProfRecord IndexedMR = makeRecord(
458 /*AllocFrames=*/
460 {0, 1},
461 {2, 3},
463 /*CallSiteFrames=*/{
464 {4, 5},
466 // We skip adding the frame mappings here unlike the test_memprof unit test
467 // above to exercise the failure path when getMemProfRecord is invoked.
468 Writer.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
470 auto Profile = Writer.writeBuffer();
471 readProfile(std::move(Profile));
473 // Missing frames give a hash_mismatch error.
474 auto RecordOr = Reader->getMemProfRecord(0x9999);
475 ASSERT_TRUE(
476 ErrorEquals(instrprof_error::hash_mismatch, RecordOr.takeError()));
478 // Missing functions give a unknown_function error.
479 RecordOr = Reader->getMemProfRecord(0x1111);
480 ASSERT_TRUE(
481 ErrorEquals(instrprof_error::unknown_function, RecordOr.takeError()));
484 TEST_F(InstrProfTest, test_memprof_merge) {
485 Writer.addRecord({"func1", 0x1234, {42}}, Err);
487 InstrProfWriter Writer2;
488 ASSERT_THAT_ERROR(Writer2.mergeProfileKind(InstrProfKind::MemProf),
489 Succeeded());
491 const IndexedMemProfRecord IndexedMR = makeRecord(
492 /*AllocFrames=*/
494 {0, 1},
495 {2, 3},
497 /*CallSiteFrames=*/{
498 {4, 5},
501 const FrameIdMapTy IdToFrameMap = getFrameMapping();
502 for (const auto &I : IdToFrameMap) {
503 Writer.addMemProfFrame(I.first, I.getSecond(), Err);
505 Writer2.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
507 ASSERT_THAT_ERROR(Writer.mergeProfileKind(Writer2.getProfileKind()),
508 Succeeded());
509 Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
511 auto Profile = Writer.writeBuffer();
512 readProfile(std::move(Profile));
514 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("func1", 0x1234);
515 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
516 ASSERT_EQ(1U, R->Counts.size());
517 ASSERT_EQ(42U, R->Counts[0]);
519 auto RecordOr = Reader->getMemProfRecord(0x9999);
520 ASSERT_THAT_ERROR(RecordOr.takeError(), Succeeded());
521 const memprof::MemProfRecord &Record = RecordOr.get();
523 memprof::FrameId LastUnmappedFrameId = 0;
524 bool HasFrameMappingError = false;
526 auto IdToFrameCallback = [&](const memprof::FrameId Id) {
527 auto Iter = IdToFrameMap.find(Id);
528 if (Iter == IdToFrameMap.end()) {
529 LastUnmappedFrameId = Id;
530 HasFrameMappingError = true;
531 return memprof::Frame(0, 0, 0, false);
533 return Iter->second;
536 const memprof::MemProfRecord WantRecord(IndexedMR, IdToFrameCallback);
537 ASSERT_FALSE(HasFrameMappingError)
538 << "could not map frame id: " << LastUnmappedFrameId;
539 EXPECT_THAT(WantRecord, EqualsRecord(Record));
542 TEST_F(InstrProfTest, test_irpgo_function_name) {
543 LLVMContext Ctx;
544 auto M = std::make_unique<Module>("MyModule.cpp", Ctx);
545 auto *FTy = FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false);
547 std::vector<std::tuple<StringRef, Function::LinkageTypes, StringRef>> Data;
548 Data.emplace_back("ExternalFoo", Function::ExternalLinkage, "ExternalFoo");
549 Data.emplace_back("InternalFoo", Function::InternalLinkage,
550 "MyModule.cpp;InternalFoo");
551 Data.emplace_back("\01-[C dynamicFoo:]", Function::ExternalLinkage,
552 "-[C dynamicFoo:]");
553 Data.emplace_back("\01-[C internalFoo:]", Function::InternalLinkage,
554 "MyModule.cpp;-[C internalFoo:]");
556 for (auto &[Name, Linkage, ExpectedIRPGOFuncName] : Data)
557 Function::Create(FTy, Linkage, Name, M.get());
559 for (auto &[Name, Linkage, ExpectedIRPGOFuncName] : Data) {
560 auto *F = M->getFunction(Name);
561 auto IRPGOFuncName = getIRPGOFuncName(*F);
562 EXPECT_EQ(IRPGOFuncName, ExpectedIRPGOFuncName);
564 auto [Filename, ParsedIRPGOFuncName] =
565 getParsedIRPGOFuncName(IRPGOFuncName);
566 StringRef ExpectedParsedIRPGOFuncName = IRPGOFuncName;
567 if (ExpectedParsedIRPGOFuncName.consume_front("MyModule.cpp;")) {
568 EXPECT_EQ(Filename, "MyModule.cpp");
569 } else {
570 EXPECT_EQ(Filename, "");
572 EXPECT_EQ(ParsedIRPGOFuncName, ExpectedParsedIRPGOFuncName);
576 TEST_F(InstrProfTest, test_pgo_function_name) {
577 LLVMContext Ctx;
578 auto M = std::make_unique<Module>("MyModule.cpp", Ctx);
579 auto *FTy = FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false);
581 std::vector<std::tuple<StringRef, Function::LinkageTypes, StringRef>> Data;
582 Data.emplace_back("ExternalFoo", Function::ExternalLinkage, "ExternalFoo");
583 Data.emplace_back("InternalFoo", Function::InternalLinkage,
584 "MyModule.cpp:InternalFoo");
585 Data.emplace_back("\01-[C externalFoo:]", Function::ExternalLinkage,
586 "-[C externalFoo:]");
587 Data.emplace_back("\01-[C internalFoo:]", Function::InternalLinkage,
588 "MyModule.cpp:-[C internalFoo:]");
590 for (auto &[Name, Linkage, ExpectedPGOFuncName] : Data)
591 Function::Create(FTy, Linkage, Name, M.get());
593 for (auto &[Name, Linkage, ExpectedPGOFuncName] : Data) {
594 auto *F = M->getFunction(Name);
595 EXPECT_EQ(getPGOFuncName(*F), ExpectedPGOFuncName);
599 TEST_F(InstrProfTest, test_irpgo_read_deprecated_names) {
600 LLVMContext Ctx;
601 auto M = std::make_unique<Module>("MyModule.cpp", Ctx);
602 auto *FTy = FunctionType::get(Type::getVoidTy(Ctx), /*isVarArg=*/false);
603 auto *InternalFooF =
604 Function::Create(FTy, Function::InternalLinkage, "InternalFoo", M.get());
605 auto *ExternalFooF =
606 Function::Create(FTy, Function::ExternalLinkage, "ExternalFoo", M.get());
608 auto *InternalBarF =
609 Function::Create(FTy, Function::InternalLinkage, "InternalBar", M.get());
610 auto *ExternalBarF =
611 Function::Create(FTy, Function::ExternalLinkage, "ExternalBar", M.get());
613 Writer.addRecord({getIRPGOFuncName(*InternalFooF), 0x1234, {1}}, Err);
614 Writer.addRecord({getIRPGOFuncName(*ExternalFooF), 0x5678, {1}}, Err);
615 // Write a record with a deprecated name
616 Writer.addRecord({getPGOFuncName(*InternalBarF), 0x1111, {2}}, Err);
617 Writer.addRecord({getPGOFuncName(*ExternalBarF), 0x2222, {2}}, Err);
619 auto Profile = Writer.writeBuffer();
620 readProfile(std::move(Profile));
622 EXPECT_THAT_EXPECTED(
623 Reader->getInstrProfRecord(getIRPGOFuncName(*InternalFooF), 0x1234,
624 getPGOFuncName(*InternalFooF)),
625 Succeeded());
626 EXPECT_THAT_EXPECTED(
627 Reader->getInstrProfRecord(getIRPGOFuncName(*ExternalFooF), 0x5678,
628 getPGOFuncName(*ExternalFooF)),
629 Succeeded());
630 // Ensure we can still read this old record name
631 EXPECT_THAT_EXPECTED(
632 Reader->getInstrProfRecord(getIRPGOFuncName(*InternalBarF), 0x1111,
633 getPGOFuncName(*InternalBarF)),
634 Succeeded());
635 EXPECT_THAT_EXPECTED(
636 Reader->getInstrProfRecord(getIRPGOFuncName(*ExternalBarF), 0x2222,
637 getPGOFuncName(*ExternalBarF)),
638 Succeeded());
641 static const char callee1[] = "callee1";
642 static const char callee2[] = "callee2";
643 static const char callee3[] = "callee3";
644 static const char callee4[] = "callee4";
645 static const char callee5[] = "callee5";
646 static const char callee6[] = "callee6";
648 TEST_P(InstrProfReaderWriterTest, icall_data_read_write) {
649 NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
651 // 4 value sites.
652 Record1.reserveSites(IPVK_IndirectCallTarget, 4);
653 InstrProfValueData VD0[] = {
654 {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}};
655 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
656 // No value profile data at the second site.
657 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
658 InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}};
659 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
660 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
661 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
663 Writer.addRecord(std::move(Record1), getProfWeight(), Err);
664 Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
665 Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
666 Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
668 // Set writer value prof data endianness.
669 Writer.setValueProfDataEndianness(getEndianness());
671 auto Profile = Writer.writeBuffer();
672 readProfile(std::move(Profile));
674 // Set reader value prof data endianness.
675 Reader->setValueProfDataEndianness(getEndianness());
677 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
678 ASSERT_THAT_ERROR(R.takeError(), Succeeded());
679 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
680 EXPECT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
681 EXPECT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
682 EXPECT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
683 EXPECT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
685 uint64_t TotalC;
686 std::unique_ptr<InstrProfValueData[]> VD =
687 R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);
689 EXPECT_EQ(3U * getProfWeight(), VD[0].Count);
690 EXPECT_EQ(2U * getProfWeight(), VD[1].Count);
691 EXPECT_EQ(1U * getProfWeight(), VD[2].Count);
692 EXPECT_EQ(6U * getProfWeight(), TotalC);
694 EXPECT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
695 EXPECT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
696 EXPECT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
699 INSTANTIATE_TEST_SUITE_P(
700 WeightAndEndiannessTest, InstrProfReaderWriterTest,
701 ::testing::Combine(
702 ::testing::Bool(), /* Sparse */
703 ::testing::Values(1U, 10U), /* ProfWeight */
704 ::testing::Values(llvm::endianness::big,
705 llvm::endianness::little) /* Endianness */
708 TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
709 NamedInstrProfRecord Record("caller", 0x1234, {1, 2});
710 Record.reserveSites(IPVK_IndirectCallTarget, 1);
711 InstrProfValueData VD0[] = {{1000, 1}, {2000, 2}, {3000, 3}, {5000, 5},
712 {4000, 4}, {6000, 6}};
713 Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 6, nullptr);
714 Writer.addRecord(std::move(Record), Err);
715 auto Profile = Writer.writeBuffer();
716 readProfile(std::move(Profile));
717 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
718 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
720 LLVMContext Ctx;
721 std::unique_ptr<Module> M(new Module("MyModule", Ctx));
722 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
723 /*isVarArg=*/false);
724 Function *F =
725 Function::Create(FTy, Function::ExternalLinkage, "caller", M.get());
726 BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
728 IRBuilder<> Builder(BB);
729 BasicBlock *TBB = BasicBlock::Create(Ctx, "", F);
730 BasicBlock *FBB = BasicBlock::Create(Ctx, "", F);
732 // Use branch instruction to annotate with value profile data for simplicity
733 Instruction *Inst = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
734 Instruction *Inst2 = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
735 annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0);
737 InstrProfValueData ValueData[5];
738 uint32_t N;
739 uint64_t T;
740 bool Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
741 ValueData, N, T);
742 ASSERT_TRUE(Res);
743 ASSERT_EQ(3U, N);
744 ASSERT_EQ(21U, T);
745 // The result should be sorted already:
746 ASSERT_EQ(6000U, ValueData[0].Value);
747 ASSERT_EQ(6U, ValueData[0].Count);
748 ASSERT_EQ(5000U, ValueData[1].Value);
749 ASSERT_EQ(5U, ValueData[1].Count);
750 ASSERT_EQ(4000U, ValueData[2].Value);
751 ASSERT_EQ(4U, ValueData[2].Count);
752 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 1, ValueData,
753 N, T);
754 ASSERT_TRUE(Res);
755 ASSERT_EQ(1U, N);
756 ASSERT_EQ(21U, T);
758 Res = getValueProfDataFromInst(*Inst2, IPVK_IndirectCallTarget, 5, ValueData,
759 N, T);
760 ASSERT_FALSE(Res);
762 // Remove the MD_prof metadata
763 Inst->setMetadata(LLVMContext::MD_prof, 0);
764 // Annotate 5 records this time.
765 annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0, 5);
766 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
767 ValueData, N, T);
768 ASSERT_TRUE(Res);
769 ASSERT_EQ(5U, N);
770 ASSERT_EQ(21U, T);
771 ASSERT_EQ(6000U, ValueData[0].Value);
772 ASSERT_EQ(6U, ValueData[0].Count);
773 ASSERT_EQ(5000U, ValueData[1].Value);
774 ASSERT_EQ(5U, ValueData[1].Count);
775 ASSERT_EQ(4000U, ValueData[2].Value);
776 ASSERT_EQ(4U, ValueData[2].Count);
777 ASSERT_EQ(3000U, ValueData[3].Value);
778 ASSERT_EQ(3U, ValueData[3].Count);
779 ASSERT_EQ(2000U, ValueData[4].Value);
780 ASSERT_EQ(2U, ValueData[4].Count);
782 // Remove the MD_prof metadata
783 Inst->setMetadata(LLVMContext::MD_prof, 0);
784 // Annotate with 4 records.
785 InstrProfValueData VD0Sorted[] = {{1000, 6}, {2000, 5}, {3000, 4}, {4000, 3},
786 {5000, 2}, {6000, 1}};
787 annotateValueSite(*M, *Inst, ArrayRef(VD0Sorted).slice(2), 10,
788 IPVK_IndirectCallTarget, 5);
789 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
790 ValueData, N, T);
791 ASSERT_TRUE(Res);
792 ASSERT_EQ(4U, N);
793 ASSERT_EQ(10U, T);
794 ASSERT_EQ(3000U, ValueData[0].Value);
795 ASSERT_EQ(4U, ValueData[0].Count);
796 ASSERT_EQ(4000U, ValueData[1].Value);
797 ASSERT_EQ(3U, ValueData[1].Count);
798 ASSERT_EQ(5000U, ValueData[2].Value);
799 ASSERT_EQ(2U, ValueData[2].Count);
800 ASSERT_EQ(6000U, ValueData[3].Value);
801 ASSERT_EQ(1U, ValueData[3].Count);
804 TEST_P(MaybeSparseInstrProfTest, icall_data_merge) {
805 static const char caller[] = "caller";
806 NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
807 NamedInstrProfRecord Record12(caller, 0x1234, {1, 2});
809 // 5 value sites.
810 Record11.reserveSites(IPVK_IndirectCallTarget, 5);
811 InstrProfValueData VD0[] = {{uint64_t(callee1), 1},
812 {uint64_t(callee2), 2},
813 {uint64_t(callee3), 3},
814 {uint64_t(callee4), 4}};
815 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr);
817 // No value profile data at the second site.
818 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
820 InstrProfValueData VD2[] = {
821 {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}};
822 Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
824 InstrProfValueData VD3[] = {{uint64_t(callee1), 1}};
825 Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
827 InstrProfValueData VD4[] = {{uint64_t(callee1), 1},
828 {uint64_t(callee2), 2},
829 {uint64_t(callee3), 3}};
830 Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr);
832 // A different record for the same caller.
833 Record12.reserveSites(IPVK_IndirectCallTarget, 5);
834 InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}};
835 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr);
837 // No value profile data at the second site.
838 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
840 InstrProfValueData VD22[] = {
841 {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}};
842 Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr);
844 Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr);
846 InstrProfValueData VD42[] = {{uint64_t(callee1), 1},
847 {uint64_t(callee2), 2},
848 {uint64_t(callee3), 3}};
849 Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr);
851 Writer.addRecord(std::move(Record11), Err);
852 // Merge profile data.
853 Writer.addRecord(std::move(Record12), Err);
855 Writer.addRecord({callee1, 0x1235, {3, 4}}, Err);
856 Writer.addRecord({callee2, 0x1235, {3, 4}}, Err);
857 Writer.addRecord({callee3, 0x1235, {3, 4}}, Err);
858 Writer.addRecord({callee3, 0x1235, {3, 4}}, Err);
859 Writer.addRecord({callee4, 0x1235, {3, 5}}, Err);
860 auto Profile = Writer.writeBuffer();
861 readProfile(std::move(Profile));
863 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
864 EXPECT_THAT_ERROR(R.takeError(), Succeeded());
865 ASSERT_EQ(5U, R->getNumValueSites(IPVK_IndirectCallTarget));
866 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
867 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
868 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
869 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
870 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
872 std::unique_ptr<InstrProfValueData[]> VD =
873 R->getValueForSite(IPVK_IndirectCallTarget, 0);
874 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2"));
875 ASSERT_EQ(7U, VD[0].Count);
876 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3"));
877 ASSERT_EQ(6U, VD[1].Count);
878 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4"));
879 ASSERT_EQ(4U, VD[2].Count);
880 ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1"));
881 ASSERT_EQ(1U, VD[3].Count);
883 std::unique_ptr<InstrProfValueData[]> VD_2(
884 R->getValueForSite(IPVK_IndirectCallTarget, 2));
885 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3"));
886 ASSERT_EQ(6U, VD_2[0].Count);
887 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4"));
888 ASSERT_EQ(4U, VD_2[1].Count);
889 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2"));
890 ASSERT_EQ(3U, VD_2[2].Count);
891 ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1"));
892 ASSERT_EQ(1U, VD_2[3].Count);
894 std::unique_ptr<InstrProfValueData[]> VD_3(
895 R->getValueForSite(IPVK_IndirectCallTarget, 3));
896 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1"));
897 ASSERT_EQ(1U, VD_3[0].Count);
899 std::unique_ptr<InstrProfValueData[]> VD_4(
900 R->getValueForSite(IPVK_IndirectCallTarget, 4));
901 ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3"));
902 ASSERT_EQ(6U, VD_4[0].Count);
903 ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2"));
904 ASSERT_EQ(4U, VD_4[1].Count);
905 ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1"));
906 ASSERT_EQ(2U, VD_4[2].Count);
909 struct ValueProfileMergeEdgeCaseTest
910 : public InstrProfTest,
911 public ::testing::WithParamInterface<std::tuple<bool, uint32_t>> {
912 void SetUp() override { Writer.setOutputSparse(std::get<0>(GetParam())); }
914 uint32_t getValueProfileKind() const { return std::get<1>(GetParam()); }
917 TEST_P(ValueProfileMergeEdgeCaseTest, value_profile_data_merge_saturation) {
918 const uint32_t ValueKind = getValueProfileKind();
919 static const char bar[] = "bar";
920 const uint64_t ProfiledValue = 0x5678;
922 const uint64_t MaxValCount = std::numeric_limits<uint64_t>::max();
923 const uint64_t MaxEdgeCount = getInstrMaxCountValue();
925 instrprof_error Result;
926 auto Err = [&](Error E) {
927 Result = std::get<0>(InstrProfError::take(std::move(E)));
929 Result = instrprof_error::success;
930 Writer.addRecord({"foo", 0x1234, {1}}, Err);
931 ASSERT_EQ(Result, instrprof_error::success);
933 // Verify counter overflow.
934 Result = instrprof_error::success;
935 Writer.addRecord({"foo", 0x1234, {MaxEdgeCount}}, Err);
936 ASSERT_EQ(Result, instrprof_error::counter_overflow);
938 Result = instrprof_error::success;
939 Writer.addRecord({bar, 0x9012, {8}}, Err);
940 ASSERT_EQ(Result, instrprof_error::success);
942 NamedInstrProfRecord Record4("baz", 0x5678, {3, 4});
943 Record4.reserveSites(ValueKind, 1);
944 InstrProfValueData VD4[] = {{ProfiledValue, 1}};
945 Record4.addValueData(ValueKind, 0, VD4, 1, nullptr);
946 Result = instrprof_error::success;
947 Writer.addRecord(std::move(Record4), Err);
948 ASSERT_EQ(Result, instrprof_error::success);
950 // Verify value data counter overflow.
951 NamedInstrProfRecord Record5("baz", 0x5678, {5, 6});
952 Record5.reserveSites(ValueKind, 1);
953 InstrProfValueData VD5[] = {{ProfiledValue, MaxValCount}};
954 Record5.addValueData(ValueKind, 0, VD5, 1, nullptr);
955 Result = instrprof_error::success;
956 Writer.addRecord(std::move(Record5), Err);
957 ASSERT_EQ(Result, instrprof_error::counter_overflow);
959 auto Profile = Writer.writeBuffer();
960 readProfile(std::move(Profile));
962 // Verify saturation of counts.
963 Expected<InstrProfRecord> ReadRecord1 =
964 Reader->getInstrProfRecord("foo", 0x1234);
965 ASSERT_THAT_ERROR(ReadRecord1.takeError(), Succeeded());
966 EXPECT_EQ(MaxEdgeCount, ReadRecord1->Counts[0]);
968 Expected<InstrProfRecord> ReadRecord2 =
969 Reader->getInstrProfRecord("baz", 0x5678);
970 ASSERT_TRUE(bool(ReadRecord2));
971 ASSERT_EQ(1U, ReadRecord2->getNumValueSites(ValueKind));
972 std::unique_ptr<InstrProfValueData[]> VD =
973 ReadRecord2->getValueForSite(ValueKind, 0);
974 EXPECT_EQ(ProfiledValue, VD[0].Value);
975 EXPECT_EQ(MaxValCount, VD[0].Count);
978 // This test tests that when there are too many values for a given site, the
979 // merged results are properly truncated.
980 TEST_P(ValueProfileMergeEdgeCaseTest, value_profile_data_merge_site_trunc) {
981 const uint32_t ValueKind = getValueProfileKind();
982 static const char caller[] = "caller";
984 NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
985 NamedInstrProfRecord Record12(caller, 0x1234, {1, 2});
987 // 2 value sites.
988 Record11.reserveSites(ValueKind, 2);
989 InstrProfValueData VD0[255];
990 for (int I = 0; I < 255; I++) {
991 VD0[I].Value = 2 * I;
992 VD0[I].Count = 2 * I + 1000;
995 Record11.addValueData(ValueKind, 0, VD0, 255, nullptr);
996 Record11.addValueData(ValueKind, 1, nullptr, 0, nullptr);
998 Record12.reserveSites(ValueKind, 2);
999 InstrProfValueData VD1[255];
1000 for (int I = 0; I < 255; I++) {
1001 VD1[I].Value = 2 * I + 1;
1002 VD1[I].Count = 2 * I + 1001;
1005 Record12.addValueData(ValueKind, 0, VD1, 255, nullptr);
1006 Record12.addValueData(ValueKind, 1, nullptr, 0, nullptr);
1008 Writer.addRecord(std::move(Record11), Err);
1009 // Merge profile data.
1010 Writer.addRecord(std::move(Record12), Err);
1012 auto Profile = Writer.writeBuffer();
1013 readProfile(std::move(Profile));
1015 Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
1016 ASSERT_THAT_ERROR(R.takeError(), Succeeded());
1017 std::unique_ptr<InstrProfValueData[]> VD(R->getValueForSite(ValueKind, 0));
1018 ASSERT_EQ(2U, R->getNumValueSites(ValueKind));
1019 EXPECT_EQ(255U, R->getNumValueDataForSite(ValueKind, 0));
1020 for (unsigned I = 0; I < 255; I++) {
1021 EXPECT_EQ(VD[I].Value, 509 - I);
1022 EXPECT_EQ(VD[I].Count, 1509 - I);
1026 INSTANTIATE_TEST_SUITE_P(
1027 EdgeCaseTest, ValueProfileMergeEdgeCaseTest,
1028 ::testing::Combine(::testing::Bool(), /* Sparse */
1029 ::testing::Values(IPVK_IndirectCallTarget,
1030 IPVK_MemOPSize) /* ValueKind */
1033 static void addValueProfData(InstrProfRecord &Record) {
1034 Record.reserveSites(IPVK_IndirectCallTarget, 5);
1035 InstrProfValueData VD0[] = {{uint64_t(callee1), 400},
1036 {uint64_t(callee2), 1000},
1037 {uint64_t(callee3), 500},
1038 {uint64_t(callee4), 300},
1039 {uint64_t(callee5), 100}};
1040 Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 5, nullptr);
1041 InstrProfValueData VD1[] = {{uint64_t(callee5), 800},
1042 {uint64_t(callee3), 1000},
1043 {uint64_t(callee2), 2500},
1044 {uint64_t(callee1), 1300}};
1045 Record.addValueData(IPVK_IndirectCallTarget, 1, VD1, 4, nullptr);
1046 InstrProfValueData VD2[] = {{uint64_t(callee6), 800},
1047 {uint64_t(callee3), 1000},
1048 {uint64_t(callee4), 5500}};
1049 Record.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
1050 InstrProfValueData VD3[] = {{uint64_t(callee2), 1800},
1051 {uint64_t(callee3), 2000}};
1052 Record.addValueData(IPVK_IndirectCallTarget, 3, VD3, 2, nullptr);
1053 Record.addValueData(IPVK_IndirectCallTarget, 4, nullptr, 0, nullptr);
1056 TEST(ValueProfileReadWriteTest, value_prof_data_read_write) {
1057 InstrProfRecord SrcRecord({1ULL << 31, 2});
1058 addValueProfData(SrcRecord);
1059 std::unique_ptr<ValueProfData> VPData =
1060 ValueProfData::serializeFrom(SrcRecord);
1062 InstrProfRecord Record({1ULL << 31, 2});
1063 VPData->deserializeTo(Record, nullptr);
1065 // Now read data from Record and sanity check the data
1066 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
1067 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
1068 ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
1069 ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
1070 ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
1071 ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
1073 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
1074 return VD1.Count > VD2.Count;
1076 std::unique_ptr<InstrProfValueData[]> VD_0(
1077 Record.getValueForSite(IPVK_IndirectCallTarget, 0));
1078 llvm::sort(&VD_0[0], &VD_0[5], Cmp);
1079 ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2"));
1080 ASSERT_EQ(1000U, VD_0[0].Count);
1081 ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3"));
1082 ASSERT_EQ(500U, VD_0[1].Count);
1083 ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1"));
1084 ASSERT_EQ(400U, VD_0[2].Count);
1085 ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4"));
1086 ASSERT_EQ(300U, VD_0[3].Count);
1087 ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5"));
1088 ASSERT_EQ(100U, VD_0[4].Count);
1090 std::unique_ptr<InstrProfValueData[]> VD_1(
1091 Record.getValueForSite(IPVK_IndirectCallTarget, 1));
1092 llvm::sort(&VD_1[0], &VD_1[4], Cmp);
1093 ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2"));
1094 ASSERT_EQ(2500U, VD_1[0].Count);
1095 ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1"));
1096 ASSERT_EQ(1300U, VD_1[1].Count);
1097 ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3"));
1098 ASSERT_EQ(1000U, VD_1[2].Count);
1099 ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5"));
1100 ASSERT_EQ(800U, VD_1[3].Count);
1102 std::unique_ptr<InstrProfValueData[]> VD_2(
1103 Record.getValueForSite(IPVK_IndirectCallTarget, 2));
1104 llvm::sort(&VD_2[0], &VD_2[3], Cmp);
1105 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4"));
1106 ASSERT_EQ(5500U, VD_2[0].Count);
1107 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3"));
1108 ASSERT_EQ(1000U, VD_2[1].Count);
1109 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6"));
1110 ASSERT_EQ(800U, VD_2[2].Count);
1112 std::unique_ptr<InstrProfValueData[]> VD_3(
1113 Record.getValueForSite(IPVK_IndirectCallTarget, 3));
1114 llvm::sort(&VD_3[0], &VD_3[2], Cmp);
1115 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3"));
1116 ASSERT_EQ(2000U, VD_3[0].Count);
1117 ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2"));
1118 ASSERT_EQ(1800U, VD_3[1].Count);
1121 TEST(ValueProfileReadWriteTest, symtab_mapping) {
1122 NamedInstrProfRecord SrcRecord("caller", 0x1234, {1ULL << 31, 2});
1123 addValueProfData(SrcRecord);
1124 std::unique_ptr<ValueProfData> VPData =
1125 ValueProfData::serializeFrom(SrcRecord);
1127 NamedInstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
1128 InstrProfSymtab Symtab;
1129 Symtab.mapAddress(uint64_t(callee1), 0x1000ULL);
1130 Symtab.mapAddress(uint64_t(callee2), 0x2000ULL);
1131 Symtab.mapAddress(uint64_t(callee3), 0x3000ULL);
1132 Symtab.mapAddress(uint64_t(callee4), 0x4000ULL);
1133 // Missing mapping for callee5
1135 VPData->deserializeTo(Record, &Symtab);
1137 // Now read data from Record and sanity check the data
1138 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
1139 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
1141 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
1142 return VD1.Count > VD2.Count;
1144 std::unique_ptr<InstrProfValueData[]> VD_0(
1145 Record.getValueForSite(IPVK_IndirectCallTarget, 0));
1146 llvm::sort(&VD_0[0], &VD_0[5], Cmp);
1147 ASSERT_EQ(VD_0[0].Value, 0x2000ULL);
1148 ASSERT_EQ(1000U, VD_0[0].Count);
1149 ASSERT_EQ(VD_0[1].Value, 0x3000ULL);
1150 ASSERT_EQ(500U, VD_0[1].Count);
1151 ASSERT_EQ(VD_0[2].Value, 0x1000ULL);
1152 ASSERT_EQ(400U, VD_0[2].Count);
1154 // callee5 does not have a mapped value -- default to 0.
1155 ASSERT_EQ(VD_0[4].Value, 0ULL);
1158 TEST_P(MaybeSparseInstrProfTest, get_max_function_count) {
1159 Writer.addRecord({"foo", 0x1234, {1ULL << 31, 2}}, Err);
1160 Writer.addRecord({"bar", 0, {1ULL << 63}}, Err);
1161 Writer.addRecord({"baz", 0x5678, {0, 0, 0, 0}}, Err);
1162 auto Profile = Writer.writeBuffer();
1163 readProfile(std::move(Profile));
1165 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount(/* IsCS */ false));
1168 TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) {
1169 Writer.addRecord({"foo", 0x1234, {1, 2}}, 3, Err);
1170 Writer.addRecord({"foo", 0x1235, {3, 4}}, 5, Err);
1171 auto Profile = Writer.writeBuffer();
1172 readProfile(std::move(Profile));
1174 std::vector<uint64_t> Counts;
1175 EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1234, Counts),
1176 Succeeded());
1177 ASSERT_EQ(2U, Counts.size());
1178 ASSERT_EQ(3U, Counts[0]);
1179 ASSERT_EQ(6U, Counts[1]);
1181 EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1235, Counts),
1182 Succeeded());
1183 ASSERT_EQ(2U, Counts.size());
1184 ASSERT_EQ(15U, Counts[0]);
1185 ASSERT_EQ(20U, Counts[1]);
1188 // Testing symtab creator interface used by indexed profile reader.
1189 TEST(SymtabTest, instr_prof_symtab_test) {
1190 std::vector<StringRef> FuncNames;
1191 FuncNames.push_back("func1");
1192 FuncNames.push_back("func2");
1193 FuncNames.push_back("func3");
1194 FuncNames.push_back("bar1");
1195 FuncNames.push_back("bar2");
1196 FuncNames.push_back("bar3");
1197 InstrProfSymtab Symtab;
1198 EXPECT_THAT_ERROR(Symtab.create(FuncNames), Succeeded());
1199 StringRef R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func1"));
1200 ASSERT_EQ(StringRef("func1"), R);
1201 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func2"));
1202 ASSERT_EQ(StringRef("func2"), R);
1203 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func3"));
1204 ASSERT_EQ(StringRef("func3"), R);
1205 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar1"));
1206 ASSERT_EQ(StringRef("bar1"), R);
1207 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar2"));
1208 ASSERT_EQ(StringRef("bar2"), R);
1209 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar3"));
1210 ASSERT_EQ(StringRef("bar3"), R);
1212 // negative tests
1213 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar4"));
1214 ASSERT_EQ(StringRef(), R);
1215 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("foo4"));
1216 ASSERT_EQ(StringRef(), R);
1218 // Now incrementally update the symtab
1219 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_1"), Succeeded());
1220 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_2"), Succeeded());
1221 EXPECT_THAT_ERROR(Symtab.addFuncName("blah_3"), Succeeded());
1223 // Check again
1224 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("blah_1"));
1225 ASSERT_EQ(StringRef("blah_1"), R);
1226 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("blah_2"));
1227 ASSERT_EQ(StringRef("blah_2"), R);
1228 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("blah_3"));
1229 ASSERT_EQ(StringRef("blah_3"), R);
1230 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func1"));
1231 ASSERT_EQ(StringRef("func1"), R);
1232 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func2"));
1233 ASSERT_EQ(StringRef("func2"), R);
1234 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("func3"));
1235 ASSERT_EQ(StringRef("func3"), R);
1236 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar1"));
1237 ASSERT_EQ(StringRef("bar1"), R);
1238 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar2"));
1239 ASSERT_EQ(StringRef("bar2"), R);
1240 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash("bar3"));
1241 ASSERT_EQ(StringRef("bar3"), R);
1244 // Test that we get an error when creating a bogus symtab.
1245 TEST(SymtabTest, instr_prof_bogus_symtab_empty_func_name) {
1246 InstrProfSymtab Symtab;
1247 EXPECT_TRUE(ErrorEquals(instrprof_error::malformed, Symtab.addFuncName("")));
1250 // Testing symtab creator interface used by value profile transformer.
1251 TEST(SymtabTest, instr_prof_symtab_module_test) {
1252 LLVMContext Ctx;
1253 std::unique_ptr<Module> M = std::make_unique<Module>("MyModule.cpp", Ctx);
1254 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
1255 /*isVarArg=*/false);
1256 Function::Create(FTy, Function::ExternalLinkage, "Gfoo", M.get());
1257 Function::Create(FTy, Function::ExternalLinkage, "Gblah", M.get());
1258 Function::Create(FTy, Function::ExternalLinkage, "Gbar", M.get());
1259 Function::Create(FTy, Function::InternalLinkage, "Ifoo", M.get());
1260 Function::Create(FTy, Function::InternalLinkage, "Iblah", M.get());
1261 Function::Create(FTy, Function::InternalLinkage, "Ibar", M.get());
1262 Function::Create(FTy, Function::PrivateLinkage, "Pfoo", M.get());
1263 Function::Create(FTy, Function::PrivateLinkage, "Pblah", M.get());
1264 Function::Create(FTy, Function::PrivateLinkage, "Pbar", M.get());
1265 Function::Create(FTy, Function::WeakODRLinkage, "Wfoo", M.get());
1266 Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get());
1267 Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get());
1269 InstrProfSymtab ProfSymtab;
1270 EXPECT_THAT_ERROR(ProfSymtab.create(*M), Succeeded());
1272 StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar",
1273 "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"};
1275 for (unsigned I = 0; I < std::size(Funcs); I++) {
1276 Function *F = M->getFunction(Funcs[I]);
1278 std::string IRPGOName = getIRPGOFuncName(*F);
1279 auto IRPGOFuncName =
1280 ProfSymtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(IRPGOName));
1281 EXPECT_EQ(StringRef(IRPGOName), IRPGOFuncName);
1282 EXPECT_EQ(StringRef(Funcs[I]),
1283 getParsedIRPGOFuncName(IRPGOFuncName).second);
1284 // Ensure we can still read this old record name.
1285 std::string PGOName = getPGOFuncName(*F);
1286 auto PGOFuncName =
1287 ProfSymtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(PGOName));
1288 EXPECT_EQ(StringRef(PGOName), PGOFuncName);
1289 EXPECT_THAT(PGOFuncName.str(), EndsWith(Funcs[I].str()));
1293 // Testing symtab serialization and creator/deserialization interface
1294 // used by coverage map reader, and raw profile reader.
1295 TEST(SymtabTest, instr_prof_symtab_compression_test) {
1296 std::vector<std::string> FuncNames1;
1297 std::vector<std::string> FuncNames2;
1298 for (int I = 0; I < 3; I++) {
1299 std::string str;
1300 raw_string_ostream OS(str);
1301 OS << "func_" << I;
1302 FuncNames1.push_back(OS.str());
1303 str.clear();
1304 OS << "f oooooooooooooo_" << I;
1305 FuncNames1.push_back(OS.str());
1306 str.clear();
1307 OS << "BAR_" << I;
1308 FuncNames2.push_back(OS.str());
1309 str.clear();
1310 OS << "BlahblahBlahblahBar_" << I;
1311 FuncNames2.push_back(OS.str());
1314 for (bool DoCompression : {false, true}) {
1315 // Compressing:
1316 std::string FuncNameStrings1;
1317 EXPECT_THAT_ERROR(collectGlobalObjectNameStrings(
1318 FuncNames1,
1319 (DoCompression && compression::zlib::isAvailable()),
1320 FuncNameStrings1),
1321 Succeeded());
1323 // Compressing:
1324 std::string FuncNameStrings2;
1325 EXPECT_THAT_ERROR(collectGlobalObjectNameStrings(
1326 FuncNames2,
1327 (DoCompression && compression::zlib::isAvailable()),
1328 FuncNameStrings2),
1329 Succeeded());
1331 for (int Padding = 0; Padding < 2; Padding++) {
1332 // Join with paddings :
1333 std::string FuncNameStrings = FuncNameStrings1;
1334 for (int P = 0; P < Padding; P++) {
1335 FuncNameStrings.push_back('\0');
1337 FuncNameStrings += FuncNameStrings2;
1339 // Now decompress:
1340 InstrProfSymtab Symtab;
1341 EXPECT_THAT_ERROR(Symtab.create(StringRef(FuncNameStrings)), Succeeded());
1343 // Now do the checks:
1344 // First sampling some data points:
1345 StringRef R =
1346 Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(FuncNames1[0]));
1347 ASSERT_EQ(StringRef("func_0"), R);
1348 R = Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(FuncNames1[1]));
1349 ASSERT_EQ(StringRef("f oooooooooooooo_0"), R);
1350 for (int I = 0; I < 3; I++) {
1351 std::string N[4];
1352 N[0] = FuncNames1[2 * I];
1353 N[1] = FuncNames1[2 * I + 1];
1354 N[2] = FuncNames2[2 * I];
1355 N[3] = FuncNames2[2 * I + 1];
1356 for (int J = 0; J < 4; J++) {
1357 StringRef R =
1358 Symtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(N[J]));
1359 ASSERT_EQ(StringRef(N[J]), R);
1366 TEST_P(MaybeSparseInstrProfTest, remapping_test) {
1367 Writer.addRecord({"_Z3fooi", 0x1234, {1, 2, 3, 4}}, Err);
1368 Writer.addRecord({"file;_Z3barf", 0x567, {5, 6, 7}}, Err);
1369 auto Profile = Writer.writeBuffer();
1370 readProfile(std::move(Profile), llvm::MemoryBuffer::getMemBuffer(R"(
1371 type i l
1372 name 3bar 4quux
1373 )"));
1375 std::vector<uint64_t> Counts;
1376 for (StringRef FooName : {"_Z3fooi", "_Z3fool"}) {
1377 EXPECT_THAT_ERROR(Reader->getFunctionCounts(FooName, 0x1234, Counts),
1378 Succeeded());
1379 ASSERT_EQ(4u, Counts.size());
1380 EXPECT_EQ(1u, Counts[0]);
1381 EXPECT_EQ(2u, Counts[1]);
1382 EXPECT_EQ(3u, Counts[2]);
1383 EXPECT_EQ(4u, Counts[3]);
1386 for (StringRef BarName : {"file;_Z3barf", "file;_Z4quuxf"}) {
1387 EXPECT_THAT_ERROR(Reader->getFunctionCounts(BarName, 0x567, Counts),
1388 Succeeded());
1389 ASSERT_EQ(3u, Counts.size());
1390 EXPECT_EQ(5u, Counts[0]);
1391 EXPECT_EQ(6u, Counts[1]);
1392 EXPECT_EQ(7u, Counts[2]);
1395 for (StringRef BadName : {"_Z3foof", "_Z4quuxi", "_Z3barl", "", "_ZZZ",
1396 "_Z3barf", "otherfile:_Z4quuxf"}) {
1397 EXPECT_THAT_ERROR(Reader->getFunctionCounts(BadName, 0x1234, Counts),
1398 Failed());
1399 EXPECT_THAT_ERROR(Reader->getFunctionCounts(BadName, 0x567, Counts),
1400 Failed());
1404 TEST_F(SparseInstrProfTest, preserve_no_records) {
1405 Writer.addRecord({"foo", 0x1234, {0}}, Err);
1406 Writer.addRecord({"bar", 0x4321, {0, 0}}, Err);
1407 Writer.addRecord({"baz", 0x4321, {0, 0, 0}}, Err);
1409 auto Profile = Writer.writeBuffer();
1410 readProfile(std::move(Profile));
1412 auto I = Reader->begin(), E = Reader->end();
1413 ASSERT_TRUE(I == E);
1416 INSTANTIATE_TEST_SUITE_P(MaybeSparse, MaybeSparseInstrProfTest,
1417 ::testing::Bool());
1419 #if defined(_LP64) && defined(EXPENSIVE_CHECKS)
1420 TEST(ProfileReaderTest, ReadsLargeFiles) {
1421 const size_t LargeSize = 1ULL << 32; // 4GB
1423 auto RawProfile = WritableMemoryBuffer::getNewUninitMemBuffer(LargeSize);
1424 if (!RawProfile)
1425 GTEST_SKIP();
1426 auto RawProfileReaderOrErr = InstrProfReader::create(std::move(RawProfile));
1427 ASSERT_TRUE(
1428 std::get<0>(InstrProfError::take(RawProfileReaderOrErr.takeError())) ==
1429 instrprof_error::unrecognized_format);
1431 auto IndexedProfile = WritableMemoryBuffer::getNewUninitMemBuffer(LargeSize);
1432 if (!IndexedProfile)
1433 GTEST_SKIP();
1434 auto IndexedReaderOrErr =
1435 IndexedInstrProfReader::create(std::move(IndexedProfile), nullptr);
1436 ASSERT_TRUE(
1437 std::get<0>(InstrProfError::take(IndexedReaderOrErr.takeError())) ==
1438 instrprof_error::bad_magic);
1440 #endif
1442 } // end anonymous namespace