1ffec81caSEugene Zelenko //===- unittest/ProfileData/InstrProfTest.cpp -------------------*- C++ -*-===//
22b6c537bSJustin Bogner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62b6c537bSJustin Bogner //
72b6c537bSJustin Bogner //===----------------------------------------------------------------------===//
82b6c537bSJustin Bogner 
959411db5SXinliang David Li #include "llvm/IR/Function.h"
10402477d2SXinliang David Li #include "llvm/IR/IRBuilder.h"
1159411db5SXinliang David Li #include "llvm/IR/LLVMContext.h"
1259411db5SXinliang David Li #include "llvm/IR/Module.h"
132b6c537bSJustin Bogner #include "llvm/ProfileData/InstrProfReader.h"
142b6c537bSJustin Bogner #include "llvm/ProfileData/InstrProfWriter.h"
150a418490SSnehasish Kumar #include "llvm/ProfileData/MemProf.h"
1627a4f254SSnehasish Kumar #include "llvm/ProfileData/MemProfData.inc"
17e413f1a0SXinliang David Li #include "llvm/Support/Compression.h"
186dd6a616SSnehasish Kumar #include "llvm/Support/raw_ostream.h"
1994b98b2cSDavid Blaikie #include "llvm/Testing/Support/Error.h"
2094b98b2cSDavid Blaikie #include "llvm/Testing/Support/SupportHelpers.h"
212b6c537bSJustin Bogner #include "gtest/gtest.h"
222b6c537bSJustin Bogner #include <cstdarg>
232b6c537bSJustin Bogner 
242b6c537bSJustin Bogner using namespace llvm;
252b6c537bSJustin Bogner 
2694b98b2cSDavid Blaikie LLVM_NODISCARD static ::testing::AssertionResult
ErrorEquals(instrprof_error Expected,Error E)2794b98b2cSDavid Blaikie ErrorEquals(instrprof_error Expected, Error E) {
289152fd17SVedant Kumar   instrprof_error Found;
299152fd17SVedant Kumar   std::string FoundMsg;
309152fd17SVedant Kumar   handleAllErrors(std::move(E), [&](const InstrProfError &IPE) {
319152fd17SVedant Kumar     Found = IPE.get();
329152fd17SVedant Kumar     FoundMsg = IPE.message();
339152fd17SVedant Kumar   });
342b6c537bSJustin Bogner   if (Expected == Found)
352b6c537bSJustin Bogner     return ::testing::AssertionSuccess();
369152fd17SVedant Kumar   return ::testing::AssertionFailure() << "error: " << FoundMsg << "\n";
372b6c537bSJustin Bogner }
382b6c537bSJustin Bogner 
392b6c537bSJustin Bogner namespace {
402b6c537bSJustin Bogner 
412b6c537bSJustin Bogner struct InstrProfTest : ::testing::Test {
422b6c537bSJustin Bogner   InstrProfWriter Writer;
432b6c537bSJustin Bogner   std::unique_ptr<IndexedInstrProfReader> Reader;
442b6c537bSJustin Bogner 
SetUp__anon741d935d0211::InstrProfTest4531eb8349SLogan Smith   void SetUp() override { Writer.setOutputSparse(false); }
4600dab228SVedant Kumar 
readProfile__anon741d935d0211::InstrProfTest47ceed4eb1SRichard Smith   void readProfile(std::unique_ptr<MemoryBuffer> Profile,
48ceed4eb1SRichard Smith                    std::unique_ptr<MemoryBuffer> Remapping = nullptr) {
49ceed4eb1SRichard Smith     auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile),
50ceed4eb1SRichard Smith                                                       std::move(Remapping));
5194b98b2cSDavid Blaikie     EXPECT_THAT_ERROR(ReaderOrErr.takeError(), Succeeded());
522b6c537bSJustin Bogner     Reader = std::move(ReaderOrErr.get());
532b6c537bSJustin Bogner   }
542b6c537bSJustin Bogner };
552b6c537bSJustin Bogner 
5600dab228SVedant Kumar struct SparseInstrProfTest : public InstrProfTest {
SetUp__anon741d935d0211::SparseInstrProfTest5731eb8349SLogan Smith   void SetUp() override { Writer.setOutputSparse(true); }
5800dab228SVedant Kumar };
5900dab228SVedant Kumar 
6000dab228SVedant Kumar struct MaybeSparseInstrProfTest : public InstrProfTest,
6100dab228SVedant Kumar                                   public ::testing::WithParamInterface<bool> {
SetUp__anon741d935d0211::MaybeSparseInstrProfTest6231eb8349SLogan Smith   void SetUp() override { Writer.setOutputSparse(GetParam()); }
6300dab228SVedant Kumar };
6400dab228SVedant Kumar 
TEST_P(MaybeSparseInstrProfTest,write_and_read_empty_profile)6500dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, write_and_read_empty_profile) {
662b6c537bSJustin Bogner   auto Profile = Writer.writeBuffer();
672b6c537bSJustin Bogner   readProfile(std::move(Profile));
682b6c537bSJustin Bogner   ASSERT_TRUE(Reader->begin() == Reader->end());
692b6c537bSJustin Bogner }
702b6c537bSJustin Bogner 
__anon741d935d0302(Error E) 7198cce003SDavid Blaikie static const auto Err = [](Error E) {
7298cce003SDavid Blaikie   consumeError(std::move(E));
7398cce003SDavid Blaikie   FAIL();
7498cce003SDavid Blaikie };
7598cce003SDavid Blaikie 
TEST_P(MaybeSparseInstrProfTest,write_and_read_one_function)7600dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, write_and_read_one_function) {
7798cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1234, {1, 2, 3, 4}}, Err);
782b6c537bSJustin Bogner   auto Profile = Writer.writeBuffer();
792b6c537bSJustin Bogner   readProfile(std::move(Profile));
802b6c537bSJustin Bogner 
812b6c537bSJustin Bogner   auto I = Reader->begin(), E = Reader->end();
822b6c537bSJustin Bogner   ASSERT_TRUE(I != E);
832b6c537bSJustin Bogner   ASSERT_EQ(StringRef("foo"), I->Name);
842b6c537bSJustin Bogner   ASSERT_EQ(0x1234U, I->Hash);
852b6c537bSJustin Bogner   ASSERT_EQ(4U, I->Counts.size());
862b6c537bSJustin Bogner   ASSERT_EQ(1U, I->Counts[0]);
872b6c537bSJustin Bogner   ASSERT_EQ(2U, I->Counts[1]);
882b6c537bSJustin Bogner   ASSERT_EQ(3U, I->Counts[2]);
892b6c537bSJustin Bogner   ASSERT_EQ(4U, I->Counts[3]);
902b6c537bSJustin Bogner   ASSERT_TRUE(++I == E);
912b6c537bSJustin Bogner }
922b6c537bSJustin Bogner 
TEST_P(MaybeSparseInstrProfTest,get_instr_prof_record)9300dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_instr_prof_record) {
9498cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1234, {1, 2}}, Err);
9598cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1235, {3, 4}}, Err);
962004f003SXinliang David Li   auto Profile = Writer.writeBuffer();
972004f003SXinliang David Li   readProfile(std::move(Profile));
982004f003SXinliang David Li 
999152fd17SVedant Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234);
10094b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
101fed557efSDavid Blaikie   ASSERT_EQ(2U, R->Counts.size());
102fed557efSDavid Blaikie   ASSERT_EQ(1U, R->Counts[0]);
103fed557efSDavid Blaikie   ASSERT_EQ(2U, R->Counts[1]);
1042004f003SXinliang David Li 
1052004f003SXinliang David Li   R = Reader->getInstrProfRecord("foo", 0x1235);
10694b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
107fed557efSDavid Blaikie   ASSERT_EQ(2U, R->Counts.size());
108fed557efSDavid Blaikie   ASSERT_EQ(3U, R->Counts[0]);
109fed557efSDavid Blaikie   ASSERT_EQ(4U, R->Counts[1]);
1102004f003SXinliang David Li 
1112004f003SXinliang David Li   R = Reader->getInstrProfRecord("foo", 0x5678);
1129152fd17SVedant Kumar   ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.takeError()));
1132004f003SXinliang David Li 
1142004f003SXinliang David Li   R = Reader->getInstrProfRecord("bar", 0x1234);
1159152fd17SVedant Kumar   ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.takeError()));
1162004f003SXinliang David Li }
1172004f003SXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,get_function_counts)11800dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_function_counts) {
11998cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1234, {1, 2}}, Err);
12098cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1235, {3, 4}}, Err);
1212b6c537bSJustin Bogner   auto Profile = Writer.writeBuffer();
1222b6c537bSJustin Bogner   readProfile(std::move(Profile));
1232b6c537bSJustin Bogner 
1242b6c537bSJustin Bogner   std::vector<uint64_t> Counts;
12594b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1234, Counts),
12694b98b2cSDavid Blaikie                     Succeeded());
1272b6c537bSJustin Bogner   ASSERT_EQ(2U, Counts.size());
1282b6c537bSJustin Bogner   ASSERT_EQ(1U, Counts[0]);
1292b6c537bSJustin Bogner   ASSERT_EQ(2U, Counts[1]);
1302b6c537bSJustin Bogner 
13194b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1235, Counts),
13294b98b2cSDavid Blaikie                     Succeeded());
13309829f44SJustin Bogner   ASSERT_EQ(2U, Counts.size());
13409829f44SJustin Bogner   ASSERT_EQ(3U, Counts[0]);
13509829f44SJustin Bogner   ASSERT_EQ(4U, Counts[1]);
13609829f44SJustin Bogner 
1379152fd17SVedant Kumar   Error E1 = Reader->getFunctionCounts("foo", 0x5678, Counts);
1389152fd17SVedant Kumar   ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, std::move(E1)));
1392b6c537bSJustin Bogner 
1409152fd17SVedant Kumar   Error E2 = Reader->getFunctionCounts("bar", 0x1234, Counts);
1419152fd17SVedant Kumar   ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, std::move(E2)));
1422b6c537bSJustin Bogner }
1432b6c537bSJustin Bogner 
1446c93ee8dSXinliang David Li // Profile data is copied from general.proftext
TEST_F(InstrProfTest,get_profile_summary)1456c93ee8dSXinliang David Li TEST_F(InstrProfTest, get_profile_summary) {
14698cce003SDavid Blaikie   Writer.addRecord({"func1", 0x1234, {97531}}, Err);
14798cce003SDavid Blaikie   Writer.addRecord({"func2", 0x1234, {0, 0}}, Err);
14898cce003SDavid Blaikie   Writer.addRecord(
14998cce003SDavid Blaikie       {"func3",
1505b079d83SDavid Blaikie        0x1234,
15198cce003SDavid Blaikie        {2305843009213693952, 1152921504606846976, 576460752303423488,
15298cce003SDavid Blaikie         288230376151711744, 144115188075855872, 72057594037927936}},
15398cce003SDavid Blaikie       Err);
15498cce003SDavid Blaikie   Writer.addRecord({"func4", 0x1234, {0}}, Err);
1556c93ee8dSXinliang David Li   auto Profile = Writer.writeBuffer();
1566c93ee8dSXinliang David Li   readProfile(std::move(Profile));
1576c93ee8dSXinliang David Li 
1587cefdb81SEaswaran Raman   auto VerifySummary = [](ProfileSummary &IPS) mutable {
1597cefdb81SEaswaran Raman     ASSERT_EQ(ProfileSummary::PSK_Instr, IPS.getKind());
1607c4f25d2SEaswaran Raman     ASSERT_EQ(2305843009213693952U, IPS.getMaxFunctionCount());
1617cefdb81SEaswaran Raman     ASSERT_EQ(2305843009213693952U, IPS.getMaxCount());
1627cefdb81SEaswaran Raman     ASSERT_EQ(10U, IPS.getNumCounts());
1637c4f25d2SEaswaran Raman     ASSERT_EQ(4539628424389557499U, IPS.getTotalCount());
164d6790a0aSMircea Trofin     const std::vector<ProfileSummaryEntry> &Details = IPS.getDetailedSummary();
1656c93ee8dSXinliang David Li     uint32_t Cutoff = 800000;
1666c93ee8dSXinliang David Li     auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) {
1676c93ee8dSXinliang David Li       return PE.Cutoff == Cutoff;
1686c93ee8dSXinliang David Li     };
169562e8294SDavid Majnemer     auto EightyPerc = find_if(Details, Predicate);
1706c93ee8dSXinliang David Li     Cutoff = 900000;
171562e8294SDavid Majnemer     auto NinetyPerc = find_if(Details, Predicate);
1726c93ee8dSXinliang David Li     Cutoff = 950000;
173562e8294SDavid Majnemer     auto NinetyFivePerc = find_if(Details, Predicate);
1746c93ee8dSXinliang David Li     Cutoff = 990000;
175562e8294SDavid Majnemer     auto NinetyNinePerc = find_if(Details, Predicate);
1764309570dSEaswaran Raman     ASSERT_EQ(576460752303423488U, EightyPerc->MinCount);
1774309570dSEaswaran Raman     ASSERT_EQ(288230376151711744U, NinetyPerc->MinCount);
1784309570dSEaswaran Raman     ASSERT_EQ(288230376151711744U, NinetyFivePerc->MinCount);
1794309570dSEaswaran Raman     ASSERT_EQ(72057594037927936U, NinetyNinePerc->MinCount);
1807c4f25d2SEaswaran Raman   };
181a6ff69f6SRong Xu   ProfileSummary &PS = Reader->getSummary(/* IsCS */ false);
182f9709ee0SEaswaran Raman   VerifySummary(PS);
18326628d30SEaswaran Raman 
18426628d30SEaswaran Raman   // Test that conversion of summary to and from Metadata works.
18503b42e41SMehdi Amini   LLVMContext Context;
18603b42e41SMehdi Amini   Metadata *MD = PS.getMD(Context);
1877c4f25d2SEaswaran Raman   ASSERT_TRUE(MD);
1887c4f25d2SEaswaran Raman   ProfileSummary *PSFromMD = ProfileSummary::getFromMD(MD);
1897c4f25d2SEaswaran Raman   ASSERT_TRUE(PSFromMD);
1907cefdb81SEaswaran Raman   VerifySummary(*PSFromMD);
1917cefdb81SEaswaran Raman   delete PSFromMD;
19226628d30SEaswaran Raman 
19326628d30SEaswaran Raman   // Test that summary can be attached to and read back from module.
19403b42e41SMehdi Amini   Module M("my_module", Context);
195a6ff69f6SRong Xu   M.setProfileSummary(MD, ProfileSummary::PSK_Instr);
196a6ff69f6SRong Xu   MD = M.getProfileSummary(/* IsCS */ false);
19726628d30SEaswaran Raman   ASSERT_TRUE(MD);
19826628d30SEaswaran Raman   PSFromMD = ProfileSummary::getFromMD(MD);
19926628d30SEaswaran Raman   ASSERT_TRUE(PSFromMD);
2007cefdb81SEaswaran Raman   VerifySummary(*PSFromMD);
2017cefdb81SEaswaran Raman   delete PSFromMD;
2026c93ee8dSXinliang David Li }
2036c93ee8dSXinliang David Li 
TEST_F(InstrProfTest,test_writer_merge)204e3a0bf50SVedant Kumar TEST_F(InstrProfTest, test_writer_merge) {
20598cce003SDavid Blaikie   Writer.addRecord({"func1", 0x1234, {42}}, Err);
206e3a0bf50SVedant Kumar 
207e3a0bf50SVedant Kumar   InstrProfWriter Writer2;
20898cce003SDavid Blaikie   Writer2.addRecord({"func2", 0x1234, {0, 0}}, Err);
209e3a0bf50SVedant Kumar 
21098cce003SDavid Blaikie   Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
211e3a0bf50SVedant Kumar 
212e3a0bf50SVedant Kumar   auto Profile = Writer.writeBuffer();
213e3a0bf50SVedant Kumar   readProfile(std::move(Profile));
214e3a0bf50SVedant Kumar 
215e3a0bf50SVedant Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("func1", 0x1234);
21694b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
217e3a0bf50SVedant Kumar   ASSERT_EQ(1U, R->Counts.size());
218e3a0bf50SVedant Kumar   ASSERT_EQ(42U, R->Counts[0]);
219e3a0bf50SVedant Kumar 
220e3a0bf50SVedant Kumar   R = Reader->getInstrProfRecord("func2", 0x1234);
22194b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
222e3a0bf50SVedant Kumar   ASSERT_EQ(2U, R->Counts.size());
223e3a0bf50SVedant Kumar   ASSERT_EQ(0U, R->Counts[0]);
224e3a0bf50SVedant Kumar   ASSERT_EQ(0U, R->Counts[1]);
225e3a0bf50SVedant Kumar }
226e3a0bf50SVedant Kumar 
2276dd6a616SSnehasish Kumar using ::llvm::memprof::IndexedMemProfRecord;
22827a4f254SSnehasish Kumar using ::llvm::memprof::MemInfoBlock;
2296dd6a616SSnehasish Kumar using FrameIdMapTy =
2306dd6a616SSnehasish Kumar     llvm::DenseMap<::llvm::memprof::FrameId, ::llvm::memprof::Frame>;
2316dd6a616SSnehasish Kumar 
getFrameMapping()2326dd6a616SSnehasish Kumar static FrameIdMapTy getFrameMapping() {
2336dd6a616SSnehasish Kumar   FrameIdMapTy Mapping;
2346dd6a616SSnehasish Kumar   Mapping.insert({0, {0x123, 1, 2, false}});
2356dd6a616SSnehasish Kumar   Mapping.insert({1, {0x345, 3, 4, true}});
2366dd6a616SSnehasish Kumar   Mapping.insert({2, {0x125, 5, 6, false}});
2376dd6a616SSnehasish Kumar   Mapping.insert({3, {0x567, 7, 8, true}});
2386dd6a616SSnehasish Kumar   Mapping.insert({4, {0x124, 5, 6, false}});
2396dd6a616SSnehasish Kumar   Mapping.insert({5, {0x789, 8, 9, true}});
2406dd6a616SSnehasish Kumar   return Mapping;
2416dd6a616SSnehasish Kumar }
2426dd6a616SSnehasish Kumar 
makeRecord(std::initializer_list<std::initializer_list<::llvm::memprof::FrameId>> AllocFrames,std::initializer_list<std::initializer_list<::llvm::memprof::FrameId>> CallSiteFrames,const MemInfoBlock & Block=MemInfoBlock ())2436dd6a616SSnehasish Kumar IndexedMemProfRecord makeRecord(
2446dd6a616SSnehasish Kumar     std::initializer_list<std::initializer_list<::llvm::memprof::FrameId>>
24527a4f254SSnehasish Kumar         AllocFrames,
2466dd6a616SSnehasish Kumar     std::initializer_list<std::initializer_list<::llvm::memprof::FrameId>>
24727a4f254SSnehasish Kumar         CallSiteFrames,
24827a4f254SSnehasish Kumar     const MemInfoBlock &Block = MemInfoBlock()) {
2496dd6a616SSnehasish Kumar   llvm::memprof::IndexedMemProfRecord MR;
25027a4f254SSnehasish Kumar   for (const auto &Frames : AllocFrames)
25127a4f254SSnehasish Kumar     MR.AllocSites.emplace_back(Frames, Block);
25227a4f254SSnehasish Kumar   for (const auto &Frames : CallSiteFrames)
25327a4f254SSnehasish Kumar     MR.CallSites.push_back(Frames);
25427a4f254SSnehasish Kumar   return MR;
25527a4f254SSnehasish Kumar }
25627a4f254SSnehasish Kumar 
2576dd6a616SSnehasish Kumar MATCHER_P(EqualsRecord, Want, "") {
2586dd6a616SSnehasish Kumar   const memprof::MemProfRecord &Got = arg;
2596dd6a616SSnehasish Kumar 
__anon741d935d0602() 2606dd6a616SSnehasish Kumar   auto PrintAndFail = [&]() {
2616dd6a616SSnehasish Kumar     std::string Buffer;
2626dd6a616SSnehasish Kumar     llvm::raw_string_ostream OS(Buffer);
2636dd6a616SSnehasish Kumar     OS << "Want:\n";
2646dd6a616SSnehasish Kumar     Want.print(OS);
2656dd6a616SSnehasish Kumar     OS << "Got:\n";
2666dd6a616SSnehasish Kumar     Got.print(OS);
2676dd6a616SSnehasish Kumar     OS.flush();
2686dd6a616SSnehasish Kumar     *result_listener << "MemProf Record differs!\n" << Buffer;
2696dd6a616SSnehasish Kumar     return false;
2706dd6a616SSnehasish Kumar   };
2716dd6a616SSnehasish Kumar 
2726dd6a616SSnehasish Kumar   if (Want.AllocSites.size() != Got.AllocSites.size())
2736dd6a616SSnehasish Kumar     return PrintAndFail();
2746dd6a616SSnehasish Kumar   if (Want.CallSites.size() != Got.CallSites.size())
2756dd6a616SSnehasish Kumar     return PrintAndFail();
2766dd6a616SSnehasish Kumar 
2776dd6a616SSnehasish Kumar   for (size_t I = 0; I < Got.AllocSites.size(); I++) {
2786dd6a616SSnehasish Kumar     if (Want.AllocSites[I].Info != Got.AllocSites[I].Info)
2796dd6a616SSnehasish Kumar       return PrintAndFail();
2806dd6a616SSnehasish Kumar     if (Want.AllocSites[I].CallStack != Got.AllocSites[I].CallStack)
2816dd6a616SSnehasish Kumar       return PrintAndFail();
2826dd6a616SSnehasish Kumar   }
2836dd6a616SSnehasish Kumar 
2846dd6a616SSnehasish Kumar   for (size_t I = 0; I < Got.CallSites.size(); I++) {
2856dd6a616SSnehasish Kumar     if (Want.CallSites[I] != Got.CallSites[I])
2866dd6a616SSnehasish Kumar       return PrintAndFail();
2876dd6a616SSnehasish Kumar   }
2886dd6a616SSnehasish Kumar   return true;
2896dd6a616SSnehasish Kumar }
2906dd6a616SSnehasish Kumar 
TEST_F(InstrProfTest,test_memprof)2910a418490SSnehasish Kumar TEST_F(InstrProfTest, test_memprof) {
2920a418490SSnehasish Kumar   ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::MemProf),
2930a418490SSnehasish Kumar                     Succeeded());
29427a4f254SSnehasish Kumar 
2956dd6a616SSnehasish Kumar   const IndexedMemProfRecord IndexedMR = makeRecord(
29627a4f254SSnehasish Kumar       /*AllocFrames=*/
29727a4f254SSnehasish Kumar       {
2986dd6a616SSnehasish Kumar           {0, 1},
2996dd6a616SSnehasish Kumar           {2, 3},
30027a4f254SSnehasish Kumar       },
30127a4f254SSnehasish Kumar       /*CallSiteFrames=*/{
3026dd6a616SSnehasish Kumar           {4, 5},
30327a4f254SSnehasish Kumar       });
3046dd6a616SSnehasish Kumar   const FrameIdMapTy IdToFrameMap = getFrameMapping();
3056dd6a616SSnehasish Kumar   for (const auto &I : IdToFrameMap) {
3066dd6a616SSnehasish Kumar     Writer.addMemProfFrame(I.first, I.getSecond(), Err);
3076dd6a616SSnehasish Kumar   }
3086dd6a616SSnehasish Kumar   Writer.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
3090a418490SSnehasish Kumar 
3100a418490SSnehasish Kumar   auto Profile = Writer.writeBuffer();
3110a418490SSnehasish Kumar   readProfile(std::move(Profile));
3120a418490SSnehasish Kumar 
3136dd6a616SSnehasish Kumar   auto RecordOr = Reader->getMemProfRecord(0x9999);
3146dd6a616SSnehasish Kumar   ASSERT_THAT_ERROR(RecordOr.takeError(), Succeeded());
3156dd6a616SSnehasish Kumar   const memprof::MemProfRecord &Record = RecordOr.get();
3166dd6a616SSnehasish Kumar 
3176dd6a616SSnehasish Kumar   memprof::FrameId LastUnmappedFrameId = 0;
3186dd6a616SSnehasish Kumar   bool HasFrameMappingError = false;
3196dd6a616SSnehasish Kumar   auto IdToFrameCallback = [&](const memprof::FrameId Id) {
3206dd6a616SSnehasish Kumar     auto Iter = IdToFrameMap.find(Id);
3216dd6a616SSnehasish Kumar     if (Iter == IdToFrameMap.end()) {
3226dd6a616SSnehasish Kumar       LastUnmappedFrameId = Id;
3236dd6a616SSnehasish Kumar       HasFrameMappingError = true;
3246dd6a616SSnehasish Kumar       return memprof::Frame(0, 0, 0, false);
3256dd6a616SSnehasish Kumar     }
3266dd6a616SSnehasish Kumar     return Iter->second;
3276dd6a616SSnehasish Kumar   };
3286dd6a616SSnehasish Kumar 
3296dd6a616SSnehasish Kumar   const memprof::MemProfRecord WantRecord(IndexedMR, IdToFrameCallback);
3306dd6a616SSnehasish Kumar   ASSERT_FALSE(HasFrameMappingError)
3316dd6a616SSnehasish Kumar       << "could not map frame id: " << LastUnmappedFrameId;
3326dd6a616SSnehasish Kumar   EXPECT_THAT(WantRecord, EqualsRecord(Record));
3336dd6a616SSnehasish Kumar }
3346dd6a616SSnehasish Kumar 
TEST_F(InstrProfTest,test_memprof_getrecord_error)3356dd6a616SSnehasish Kumar TEST_F(InstrProfTest, test_memprof_getrecord_error) {
3366dd6a616SSnehasish Kumar   ASSERT_THAT_ERROR(Writer.mergeProfileKind(InstrProfKind::MemProf),
3376dd6a616SSnehasish Kumar                     Succeeded());
3386dd6a616SSnehasish Kumar 
3396dd6a616SSnehasish Kumar   const IndexedMemProfRecord IndexedMR = makeRecord(
3406dd6a616SSnehasish Kumar       /*AllocFrames=*/
3416dd6a616SSnehasish Kumar       {
3426dd6a616SSnehasish Kumar           {0, 1},
3436dd6a616SSnehasish Kumar           {2, 3},
3446dd6a616SSnehasish Kumar       },
3456dd6a616SSnehasish Kumar       /*CallSiteFrames=*/{
3466dd6a616SSnehasish Kumar           {4, 5},
3476dd6a616SSnehasish Kumar       });
3486dd6a616SSnehasish Kumar   // We skip adding the frame mappings here unlike the test_memprof unit test
3496dd6a616SSnehasish Kumar   // above to exercise the failure path when getMemProfRecord is invoked.
3506dd6a616SSnehasish Kumar   Writer.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
3516dd6a616SSnehasish Kumar 
3526dd6a616SSnehasish Kumar   auto Profile = Writer.writeBuffer();
3536dd6a616SSnehasish Kumar   readProfile(std::move(Profile));
3546dd6a616SSnehasish Kumar 
35565529486STeresa Johnson   // Missing frames give a hash_mismatch error.
3566dd6a616SSnehasish Kumar   auto RecordOr = Reader->getMemProfRecord(0x9999);
35765529486STeresa Johnson   ASSERT_TRUE(
35865529486STeresa Johnson       ErrorEquals(instrprof_error::hash_mismatch, RecordOr.takeError()));
35965529486STeresa Johnson 
36065529486STeresa Johnson   // Missing functions give a unknown_function error.
36165529486STeresa Johnson   RecordOr = Reader->getMemProfRecord(0x1111);
36265529486STeresa Johnson   ASSERT_TRUE(
36365529486STeresa Johnson       ErrorEquals(instrprof_error::unknown_function, RecordOr.takeError()));
3640a418490SSnehasish Kumar }
3650a418490SSnehasish Kumar 
TEST_F(InstrProfTest,test_memprof_merge)3660a418490SSnehasish Kumar TEST_F(InstrProfTest, test_memprof_merge) {
3670a418490SSnehasish Kumar   Writer.addRecord({"func1", 0x1234, {42}}, Err);
3680a418490SSnehasish Kumar 
3690a418490SSnehasish Kumar   InstrProfWriter Writer2;
3700a418490SSnehasish Kumar   ASSERT_THAT_ERROR(Writer2.mergeProfileKind(InstrProfKind::MemProf),
3710a418490SSnehasish Kumar                     Succeeded());
3720a418490SSnehasish Kumar 
3736dd6a616SSnehasish Kumar   const IndexedMemProfRecord IndexedMR = makeRecord(
37427a4f254SSnehasish Kumar       /*AllocFrames=*/
37527a4f254SSnehasish Kumar       {
3766dd6a616SSnehasish Kumar           {0, 1},
3776dd6a616SSnehasish Kumar           {2, 3},
37827a4f254SSnehasish Kumar       },
37927a4f254SSnehasish Kumar       /*CallSiteFrames=*/{
3806dd6a616SSnehasish Kumar           {4, 5},
38127a4f254SSnehasish Kumar       });
3826dd6a616SSnehasish Kumar 
3836dd6a616SSnehasish Kumar   const FrameIdMapTy IdToFrameMap = getFrameMapping();
3846dd6a616SSnehasish Kumar   for (const auto &I : IdToFrameMap) {
3856dd6a616SSnehasish Kumar     Writer.addMemProfFrame(I.first, I.getSecond(), Err);
3866dd6a616SSnehasish Kumar   }
3876dd6a616SSnehasish Kumar   Writer2.addMemProfRecord(/*Id=*/0x9999, IndexedMR);
3880a418490SSnehasish Kumar 
3890a418490SSnehasish Kumar   ASSERT_THAT_ERROR(Writer.mergeProfileKind(Writer2.getProfileKind()),
3900a418490SSnehasish Kumar                     Succeeded());
3910a418490SSnehasish Kumar   Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
3920a418490SSnehasish Kumar 
3930a418490SSnehasish Kumar   auto Profile = Writer.writeBuffer();
3940a418490SSnehasish Kumar   readProfile(std::move(Profile));
3950a418490SSnehasish Kumar 
3960a418490SSnehasish Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("func1", 0x1234);
3970a418490SSnehasish Kumar   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
3980a418490SSnehasish Kumar   ASSERT_EQ(1U, R->Counts.size());
3990a418490SSnehasish Kumar   ASSERT_EQ(42U, R->Counts[0]);
4000a418490SSnehasish Kumar 
4016dd6a616SSnehasish Kumar   auto RecordOr = Reader->getMemProfRecord(0x9999);
4026dd6a616SSnehasish Kumar   ASSERT_THAT_ERROR(RecordOr.takeError(), Succeeded());
4036dd6a616SSnehasish Kumar   const memprof::MemProfRecord &Record = RecordOr.get();
4046dd6a616SSnehasish Kumar 
4056dd6a616SSnehasish Kumar   memprof::FrameId LastUnmappedFrameId = 0;
4066dd6a616SSnehasish Kumar   bool HasFrameMappingError = false;
4076dd6a616SSnehasish Kumar 
4086dd6a616SSnehasish Kumar   auto IdToFrameCallback = [&](const memprof::FrameId Id) {
4096dd6a616SSnehasish Kumar     auto Iter = IdToFrameMap.find(Id);
4106dd6a616SSnehasish Kumar     if (Iter == IdToFrameMap.end()) {
4116dd6a616SSnehasish Kumar       LastUnmappedFrameId = Id;
4126dd6a616SSnehasish Kumar       HasFrameMappingError = true;
4136dd6a616SSnehasish Kumar       return memprof::Frame(0, 0, 0, false);
4146dd6a616SSnehasish Kumar     }
4156dd6a616SSnehasish Kumar     return Iter->second;
4166dd6a616SSnehasish Kumar   };
4176dd6a616SSnehasish Kumar 
4186dd6a616SSnehasish Kumar   const memprof::MemProfRecord WantRecord(IndexedMR, IdToFrameCallback);
4196dd6a616SSnehasish Kumar   ASSERT_FALSE(HasFrameMappingError)
4206dd6a616SSnehasish Kumar       << "could not map frame id: " << LastUnmappedFrameId;
4216dd6a616SSnehasish Kumar   EXPECT_THAT(WantRecord, EqualsRecord(Record));
4220a418490SSnehasish Kumar }
4230a418490SSnehasish Kumar 
424a3e0d45bSXinliang David Li static const char callee1[] = "callee1";
425a3e0d45bSXinliang David Li static const char callee2[] = "callee2";
426a3e0d45bSXinliang David Li static const char callee3[] = "callee3";
427a3e0d45bSXinliang David Li static const char callee4[] = "callee4";
428a3e0d45bSXinliang David Li static const char callee5[] = "callee5";
429a3e0d45bSXinliang David Li static const char callee6[] = "callee6";
430a3e0d45bSXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,get_icall_data_read_write)43100dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write) {
432cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
4332004f003SXinliang David Li 
4342004f003SXinliang David Li   // 4 value sites.
4352004f003SXinliang David Li   Record1.reserveSites(IPVK_IndirectCallTarget, 4);
436a3e0d45bSXinliang David Li   InstrProfValueData VD0[] = {
437a3e0d45bSXinliang David Li       {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}};
438ffec81caSEugene Zelenko   Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
439ee415895SXinliang David Li   // No value profile data at the second site.
440ffec81caSEugene Zelenko   Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
441a3e0d45bSXinliang David Li   InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}};
442ffec81caSEugene Zelenko   Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
443a3e0d45bSXinliang David Li   InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
444ffec81caSEugene Zelenko   Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
4452004f003SXinliang David Li 
44698cce003SDavid Blaikie   Writer.addRecord(std::move(Record1), Err);
44798cce003SDavid Blaikie   Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
44898cce003SDavid Blaikie   Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
44998cce003SDavid Blaikie   Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
4502004f003SXinliang David Li   auto Profile = Writer.writeBuffer();
4512004f003SXinliang David Li   readProfile(std::move(Profile));
4522004f003SXinliang David Li 
4539152fd17SVedant Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
45494b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
455fed557efSDavid Blaikie   ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
456fed557efSDavid Blaikie   ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
457fed557efSDavid Blaikie   ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
458fed557efSDavid Blaikie   ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
459fed557efSDavid Blaikie   ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
4602004f003SXinliang David Li 
4611e4c809cSXinliang David Li   uint64_t TotalC;
4622004f003SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD =
463fed557efSDavid Blaikie       R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);
46451dc04cfSXinliang David Li 
46551dc04cfSXinliang David Li   ASSERT_EQ(3U, VD[0].Count);
46651dc04cfSXinliang David Li   ASSERT_EQ(2U, VD[1].Count);
46751dc04cfSXinliang David Li   ASSERT_EQ(1U, VD[2].Count);
4681e4c809cSXinliang David Li   ASSERT_EQ(6U, TotalC);
46951dc04cfSXinliang David Li 
47051dc04cfSXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
47151dc04cfSXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
47251dc04cfSXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
47351dc04cfSXinliang David Li }
47451dc04cfSXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,annotate_vp_data)475402477d2SXinliang David Li TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) {
476cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record("caller", 0x1234, {1, 2});
477402477d2SXinliang David Li   Record.reserveSites(IPVK_IndirectCallTarget, 1);
47869683f13SRong Xu   InstrProfValueData VD0[] = {{1000, 1}, {2000, 2}, {3000, 3}, {5000, 5},
47969683f13SRong Xu                               {4000, 4}, {6000, 6}};
48069683f13SRong Xu   Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 6, nullptr);
48198cce003SDavid Blaikie   Writer.addRecord(std::move(Record), Err);
482402477d2SXinliang David Li   auto Profile = Writer.writeBuffer();
483402477d2SXinliang David Li   readProfile(std::move(Profile));
4849152fd17SVedant Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
48594b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
486402477d2SXinliang David Li 
487402477d2SXinliang David Li   LLVMContext Ctx;
488402477d2SXinliang David Li   std::unique_ptr<Module> M(new Module("MyModule", Ctx));
489402477d2SXinliang David Li   FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
490402477d2SXinliang David Li                                         /*isVarArg=*/false);
491402477d2SXinliang David Li   Function *F =
492402477d2SXinliang David Li       Function::Create(FTy, Function::ExternalLinkage, "caller", M.get());
493402477d2SXinliang David Li   BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
494402477d2SXinliang David Li 
495402477d2SXinliang David Li   IRBuilder<> Builder(BB);
496402477d2SXinliang David Li   BasicBlock *TBB = BasicBlock::Create(Ctx, "", F);
497402477d2SXinliang David Li   BasicBlock *FBB = BasicBlock::Create(Ctx, "", F);
498402477d2SXinliang David Li 
499402477d2SXinliang David Li   // Use branch instruction to annotate with value profile data for simplicity
500402477d2SXinliang David Li   Instruction *Inst = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
501402477d2SXinliang David Li   Instruction *Inst2 = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
502fed557efSDavid Blaikie   annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0);
503402477d2SXinliang David Li 
504402477d2SXinliang David Li   InstrProfValueData ValueData[5];
505402477d2SXinliang David Li   uint32_t N;
506402477d2SXinliang David Li   uint64_t T;
507402477d2SXinliang David Li   bool Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
508402477d2SXinliang David Li                                       ValueData, N, T);
509402477d2SXinliang David Li   ASSERT_TRUE(Res);
510402477d2SXinliang David Li   ASSERT_EQ(3U, N);
51169683f13SRong Xu   ASSERT_EQ(21U, T);
512402477d2SXinliang David Li   // The result should be sorted already:
51369683f13SRong Xu   ASSERT_EQ(6000U, ValueData[0].Value);
51469683f13SRong Xu   ASSERT_EQ(6U, ValueData[0].Count);
51569683f13SRong Xu   ASSERT_EQ(5000U, ValueData[1].Value);
51669683f13SRong Xu   ASSERT_EQ(5U, ValueData[1].Count);
51769683f13SRong Xu   ASSERT_EQ(4000U, ValueData[2].Value);
51869683f13SRong Xu   ASSERT_EQ(4U, ValueData[2].Count);
519402477d2SXinliang David Li   Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 1, ValueData,
520402477d2SXinliang David Li                                  N, T);
521402477d2SXinliang David Li   ASSERT_TRUE(Res);
522402477d2SXinliang David Li   ASSERT_EQ(1U, N);
52369683f13SRong Xu   ASSERT_EQ(21U, T);
524402477d2SXinliang David Li 
525402477d2SXinliang David Li   Res = getValueProfDataFromInst(*Inst2, IPVK_IndirectCallTarget, 5, ValueData,
526402477d2SXinliang David Li                                  N, T);
527402477d2SXinliang David Li   ASSERT_FALSE(Res);
52869683f13SRong Xu 
52969683f13SRong Xu   // Remove the MD_prof metadata
53069683f13SRong Xu   Inst->setMetadata(LLVMContext::MD_prof, 0);
53169683f13SRong Xu   // Annotate 5 records this time.
53269683f13SRong Xu   annotateValueSite(*M, *Inst, R.get(), IPVK_IndirectCallTarget, 0, 5);
53369683f13SRong Xu   Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
53469683f13SRong Xu                                       ValueData, N, T);
53569683f13SRong Xu   ASSERT_TRUE(Res);
53669683f13SRong Xu   ASSERT_EQ(5U, N);
53769683f13SRong Xu   ASSERT_EQ(21U, T);
53869683f13SRong Xu   ASSERT_EQ(6000U, ValueData[0].Value);
53969683f13SRong Xu   ASSERT_EQ(6U, ValueData[0].Count);
54069683f13SRong Xu   ASSERT_EQ(5000U, ValueData[1].Value);
54169683f13SRong Xu   ASSERT_EQ(5U, ValueData[1].Count);
54269683f13SRong Xu   ASSERT_EQ(4000U, ValueData[2].Value);
54369683f13SRong Xu   ASSERT_EQ(4U, ValueData[2].Count);
54469683f13SRong Xu   ASSERT_EQ(3000U, ValueData[3].Value);
54569683f13SRong Xu   ASSERT_EQ(3U, ValueData[3].Count);
54669683f13SRong Xu   ASSERT_EQ(2000U, ValueData[4].Value);
54769683f13SRong Xu   ASSERT_EQ(2U, ValueData[4].Count);
548bb49490dSRong Xu 
549bb49490dSRong Xu   // Remove the MD_prof metadata
550bb49490dSRong Xu   Inst->setMetadata(LLVMContext::MD_prof, 0);
551bb49490dSRong Xu   // Annotate with 4 records.
552bb49490dSRong Xu   InstrProfValueData VD0Sorted[] = {{1000, 6}, {2000, 5}, {3000, 4}, {4000, 3},
553bb49490dSRong Xu                               {5000, 2}, {6000, 1}};
554311ada11SRong Xu   annotateValueSite(*M, *Inst, makeArrayRef(VD0Sorted).slice(2), 10,
555311ada11SRong Xu                     IPVK_IndirectCallTarget, 5);
556bb49490dSRong Xu   Res = getValueProfDataFromInst(*Inst, IPVK_IndirectCallTarget, 5,
557bb49490dSRong Xu                                       ValueData, N, T);
558bb49490dSRong Xu   ASSERT_TRUE(Res);
559bb49490dSRong Xu   ASSERT_EQ(4U, N);
560bb49490dSRong Xu   ASSERT_EQ(10U, T);
561bb49490dSRong Xu   ASSERT_EQ(3000U, ValueData[0].Value);
562bb49490dSRong Xu   ASSERT_EQ(4U, ValueData[0].Count);
563bb49490dSRong Xu   ASSERT_EQ(4000U, ValueData[1].Value);
564bb49490dSRong Xu   ASSERT_EQ(3U, ValueData[1].Count);
565bb49490dSRong Xu   ASSERT_EQ(5000U, ValueData[2].Value);
566bb49490dSRong Xu   ASSERT_EQ(2U, ValueData[2].Count);
567bb49490dSRong Xu   ASSERT_EQ(6000U, ValueData[3].Value);
568bb49490dSRong Xu   ASSERT_EQ(1U, ValueData[3].Count);
569402477d2SXinliang David Li }
570402477d2SXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,get_icall_data_read_write_with_weight)57100dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_with_weight) {
572cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
57351dc04cfSXinliang David Li 
57451dc04cfSXinliang David Li   // 4 value sites.
57551dc04cfSXinliang David Li   Record1.reserveSites(IPVK_IndirectCallTarget, 4);
576a3e0d45bSXinliang David Li   InstrProfValueData VD0[] = {
577a3e0d45bSXinliang David Li       {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}};
57851dc04cfSXinliang David Li   Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
57951dc04cfSXinliang David Li   // No value profile data at the second site.
58051dc04cfSXinliang David Li   Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
581a3e0d45bSXinliang David Li   InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}};
58251dc04cfSXinliang David Li   Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
583a3e0d45bSXinliang David Li   InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
58451dc04cfSXinliang David Li   Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
58551dc04cfSXinliang David Li 
58698cce003SDavid Blaikie   Writer.addRecord(std::move(Record1), 10, Err);
58798cce003SDavid Blaikie   Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
58898cce003SDavid Blaikie   Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
58998cce003SDavid Blaikie   Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
59051dc04cfSXinliang David Li   auto Profile = Writer.writeBuffer();
59151dc04cfSXinliang David Li   readProfile(std::move(Profile));
59251dc04cfSXinliang David Li 
5939152fd17SVedant Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
59494b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
595fed557efSDavid Blaikie   ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
596fed557efSDavid Blaikie   ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
597fed557efSDavid Blaikie   ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
598fed557efSDavid Blaikie   ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
599fed557efSDavid Blaikie   ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
60051dc04cfSXinliang David Li 
6011e4c809cSXinliang David Li   uint64_t TotalC;
60251dc04cfSXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD =
603fed557efSDavid Blaikie       R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC);
60451dc04cfSXinliang David Li   ASSERT_EQ(30U, VD[0].Count);
60551dc04cfSXinliang David Li   ASSERT_EQ(20U, VD[1].Count);
60651dc04cfSXinliang David Li   ASSERT_EQ(10U, VD[2].Count);
6071e4c809cSXinliang David Li   ASSERT_EQ(60U, TotalC);
60851dc04cfSXinliang David Li 
6092004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
6102004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
6112004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
6122004f003SXinliang David Li }
6132004f003SXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,get_icall_data_read_write_big_endian)61400dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_icall_data_read_write_big_endian) {
615cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record1("caller", 0x1234, {1, 2});
61646ad363bSXinliang David Li 
61746ad363bSXinliang David Li   // 4 value sites.
61846ad363bSXinliang David Li   Record1.reserveSites(IPVK_IndirectCallTarget, 4);
619a3e0d45bSXinliang David Li   InstrProfValueData VD0[] = {
620a3e0d45bSXinliang David Li       {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}};
62146ad363bSXinliang David Li   Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
62246ad363bSXinliang David Li   // No value profile data at the second site.
62346ad363bSXinliang David Li   Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
624a3e0d45bSXinliang David Li   InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}};
62546ad363bSXinliang David Li   Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
626a3e0d45bSXinliang David Li   InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
62746ad363bSXinliang David Li   Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
62846ad363bSXinliang David Li 
62998cce003SDavid Blaikie   Writer.addRecord(std::move(Record1), Err);
63098cce003SDavid Blaikie   Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
63198cce003SDavid Blaikie   Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
63298cce003SDavid Blaikie   Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
63346ad363bSXinliang David Li 
63446ad363bSXinliang David Li   // Set big endian output.
63546ad363bSXinliang David Li   Writer.setValueProfDataEndianness(support::big);
63646ad363bSXinliang David Li 
63746ad363bSXinliang David Li   auto Profile = Writer.writeBuffer();
63846ad363bSXinliang David Li   readProfile(std::move(Profile));
63946ad363bSXinliang David Li 
64046ad363bSXinliang David Li   // Set big endian input.
64146ad363bSXinliang David Li   Reader->setValueProfDataEndianness(support::big);
64246ad363bSXinliang David Li 
6439152fd17SVedant Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
64494b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
645fed557efSDavid Blaikie   ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget));
646fed557efSDavid Blaikie   ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
647fed557efSDavid Blaikie   ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
648fed557efSDavid Blaikie   ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
649fed557efSDavid Blaikie   ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
65046ad363bSXinliang David Li 
65146ad363bSXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD =
652fed557efSDavid Blaikie       R->getValueForSite(IPVK_IndirectCallTarget, 0);
65346ad363bSXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
65446ad363bSXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
65546ad363bSXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
65646ad363bSXinliang David Li 
65746ad363bSXinliang David Li   // Restore little endian default:
65846ad363bSXinliang David Li   Writer.setValueProfDataEndianness(support::little);
65946ad363bSXinliang David Li }
66046ad363bSXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,get_icall_data_merge1)66100dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1) {
6627345ac0cSNAKAMURA Takumi   static const char caller[] = "caller";
663cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
664cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record12(caller, 0x1234, {1, 2});
6652004f003SXinliang David Li 
6662004f003SXinliang David Li   // 5 value sites.
6672004f003SXinliang David Li   Record11.reserveSites(IPVK_IndirectCallTarget, 5);
6687345ac0cSNAKAMURA Takumi   InstrProfValueData VD0[] = {{uint64_t(callee1), 1},
6697345ac0cSNAKAMURA Takumi                               {uint64_t(callee2), 2},
6707345ac0cSNAKAMURA Takumi                               {uint64_t(callee3), 3},
6717345ac0cSNAKAMURA Takumi                               {uint64_t(callee4), 4}};
672ffec81caSEugene Zelenko   Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr);
6732004f003SXinliang David Li 
674872df22cSXinliang David Li   // No value profile data at the second site.
675ffec81caSEugene Zelenko   Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
6762004f003SXinliang David Li 
677872df22cSXinliang David Li   InstrProfValueData VD2[] = {
678872df22cSXinliang David Li       {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}};
679ffec81caSEugene Zelenko   Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
6802004f003SXinliang David Li 
6817345ac0cSNAKAMURA Takumi   InstrProfValueData VD3[] = {{uint64_t(callee1), 1}};
682ffec81caSEugene Zelenko   Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
6832004f003SXinliang David Li 
6847345ac0cSNAKAMURA Takumi   InstrProfValueData VD4[] = {{uint64_t(callee1), 1},
6857345ac0cSNAKAMURA Takumi                               {uint64_t(callee2), 2},
6867345ac0cSNAKAMURA Takumi                               {uint64_t(callee3), 3}};
687ffec81caSEugene Zelenko   Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr);
6882004f003SXinliang David Li 
68968318e04SDavid Majnemer   // A different record for the same caller.
6902004f003SXinliang David Li   Record12.reserveSites(IPVK_IndirectCallTarget, 5);
691872df22cSXinliang David Li   InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}};
692ffec81caSEugene Zelenko   Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr);
6932004f003SXinliang David Li 
694872df22cSXinliang David Li   // No value profile data at the second site.
695ffec81caSEugene Zelenko   Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
6962004f003SXinliang David Li 
697872df22cSXinliang David Li   InstrProfValueData VD22[] = {
698872df22cSXinliang David Li       {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}};
699ffec81caSEugene Zelenko   Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr);
7002004f003SXinliang David Li 
701ffec81caSEugene Zelenko   Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr);
7022004f003SXinliang David Li 
70346ad363bSXinliang David Li   InstrProfValueData VD42[] = {{uint64_t(callee1), 1},
70446ad363bSXinliang David Li                                {uint64_t(callee2), 2},
70546ad363bSXinliang David Li                                {uint64_t(callee3), 3}};
706ffec81caSEugene Zelenko   Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr);
7072004f003SXinliang David Li 
70898cce003SDavid Blaikie   Writer.addRecord(std::move(Record11), Err);
7092004f003SXinliang David Li   // Merge profile data.
71098cce003SDavid Blaikie   Writer.addRecord(std::move(Record12), Err);
7112004f003SXinliang David Li 
71298cce003SDavid Blaikie   Writer.addRecord({callee1, 0x1235, {3, 4}}, Err);
71398cce003SDavid Blaikie   Writer.addRecord({callee2, 0x1235, {3, 4}}, Err);
71498cce003SDavid Blaikie   Writer.addRecord({callee3, 0x1235, {3, 4}}, Err);
71598cce003SDavid Blaikie   Writer.addRecord({callee3, 0x1235, {3, 4}}, Err);
71698cce003SDavid Blaikie   Writer.addRecord({callee4, 0x1235, {3, 5}}, Err);
7172004f003SXinliang David Li   auto Profile = Writer.writeBuffer();
7182004f003SXinliang David Li   readProfile(std::move(Profile));
7192004f003SXinliang David Li 
7209152fd17SVedant Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
72194b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
722fed557efSDavid Blaikie   ASSERT_EQ(5U, R->getNumValueSites(IPVK_IndirectCallTarget));
723fed557efSDavid Blaikie   ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
724fed557efSDavid Blaikie   ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
725fed557efSDavid Blaikie   ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
726fed557efSDavid Blaikie   ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
727fed557efSDavid Blaikie   ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
7282004f003SXinliang David Li 
7292004f003SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD =
730fed557efSDavid Blaikie       R->getValueForSite(IPVK_IndirectCallTarget, 0);
7312004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2"));
7322004f003SXinliang David Li   ASSERT_EQ(7U, VD[0].Count);
7332004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3"));
7342004f003SXinliang David Li   ASSERT_EQ(6U, VD[1].Count);
7352004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4"));
7362004f003SXinliang David Li   ASSERT_EQ(4U, VD[2].Count);
7372004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1"));
7382004f003SXinliang David Li   ASSERT_EQ(1U, VD[3].Count);
7392004f003SXinliang David Li 
7402004f003SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD_2(
741fed557efSDavid Blaikie       R->getValueForSite(IPVK_IndirectCallTarget, 2));
7422004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3"));
7432004f003SXinliang David Li   ASSERT_EQ(6U, VD_2[0].Count);
7442004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4"));
7452004f003SXinliang David Li   ASSERT_EQ(4U, VD_2[1].Count);
7462004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2"));
7472004f003SXinliang David Li   ASSERT_EQ(3U, VD_2[2].Count);
7482004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1"));
7492004f003SXinliang David Li   ASSERT_EQ(1U, VD_2[3].Count);
7502004f003SXinliang David Li 
7512004f003SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD_3(
752fed557efSDavid Blaikie       R->getValueForSite(IPVK_IndirectCallTarget, 3));
7532004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1"));
7542004f003SXinliang David Li   ASSERT_EQ(1U, VD_3[0].Count);
7552004f003SXinliang David Li 
7562004f003SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD_4(
757fed557efSDavid Blaikie       R->getValueForSite(IPVK_IndirectCallTarget, 4));
7582004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3"));
7592004f003SXinliang David Li   ASSERT_EQ(6U, VD_4[0].Count);
7602004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2"));
7612004f003SXinliang David Li   ASSERT_EQ(4U, VD_4[1].Count);
7622004f003SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1"));
7632004f003SXinliang David Li   ASSERT_EQ(2U, VD_4[2].Count);
7642004f003SXinliang David Li }
7652004f003SXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,get_icall_data_merge1_saturation)76600dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge1_saturation) {
7677345ac0cSNAKAMURA Takumi   static const char bar[] = "bar";
7687345ac0cSNAKAMURA Takumi 
769be9db3c0SDaniel Sanders   const uint64_t Max = std::numeric_limits<uint64_t>::max();
770be9db3c0SDaniel Sanders 
77198cce003SDavid Blaikie   instrprof_error Result;
77298cce003SDavid Blaikie   auto Err = [&](Error E) { Result = InstrProfError::take(std::move(E)); };
77398cce003SDavid Blaikie   Result = instrprof_error::success;
77498cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1234, {1}}, Err);
77598cce003SDavid Blaikie   ASSERT_EQ(Result, instrprof_error::success);
776be9db3c0SDaniel Sanders 
77748dd080cSNathan Slingerland   // Verify counter overflow.
77898cce003SDavid Blaikie   Result = instrprof_error::success;
77998cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1234, {Max}}, Err);
78098cce003SDavid Blaikie   ASSERT_EQ(Result, instrprof_error::counter_overflow);
781be9db3c0SDaniel Sanders 
78298cce003SDavid Blaikie   Result = instrprof_error::success;
78398cce003SDavid Blaikie   Writer.addRecord({bar, 0x9012, {8}}, Err);
78498cce003SDavid Blaikie   ASSERT_EQ(Result, instrprof_error::success);
785be9db3c0SDaniel Sanders 
786cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record4("baz", 0x5678, {3, 4});
78748dd080cSNathan Slingerland   Record4.reserveSites(IPVK_IndirectCallTarget, 1);
7887345ac0cSNAKAMURA Takumi   InstrProfValueData VD4[] = {{uint64_t(bar), 1}};
78948dd080cSNathan Slingerland   Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
79098cce003SDavid Blaikie   Result = instrprof_error::success;
79198cce003SDavid Blaikie   Writer.addRecord(std::move(Record4), Err);
79298cce003SDavid Blaikie   ASSERT_EQ(Result, instrprof_error::success);
79348dd080cSNathan Slingerland 
79448dd080cSNathan Slingerland   // Verify value data counter overflow.
795cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record5("baz", 0x5678, {5, 6});
79648dd080cSNathan Slingerland   Record5.reserveSites(IPVK_IndirectCallTarget, 1);
7977345ac0cSNAKAMURA Takumi   InstrProfValueData VD5[] = {{uint64_t(bar), Max}};
79848dd080cSNathan Slingerland   Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
79998cce003SDavid Blaikie   Result = instrprof_error::success;
80098cce003SDavid Blaikie   Writer.addRecord(std::move(Record5), Err);
80198cce003SDavid Blaikie   ASSERT_EQ(Result, instrprof_error::counter_overflow);
802be9db3c0SDaniel Sanders 
803be9db3c0SDaniel Sanders   auto Profile = Writer.writeBuffer();
804be9db3c0SDaniel Sanders   readProfile(std::move(Profile));
805be9db3c0SDaniel Sanders 
806be9db3c0SDaniel Sanders   // Verify saturation of counts.
8079152fd17SVedant Kumar   Expected<InstrProfRecord> ReadRecord1 =
80848dd080cSNathan Slingerland       Reader->getInstrProfRecord("foo", 0x1234);
80994b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(ReadRecord1.takeError(), Succeeded());
810fed557efSDavid Blaikie   ASSERT_EQ(Max, ReadRecord1->Counts[0]);
811aa5702d9SNathan Slingerland 
8129152fd17SVedant Kumar   Expected<InstrProfRecord> ReadRecord2 =
81348dd080cSNathan Slingerland       Reader->getInstrProfRecord("baz", 0x5678);
8149152fd17SVedant Kumar   ASSERT_TRUE(bool(ReadRecord2));
815fed557efSDavid Blaikie   ASSERT_EQ(1U, ReadRecord2->getNumValueSites(IPVK_IndirectCallTarget));
816be9db3c0SDaniel Sanders   std::unique_ptr<InstrProfValueData[]> VD =
817fed557efSDavid Blaikie       ReadRecord2->getValueForSite(IPVK_IndirectCallTarget, 0);
81848dd080cSNathan Slingerland   ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3));
81948dd080cSNathan Slingerland   ASSERT_EQ(Max, VD[0].Count);
820be9db3c0SDaniel Sanders }
821be9db3c0SDaniel Sanders 
822872df22cSXinliang David Li // This test tests that when there are too many values
823872df22cSXinliang David Li // for a given site, the merged results are properly
824872df22cSXinliang David Li // truncated.
TEST_P(MaybeSparseInstrProfTest,get_icall_data_merge_site_trunc)82500dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_icall_data_merge_site_trunc) {
826872df22cSXinliang David Li   static const char caller[] = "caller";
827872df22cSXinliang David Li 
828cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record11(caller, 0x1234, {1, 2});
829cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record12(caller, 0x1234, {1, 2});
830872df22cSXinliang David Li 
831872df22cSXinliang David Li   // 2 value sites.
832872df22cSXinliang David Li   Record11.reserveSites(IPVK_IndirectCallTarget, 2);
833872df22cSXinliang David Li   InstrProfValueData VD0[255];
834872df22cSXinliang David Li   for (int I = 0; I < 255; I++) {
835872df22cSXinliang David Li     VD0[I].Value = 2 * I;
836872df22cSXinliang David Li     VD0[I].Count = 2 * I + 1000;
837872df22cSXinliang David Li   }
838872df22cSXinliang David Li 
839872df22cSXinliang David Li   Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr);
840872df22cSXinliang David Li   Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
841872df22cSXinliang David Li 
842872df22cSXinliang David Li   Record12.reserveSites(IPVK_IndirectCallTarget, 2);
843872df22cSXinliang David Li   InstrProfValueData VD1[255];
844872df22cSXinliang David Li   for (int I = 0; I < 255; I++) {
845872df22cSXinliang David Li     VD1[I].Value = 2 * I + 1;
846872df22cSXinliang David Li     VD1[I].Count = 2 * I + 1001;
847872df22cSXinliang David Li   }
848872df22cSXinliang David Li 
849872df22cSXinliang David Li   Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr);
850872df22cSXinliang David Li   Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
851872df22cSXinliang David Li 
85298cce003SDavid Blaikie   Writer.addRecord(std::move(Record11), Err);
853872df22cSXinliang David Li   // Merge profile data.
85498cce003SDavid Blaikie   Writer.addRecord(std::move(Record12), Err);
855872df22cSXinliang David Li 
856872df22cSXinliang David Li   auto Profile = Writer.writeBuffer();
857872df22cSXinliang David Li   readProfile(std::move(Profile));
858872df22cSXinliang David Li 
8599152fd17SVedant Kumar   Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
86094b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(R.takeError(), Succeeded());
861872df22cSXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD(
862fed557efSDavid Blaikie       R->getValueForSite(IPVK_IndirectCallTarget, 0));
863fed557efSDavid Blaikie   ASSERT_EQ(2U, R->getNumValueSites(IPVK_IndirectCallTarget));
864fed557efSDavid Blaikie   ASSERT_EQ(255U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
865249edf3dSNAKAMURA Takumi   for (unsigned I = 0; I < 255; I++) {
866872df22cSXinliang David Li     ASSERT_EQ(VD[I].Value, 509 - I);
867872df22cSXinliang David Li     ASSERT_EQ(VD[I].Count, 1509 - I);
868872df22cSXinliang David Li   }
869872df22cSXinliang David Li }
870872df22cSXinliang David Li 
addValueProfData(InstrProfRecord & Record)8718e6b917eSXinliang David Li static void addValueProfData(InstrProfRecord &Record) {
8728e6b917eSXinliang David Li   Record.reserveSites(IPVK_IndirectCallTarget, 5);
8738e6b917eSXinliang David Li   InstrProfValueData VD0[] = {{uint64_t(callee1), 400},
8748e6b917eSXinliang David Li                               {uint64_t(callee2), 1000},
8758e6b917eSXinliang David Li                               {uint64_t(callee3), 500},
8768e6b917eSXinliang David Li                               {uint64_t(callee4), 300},
8778e6b917eSXinliang David Li                               {uint64_t(callee5), 100}};
8788e6b917eSXinliang David Li   Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 5, nullptr);
8798e6b917eSXinliang David Li   InstrProfValueData VD1[] = {{uint64_t(callee5), 800},
8808e6b917eSXinliang David Li                               {uint64_t(callee3), 1000},
8818e6b917eSXinliang David Li                               {uint64_t(callee2), 2500},
8828e6b917eSXinliang David Li                               {uint64_t(callee1), 1300}};
8838e6b917eSXinliang David Li   Record.addValueData(IPVK_IndirectCallTarget, 1, VD1, 4, nullptr);
8848e6b917eSXinliang David Li   InstrProfValueData VD2[] = {{uint64_t(callee6), 800},
8858e6b917eSXinliang David Li                               {uint64_t(callee3), 1000},
8868e6b917eSXinliang David Li                               {uint64_t(callee4), 5500}};
8878e6b917eSXinliang David Li   Record.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
8888e6b917eSXinliang David Li   InstrProfValueData VD3[] = {{uint64_t(callee2), 1800},
8898e6b917eSXinliang David Li                               {uint64_t(callee3), 2000}};
8908e6b917eSXinliang David Li   Record.addValueData(IPVK_IndirectCallTarget, 3, VD3, 2, nullptr);
8918e6b917eSXinliang David Li   Record.addValueData(IPVK_IndirectCallTarget, 4, nullptr, 0, nullptr);
8928e6b917eSXinliang David Li }
893ed966771SXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,value_prof_data_read_write)8948e6b917eSXinliang David Li TEST_P(MaybeSparseInstrProfTest, value_prof_data_read_write) {
895cf9d52c6SDavid Blaikie   InstrProfRecord SrcRecord({1ULL << 31, 2});
8968e6b917eSXinliang David Li   addValueProfData(SrcRecord);
8978e6b917eSXinliang David Li   std::unique_ptr<ValueProfData> VPData =
8988e6b917eSXinliang David Li       ValueProfData::serializeFrom(SrcRecord);
899ed966771SXinliang David Li 
900cf9d52c6SDavid Blaikie   InstrProfRecord Record({1ULL << 31, 2});
9016ac3f739SEugene Zelenko   VPData->deserializeTo(Record, nullptr);
902ed966771SXinliang David Li 
903ed966771SXinliang David Li   // Now read data from Record and sanity check the data
904ed966771SXinliang David Li   ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
905ed966771SXinliang David Li   ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
906ed966771SXinliang David Li   ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
907ed966771SXinliang David Li   ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
908ed966771SXinliang David Li   ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
909ed966771SXinliang David Li   ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
910ed966771SXinliang David Li 
911ed966771SXinliang David Li   auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
912ed966771SXinliang David Li     return VD1.Count > VD2.Count;
913ed966771SXinliang David Li   };
914ed966771SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD_0(
915ed966771SXinliang David Li       Record.getValueForSite(IPVK_IndirectCallTarget, 0));
91613e70cb1SMandeep Singh Grang   llvm::sort(&VD_0[0], &VD_0[5], Cmp);
917ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2"));
918ed966771SXinliang David Li   ASSERT_EQ(1000U, VD_0[0].Count);
919ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3"));
920ed966771SXinliang David Li   ASSERT_EQ(500U, VD_0[1].Count);
921ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1"));
922ed966771SXinliang David Li   ASSERT_EQ(400U, VD_0[2].Count);
923ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4"));
924ed966771SXinliang David Li   ASSERT_EQ(300U, VD_0[3].Count);
925ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5"));
926ed966771SXinliang David Li   ASSERT_EQ(100U, VD_0[4].Count);
927ed966771SXinliang David Li 
928ed966771SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD_1(
929ed966771SXinliang David Li       Record.getValueForSite(IPVK_IndirectCallTarget, 1));
93013e70cb1SMandeep Singh Grang   llvm::sort(&VD_1[0], &VD_1[4], Cmp);
931ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2"));
932ed966771SXinliang David Li   ASSERT_EQ(2500U, VD_1[0].Count);
933ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1"));
934ed966771SXinliang David Li   ASSERT_EQ(1300U, VD_1[1].Count);
935ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3"));
936ed966771SXinliang David Li   ASSERT_EQ(1000U, VD_1[2].Count);
937ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5"));
938ed966771SXinliang David Li   ASSERT_EQ(800U, VD_1[3].Count);
939ed966771SXinliang David Li 
940ed966771SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD_2(
941ed966771SXinliang David Li       Record.getValueForSite(IPVK_IndirectCallTarget, 2));
94213e70cb1SMandeep Singh Grang   llvm::sort(&VD_2[0], &VD_2[3], Cmp);
943ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4"));
944ed966771SXinliang David Li   ASSERT_EQ(5500U, VD_2[0].Count);
945ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3"));
946ed966771SXinliang David Li   ASSERT_EQ(1000U, VD_2[1].Count);
947ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6"));
948ed966771SXinliang David Li   ASSERT_EQ(800U, VD_2[2].Count);
949ed966771SXinliang David Li 
950ed966771SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD_3(
951ed966771SXinliang David Li       Record.getValueForSite(IPVK_IndirectCallTarget, 3));
95213e70cb1SMandeep Singh Grang   llvm::sort(&VD_3[0], &VD_3[2], Cmp);
953ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3"));
954ed966771SXinliang David Li   ASSERT_EQ(2000U, VD_3[0].Count);
955ed966771SXinliang David Li   ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2"));
956ed966771SXinliang David Li   ASSERT_EQ(1800U, VD_3[1].Count);
957ed966771SXinliang David Li }
958ed966771SXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,value_prof_data_read_write_mapping)9598e6b917eSXinliang David Li TEST_P(MaybeSparseInstrProfTest, value_prof_data_read_write_mapping) {
96028464483SXinliang David Li 
961cf9d52c6SDavid Blaikie   NamedInstrProfRecord SrcRecord("caller", 0x1234, {1ULL << 31, 2});
9628e6b917eSXinliang David Li   addValueProfData(SrcRecord);
9638e6b917eSXinliang David Li   std::unique_ptr<ValueProfData> VPData =
9648e6b917eSXinliang David Li       ValueProfData::serializeFrom(SrcRecord);
96528464483SXinliang David Li 
966cf9d52c6SDavid Blaikie   NamedInstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
96728464483SXinliang David Li   InstrProfSymtab Symtab;
96828464483SXinliang David Li   Symtab.mapAddress(uint64_t(callee1), 0x1000ULL);
96928464483SXinliang David Li   Symtab.mapAddress(uint64_t(callee2), 0x2000ULL);
97028464483SXinliang David Li   Symtab.mapAddress(uint64_t(callee3), 0x3000ULL);
97128464483SXinliang David Li   Symtab.mapAddress(uint64_t(callee4), 0x4000ULL);
97228464483SXinliang David Li   // Missing mapping for callee5
97328464483SXinliang David Li 
974556f8f6aSMircea Trofin   VPData->deserializeTo(Record, &Symtab);
97528464483SXinliang David Li 
97628464483SXinliang David Li   // Now read data from Record and sanity check the data
9778e6b917eSXinliang David Li   ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
97828464483SXinliang David Li   ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
97928464483SXinliang David Li 
98028464483SXinliang David Li   auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
98128464483SXinliang David Li     return VD1.Count > VD2.Count;
98228464483SXinliang David Li   };
98328464483SXinliang David Li   std::unique_ptr<InstrProfValueData[]> VD_0(
98428464483SXinliang David Li       Record.getValueForSite(IPVK_IndirectCallTarget, 0));
98513e70cb1SMandeep Singh Grang   llvm::sort(&VD_0[0], &VD_0[5], Cmp);
98628464483SXinliang David Li   ASSERT_EQ(VD_0[0].Value, 0x2000ULL);
98728464483SXinliang David Li   ASSERT_EQ(1000U, VD_0[0].Count);
98828464483SXinliang David Li   ASSERT_EQ(VD_0[1].Value, 0x3000ULL);
98928464483SXinliang David Li   ASSERT_EQ(500U, VD_0[1].Count);
99028464483SXinliang David Li   ASSERT_EQ(VD_0[2].Value, 0x1000ULL);
99128464483SXinliang David Li   ASSERT_EQ(400U, VD_0[2].Count);
99228464483SXinliang David Li 
99328464483SXinliang David Li   // callee5 does not have a mapped value -- default to 0.
99428464483SXinliang David Li   ASSERT_EQ(VD_0[4].Value, 0ULL);
99528464483SXinliang David Li }
99628464483SXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,get_max_function_count)99700dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_max_function_count) {
99898cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1234, {1ULL << 31, 2}}, Err);
99998cce003SDavid Blaikie   Writer.addRecord({"bar", 0, {1ULL << 63}}, Err);
100098cce003SDavid Blaikie   Writer.addRecord({"baz", 0x5678, {0, 0, 0, 0}}, Err);
10012b6c537bSJustin Bogner   auto Profile = Writer.writeBuffer();
10022b6c537bSJustin Bogner   readProfile(std::move(Profile));
10032b6c537bSJustin Bogner 
1004a6ff69f6SRong Xu   ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount(/* IsCS */ false));
10052b6c537bSJustin Bogner }
10062b6c537bSJustin Bogner 
TEST_P(MaybeSparseInstrProfTest,get_weighted_function_counts)100700dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) {
100898cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1234, {1, 2}}, 3, Err);
100998cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1235, {3, 4}}, 5, Err);
10107f5b47ddSNathan Slingerland   auto Profile = Writer.writeBuffer();
10117f5b47ddSNathan Slingerland   readProfile(std::move(Profile));
10127f5b47ddSNathan Slingerland 
10137f5b47ddSNathan Slingerland   std::vector<uint64_t> Counts;
101494b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1234, Counts),
101594b98b2cSDavid Blaikie                     Succeeded());
10167f5b47ddSNathan Slingerland   ASSERT_EQ(2U, Counts.size());
10177f5b47ddSNathan Slingerland   ASSERT_EQ(3U, Counts[0]);
10187f5b47ddSNathan Slingerland   ASSERT_EQ(6U, Counts[1]);
10197f5b47ddSNathan Slingerland 
102094b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(Reader->getFunctionCounts("foo", 0x1235, Counts),
102194b98b2cSDavid Blaikie                     Succeeded());
10227f5b47ddSNathan Slingerland   ASSERT_EQ(2U, Counts.size());
10237f5b47ddSNathan Slingerland   ASSERT_EQ(15U, Counts[0]);
10247f5b47ddSNathan Slingerland   ASSERT_EQ(20U, Counts[1]);
10257f5b47ddSNathan Slingerland }
10267f5b47ddSNathan Slingerland 
1027a0601e76SXinliang David Li // Testing symtab creator interface used by indexed profile reader.
TEST_P(MaybeSparseInstrProfTest,instr_prof_symtab_test)102800dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_test) {
10292ee5c4dbSXinliang David Li   std::vector<StringRef> FuncNames;
10302ee5c4dbSXinliang David Li   FuncNames.push_back("func1");
10312ee5c4dbSXinliang David Li   FuncNames.push_back("func2");
10322ee5c4dbSXinliang David Li   FuncNames.push_back("func3");
10332ee5c4dbSXinliang David Li   FuncNames.push_back("bar1");
10342ee5c4dbSXinliang David Li   FuncNames.push_back("bar2");
10352ee5c4dbSXinliang David Li   FuncNames.push_back("bar3");
10362ee5c4dbSXinliang David Li   InstrProfSymtab Symtab;
103794b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(Symtab.create(FuncNames), Succeeded());
10382ee5c4dbSXinliang David Li   StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
10392ee5c4dbSXinliang David Li   ASSERT_EQ(StringRef("func1"), R);
10402ee5c4dbSXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
10412ee5c4dbSXinliang David Li   ASSERT_EQ(StringRef("func2"), R);
10422ee5c4dbSXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
10432ee5c4dbSXinliang David Li   ASSERT_EQ(StringRef("func3"), R);
10442ee5c4dbSXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
10452ee5c4dbSXinliang David Li   ASSERT_EQ(StringRef("bar1"), R);
10462ee5c4dbSXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
10472ee5c4dbSXinliang David Li   ASSERT_EQ(StringRef("bar2"), R);
10482ee5c4dbSXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
10492ee5c4dbSXinliang David Li   ASSERT_EQ(StringRef("bar3"), R);
1050c96d3d10SXinliang David Li 
105186b4b91eSXinliang David Li   // negative tests
105286b4b91eSXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar4"));
105386b4b91eSXinliang David Li   ASSERT_EQ(StringRef(), R);
105486b4b91eSXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("foo4"));
105586b4b91eSXinliang David Li   ASSERT_EQ(StringRef(), R);
105686b4b91eSXinliang David Li 
1057c96d3d10SXinliang David Li   // Now incrementally update the symtab
105894b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(Symtab.addFuncName("blah_1"), Succeeded());
105994b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(Symtab.addFuncName("blah_2"), Succeeded());
106094b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(Symtab.addFuncName("blah_3"), Succeeded());
1061c96d3d10SXinliang David Li 
1062c96d3d10SXinliang David Li   // Check again
1063c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1"));
1064c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("blah_1"), R);
1065c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2"));
1066c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("blah_2"), R);
1067c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3"));
1068c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("blah_3"), R);
1069c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
1070c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("func1"), R);
1071c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
1072c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("func2"), R);
1073c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
1074c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("func3"), R);
1075c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
1076c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("bar1"), R);
1077c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
1078c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("bar2"), R);
1079c96d3d10SXinliang David Li   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
1080c96d3d10SXinliang David Li   ASSERT_EQ(StringRef("bar3"), R);
10812ee5c4dbSXinliang David Li }
10822ee5c4dbSXinliang David Li 
1083b5794ca9SVedant Kumar // Test that we get an error when creating a bogus symtab.
TEST_P(MaybeSparseInstrProfTest,instr_prof_bogus_symtab_empty_func_name)1084b5794ca9SVedant Kumar TEST_P(MaybeSparseInstrProfTest, instr_prof_bogus_symtab_empty_func_name) {
1085b5794ca9SVedant Kumar   InstrProfSymtab Symtab;
108694b98b2cSDavid Blaikie   EXPECT_TRUE(ErrorEquals(instrprof_error::malformed, Symtab.addFuncName("")));
1087b5794ca9SVedant Kumar }
1088b5794ca9SVedant Kumar 
1089a0601e76SXinliang David Li // Testing symtab creator interface used by value profile transformer.
TEST_P(MaybeSparseInstrProfTest,instr_prof_symtab_module_test)109000dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_module_test) {
109159411db5SXinliang David Li   LLVMContext Ctx;
10920eaee545SJonas Devlieghere   std::unique_ptr<Module> M = std::make_unique<Module>("MyModule.cpp", Ctx);
109359411db5SXinliang David Li   FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
109459411db5SXinliang David Li                                         /*isVarArg=*/false);
109559411db5SXinliang David Li   Function::Create(FTy, Function::ExternalLinkage, "Gfoo", M.get());
109659411db5SXinliang David Li   Function::Create(FTy, Function::ExternalLinkage, "Gblah", M.get());
109759411db5SXinliang David Li   Function::Create(FTy, Function::ExternalLinkage, "Gbar", M.get());
109859411db5SXinliang David Li   Function::Create(FTy, Function::InternalLinkage, "Ifoo", M.get());
109959411db5SXinliang David Li   Function::Create(FTy, Function::InternalLinkage, "Iblah", M.get());
110059411db5SXinliang David Li   Function::Create(FTy, Function::InternalLinkage, "Ibar", M.get());
110159411db5SXinliang David Li   Function::Create(FTy, Function::PrivateLinkage, "Pfoo", M.get());
110259411db5SXinliang David Li   Function::Create(FTy, Function::PrivateLinkage, "Pblah", M.get());
110359411db5SXinliang David Li   Function::Create(FTy, Function::PrivateLinkage, "Pbar", M.get());
110459411db5SXinliang David Li   Function::Create(FTy, Function::WeakODRLinkage, "Wfoo", M.get());
110559411db5SXinliang David Li   Function::Create(FTy, Function::WeakODRLinkage, "Wblah", M.get());
110659411db5SXinliang David Li   Function::Create(FTy, Function::WeakODRLinkage, "Wbar", M.get());
110759411db5SXinliang David Li 
110859411db5SXinliang David Li   InstrProfSymtab ProfSymtab;
110994b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(ProfSymtab.create(*M), Succeeded());
111059411db5SXinliang David Li 
111159411db5SXinliang David Li   StringRef Funcs[] = {"Gfoo", "Gblah", "Gbar", "Ifoo", "Iblah", "Ibar",
111259411db5SXinliang David Li                        "Pfoo", "Pblah", "Pbar", "Wfoo", "Wblah", "Wbar"};
111359411db5SXinliang David Li 
111459411db5SXinliang David Li   for (unsigned I = 0; I < sizeof(Funcs) / sizeof(*Funcs); I++) {
111559411db5SXinliang David Li     Function *F = M->getFunction(Funcs[I]);
11166ac3f739SEugene Zelenko     ASSERT_TRUE(F != nullptr);
1117da656fe5SXinliang David Li     std::string PGOName = getPGOFuncName(*F);
11183865fdc4SXinliang David Li     uint64_t Key = IndexedInstrProf::ComputeHash(PGOName);
1119da656fe5SXinliang David Li     ASSERT_EQ(StringRef(PGOName),
11203865fdc4SXinliang David Li               ProfSymtab.getFuncName(Key));
11213865fdc4SXinliang David Li     ASSERT_EQ(StringRef(Funcs[I]), ProfSymtab.getOrigFuncName(Key));
112259411db5SXinliang David Li   }
112359411db5SXinliang David Li }
112459411db5SXinliang David Li 
1125a0601e76SXinliang David Li // Testing symtab serialization and creator/deserialization interface
1126a0601e76SXinliang David Li // used by coverage map reader, and raw profile reader.
TEST_P(MaybeSparseInstrProfTest,instr_prof_symtab_compression_test)112700dab228SVedant Kumar TEST_P(MaybeSparseInstrProfTest, instr_prof_symtab_compression_test) {
1128e413f1a0SXinliang David Li   std::vector<std::string> FuncNames1;
1129e413f1a0SXinliang David Li   std::vector<std::string> FuncNames2;
1130c2f25cc4SXinliang David Li   for (int I = 0; I < 3; I++) {
1131e413f1a0SXinliang David Li     std::string str;
1132e413f1a0SXinliang David Li     raw_string_ostream OS(str);
1133e413f1a0SXinliang David Li     OS << "func_" << I;
1134e413f1a0SXinliang David Li     FuncNames1.push_back(OS.str());
1135e413f1a0SXinliang David Li     str.clear();
113686705ba5SVedant Kumar     OS << "f oooooooooooooo_" << I;
1137e413f1a0SXinliang David Li     FuncNames1.push_back(OS.str());
1138e413f1a0SXinliang David Li     str.clear();
1139e413f1a0SXinliang David Li     OS << "BAR_" << I;
1140e413f1a0SXinliang David Li     FuncNames2.push_back(OS.str());
1141e413f1a0SXinliang David Li     str.clear();
1142e413f1a0SXinliang David Li     OS << "BlahblahBlahblahBar_" << I;
1143e413f1a0SXinliang David Li     FuncNames2.push_back(OS.str());
1144e413f1a0SXinliang David Li   }
1145e413f1a0SXinliang David Li 
1146dd4ae7b5SXinliang David Li   for (bool DoCompression : {false, true}) {
1147e413f1a0SXinliang David Li     // Compressing:
1148e413f1a0SXinliang David Li     std::string FuncNameStrings1;
114994b98b2cSDavid Blaikie     EXPECT_THAT_ERROR(collectPGOFuncNameStrings(
1150*ea61750cSCole Kissane                           FuncNames1,
1151*ea61750cSCole Kissane                           (DoCompression && compression::zlib::isAvailable()),
115294b98b2cSDavid Blaikie                           FuncNameStrings1),
115394b98b2cSDavid Blaikie                       Succeeded());
1154e413f1a0SXinliang David Li 
1155e413f1a0SXinliang David Li     // Compressing:
1156e413f1a0SXinliang David Li     std::string FuncNameStrings2;
115794b98b2cSDavid Blaikie     EXPECT_THAT_ERROR(collectPGOFuncNameStrings(
1158*ea61750cSCole Kissane                           FuncNames2,
1159*ea61750cSCole Kissane                           (DoCompression && compression::zlib::isAvailable()),
116094b98b2cSDavid Blaikie                           FuncNameStrings2),
116194b98b2cSDavid Blaikie                       Succeeded());
1162e413f1a0SXinliang David Li 
1163c2f25cc4SXinliang David Li     for (int Padding = 0; Padding < 2; Padding++) {
1164e413f1a0SXinliang David Li       // Join with paddings :
1165e413f1a0SXinliang David Li       std::string FuncNameStrings = FuncNameStrings1;
1166e413f1a0SXinliang David Li       for (int P = 0; P < Padding; P++) {
1167e413f1a0SXinliang David Li         FuncNameStrings.push_back('\0');
1168e413f1a0SXinliang David Li       }
1169e413f1a0SXinliang David Li       FuncNameStrings += FuncNameStrings2;
1170e413f1a0SXinliang David Li 
11718dec8b1eSXinliang David Li       // Now decompress:
1172e413f1a0SXinliang David Li       InstrProfSymtab Symtab;
117394b98b2cSDavid Blaikie       EXPECT_THAT_ERROR(Symtab.create(StringRef(FuncNameStrings)), Succeeded());
1174e413f1a0SXinliang David Li 
11758dec8b1eSXinliang David Li       // Now do the checks:
11768dec8b1eSXinliang David Li       // First sampling some data points:
1177a8ba7affSXinliang David Li       StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[0]));
11788dec8b1eSXinliang David Li       ASSERT_EQ(StringRef("func_0"), R);
11798dec8b1eSXinliang David Li       R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[1]));
118086705ba5SVedant Kumar       ASSERT_EQ(StringRef("f oooooooooooooo_0"), R);
1181c2f25cc4SXinliang David Li       for (int I = 0; I < 3; I++) {
1182e413f1a0SXinliang David Li         std::string N[4];
1183e413f1a0SXinliang David Li         N[0] = FuncNames1[2 * I];
1184e413f1a0SXinliang David Li         N[1] = FuncNames1[2 * I + 1];
1185e413f1a0SXinliang David Li         N[2] = FuncNames2[2 * I];
1186e413f1a0SXinliang David Li         N[3] = FuncNames2[2 * I + 1];
1187e413f1a0SXinliang David Li         for (int J = 0; J < 4; J++) {
1188e413f1a0SXinliang David Li           StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(N[J]));
1189e413f1a0SXinliang David Li           ASSERT_EQ(StringRef(N[J]), R);
1190e413f1a0SXinliang David Li         }
1191e413f1a0SXinliang David Li       }
1192e413f1a0SXinliang David Li     }
1193e413f1a0SXinliang David Li   }
1194e413f1a0SXinliang David Li }
1195e413f1a0SXinliang David Li 
TEST_P(MaybeSparseInstrProfTest,remapping_test)1196ceed4eb1SRichard Smith TEST_P(MaybeSparseInstrProfTest, remapping_test) {
1197ceed4eb1SRichard Smith   Writer.addRecord({"_Z3fooi", 0x1234, {1, 2, 3, 4}}, Err);
1198ceed4eb1SRichard Smith   Writer.addRecord({"file:_Z3barf", 0x567, {5, 6, 7}}, Err);
1199ceed4eb1SRichard Smith   auto Profile = Writer.writeBuffer();
1200ceed4eb1SRichard Smith   readProfile(std::move(Profile), llvm::MemoryBuffer::getMemBuffer(R"(
1201ceed4eb1SRichard Smith     type i l
1202ceed4eb1SRichard Smith     name 3bar 4quux
1203ceed4eb1SRichard Smith   )"));
1204ceed4eb1SRichard Smith 
1205ceed4eb1SRichard Smith   std::vector<uint64_t> Counts;
1206ceed4eb1SRichard Smith   for (StringRef FooName : {"_Z3fooi", "_Z3fool"}) {
1207ceed4eb1SRichard Smith     EXPECT_THAT_ERROR(Reader->getFunctionCounts(FooName, 0x1234, Counts),
1208ceed4eb1SRichard Smith                       Succeeded());
1209ceed4eb1SRichard Smith     ASSERT_EQ(4u, Counts.size());
1210ceed4eb1SRichard Smith     EXPECT_EQ(1u, Counts[0]);
1211ceed4eb1SRichard Smith     EXPECT_EQ(2u, Counts[1]);
1212ceed4eb1SRichard Smith     EXPECT_EQ(3u, Counts[2]);
1213ceed4eb1SRichard Smith     EXPECT_EQ(4u, Counts[3]);
1214ceed4eb1SRichard Smith   }
1215ceed4eb1SRichard Smith 
1216ceed4eb1SRichard Smith   for (StringRef BarName : {"file:_Z3barf", "file:_Z4quuxf"}) {
1217ceed4eb1SRichard Smith     EXPECT_THAT_ERROR(Reader->getFunctionCounts(BarName, 0x567, Counts),
1218ceed4eb1SRichard Smith                       Succeeded());
1219ceed4eb1SRichard Smith     ASSERT_EQ(3u, Counts.size());
1220ceed4eb1SRichard Smith     EXPECT_EQ(5u, Counts[0]);
1221ceed4eb1SRichard Smith     EXPECT_EQ(6u, Counts[1]);
1222ceed4eb1SRichard Smith     EXPECT_EQ(7u, Counts[2]);
1223ceed4eb1SRichard Smith   }
1224ceed4eb1SRichard Smith 
1225ceed4eb1SRichard Smith   for (StringRef BadName : {"_Z3foof", "_Z4quuxi", "_Z3barl", "", "_ZZZ",
1226ceed4eb1SRichard Smith                             "_Z3barf", "otherfile:_Z4quuxf"}) {
1227ceed4eb1SRichard Smith     EXPECT_THAT_ERROR(Reader->getFunctionCounts(BadName, 0x1234, Counts),
1228ceed4eb1SRichard Smith                       Failed());
1229ceed4eb1SRichard Smith     EXPECT_THAT_ERROR(Reader->getFunctionCounts(BadName, 0x567, Counts),
1230ceed4eb1SRichard Smith                       Failed());
1231ceed4eb1SRichard Smith   }
1232ceed4eb1SRichard Smith }
1233ceed4eb1SRichard Smith 
TEST_F(SparseInstrProfTest,preserve_no_records)123400dab228SVedant Kumar TEST_F(SparseInstrProfTest, preserve_no_records) {
123598cce003SDavid Blaikie   Writer.addRecord({"foo", 0x1234, {0}}, Err);
123698cce003SDavid Blaikie   Writer.addRecord({"bar", 0x4321, {0, 0}}, Err);
1237910d3d05SVedant Kumar   Writer.addRecord({"baz", 0x4321, {0, 0, 0}}, Err);
123800dab228SVedant Kumar 
123900dab228SVedant Kumar   auto Profile = Writer.writeBuffer();
124000dab228SVedant Kumar   readProfile(std::move(Profile));
124100dab228SVedant Kumar 
124200dab228SVedant Kumar   auto I = Reader->begin(), E = Reader->end();
124300dab228SVedant Kumar   ASSERT_TRUE(I == E);
124400dab228SVedant Kumar }
124500dab228SVedant Kumar 
1246d4d80a29SBenjamin Kramer INSTANTIATE_TEST_SUITE_P(MaybeSparse, MaybeSparseInstrProfTest,
1247d4d80a29SBenjamin Kramer                          ::testing::Bool());
124800dab228SVedant Kumar 
1249d6c15b66SVedant Kumar #if defined(_LP64) && defined(EXPENSIVE_CHECKS)
TEST(ProfileReaderTest,ReadsLargeFiles)1250d6c15b66SVedant Kumar TEST(ProfileReaderTest, ReadsLargeFiles) {
1251d6c15b66SVedant Kumar   const size_t LargeSize = 1ULL << 32; // 4GB
1252d6c15b66SVedant Kumar 
1253d6c15b66SVedant Kumar   auto RawProfile = WritableMemoryBuffer::getNewUninitMemBuffer(LargeSize);
1254d6c15b66SVedant Kumar   if (!RawProfile)
1255d6c15b66SVedant Kumar     return;
1256d6c15b66SVedant Kumar   auto RawProfileReaderOrErr = InstrProfReader::create(std::move(RawProfile));
1257d6c15b66SVedant Kumar   ASSERT_TRUE(InstrProfError::take(RawProfileReaderOrErr.takeError()) ==
1258d6c15b66SVedant Kumar               instrprof_error::unrecognized_format);
1259d6c15b66SVedant Kumar 
1260d6c15b66SVedant Kumar   auto IndexedProfile = WritableMemoryBuffer::getNewUninitMemBuffer(LargeSize);
1261d6c15b66SVedant Kumar   if (!IndexedProfile)
1262d6c15b66SVedant Kumar     return;
1263d6c15b66SVedant Kumar   auto IndexedReaderOrErr =
1264d6c15b66SVedant Kumar       IndexedInstrProfReader::create(std::move(IndexedProfile), nullptr);
1265d6c15b66SVedant Kumar   ASSERT_TRUE(InstrProfError::take(IndexedReaderOrErr.takeError()) ==
1266d6c15b66SVedant Kumar               instrprof_error::bad_magic);
1267d6c15b66SVedant Kumar }
1268d6c15b66SVedant Kumar #endif
1269d6c15b66SVedant Kumar 
12702b6c537bSJustin Bogner } // end anonymous namespace
1271