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