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/LLVMContext.h"
12 #include "llvm/IR/Module.h"
13 #include "llvm/ProfileData/InstrProfReader.h"
14 #include "llvm/ProfileData/InstrProfWriter.h"
15 #include "llvm/Support/Compression.h"
16 #include "gtest/gtest.h"
17 #include <cstdarg>
18 
19 using namespace llvm;
20 
21 static ::testing::AssertionResult NoError(std::error_code EC) {
22   if (!EC)
23     return ::testing::AssertionSuccess();
24   return ::testing::AssertionFailure() << "error " << EC.value()
25                                        << ": " << EC.message();
26 }
27 
28 static ::testing::AssertionResult ErrorEquals(std::error_code Expected,
29                                               std::error_code Found) {
30   if (Expected == Found)
31     return ::testing::AssertionSuccess();
32   return ::testing::AssertionFailure() << "error " << Found.value()
33                                        << ": " << Found.message();
34 }
35 
36 namespace {
37 
38 struct InstrProfTest : ::testing::Test {
39   InstrProfWriter Writer;
40   std::unique_ptr<IndexedInstrProfReader> Reader;
41 
42   void readProfile(std::unique_ptr<MemoryBuffer> Profile) {
43     auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile));
44     ASSERT_TRUE(NoError(ReaderOrErr.getError()));
45     Reader = std::move(ReaderOrErr.get());
46   }
47 };
48 
49 TEST_F(InstrProfTest, write_and_read_empty_profile) {
50   auto Profile = Writer.writeBuffer();
51   readProfile(std::move(Profile));
52   ASSERT_TRUE(Reader->begin() == Reader->end());
53 }
54 
55 TEST_F(InstrProfTest, write_and_read_one_function) {
56   InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4});
57   Writer.addRecord(std::move(Record));
58   auto Profile = Writer.writeBuffer();
59   readProfile(std::move(Profile));
60 
61   auto I = Reader->begin(), E = Reader->end();
62   ASSERT_TRUE(I != E);
63   ASSERT_EQ(StringRef("foo"), I->Name);
64   ASSERT_EQ(0x1234U, I->Hash);
65   ASSERT_EQ(4U, I->Counts.size());
66   ASSERT_EQ(1U, I->Counts[0]);
67   ASSERT_EQ(2U, I->Counts[1]);
68   ASSERT_EQ(3U, I->Counts[2]);
69   ASSERT_EQ(4U, I->Counts[3]);
70   ASSERT_TRUE(++I == E);
71 }
72 
73 TEST_F(InstrProfTest, get_instr_prof_record) {
74   InstrProfRecord Record1("foo", 0x1234, {1, 2});
75   InstrProfRecord Record2("foo", 0x1235, {3, 4});
76   Writer.addRecord(std::move(Record1));
77   Writer.addRecord(std::move(Record2));
78   auto Profile = Writer.writeBuffer();
79   readProfile(std::move(Profile));
80 
81   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234);
82   ASSERT_TRUE(NoError(R.getError()));
83   ASSERT_EQ(2U, R.get().Counts.size());
84   ASSERT_EQ(1U, R.get().Counts[0]);
85   ASSERT_EQ(2U, R.get().Counts[1]);
86 
87   R = Reader->getInstrProfRecord("foo", 0x1235);
88   ASSERT_TRUE(NoError(R.getError()));
89   ASSERT_EQ(2U, R.get().Counts.size());
90   ASSERT_EQ(3U, R.get().Counts[0]);
91   ASSERT_EQ(4U, R.get().Counts[1]);
92 
93   R = Reader->getInstrProfRecord("foo", 0x5678);
94   ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.getError()));
95 
96   R = Reader->getInstrProfRecord("bar", 0x1234);
97   ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.getError()));
98 }
99 
100 TEST_F(InstrProfTest, get_function_counts) {
101   InstrProfRecord Record1("foo", 0x1234, {1, 2});
102   InstrProfRecord Record2("foo", 0x1235, {3, 4});
103   Writer.addRecord(std::move(Record1));
104   Writer.addRecord(std::move(Record2));
105   auto Profile = Writer.writeBuffer();
106   readProfile(std::move(Profile));
107 
108   std::vector<uint64_t> Counts;
109   ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts)));
110   ASSERT_EQ(2U, Counts.size());
111   ASSERT_EQ(1U, Counts[0]);
112   ASSERT_EQ(2U, Counts[1]);
113 
114   ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts)));
115   ASSERT_EQ(2U, Counts.size());
116   ASSERT_EQ(3U, Counts[0]);
117   ASSERT_EQ(4U, Counts[1]);
118 
119   std::error_code EC;
120   EC = Reader->getFunctionCounts("foo", 0x5678, Counts);
121   ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, EC));
122 
123   EC = Reader->getFunctionCounts("bar", 0x1234, Counts);
124   ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, EC));
125 }
126 
127 TEST_F(InstrProfTest, get_icall_data_read_write) {
128   InstrProfRecord Record1("caller", 0x1234, {1, 2});
129   InstrProfRecord Record2("callee1", 0x1235, {3, 4});
130   InstrProfRecord Record3("callee2", 0x1235, {3, 4});
131   InstrProfRecord Record4("callee3", 0x1235, {3, 4});
132 
133   // 4 value sites.
134   Record1.reserveSites(IPVK_IndirectCallTarget, 4);
135   InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
136                               {(uint64_t) "callee2", 2},
137                               {(uint64_t) "callee3", 3}};
138   Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
139   // No value profile data at the second site.
140   Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
141   InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
142                               {(uint64_t) "callee2", 2}};
143   Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
144   InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
145   Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
146 
147   Writer.addRecord(std::move(Record1));
148   Writer.addRecord(std::move(Record2));
149   Writer.addRecord(std::move(Record3));
150   Writer.addRecord(std::move(Record4));
151   auto Profile = Writer.writeBuffer();
152   readProfile(std::move(Profile));
153 
154   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
155   ASSERT_TRUE(NoError(R.getError()));
156   ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
157   ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
158   ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
159   ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
160   ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
161 
162   std::unique_ptr<InstrProfValueData[]> VD =
163       R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
164 
165   ASSERT_EQ(3U, VD[0].Count);
166   ASSERT_EQ(2U, VD[1].Count);
167   ASSERT_EQ(1U, VD[2].Count);
168 
169   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
170   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
171   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
172 }
173 
174 TEST_F(InstrProfTest, get_icall_data_read_write_with_weight) {
175   InstrProfRecord Record1("caller", 0x1234, {1, 2});
176   InstrProfRecord Record2("callee1", 0x1235, {3, 4});
177   InstrProfRecord Record3("callee2", 0x1235, {3, 4});
178   InstrProfRecord Record4("callee3", 0x1235, {3, 4});
179 
180   // 4 value sites.
181   Record1.reserveSites(IPVK_IndirectCallTarget, 4);
182   InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
183                               {(uint64_t) "callee2", 2},
184                               {(uint64_t) "callee3", 3}};
185   Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
186   // No value profile data at the second site.
187   Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
188   InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
189                               {(uint64_t) "callee2", 2}};
190   Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
191   InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
192   Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
193 
194   Writer.addRecord(std::move(Record1), 10);
195   Writer.addRecord(std::move(Record2));
196   Writer.addRecord(std::move(Record3));
197   Writer.addRecord(std::move(Record4));
198   auto Profile = Writer.writeBuffer();
199   readProfile(std::move(Profile));
200 
201   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
202   ASSERT_TRUE(NoError(R.getError()));
203   ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
204   ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
205   ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
206   ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
207   ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
208 
209   std::unique_ptr<InstrProfValueData[]> VD =
210       R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
211   ASSERT_EQ(30U, VD[0].Count);
212   ASSERT_EQ(20U, VD[1].Count);
213   ASSERT_EQ(10U, VD[2].Count);
214 
215   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
216   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
217   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
218 }
219 
220 TEST_F(InstrProfTest, get_icall_data_read_write_big_endian) {
221   InstrProfRecord Record1("caller", 0x1234, {1, 2});
222   InstrProfRecord Record2("callee1", 0x1235, {3, 4});
223   InstrProfRecord Record3("callee2", 0x1235, {3, 4});
224   InstrProfRecord Record4("callee3", 0x1235, {3, 4});
225 
226   // 4 value sites.
227   Record1.reserveSites(IPVK_IndirectCallTarget, 4);
228   InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
229                               {(uint64_t) "callee2", 2},
230                               {(uint64_t) "callee3", 3}};
231   Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
232   // No value profile data at the second site.
233   Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
234   InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
235                               {(uint64_t) "callee2", 2}};
236   Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
237   InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
238   Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
239 
240   Writer.addRecord(std::move(Record1));
241   Writer.addRecord(std::move(Record2));
242   Writer.addRecord(std::move(Record3));
243   Writer.addRecord(std::move(Record4));
244 
245   // Set big endian output.
246   Writer.setValueProfDataEndianness(support::big);
247 
248   auto Profile = Writer.writeBuffer();
249   readProfile(std::move(Profile));
250 
251   // Set big endian input.
252   Reader->setValueProfDataEndianness(support::big);
253 
254   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
255   ASSERT_TRUE(NoError(R.getError()));
256   ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
257   ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
258   ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
259   ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
260   ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
261 
262   std::unique_ptr<InstrProfValueData[]> VD =
263       R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
264   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
265   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
266   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
267 
268   // Restore little endian default:
269   Writer.setValueProfDataEndianness(support::little);
270 }
271 
272 TEST_F(InstrProfTest, get_icall_data_merge1) {
273   static const char caller[] = "caller";
274   static const char callee1[] = "callee1";
275   static const char callee2[] = "callee2";
276   static const char callee3[] = "callee3";
277   static const char callee4[] = "callee4";
278 
279   InstrProfRecord Record11(caller, 0x1234, {1, 2});
280   InstrProfRecord Record12(caller, 0x1234, {1, 2});
281   InstrProfRecord Record2(callee1, 0x1235, {3, 4});
282   InstrProfRecord Record3(callee2, 0x1235, {3, 4});
283   InstrProfRecord Record4(callee3, 0x1235, {3, 4});
284   InstrProfRecord Record5(callee3, 0x1235, {3, 4});
285   InstrProfRecord Record6(callee4, 0x1235, {3, 5});
286 
287   // 5 value sites.
288   Record11.reserveSites(IPVK_IndirectCallTarget, 5);
289   InstrProfValueData VD0[] = {{uint64_t(callee1), 1},
290                               {uint64_t(callee2), 2},
291                               {uint64_t(callee3), 3},
292                               {uint64_t(callee4), 4}};
293   Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr);
294 
295   // No value profile data at the second site.
296   Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
297 
298   InstrProfValueData VD2[] = {
299       {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}};
300   Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
301 
302   InstrProfValueData VD3[] = {{uint64_t(callee1), 1}};
303   Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
304 
305   InstrProfValueData VD4[] = {{uint64_t(callee1), 1},
306                               {uint64_t(callee2), 2},
307                               {uint64_t(callee3), 3}};
308   Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr);
309 
310   // A differnt record for the same caller.
311   Record12.reserveSites(IPVK_IndirectCallTarget, 5);
312   InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}};
313   Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr);
314 
315   // No value profile data at the second site.
316   Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
317 
318   InstrProfValueData VD22[] = {
319       {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}};
320   Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr);
321 
322   Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr);
323 
324   InstrProfValueData VD42[] = {{uint64_t(callee1), 1},
325                                {uint64_t(callee2), 2},
326                                {uint64_t(callee3), 3}};
327   Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr);
328 
329   Writer.addRecord(std::move(Record11));
330   // Merge profile data.
331   Writer.addRecord(std::move(Record12));
332 
333   Writer.addRecord(std::move(Record2));
334   Writer.addRecord(std::move(Record3));
335   Writer.addRecord(std::move(Record4));
336   Writer.addRecord(std::move(Record5));
337   Writer.addRecord(std::move(Record6));
338   auto Profile = Writer.writeBuffer();
339   readProfile(std::move(Profile));
340 
341   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
342   ASSERT_TRUE(NoError(R.getError()));
343   ASSERT_EQ(5U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
344   ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
345   ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
346   ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
347   ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
348   ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
349 
350   std::unique_ptr<InstrProfValueData[]> VD =
351       R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
352   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2"));
353   ASSERT_EQ(7U, VD[0].Count);
354   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3"));
355   ASSERT_EQ(6U, VD[1].Count);
356   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4"));
357   ASSERT_EQ(4U, VD[2].Count);
358   ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1"));
359   ASSERT_EQ(1U, VD[3].Count);
360 
361   std::unique_ptr<InstrProfValueData[]> VD_2(
362       R.get().getValueForSite(IPVK_IndirectCallTarget, 2));
363   ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3"));
364   ASSERT_EQ(6U, VD_2[0].Count);
365   ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4"));
366   ASSERT_EQ(4U, VD_2[1].Count);
367   ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2"));
368   ASSERT_EQ(3U, VD_2[2].Count);
369   ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1"));
370   ASSERT_EQ(1U, VD_2[3].Count);
371 
372   std::unique_ptr<InstrProfValueData[]> VD_3(
373       R.get().getValueForSite(IPVK_IndirectCallTarget, 3));
374   ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1"));
375   ASSERT_EQ(1U, VD_3[0].Count);
376 
377   std::unique_ptr<InstrProfValueData[]> VD_4(
378       R.get().getValueForSite(IPVK_IndirectCallTarget, 4));
379   ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3"));
380   ASSERT_EQ(6U, VD_4[0].Count);
381   ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2"));
382   ASSERT_EQ(4U, VD_4[1].Count);
383   ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1"));
384   ASSERT_EQ(2U, VD_4[2].Count);
385 }
386 
387 TEST_F(InstrProfTest, get_icall_data_merge1_saturation) {
388   static const char bar[] = "bar";
389 
390   const uint64_t Max = std::numeric_limits<uint64_t>::max();
391 
392   InstrProfRecord Record1("foo", 0x1234, {1});
393   auto Result1 = Writer.addRecord(std::move(Record1));
394   ASSERT_EQ(Result1, instrprof_error::success);
395 
396   // Verify counter overflow.
397   InstrProfRecord Record2("foo", 0x1234, {Max});
398   auto Result2 = Writer.addRecord(std::move(Record2));
399   ASSERT_EQ(Result2, instrprof_error::counter_overflow);
400 
401   InstrProfRecord Record3(bar, 0x9012, {8});
402   auto Result3 = Writer.addRecord(std::move(Record3));
403   ASSERT_EQ(Result3, instrprof_error::success);
404 
405   InstrProfRecord Record4("baz", 0x5678, {3, 4});
406   Record4.reserveSites(IPVK_IndirectCallTarget, 1);
407   InstrProfValueData VD4[] = {{uint64_t(bar), 1}};
408   Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
409   auto Result4 = Writer.addRecord(std::move(Record4));
410   ASSERT_EQ(Result4, instrprof_error::success);
411 
412   // Verify value data counter overflow.
413   InstrProfRecord Record5("baz", 0x5678, {5, 6});
414   Record5.reserveSites(IPVK_IndirectCallTarget, 1);
415   InstrProfValueData VD5[] = {{uint64_t(bar), Max}};
416   Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
417   auto Result5 = Writer.addRecord(std::move(Record5));
418   ASSERT_EQ(Result5, instrprof_error::counter_overflow);
419 
420   auto Profile = Writer.writeBuffer();
421   readProfile(std::move(Profile));
422 
423   // Verify saturation of counts.
424   ErrorOr<InstrProfRecord> ReadRecord1 =
425       Reader->getInstrProfRecord("foo", 0x1234);
426   ASSERT_TRUE(NoError(ReadRecord1.getError()));
427   ASSERT_EQ(Max, ReadRecord1.get().Counts[0]);
428 
429   ErrorOr<InstrProfRecord> ReadRecord2 =
430       Reader->getInstrProfRecord("baz", 0x5678);
431   ASSERT_EQ(1U, ReadRecord2.get().getNumValueSites(IPVK_IndirectCallTarget));
432   std::unique_ptr<InstrProfValueData[]> VD =
433       ReadRecord2.get().getValueForSite(IPVK_IndirectCallTarget, 0);
434   ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3));
435   ASSERT_EQ(Max, VD[0].Count);
436 }
437 
438 // This test tests that when there are too many values
439 // for a given site, the merged results are properly
440 // truncated.
441 TEST_F(InstrProfTest, get_icall_data_merge_site_trunc) {
442   static const char caller[] = "caller";
443 
444   InstrProfRecord Record11(caller, 0x1234, {1, 2});
445   InstrProfRecord Record12(caller, 0x1234, {1, 2});
446 
447   // 2 value sites.
448   Record11.reserveSites(IPVK_IndirectCallTarget, 2);
449   InstrProfValueData VD0[255];
450   for (int I = 0; I < 255; I++) {
451     VD0[I].Value = 2 * I;
452     VD0[I].Count = 2 * I + 1000;
453   }
454 
455   Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr);
456   Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
457 
458   Record12.reserveSites(IPVK_IndirectCallTarget, 2);
459   InstrProfValueData VD1[255];
460   for (int I = 0; I < 255; I++) {
461     VD1[I].Value = 2 * I + 1;
462     VD1[I].Count = 2 * I + 1001;
463   }
464 
465   Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr);
466   Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
467 
468   Writer.addRecord(std::move(Record11));
469   // Merge profile data.
470   Writer.addRecord(std::move(Record12));
471 
472   auto Profile = Writer.writeBuffer();
473   readProfile(std::move(Profile));
474 
475   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
476   ASSERT_TRUE(NoError(R.getError()));
477   std::unique_ptr<InstrProfValueData[]> VD(
478       R.get().getValueForSite(IPVK_IndirectCallTarget, 0));
479   ASSERT_EQ(2U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
480   ASSERT_EQ(255U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
481   for (unsigned I = 0; I < 255; I++) {
482     ASSERT_EQ(VD[I].Value, 509 - I);
483     ASSERT_EQ(VD[I].Count, 1509 - I);
484   }
485 }
486 
487 // Synthesize runtime value profile data.
488 ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]},
489                                 {{uint64_t("callee2"), 1000}, &Site1Values[2]},
490                                 {{uint64_t("callee3"), 500}, &Site1Values[3]},
491                                 {{uint64_t("callee4"), 300}, &Site1Values[4]},
492                                 {{uint64_t("callee5"), 100}, nullptr}};
493 
494 ValueProfNode Site2Values[4] = {{{uint64_t("callee5"), 800}, &Site2Values[1]},
495                                 {{uint64_t("callee3"), 1000}, &Site2Values[2]},
496                                 {{uint64_t("callee2"), 2500}, &Site2Values[3]},
497                                 {{uint64_t("callee1"), 1300}, nullptr}};
498 
499 ValueProfNode Site3Values[3] = {{{uint64_t("callee6"), 800}, &Site3Values[1]},
500                                 {{uint64_t("callee3"), 1000}, &Site3Values[2]},
501                                 {{uint64_t("callee4"), 5500}, nullptr}};
502 
503 ValueProfNode Site4Values[2] = {{{uint64_t("callee2"), 1800}, &Site4Values[1]},
504                                 {{uint64_t("callee3"), 2000}, nullptr}};
505 
506 static ValueProfNode *ValueProfNodes[5] = {&Site1Values[0], &Site2Values[0],
507                                            &Site3Values[0], &Site4Values[0],
508                                            nullptr};
509 
510 static uint16_t NumValueSites[IPVK_Last + 1] = {5};
511 TEST_F(InstrProfTest, runtime_value_prof_data_read_write) {
512   ValueProfRuntimeRecord RTRecord;
513   initializeValueProfRuntimeRecord(&RTRecord, &NumValueSites[0],
514                                    &ValueProfNodes[0]);
515 
516   ValueProfData *VPData = serializeValueProfDataFromRT(&RTRecord, nullptr);
517 
518   InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
519 
520   VPData->deserializeTo(Record, nullptr);
521 
522   // Now read data from Record and sanity check the data
523   ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
524   ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
525   ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
526   ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
527   ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
528   ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
529 
530   auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
531     return VD1.Count > VD2.Count;
532   };
533   std::unique_ptr<InstrProfValueData[]> VD_0(
534       Record.getValueForSite(IPVK_IndirectCallTarget, 0));
535   std::sort(&VD_0[0], &VD_0[5], Cmp);
536   ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2"));
537   ASSERT_EQ(1000U, VD_0[0].Count);
538   ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3"));
539   ASSERT_EQ(500U, VD_0[1].Count);
540   ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1"));
541   ASSERT_EQ(400U, VD_0[2].Count);
542   ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4"));
543   ASSERT_EQ(300U, VD_0[3].Count);
544   ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5"));
545   ASSERT_EQ(100U, VD_0[4].Count);
546 
547   std::unique_ptr<InstrProfValueData[]> VD_1(
548       Record.getValueForSite(IPVK_IndirectCallTarget, 1));
549   std::sort(&VD_1[0], &VD_1[4], Cmp);
550   ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2"));
551   ASSERT_EQ(2500U, VD_1[0].Count);
552   ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1"));
553   ASSERT_EQ(1300U, VD_1[1].Count);
554   ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3"));
555   ASSERT_EQ(1000U, VD_1[2].Count);
556   ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5"));
557   ASSERT_EQ(800U, VD_1[3].Count);
558 
559   std::unique_ptr<InstrProfValueData[]> VD_2(
560       Record.getValueForSite(IPVK_IndirectCallTarget, 2));
561   std::sort(&VD_2[0], &VD_2[3], Cmp);
562   ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4"));
563   ASSERT_EQ(5500U, VD_2[0].Count);
564   ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3"));
565   ASSERT_EQ(1000U, VD_2[1].Count);
566   ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6"));
567   ASSERT_EQ(800U, VD_2[2].Count);
568 
569   std::unique_ptr<InstrProfValueData[]> VD_3(
570       Record.getValueForSite(IPVK_IndirectCallTarget, 3));
571   std::sort(&VD_3[0], &VD_3[2], Cmp);
572   ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3"));
573   ASSERT_EQ(2000U, VD_3[0].Count);
574   ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2"));
575   ASSERT_EQ(1800U, VD_3[1].Count);
576 
577   finalizeValueProfRuntimeRecord(&RTRecord);
578   free(VPData);
579 }
580 
581 TEST_F(InstrProfTest, get_max_function_count) {
582   InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2});
583   InstrProfRecord Record2("bar", 0, {1ULL << 63});
584   InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0});
585   Writer.addRecord(std::move(Record1));
586   Writer.addRecord(std::move(Record2));
587   Writer.addRecord(std::move(Record3));
588   auto Profile = Writer.writeBuffer();
589   readProfile(std::move(Profile));
590 
591   ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount());
592 }
593 
594 TEST_F(InstrProfTest, get_weighted_function_counts) {
595   InstrProfRecord Record1("foo", 0x1234, {1, 2});
596   InstrProfRecord Record2("foo", 0x1235, {3, 4});
597   Writer.addRecord(std::move(Record1), 3);
598   Writer.addRecord(std::move(Record2), 5);
599   auto Profile = Writer.writeBuffer();
600   readProfile(std::move(Profile));
601 
602   std::vector<uint64_t> Counts;
603   ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts)));
604   ASSERT_EQ(2U, Counts.size());
605   ASSERT_EQ(3U, Counts[0]);
606   ASSERT_EQ(6U, Counts[1]);
607 
608   ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts)));
609   ASSERT_EQ(2U, Counts.size());
610   ASSERT_EQ(15U, Counts[0]);
611   ASSERT_EQ(20U, Counts[1]);
612 }
613 
614 TEST_F(InstrProfTest, instr_prof_symtab_test) {
615   std::vector<StringRef> FuncNames;
616   FuncNames.push_back("func1");
617   FuncNames.push_back("func2");
618   FuncNames.push_back("func3");
619   FuncNames.push_back("bar1");
620   FuncNames.push_back("bar2");
621   FuncNames.push_back("bar3");
622   InstrProfSymtab Symtab;
623   Symtab.create(FuncNames);
624   StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
625   ASSERT_EQ(StringRef("func1"), R);
626   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
627   ASSERT_EQ(StringRef("func2"), R);
628   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
629   ASSERT_EQ(StringRef("func3"), R);
630   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
631   ASSERT_EQ(StringRef("bar1"), R);
632   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
633   ASSERT_EQ(StringRef("bar2"), R);
634   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
635   ASSERT_EQ(StringRef("bar3"), R);
636 
637   // Now incrementally update the symtab
638   Symtab.addFuncName("blah_1");
639   Symtab.addFuncName("blah_2");
640   Symtab.addFuncName("blah_3");
641   // Finalize it
642   Symtab.finalizeSymtab();
643 
644   // Check again
645   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1"));
646   ASSERT_EQ(StringRef("blah_1"), R);
647   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2"));
648   ASSERT_EQ(StringRef("blah_2"), R);
649   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3"));
650   ASSERT_EQ(StringRef("blah_3"), R);
651   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
652   ASSERT_EQ(StringRef("func1"), R);
653   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
654   ASSERT_EQ(StringRef("func2"), R);
655   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
656   ASSERT_EQ(StringRef("func3"), R);
657   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
658   ASSERT_EQ(StringRef("bar1"), R);
659   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
660   ASSERT_EQ(StringRef("bar2"), R);
661   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
662   ASSERT_EQ(StringRef("bar3"), R);
663 }
664 
665 TEST_F(InstrProfTest, instr_prof_symtab_module_test) {
666   LLVMContext Ctx;
667   std::unique_ptr<Module> M = llvm::make_unique<Module>("MyModule.cpp", Ctx);
668   FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
669                                         /*isVarArg=*/false);
670   Function::Create(FTy, Function::ExternalLinkage, "Gfoo", M.get());
671   Function::Create(FTy, Function::ExternalLinkage, "Gblah", M.get());
672   Function::Create(FTy, Function::ExternalLinkage, "Gbar", M.get());
673   Function::Create(FTy, Function::InternalLinkage, "Ifoo", M.get());
674   Function::Create(FTy, Function::InternalLinkage, "Iblah", M.get());
675   Function::Create(FTy, Function::InternalLinkage, "Ibar", M.get());
676   Function::Create(FTy, Function::PrivateLinkage, "Pfoo", M.get());
677   Function::Create(FTy, Function::PrivateLinkage, "Pblah", M.get());
678   Function::Create(FTy, Function::PrivateLinkage, "Pbar", M.get());
679   Function::Create(FTy, Function::WeakODRLinkage, "Wfoo", M.get());
680   Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get());
681   Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get());
682 
683   InstrProfSymtab ProfSymtab;
684   ProfSymtab.create(*(M.get()));
685 
686   StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar",
687                        "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"};
688 
689   for (unsigned I = 0; I < sizeof(Funcs) / sizeof(*Funcs); I++) {
690     Function *F = M->getFunction(Funcs[I]);
691     ASSERT_TRUE(F != nullptr);
692     std::string PGOName = getPGOFuncName(*F);
693     uint64_t Key = IndexedInstrProf::ComputeHash(PGOName);
694     ASSERT_EQ(StringRef(PGOName),
695               ProfSymtab.getFuncName(Key));
696     ASSERT_EQ(StringRef(Funcs[I]), ProfSymtab.getOrigFuncName(Key));
697   }
698 }
699 
700 TEST_F(InstrProfTest, instr_prof_symtab_compression_test) {
701   std::vector<std::string> FuncNames1;
702   std::vector<std::string> FuncNames2;
703   for (int I = 0; I < 10 * 1024; I++) {
704     std::string str;
705     raw_string_ostream OS(str);
706     OS << "func_" << I;
707     FuncNames1.push_back(OS.str());
708     str.clear();
709     OS << "fooooooooooooooo_" << I;
710     FuncNames1.push_back(OS.str());
711     str.clear();
712     OS << "BAR_" << I;
713     FuncNames2.push_back(OS.str());
714     str.clear();
715     OS << "BlahblahBlahblahBar_" << I;
716     FuncNames2.push_back(OS.str());
717   }
718 
719   for (int Padding = 0; Padding < 10; Padding++) {
720     for (int DoCompression = 0; DoCompression < 2; DoCompression++) {
721       // Compressing:
722       std::string FuncNameStrings1;
723       collectPGOFuncNameStrings(FuncNames1,
724                                 (DoCompression != 0 && zlib::isAvailable()),
725                                 FuncNameStrings1);
726 
727       // Compressing:
728       std::string FuncNameStrings2;
729       collectPGOFuncNameStrings(FuncNames2,
730                                 (DoCompression != 0 && zlib::isAvailable()),
731                                 FuncNameStrings2);
732 
733       // Join with paddings:
734       std::string FuncNameStrings = FuncNameStrings1;
735       for (int P = 0; P < Padding; P++) {
736         FuncNameStrings.push_back('\0');
737       }
738       FuncNameStrings += FuncNameStrings2;
739 
740       // Now decompress:
741       InstrProfSymtab Symtab;
742       Symtab.create(StringRef(FuncNameStrings));
743 
744       // Now do the checks:
745       // First sampling some data points:
746       StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[0]));
747       ASSERT_EQ(StringRef("func_0"), R);
748       R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[1]));
749       ASSERT_EQ(StringRef("fooooooooooooooo_0"), R);
750       R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[998]));
751       ASSERT_EQ(StringRef("func_499"), R);
752       R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[999]));
753       ASSERT_EQ(StringRef("fooooooooooooooo_499"), R);
754       R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames2[100]));
755       ASSERT_EQ(StringRef("BAR_50"), R);
756       R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames2[101]));
757       ASSERT_EQ(StringRef("BlahblahBlahblahBar_50"), R);
758       for (int I = 0; I < 10 * 1024; I++) {
759         std::string N[4];
760         N[0] = FuncNames1[2 * I];
761         N[1] = FuncNames1[2 * I + 1];
762         N[2] = FuncNames2[2 * I];
763         N[3] = FuncNames2[2 * I + 1];
764         for (int J = 0; J < 4; J++) {
765           StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(N[J]));
766           ASSERT_EQ(StringRef(N[J]), R);
767         }
768       }
769     }
770   }
771 }
772 
773 } // end anonymous namespace
774