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