InstrProfTest.cpp 38 KB

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