blob: 34bb1f295fee078988257e08448b873e1d8636f6 [file] [log] [blame]
Eugene Zelenkoffec81c2015-11-04 22:32:32 +00001//===- unittest/ProfileData/InstrProfTest.cpp -------------------*- C++ -*-===//
Justin Bogner2b6c5372015-02-18 01:58:17 +00002//
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
Xinliang David Li59411db2016-01-20 01:26:34 +000010#include "llvm/IR/Function.h"
Xinliang David Li402477d2016-02-04 19:11:43 +000011#include "llvm/IR/IRBuilder.h"
Xinliang David Li59411db2016-01-20 01:26:34 +000012#include "llvm/IR/LLVMContext.h"
13#include "llvm/IR/Module.h"
Justin Bogner2b6c5372015-02-18 01:58:17 +000014#include "llvm/ProfileData/InstrProfReader.h"
15#include "llvm/ProfileData/InstrProfWriter.h"
Xinliang David Lie413f1a2015-12-31 07:57:16 +000016#include "llvm/Support/Compression.h"
Justin Bogner2b6c5372015-02-18 01:58:17 +000017#include "gtest/gtest.h"
Justin Bogner2b6c5372015-02-18 01:58:17 +000018#include <cstdarg>
19
20using namespace llvm;
21
22static ::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
29static ::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
37namespace {
38
39struct InstrProfTest : ::testing::Test {
40 InstrProfWriter Writer;
41 std::unique_ptr<IndexedInstrProfReader> Reader;
42
Vedant Kumar00dab222016-01-29 22:54:45 +000043 void SetUp() { Writer.setOutputSparse(false); }
44
Justin Bogner2b6c5372015-02-18 01:58:17 +000045 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
Vedant Kumar00dab222016-01-29 22:54:45 +000052struct SparseInstrProfTest : public InstrProfTest {
53 void SetUp() { Writer.setOutputSparse(true); }
54};
55
56struct MaybeSparseInstrProfTest : public InstrProfTest,
57 public ::testing::WithParamInterface<bool> {
58 void SetUp() {
59 Writer.setOutputSparse(GetParam());
60 }
61};
62
63TEST_P(MaybeSparseInstrProfTest, write_and_read_empty_profile) {
Justin Bogner2b6c5372015-02-18 01:58:17 +000064 auto Profile = Writer.writeBuffer();
65 readProfile(std::move(Profile));
66 ASSERT_TRUE(Reader->begin() == Reader->end());
67}
68
Vedant Kumar00dab222016-01-29 22:54:45 +000069TEST_P(MaybeSparseInstrProfTest, write_and_read_one_function) {
Justin Bogner9e9a0572015-09-29 22:13:58 +000070 InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4});
71 Writer.addRecord(std::move(Record));
Justin Bogner2b6c5372015-02-18 01:58:17 +000072 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
Vedant Kumar00dab222016-01-29 22:54:45 +000087TEST_P(MaybeSparseInstrProfTest, get_instr_prof_record) {
Xinliang David Li2004f002015-11-02 05:08:23 +000088 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()));
David Blaikiefed557e2016-02-09 01:02:24 +000097 ASSERT_EQ(2U, R->Counts.size());
98 ASSERT_EQ(1U, R->Counts[0]);
99 ASSERT_EQ(2U, R->Counts[1]);
Xinliang David Li2004f002015-11-02 05:08:23 +0000100
101 R = Reader->getInstrProfRecord("foo", 0x1235);
102 ASSERT_TRUE(NoError(R.getError()));
David Blaikiefed557e2016-02-09 01:02:24 +0000103 ASSERT_EQ(2U, R->Counts.size());
104 ASSERT_EQ(3U, R->Counts[0]);
105 ASSERT_EQ(4U, R->Counts[1]);
Xinliang David Li2004f002015-11-02 05:08:23 +0000106
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
Vedant Kumar00dab222016-01-29 22:54:45 +0000114TEST_P(MaybeSparseInstrProfTest, get_function_counts) {
Justin Bogner9e9a0572015-09-29 22:13:58 +0000115 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));
Justin Bogner2b6c5372015-02-18 01:58:17 +0000119 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
Justin Bogner09829f42015-06-22 23:56:53 +0000128 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
Justin Bogner2b6c5372015-02-18 01:58:17 +0000133 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
Xinliang David Li6c93ee82016-02-03 04:08:18 +0000141// Profile data is copied from general.proftext
142TEST_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
Easwaran Ramanf9709ee2016-03-14 22:23:28 +0000157 auto VerifySummary = [](InstrProfSummary &IPS) mutable {
Easwaran Raman7c4f25d2016-03-01 18:30:58 +0000158 ASSERT_EQ(2305843009213693952U, IPS.getMaxFunctionCount());
159 ASSERT_EQ(2305843009213693952U, IPS.getMaxBlockCount());
160 ASSERT_EQ(10U, IPS.getNumBlocks());
161 ASSERT_EQ(4539628424389557499U, IPS.getTotalCount());
162 std::vector<ProfileSummaryEntry> &Details = IPS.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 =
172 std::find_if(Details.begin(), Details.end(), Predicate);
173 Cutoff = 990000;
174 auto NinetyNinePerc =
175 std::find_if(Details.begin(), Details.end(), Predicate);
176 ASSERT_EQ(576460752303423488U, EightyPerc->MinCount);
177 ASSERT_EQ(288230376151711744U, NinetyPerc->MinCount);
178 ASSERT_EQ(288230376151711744U, NinetyFivePerc->MinCount);
179 ASSERT_EQ(72057594037927936U, NinetyNinePerc->MinCount);
Xinliang David Li6c93ee82016-02-03 04:08:18 +0000180 };
Easwaran Raman7c4f25d2016-03-01 18:30:58 +0000181 InstrProfSummary &PS = Reader->getSummary();
Easwaran Ramanf9709ee2016-03-14 22:23:28 +0000182 VerifySummary(PS);
Easwaran Raman7c4f25d2016-03-01 18:30:58 +0000183 Metadata *MD = PS.getMD(getGlobalContext());
184 ASSERT_TRUE(MD);
185 ProfileSummary *PSFromMD = ProfileSummary::getFromMD(MD);
186 ASSERT_TRUE(PSFromMD);
187 ASSERT_TRUE(isa<InstrProfSummary>(PSFromMD));
188 InstrProfSummary *IPS = cast<InstrProfSummary>(PSFromMD);
Easwaran Ramanf9709ee2016-03-14 22:23:28 +0000189 VerifySummary(*IPS);
Easwaran Raman75c21a92016-03-03 23:55:41 +0000190 delete IPS;
Xinliang David Li6c93ee82016-02-03 04:08:18 +0000191}
192
Vedant Kumar00dab222016-01-29 22:54:45 +0000193TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) {
Xinliang David Li2004f002015-11-02 05:08:23 +0000194 InstrProfRecord Record1("caller", 0x1234, {1, 2});
195 InstrProfRecord Record2("callee1", 0x1235, {3, 4});
196 InstrProfRecord Record3("callee2", 0x1235, {3, 4});
197 InstrProfRecord Record4("callee3", 0x1235, {3, 4});
198
199 // 4 value sites.
200 Record1.reserveSites(IPVK_IndirectCallTarget, 4);
201 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
202 {(uint64_t) "callee2", 2},
203 {(uint64_t) "callee3", 3}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000204 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
Xinliang David Liee415892015-11-10 00:24:45 +0000205 // No value profile data at the second site.
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000206 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000207 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
208 {(uint64_t) "callee2", 2}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000209 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000210 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000211 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000212
213 Writer.addRecord(std::move(Record1));
214 Writer.addRecord(std::move(Record2));
215 Writer.addRecord(std::move(Record3));
216 Writer.addRecord(std::move(Record4));
217 auto Profile = Writer.writeBuffer();
218 readProfile(std::move(Profile));
219
220 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
221 ASSERT_TRUE(NoError(R.getError()));
David Blaikiefed557e2016-02-09 01:02:24 +0000222 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
223 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
224 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
225 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
226 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
Xinliang David Li2004f002015-11-02 05:08:23 +0000227
Xinliang David Li1e4c8092016-02-04 05:29:51 +0000228 uint64_t TotalC;
Xinliang David Li2004f002015-11-02 05:08:23 +0000229 std::unique_ptr<InstrProfValueData[]> VD =
David Blaikiefed557e2016-02-09 01:02:24 +0000230 R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000231
232 ASSERT_EQ(3U, VD[0].Count);
233 ASSERT_EQ(2U, VD[1].Count);
234 ASSERT_EQ(1U, VD[2].Count);
Xinliang David Li1e4c8092016-02-04 05:29:51 +0000235 ASSERT_EQ(6U, TotalC);
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000236
237 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
238 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
239 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
240}
241
Xinliang David Li402477d2016-02-04 19:11:43 +0000242TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
243 InstrProfRecord Record("caller", 0x1234, {1, 2});
244 Record.reserveSites(IPVK_IndirectCallTarget, 1);
Rong Xu69683f12016-02-10 22:19:43 +0000245 InstrProfValueData VD0[] = {{1000, 1}, {2000, 2}, {3000, 3}, {5000, 5},
246 {4000, 4}, {6000, 6}};
247 Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 6, nullptr);
Xinliang David Li402477d2016-02-04 19:11:43 +0000248 Writer.addRecord(std::move(Record));
249 auto Profile = Writer.writeBuffer();
250 readProfile(std::move(Profile));
251 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
252 ASSERT_TRUE(NoError(R.getError()));
253
254 LLVMContext Ctx;
255 std::unique_ptr<Module> M(new Module("MyModule", Ctx));
256 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
257 /*isVarArg=*/false);
258 Function *F =
259 Function::Create(FTy, Function::ExternalLinkage, "caller", M.get());
260 BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
261
262 IRBuilder<> Builder(BB);
263 BasicBlock *TBB = BasicBlock::Create(Ctx, "", F);
264 BasicBlock *FBB = BasicBlock::Create(Ctx, "", F);
265
266 // Use branch instruction to annotate with value profile data for simplicity
267 Instruction *Inst = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
268 Instruction *Inst2 = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
David Blaikiefed557e2016-02-09 01:02:24 +0000269 annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0);
Xinliang David Li402477d2016-02-04 19:11:43 +0000270
271 InstrProfValueData ValueData[5];
272 uint32_t N;
273 uint64_t T;
274 bool Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
275 ValueData, N, T);
276 ASSERT_TRUE(Res);
277 ASSERT_EQ(3U, N);
Rong Xu69683f12016-02-10 22:19:43 +0000278 ASSERT_EQ(21U, T);
Xinliang David Li402477d2016-02-04 19:11:43 +0000279 // The result should be sorted already:
Rong Xu69683f12016-02-10 22:19:43 +0000280 ASSERT_EQ(6000U, ValueData[0].Value);
281 ASSERT_EQ(6U, ValueData[0].Count);
282 ASSERT_EQ(5000U, ValueData[1].Value);
283 ASSERT_EQ(5U, ValueData[1].Count);
284 ASSERT_EQ(4000U, ValueData[2].Value);
285 ASSERT_EQ(4U, ValueData[2].Count);
Xinliang David Li402477d2016-02-04 19:11:43 +0000286 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 1, ValueData,
287 N, T);
288 ASSERT_TRUE(Res);
289 ASSERT_EQ(1U, N);
Rong Xu69683f12016-02-10 22:19:43 +0000290 ASSERT_EQ(21U, T);
Xinliang David Li402477d2016-02-04 19:11:43 +0000291
292 Res = getValueProfDataFromInst(*Inst2, IPVK_IndirectCallTarget, 5, ValueData,
293 N, T);
294 ASSERT_FALSE(Res);
Rong Xu69683f12016-02-10 22:19:43 +0000295
296 // Remove the MD_prof metadata
297 Inst->setMetadata(LLVMContext::MD_prof, 0);
298 // Annotate 5 records this time.
299 annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0, 5);
300 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
301 ValueData, N, T);
302 ASSERT_TRUE(Res);
303 ASSERT_EQ(5U, N);
304 ASSERT_EQ(21U, T);
305 ASSERT_EQ(6000U, ValueData[0].Value);
306 ASSERT_EQ(6U, ValueData[0].Count);
307 ASSERT_EQ(5000U, ValueData[1].Value);
308 ASSERT_EQ(5U, ValueData[1].Count);
309 ASSERT_EQ(4000U, ValueData[2].Value);
310 ASSERT_EQ(4U, ValueData[2].Count);
311 ASSERT_EQ(3000U, ValueData[3].Value);
312 ASSERT_EQ(3U, ValueData[3].Count);
313 ASSERT_EQ(2000U, ValueData[4].Value);
314 ASSERT_EQ(2U, ValueData[4].Count);
Rong Xubb494902016-02-12 21:36:17 +0000315
316 // Remove the MD_prof metadata
317 Inst->setMetadata(LLVMContext::MD_prof, 0);
318 // Annotate with 4 records.
319 InstrProfValueData VD0Sorted[] = {{1000, 6}, {2000, 5}, {3000, 4}, {4000, 3},
320 {5000, 2}, {6000, 1}};
321 annotateValueSite(*M, *Inst, &VD0Sorted[2], 4, 10, IPVK_IndirectCallTarget, 5);
322 Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
323 ValueData, N, T);
324 ASSERT_TRUE(Res);
325 ASSERT_EQ(4U, N);
326 ASSERT_EQ(10U, T);
327 ASSERT_EQ(3000U, ValueData[0].Value);
328 ASSERT_EQ(4U, ValueData[0].Count);
329 ASSERT_EQ(4000U, ValueData[1].Value);
330 ASSERT_EQ(3U, ValueData[1].Count);
331 ASSERT_EQ(5000U, ValueData[2].Value);
332 ASSERT_EQ(2U, ValueData[2].Count);
333 ASSERT_EQ(6000U, ValueData[3].Value);
334 ASSERT_EQ(1U, ValueData[3].Count);
Xinliang David Li402477d2016-02-04 19:11:43 +0000335}
336
Vedant Kumar00dab222016-01-29 22:54:45 +0000337TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) {
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000338 InstrProfRecord Record1("caller", 0x1234, {1, 2});
339 InstrProfRecord Record2("callee1", 0x1235, {3, 4});
340 InstrProfRecord Record3("callee2", 0x1235, {3, 4});
341 InstrProfRecord Record4("callee3", 0x1235, {3, 4});
342
343 // 4 value sites.
344 Record1.reserveSites(IPVK_IndirectCallTarget, 4);
345 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
346 {(uint64_t) "callee2", 2},
347 {(uint64_t) "callee3", 3}};
348 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
349 // No value profile data at the second site.
350 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
351 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
352 {(uint64_t) "callee2", 2}};
353 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
354 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
355 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
356
357 Writer.addRecord(std::move(Record1), 10);
358 Writer.addRecord(std::move(Record2));
359 Writer.addRecord(std::move(Record3));
360 Writer.addRecord(std::move(Record4));
361 auto Profile = Writer.writeBuffer();
362 readProfile(std::move(Profile));
363
364 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
365 ASSERT_TRUE(NoError(R.getError()));
David Blaikiefed557e2016-02-09 01:02:24 +0000366 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
367 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
368 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
369 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
370 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000371
Xinliang David Li1e4c8092016-02-04 05:29:51 +0000372 uint64_t TotalC;
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000373 std::unique_ptr<InstrProfValueData[]> VD =
David Blaikiefed557e2016-02-09 01:02:24 +0000374 R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000375 ASSERT_EQ(30U, VD[0].Count);
376 ASSERT_EQ(20U, VD[1].Count);
377 ASSERT_EQ(10U, VD[2].Count);
Xinliang David Li1e4c8092016-02-04 05:29:51 +0000378 ASSERT_EQ(60U, TotalC);
Xinliang David Li51dc04c2016-01-08 03:49:59 +0000379
Xinliang David Li2004f002015-11-02 05:08:23 +0000380 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
381 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
382 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
383}
384
Vedant Kumar00dab222016-01-29 22:54:45 +0000385TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) {
Xinliang David Li46ad3632016-01-22 19:53:31 +0000386 InstrProfRecord Record1("caller", 0x1234, {1, 2});
387 InstrProfRecord Record2("callee1", 0x1235, {3, 4});
388 InstrProfRecord Record3("callee2", 0x1235, {3, 4});
389 InstrProfRecord Record4("callee3", 0x1235, {3, 4});
390
391 // 4 value sites.
392 Record1.reserveSites(IPVK_IndirectCallTarget, 4);
393 InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
394 {(uint64_t) "callee2", 2},
395 {(uint64_t) "callee3", 3}};
396 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
397 // No value profile data at the second site.
398 Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
399 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
400 {(uint64_t) "callee2", 2}};
401 Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
402 InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
403 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
404
405 Writer.addRecord(std::move(Record1));
406 Writer.addRecord(std::move(Record2));
407 Writer.addRecord(std::move(Record3));
408 Writer.addRecord(std::move(Record4));
409
410 // Set big endian output.
411 Writer.setValueProfDataEndianness(support::big);
412
413 auto Profile = Writer.writeBuffer();
414 readProfile(std::move(Profile));
415
416 // Set big endian input.
417 Reader->setValueProfDataEndianness(support::big);
418
419 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
420 ASSERT_TRUE(NoError(R.getError()));
David Blaikiefed557e2016-02-09 01:02:24 +0000421 ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
422 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
423 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
424 ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
425 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
Xinliang David Li46ad3632016-01-22 19:53:31 +0000426
427 std::unique_ptr<InstrProfValueData[]> VD =
David Blaikiefed557e2016-02-09 01:02:24 +0000428 R->getValueForSite(IPVK_IndirectCallTarget, 0);
Xinliang David Li46ad3632016-01-22 19:53:31 +0000429 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
430 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
431 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
432
433 // Restore little endian default:
434 Writer.setValueProfDataEndianness(support::little);
435}
436
Vedant Kumar00dab222016-01-29 22:54:45 +0000437TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) {
NAKAMURA Takumi7345ac02015-12-27 06:18:57 +0000438 static const char caller[] = "caller";
439 static const char callee1[] = "callee1";
440 static const char callee2[] = "callee2";
441 static const char callee3[] = "callee3";
442 static const char callee4[] = "callee4";
443
444 InstrProfRecord Record11(caller, 0x1234, {1, 2});
445 InstrProfRecord Record12(caller, 0x1234, {1, 2});
446 InstrProfRecord Record2(callee1, 0x1235, {3, 4});
447 InstrProfRecord Record3(callee2, 0x1235, {3, 4});
448 InstrProfRecord Record4(callee3, 0x1235, {3, 4});
449 InstrProfRecord Record5(callee3, 0x1235, {3, 4});
450 InstrProfRecord Record6(callee4, 0x1235, {3, 5});
Xinliang David Li2004f002015-11-02 05:08:23 +0000451
452 // 5 value sites.
453 Record11.reserveSites(IPVK_IndirectCallTarget, 5);
NAKAMURA Takumi7345ac02015-12-27 06:18:57 +0000454 InstrProfValueData VD0[] = {{uint64_t(callee1), 1},
455 {uint64_t(callee2), 2},
456 {uint64_t(callee3), 3},
457 {uint64_t(callee4), 4}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000458 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000459
Xinliang David Li872df222016-01-08 06:54:27 +0000460 // No value profile data at the second site.
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000461 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000462
Xinliang David Li872df222016-01-08 06:54:27 +0000463 InstrProfValueData VD2[] = {
464 {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000465 Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000466
NAKAMURA Takumi7345ac02015-12-27 06:18:57 +0000467 InstrProfValueData VD3[] = {{uint64_t(callee1), 1}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000468 Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000469
NAKAMURA Takumi7345ac02015-12-27 06:18:57 +0000470 InstrProfValueData VD4[] = {{uint64_t(callee1), 1},
471 {uint64_t(callee2), 2},
472 {uint64_t(callee3), 3}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000473 Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000474
475 // A differnt record for the same caller.
476 Record12.reserveSites(IPVK_IndirectCallTarget, 5);
Xinliang David Li872df222016-01-08 06:54:27 +0000477 InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000478 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000479
Xinliang David Li872df222016-01-08 06:54:27 +0000480 // No value profile data at the second site.
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000481 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000482
Xinliang David Li872df222016-01-08 06:54:27 +0000483 InstrProfValueData VD22[] = {
484 {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000485 Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000486
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000487 Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000488
Xinliang David Li46ad3632016-01-22 19:53:31 +0000489 InstrProfValueData VD42[] = {{uint64_t(callee1), 1},
490 {uint64_t(callee2), 2},
491 {uint64_t(callee3), 3}};
Eugene Zelenkoffec81c2015-11-04 22:32:32 +0000492 Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr);
Xinliang David Li2004f002015-11-02 05:08:23 +0000493
494 Writer.addRecord(std::move(Record11));
495 // Merge profile data.
496 Writer.addRecord(std::move(Record12));
497
498 Writer.addRecord(std::move(Record2));
499 Writer.addRecord(std::move(Record3));
500 Writer.addRecord(std::move(Record4));
501 Writer.addRecord(std::move(Record5));
502 Writer.addRecord(std::move(Record6));
503 auto Profile = Writer.writeBuffer();
504 readProfile(std::move(Profile));
505
506 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
507 ASSERT_TRUE(NoError(R.getError()));
David Blaikiefed557e2016-02-09 01:02:24 +0000508 ASSERT_EQ(5U, R->getNumValueSites(IPVK_IndirectCallTarget));
509 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
510 ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
511 ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
512 ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
513 ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
Xinliang David Li2004f002015-11-02 05:08:23 +0000514
515 std::unique_ptr<InstrProfValueData[]> VD =
David Blaikiefed557e2016-02-09 01:02:24 +0000516 R->getValueForSite(IPVK_IndirectCallTarget, 0);
Xinliang David Li2004f002015-11-02 05:08:23 +0000517 ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2"));
518 ASSERT_EQ(7U, VD[0].Count);
519 ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3"));
520 ASSERT_EQ(6U, VD[1].Count);
521 ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4"));
522 ASSERT_EQ(4U, VD[2].Count);
523 ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1"));
524 ASSERT_EQ(1U, VD[3].Count);
525
526 std::unique_ptr<InstrProfValueData[]> VD_2(
David Blaikiefed557e2016-02-09 01:02:24 +0000527 R->getValueForSite(IPVK_IndirectCallTarget, 2));
Xinliang David Li2004f002015-11-02 05:08:23 +0000528 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3"));
529 ASSERT_EQ(6U, VD_2[0].Count);
530 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4"));
531 ASSERT_EQ(4U, VD_2[1].Count);
532 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2"));
533 ASSERT_EQ(3U, VD_2[2].Count);
534 ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1"));
535 ASSERT_EQ(1U, VD_2[3].Count);
536
537 std::unique_ptr<InstrProfValueData[]> VD_3(
David Blaikiefed557e2016-02-09 01:02:24 +0000538 R->getValueForSite(IPVK_IndirectCallTarget, 3));
Xinliang David Li2004f002015-11-02 05:08:23 +0000539 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1"));
540 ASSERT_EQ(1U, VD_3[0].Count);
541
542 std::unique_ptr<InstrProfValueData[]> VD_4(
David Blaikiefed557e2016-02-09 01:02:24 +0000543 R->getValueForSite(IPVK_IndirectCallTarget, 4));
Xinliang David Li2004f002015-11-02 05:08:23 +0000544 ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3"));
545 ASSERT_EQ(6U, VD_4[0].Count);
546 ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2"));
547 ASSERT_EQ(4U, VD_4[1].Count);
548 ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1"));
549 ASSERT_EQ(2U, VD_4[2].Count);
550}
551
Vedant Kumar00dab222016-01-29 22:54:45 +0000552TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1_saturation) {
NAKAMURA Takumi7345ac02015-12-27 06:18:57 +0000553 static const char bar[] = "bar";
554
Daniel Sandersbe9db3c2015-11-20 13:13:53 +0000555 const uint64_t Max = std::numeric_limits<uint64_t>::max();
556
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000557 InstrProfRecord Record1("foo", 0x1234, {1});
558 auto Result1 = Writer.addRecord(std::move(Record1));
559 ASSERT_EQ(Result1, instrprof_error::success);
Daniel Sandersbe9db3c2015-11-20 13:13:53 +0000560
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000561 // Verify counter overflow.
562 InstrProfRecord Record2("foo", 0x1234, {Max});
563 auto Result2 = Writer.addRecord(std::move(Record2));
564 ASSERT_EQ(Result2, instrprof_error::counter_overflow);
Daniel Sandersbe9db3c2015-11-20 13:13:53 +0000565
NAKAMURA Takumi7345ac02015-12-27 06:18:57 +0000566 InstrProfRecord Record3(bar, 0x9012, {8});
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000567 auto Result3 = Writer.addRecord(std::move(Record3));
568 ASSERT_EQ(Result3, instrprof_error::success);
Daniel Sandersbe9db3c2015-11-20 13:13:53 +0000569
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000570 InstrProfRecord Record4("baz", 0x5678, {3, 4});
571 Record4.reserveSites(IPVK_IndirectCallTarget, 1);
NAKAMURA Takumi7345ac02015-12-27 06:18:57 +0000572 InstrProfValueData VD4[] = {{uint64_t(bar), 1}};
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000573 Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
574 auto Result4 = Writer.addRecord(std::move(Record4));
575 ASSERT_EQ(Result4, instrprof_error::success);
576
577 // Verify value data counter overflow.
578 InstrProfRecord Record5("baz", 0x5678, {5, 6});
579 Record5.reserveSites(IPVK_IndirectCallTarget, 1);
NAKAMURA Takumi7345ac02015-12-27 06:18:57 +0000580 InstrProfValueData VD5[] = {{uint64_t(bar), Max}};
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000581 Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
582 auto Result5 = Writer.addRecord(std::move(Record5));
583 ASSERT_EQ(Result5, instrprof_error::counter_overflow);
Daniel Sandersbe9db3c2015-11-20 13:13:53 +0000584
585 auto Profile = Writer.writeBuffer();
586 readProfile(std::move(Profile));
587
588 // Verify saturation of counts.
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000589 ErrorOr<InstrProfRecord> ReadRecord1 =
590 Reader->getInstrProfRecord("foo", 0x1234);
591 ASSERT_TRUE(NoError(ReadRecord1.getError()));
David Blaikiefed557e2016-02-09 01:02:24 +0000592 ASSERT_EQ(Max, ReadRecord1->Counts[0]);
Nathan Slingerlandaa5702d2015-12-02 18:19:24 +0000593
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000594 ErrorOr<InstrProfRecord> ReadRecord2 =
595 Reader->getInstrProfRecord("baz", 0x5678);
David Blaikiefed557e2016-02-09 01:02:24 +0000596 ASSERT_EQ(1U, ReadRecord2->getNumValueSites(IPVK_IndirectCallTarget));
Daniel Sandersbe9db3c2015-11-20 13:13:53 +0000597 std::unique_ptr<InstrProfValueData[]> VD =
David Blaikiefed557e2016-02-09 01:02:24 +0000598 ReadRecord2->getValueForSite(IPVK_IndirectCallTarget, 0);
Nathan Slingerland48dd0802015-12-16 21:45:43 +0000599 ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3));
600 ASSERT_EQ(Max, VD[0].Count);
Daniel Sandersbe9db3c2015-11-20 13:13:53 +0000601}
602
Xinliang David Li872df222016-01-08 06:54:27 +0000603// This test tests that when there are too many values
604// for a given site, the merged results are properly
605// truncated.
Vedant Kumar00dab222016-01-29 22:54:45 +0000606TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge_site_trunc) {
Xinliang David Li872df222016-01-08 06:54:27 +0000607 static const char caller[] = "caller";
608
609 InstrProfRecord Record11(caller, 0x1234, {1, 2});
610 InstrProfRecord Record12(caller, 0x1234, {1, 2});
611
612 // 2 value sites.
613 Record11.reserveSites(IPVK_IndirectCallTarget, 2);
614 InstrProfValueData VD0[255];
615 for (int I = 0; I < 255; I++) {
616 VD0[I].Value = 2 * I;
617 VD0[I].Count = 2 * I + 1000;
618 }
619
620 Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr);
621 Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
622
623 Record12.reserveSites(IPVK_IndirectCallTarget, 2);
624 InstrProfValueData VD1[255];
625 for (int I = 0; I < 255; I++) {
626 VD1[I].Value = 2 * I + 1;
627 VD1[I].Count = 2 * I + 1001;
628 }
629
630 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr);
631 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
632
633 Writer.addRecord(std::move(Record11));
634 // Merge profile data.
635 Writer.addRecord(std::move(Record12));
636
637 auto Profile = Writer.writeBuffer();
638 readProfile(std::move(Profile));
639
640 ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
641 ASSERT_TRUE(NoError(R.getError()));
642 std::unique_ptr<InstrProfValueData[]> VD(
David Blaikiefed557e2016-02-09 01:02:24 +0000643 R->getValueForSite(IPVK_IndirectCallTarget, 0));
644 ASSERT_EQ(2U, R->getNumValueSites(IPVK_IndirectCallTarget));
645 ASSERT_EQ(255U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
NAKAMURA Takumi249edf32016-01-08 07:58:20 +0000646 for (unsigned I = 0; I < 255; I++) {
Xinliang David Li872df222016-01-08 06:54:27 +0000647 ASSERT_EQ(VD[I].Value, 509 - I);
648 ASSERT_EQ(VD[I].Count, 1509 - I);
649 }
650}
651
Xinliang David Lied966772015-11-25 23:31:18 +0000652// Synthesize runtime value profile data.
653ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]},
654 {{uint64_t("callee2"), 1000}, &Site1Values[2]},
655 {{uint64_t("callee3"), 500}, &Site1Values[3]},
656 {{uint64_t("callee4"), 300}, &Site1Values[4]},
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000657 {{uint64_t("callee5"), 100}, nullptr}};
Xinliang David Lied966772015-11-25 23:31:18 +0000658
659ValueProfNode Site2Values[4] = {{{uint64_t("callee5"), 800}, &Site2Values[1]},
660 {{uint64_t("callee3"), 1000}, &Site2Values[2]},
661 {{uint64_t("callee2"), 2500}, &Site2Values[3]},
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000662 {{uint64_t("callee1"), 1300}, nullptr}};
Xinliang David Lied966772015-11-25 23:31:18 +0000663
664ValueProfNode Site3Values[3] = {{{uint64_t("callee6"), 800}, &Site3Values[1]},
665 {{uint64_t("callee3"), 1000}, &Site3Values[2]},
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000666 {{uint64_t("callee4"), 5500}, nullptr}};
Xinliang David Lied966772015-11-25 23:31:18 +0000667
668ValueProfNode Site4Values[2] = {{{uint64_t("callee2"), 1800}, &Site4Values[1]},
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000669 {{uint64_t("callee3"), 2000}, nullptr}};
Xinliang David Lied966772015-11-25 23:31:18 +0000670
671static ValueProfNode *ValueProfNodes[5] = {&Site1Values[0], &Site2Values[0],
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000672 &Site3Values[0], &Site4Values[0],
673 nullptr};
674
Xinliang David Lied966772015-11-25 23:31:18 +0000675static uint16_t NumValueSites[IPVK_Last + 1] = {5};
Vedant Kumar00dab222016-01-29 22:54:45 +0000676TEST_P(MaybeSparseInstrProfTest, runtime_value_prof_data_read_write) {
Xinliang David Lied966772015-11-25 23:31:18 +0000677 ValueProfRuntimeRecord RTRecord;
678 initializeValueProfRuntimeRecord(&RTRecord, &NumValueSites[0],
679 &ValueProfNodes[0]);
680
Xinliang David Li0e6a36e2015-12-01 19:47:32 +0000681 ValueProfData *VPData = serializeValueProfDataFromRT(&RTRecord, nullptr);
Xinliang David Lied966772015-11-25 23:31:18 +0000682
683 InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
684
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000685 VPData->deserializeTo(Record, nullptr);
Xinliang David Lied966772015-11-25 23:31:18 +0000686
687 // Now read data from Record and sanity check the data
688 ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
689 ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
690 ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
691 ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
692 ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
693 ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
694
695 auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
696 return VD1.Count > VD2.Count;
697 };
698 std::unique_ptr<InstrProfValueData[]> VD_0(
699 Record.getValueForSite(IPVK_IndirectCallTarget, 0));
700 std::sort(&VD_0[0], &VD_0[5], Cmp);
701 ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2"));
702 ASSERT_EQ(1000U, VD_0[0].Count);
703 ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3"));
704 ASSERT_EQ(500U, VD_0[1].Count);
705 ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1"));
706 ASSERT_EQ(400U, VD_0[2].Count);
707 ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4"));
708 ASSERT_EQ(300U, VD_0[3].Count);
709 ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5"));
710 ASSERT_EQ(100U, VD_0[4].Count);
711
712 std::unique_ptr<InstrProfValueData[]> VD_1(
713 Record.getValueForSite(IPVK_IndirectCallTarget, 1));
714 std::sort(&VD_1[0], &VD_1[4], Cmp);
715 ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2"));
716 ASSERT_EQ(2500U, VD_1[0].Count);
717 ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1"));
718 ASSERT_EQ(1300U, VD_1[1].Count);
719 ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3"));
720 ASSERT_EQ(1000U, VD_1[2].Count);
721 ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5"));
722 ASSERT_EQ(800U, VD_1[3].Count);
723
724 std::unique_ptr<InstrProfValueData[]> VD_2(
725 Record.getValueForSite(IPVK_IndirectCallTarget, 2));
726 std::sort(&VD_2[0], &VD_2[3], Cmp);
727 ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4"));
728 ASSERT_EQ(5500U, VD_2[0].Count);
729 ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3"));
730 ASSERT_EQ(1000U, VD_2[1].Count);
731 ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6"));
732 ASSERT_EQ(800U, VD_2[2].Count);
733
734 std::unique_ptr<InstrProfValueData[]> VD_3(
735 Record.getValueForSite(IPVK_IndirectCallTarget, 3));
736 std::sort(&VD_3[0], &VD_3[2], Cmp);
737 ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3"));
738 ASSERT_EQ(2000U, VD_3[0].Count);
739 ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2"));
740 ASSERT_EQ(1800U, VD_3[1].Count);
741
742 finalizeValueProfRuntimeRecord(&RTRecord);
743 free(VPData);
744}
745
Vedant Kumar00dab222016-01-29 22:54:45 +0000746TEST_P(MaybeSparseInstrProfTest, get_max_function_count) {
Justin Bogner9e9a0572015-09-29 22:13:58 +0000747 InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2});
748 InstrProfRecord Record2("bar", 0, {1ULL << 63});
749 InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0});
750 Writer.addRecord(std::move(Record1));
751 Writer.addRecord(std::move(Record2));
752 Writer.addRecord(std::move(Record3));
Justin Bogner2b6c5372015-02-18 01:58:17 +0000753 auto Profile = Writer.writeBuffer();
754 readProfile(std::move(Profile));
755
756 ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount());
757}
758
Vedant Kumar00dab222016-01-29 22:54:45 +0000759TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) {
Nathan Slingerland7f5b47d2015-12-15 17:37:09 +0000760 InstrProfRecord Record1("foo", 0x1234, {1, 2});
761 InstrProfRecord Record2("foo", 0x1235, {3, 4});
762 Writer.addRecord(std::move(Record1), 3);
763 Writer.addRecord(std::move(Record2), 5);
764 auto Profile = Writer.writeBuffer();
765 readProfile(std::move(Profile));
766
767 std::vector<uint64_t> Counts;
768 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts)));
769 ASSERT_EQ(2U, Counts.size());
770 ASSERT_EQ(3U, Counts[0]);
771 ASSERT_EQ(6U, Counts[1]);
772
773 ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts)));
774 ASSERT_EQ(2U, Counts.size());
775 ASSERT_EQ(15U, Counts[0]);
776 ASSERT_EQ(20U, Counts[1]);
777}
778
Xinliang David Lia0601e72016-02-09 05:47:08 +0000779// Testing symtab creator interface used by indexed profile reader.
Vedant Kumar00dab222016-01-29 22:54:45 +0000780TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_test) {
Xinliang David Li2ee5c4d2015-12-19 07:44:57 +0000781 std::vector<StringRef> FuncNames;
782 FuncNames.push_back("func1");
783 FuncNames.push_back("func2");
784 FuncNames.push_back("func3");
785 FuncNames.push_back("bar1");
786 FuncNames.push_back("bar2");
787 FuncNames.push_back("bar3");
788 InstrProfSymtab Symtab;
789 Symtab.create(FuncNames);
790 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
791 ASSERT_EQ(StringRef("func1"), R);
792 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
793 ASSERT_EQ(StringRef("func2"), R);
794 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
795 ASSERT_EQ(StringRef("func3"), R);
796 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
797 ASSERT_EQ(StringRef("bar1"), R);
798 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
799 ASSERT_EQ(StringRef("bar2"), R);
800 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
801 ASSERT_EQ(StringRef("bar3"), R);
Xinliang David Lic96d3d12015-12-19 18:20:09 +0000802
Xinliang David Li86b4b912016-02-10 06:36:55 +0000803 // negative tests
804 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar4"));
805 ASSERT_EQ(StringRef(), R);
806 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("foo4"));
807 ASSERT_EQ(StringRef(), R);
808
Xinliang David Lic96d3d12015-12-19 18:20:09 +0000809 // Now incrementally update the symtab
810 Symtab.addFuncName("blah_1");
811 Symtab.addFuncName("blah_2");
812 Symtab.addFuncName("blah_3");
813 // Finalize it
814 Symtab.finalizeSymtab();
815
816 // Check again
817 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1"));
818 ASSERT_EQ(StringRef("blah_1"), R);
819 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2"));
820 ASSERT_EQ(StringRef("blah_2"), R);
821 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3"));
822 ASSERT_EQ(StringRef("blah_3"), R);
823 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
824 ASSERT_EQ(StringRef("func1"), R);
825 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
826 ASSERT_EQ(StringRef("func2"), R);
827 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
828 ASSERT_EQ(StringRef("func3"), R);
829 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
830 ASSERT_EQ(StringRef("bar1"), R);
831 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
832 ASSERT_EQ(StringRef("bar2"), R);
833 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
834 ASSERT_EQ(StringRef("bar3"), R);
Xinliang David Li2ee5c4d2015-12-19 07:44:57 +0000835}
836
Xinliang David Lia0601e72016-02-09 05:47:08 +0000837// Testing symtab creator interface used by value profile transformer.
Vedant Kumar00dab222016-01-29 22:54:45 +0000838TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_module_test) {
Xinliang David Li59411db2016-01-20 01:26:34 +0000839 LLVMContext Ctx;
840 std::unique_ptr<Module> M = llvm::make_unique<Module>("MyModule.cpp", Ctx);
841 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
842 /*isVarArg=*/false);
843 Function::Create(FTy, Function::ExternalLinkage, "Gfoo", M.get());
844 Function::Create(FTy, Function::ExternalLinkage, "Gblah", M.get());
845 Function::Create(FTy, Function::ExternalLinkage, "Gbar", M.get());
846 Function::Create(FTy, Function::InternalLinkage, "Ifoo", M.get());
847 Function::Create(FTy, Function::InternalLinkage, "Iblah", M.get());
848 Function::Create(FTy, Function::InternalLinkage, "Ibar", M.get());
849 Function::Create(FTy, Function::PrivateLinkage, "Pfoo", M.get());
850 Function::Create(FTy, Function::PrivateLinkage, "Pblah", M.get());
851 Function::Create(FTy, Function::PrivateLinkage, "Pbar", M.get());
852 Function::Create(FTy, Function::WeakODRLinkage, "Wfoo", M.get());
853 Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get());
854 Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get());
855
856 InstrProfSymtab ProfSymtab;
David Blaikiefed557e2016-02-09 01:02:24 +0000857 ProfSymtab.create(*M);
Xinliang David Li59411db2016-01-20 01:26:34 +0000858
859 StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar",
860 "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"};
861
862 for (unsigned I = 0; I < sizeof(Funcs) / sizeof(*Funcs); I++) {
863 Function *F = M->getFunction(Funcs[I]);
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000864 ASSERT_TRUE(F != nullptr);
Xinliang David Lida656fe2016-01-20 02:49:53 +0000865 std::string PGOName = getPGOFuncName(*F);
Xinliang David Li3865fdc2016-01-22 18:13:34 +0000866 uint64_t Key = IndexedInstrProf::ComputeHash(PGOName);
Xinliang David Lida656fe2016-01-20 02:49:53 +0000867 ASSERT_EQ(StringRef(PGOName),
Xinliang David Li3865fdc2016-01-22 18:13:34 +0000868 ProfSymtab.getFuncName(Key));
869 ASSERT_EQ(StringRef(Funcs[I]), ProfSymtab.getOrigFuncName(Key));
Xinliang David Li59411db2016-01-20 01:26:34 +0000870 }
871}
872
Xinliang David Lia0601e72016-02-09 05:47:08 +0000873// Testing symtab serialization and creator/deserialization interface
874// used by coverage map reader, and raw profile reader.
Vedant Kumar00dab222016-01-29 22:54:45 +0000875TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_compression_test) {
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000876 std::vector<std::string> FuncNames1;
877 std::vector<std::string> FuncNames2;
Xinliang David Lic2f25cc42016-02-09 05:36:57 +0000878 for (int I = 0; I < 3; I++) {
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000879 std::string str;
880 raw_string_ostream OS(str);
881 OS << "func_" << I;
882 FuncNames1.push_back(OS.str());
883 str.clear();
884 OS << "fooooooooooooooo_" << I;
885 FuncNames1.push_back(OS.str());
886 str.clear();
887 OS << "BAR_" << I;
888 FuncNames2.push_back(OS.str());
889 str.clear();
890 OS << "BlahblahBlahblahBar_" << I;
891 FuncNames2.push_back(OS.str());
892 }
893
Xinliang David Lidd4ae7b2016-01-29 22:29:15 +0000894 for (bool DoCompression : {false, true}) {
895 // Compressing:
896 std::string FuncNameStrings1;
897 collectPGOFuncNameStrings(
898 FuncNames1, (DoCompression && zlib::isAvailable()), FuncNameStrings1);
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000899
Xinliang David Lidd4ae7b2016-01-29 22:29:15 +0000900 // Compressing:
901 std::string FuncNameStrings2;
902 collectPGOFuncNameStrings(
903 FuncNames2, (DoCompression && zlib::isAvailable()), FuncNameStrings2);
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000904
Xinliang David Lic2f25cc42016-02-09 05:36:57 +0000905 for (int Padding = 0; Padding < 2; Padding++) {
906 // Join with paddings :
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000907 std::string FuncNameStrings = FuncNameStrings1;
908 for (int P = 0; P < Padding; P++) {
909 FuncNameStrings.push_back('\0');
910 }
911 FuncNameStrings += FuncNameStrings2;
912
Xinliang David Li8dec8b12016-01-04 23:59:14 +0000913 // Now decompress:
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000914 InstrProfSymtab Symtab;
915 Symtab.create(StringRef(FuncNameStrings));
916
Xinliang David Li8dec8b12016-01-04 23:59:14 +0000917 // Now do the checks:
918 // First sampling some data points:
Xinliang David Lia8ba7af2016-01-29 21:26:31 +0000919 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[0]));
Xinliang David Li8dec8b12016-01-04 23:59:14 +0000920 ASSERT_EQ(StringRef("func_0"), R);
921 R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[1]));
922 ASSERT_EQ(StringRef("fooooooooooooooo_0"), R);
Xinliang David Lic2f25cc42016-02-09 05:36:57 +0000923 for (int I = 0; I < 3; I++) {
Xinliang David Lie413f1a2015-12-31 07:57:16 +0000924 std::string N[4];
925 N[0] = FuncNames1[2 * I];
926 N[1] = FuncNames1[2 * I + 1];
927 N[2] = FuncNames2[2 * I];
928 N[3] = FuncNames2[2 * I + 1];
929 for (int J = 0; J < 4; J++) {
930 StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(N[J]));
931 ASSERT_EQ(StringRef(N[J]), R);
932 }
933 }
934 }
935 }
936}
937
Vedant Kumar00dab222016-01-29 22:54:45 +0000938TEST_F(SparseInstrProfTest, preserve_no_records) {
939 InstrProfRecord Record1("foo", 0x1234, {0});
940 InstrProfRecord Record2("bar", 0x4321, {0, 0});
941 InstrProfRecord Record3("bar", 0x4321, {0, 0, 0});
942
943 Writer.addRecord(std::move(Record1));
944 Writer.addRecord(std::move(Record2));
945 Writer.addRecord(std::move(Record3));
946 auto Profile = Writer.writeBuffer();
947 readProfile(std::move(Profile));
948
949 auto I = Reader->begin(), E = Reader->end();
950 ASSERT_TRUE(I == E);
951}
952
953INSTANTIATE_TEST_CASE_P(MaybeSparse, MaybeSparseInstrProfTest,
954 ::testing::Bool());
955
Justin Bogner2b6c5372015-02-18 01:58:17 +0000956} // end anonymous namespace