Home | History | Annotate | Download | only in ProfileData
      1 //===- unittest/ProfileData/InstrProfTest.cpp -------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/ProfileData/InstrProfReader.h"
     11 #include "llvm/ProfileData/InstrProfWriter.h"
     12 #include "gtest/gtest.h"
     13 
     14 #include <cstdarg>
     15 
     16 using namespace llvm;
     17 
     18 static ::testing::AssertionResult NoError(std::error_code EC) {
     19   if (!EC)
     20     return ::testing::AssertionSuccess();
     21   return ::testing::AssertionFailure() << "error " << EC.value()
     22                                        << ": " << EC.message();
     23 }
     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 
     33 namespace {
     34 
     35 struct InstrProfTest : ::testing::Test {
     36   InstrProfWriter Writer;
     37   std::unique_ptr<IndexedInstrProfReader> Reader;
     38 
     39   void readProfile(std::unique_ptr<MemoryBuffer> Profile) {
     40     auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile));
     41     ASSERT_TRUE(NoError(ReaderOrErr.getError()));
     42     Reader = std::move(ReaderOrErr.get());
     43   }
     44 };
     45 
     46 TEST_F(InstrProfTest, write_and_read_empty_profile) {
     47   auto Profile = Writer.writeBuffer();
     48   readProfile(std::move(Profile));
     49   ASSERT_TRUE(Reader->begin() == Reader->end());
     50 }
     51 
     52 TEST_F(InstrProfTest, write_and_read_one_function) {
     53   InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4});
     54   Writer.addRecord(std::move(Record));
     55   auto Profile = Writer.writeBuffer();
     56   readProfile(std::move(Profile));
     57 
     58   auto I = Reader->begin(), E = Reader->end();
     59   ASSERT_TRUE(I != E);
     60   ASSERT_EQ(StringRef("foo"), I->Name);
     61   ASSERT_EQ(0x1234U, I->Hash);
     62   ASSERT_EQ(4U, I->Counts.size());
     63   ASSERT_EQ(1U, I->Counts[0]);
     64   ASSERT_EQ(2U, I->Counts[1]);
     65   ASSERT_EQ(3U, I->Counts[2]);
     66   ASSERT_EQ(4U, I->Counts[3]);
     67   ASSERT_TRUE(++I == E);
     68 }
     69 
     70 TEST_F(InstrProfTest, get_instr_prof_record) {
     71   InstrProfRecord Record1("foo", 0x1234, {1, 2});
     72   InstrProfRecord Record2("foo", 0x1235, {3, 4});
     73   Writer.addRecord(std::move(Record1));
     74   Writer.addRecord(std::move(Record2));
     75   auto Profile = Writer.writeBuffer();
     76   readProfile(std::move(Profile));
     77 
     78   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234);
     79   ASSERT_TRUE(NoError(R.getError()));
     80   ASSERT_EQ(2U, R.get().Counts.size());
     81   ASSERT_EQ(1U, R.get().Counts[0]);
     82   ASSERT_EQ(2U, R.get().Counts[1]);
     83 
     84   R = Reader->getInstrProfRecord("foo", 0x1235);
     85   ASSERT_TRUE(NoError(R.getError()));
     86   ASSERT_EQ(2U, R.get().Counts.size());
     87   ASSERT_EQ(3U, R.get().Counts[0]);
     88   ASSERT_EQ(4U, R.get().Counts[1]);
     89 
     90   R = Reader->getInstrProfRecord("foo", 0x5678);
     91   ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.getError()));
     92 
     93   R = Reader->getInstrProfRecord("bar", 0x1234);
     94   ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.getError()));
     95 }
     96 
     97 TEST_F(InstrProfTest, get_function_counts) {
     98   InstrProfRecord Record1("foo", 0x1234, {1, 2});
     99   InstrProfRecord Record2("foo", 0x1235, {3, 4});
    100   Writer.addRecord(std::move(Record1));
    101   Writer.addRecord(std::move(Record2));
    102   auto Profile = Writer.writeBuffer();
    103   readProfile(std::move(Profile));
    104 
    105   std::vector<uint64_t> Counts;
    106   ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts)));
    107   ASSERT_EQ(2U, Counts.size());
    108   ASSERT_EQ(1U, Counts[0]);
    109   ASSERT_EQ(2U, Counts[1]);
    110 
    111   ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts)));
    112   ASSERT_EQ(2U, Counts.size());
    113   ASSERT_EQ(3U, Counts[0]);
    114   ASSERT_EQ(4U, Counts[1]);
    115 
    116   std::error_code EC;
    117   EC = Reader->getFunctionCounts("foo", 0x5678, Counts);
    118   ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, EC));
    119 
    120   EC = Reader->getFunctionCounts("bar", 0x1234, Counts);
    121   ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, EC));
    122 }
    123 
    124 TEST_F(InstrProfTest, get_icall_data_read_write) {
    125   InstrProfRecord Record1("caller", 0x1234, {1, 2});
    126   InstrProfRecord Record2("callee1", 0x1235, {3, 4});
    127   InstrProfRecord Record3("callee2", 0x1235, {3, 4});
    128   InstrProfRecord Record4("callee3", 0x1235, {3, 4});
    129 
    130   // 4 value sites.
    131   Record1.reserveSites(IPVK_IndirectCallTarget, 4);
    132   InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
    133                               {(uint64_t) "callee2", 2},
    134                               {(uint64_t) "callee3", 3}};
    135   Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
    136   // No value profile data at the second site.
    137   Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
    138   InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
    139                               {(uint64_t) "callee2", 2}};
    140   Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
    141   InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
    142   Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
    143 
    144   Writer.addRecord(std::move(Record1));
    145   Writer.addRecord(std::move(Record2));
    146   Writer.addRecord(std::move(Record3));
    147   Writer.addRecord(std::move(Record4));
    148   auto Profile = Writer.writeBuffer();
    149   readProfile(std::move(Profile));
    150 
    151   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
    152   ASSERT_TRUE(NoError(R.getError()));
    153   ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
    154   ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
    155   ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
    156   ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
    157   ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
    158 
    159   std::unique_ptr<InstrProfValueData[]> VD =
    160       R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
    161   // Now sort the target acording to frequency.
    162   std::sort(&VD[0], &VD[3],
    163             [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
    164               return VD1.Count > VD2.Count;
    165             });
    166   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
    167   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
    168   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
    169 }
    170 
    171 TEST_F(InstrProfTest, get_icall_data_read_write_big_endian) {
    172   InstrProfRecord Record1("caller", 0x1234, {1, 2});
    173   InstrProfRecord Record2("callee1", 0x1235, {3, 4});
    174   InstrProfRecord Record3("callee2", 0x1235, {3, 4});
    175   InstrProfRecord Record4("callee3", 0x1235, {3, 4});
    176 
    177   // 4 value sites.
    178   Record1.reserveSites(IPVK_IndirectCallTarget, 4);
    179   InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
    180                               {(uint64_t) "callee2", 2},
    181                               {(uint64_t) "callee3", 3}};
    182   Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
    183   // No value profile data at the second site.
    184   Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
    185   InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
    186                               {(uint64_t) "callee2", 2}};
    187   Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
    188   InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
    189   Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
    190 
    191   Writer.addRecord(std::move(Record1));
    192   Writer.addRecord(std::move(Record2));
    193   Writer.addRecord(std::move(Record3));
    194   Writer.addRecord(std::move(Record4));
    195 
    196   // Set big endian output.
    197   Writer.setValueProfDataEndianness(support::big);
    198 
    199   auto Profile = Writer.writeBuffer();
    200   readProfile(std::move(Profile));
    201 
    202   // Set big endian input.
    203   Reader->setValueProfDataEndianness(support::big);
    204 
    205   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
    206   ASSERT_TRUE(NoError(R.getError()));
    207   ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
    208   ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
    209   ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
    210   ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
    211   ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
    212 
    213   std::unique_ptr<InstrProfValueData[]> VD =
    214       R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
    215   // Now sort the target acording to frequency.
    216   std::sort(&VD[0], &VD[3],
    217             [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
    218               return VD1.Count > VD2.Count;
    219             });
    220   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
    221   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
    222   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
    223 
    224   // Restore little endian default:
    225   Writer.setValueProfDataEndianness(support::little);
    226 }
    227 
    228 TEST_F(InstrProfTest, get_icall_data_merge1) {
    229   InstrProfRecord Record11("caller", 0x1234, {1, 2});
    230   InstrProfRecord Record12("caller", 0x1234, {1, 2});
    231   InstrProfRecord Record2("callee1", 0x1235, {3, 4});
    232   InstrProfRecord Record3("callee2", 0x1235, {3, 4});
    233   InstrProfRecord Record4("callee3", 0x1235, {3, 4});
    234   InstrProfRecord Record5("callee3", 0x1235, {3, 4});
    235   InstrProfRecord Record6("callee4", 0x1235, {3, 5});
    236 
    237   // 5 value sites.
    238   Record11.reserveSites(IPVK_IndirectCallTarget, 5);
    239   InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
    240                               {(uint64_t) "callee2", 2},
    241                               {(uint64_t) "callee3", 3},
    242                               {(uint64_t) "callee4", 4}};
    243   Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr);
    244 
    245   // No valeu profile data at the second site.
    246   Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
    247 
    248   InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
    249                               {(uint64_t) "callee2", 2},
    250                               {(uint64_t) "callee3", 3}};
    251   Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
    252 
    253   InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
    254   Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
    255 
    256   InstrProfValueData VD4[] = {{(uint64_t) "callee1", 1},
    257                               {(uint64_t) "callee2", 2},
    258                               {(uint64_t) "callee3", 3}};
    259   Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr);
    260 
    261   // A differnt record for the same caller.
    262   Record12.reserveSites(IPVK_IndirectCallTarget, 5);
    263   InstrProfValueData VD02[] = {{(uint64_t) "callee2", 5},
    264                                {(uint64_t) "callee3", 3}};
    265   Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr);
    266 
    267   // No valeu profile data at the second site.
    268   Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
    269 
    270   InstrProfValueData VD22[] = {{(uint64_t) "callee2", 1},
    271                                {(uint64_t) "callee3", 3},
    272                                {(uint64_t) "callee4", 4}};
    273   Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr);
    274 
    275   Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr);
    276 
    277   InstrProfValueData VD42[] = {{(uint64_t) "callee1", 1},
    278                                {(uint64_t) "callee2", 2},
    279                                {(uint64_t) "callee3", 3}};
    280   Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr);
    281 
    282   Writer.addRecord(std::move(Record11));
    283   // Merge profile data.
    284   Writer.addRecord(std::move(Record12));
    285 
    286   Writer.addRecord(std::move(Record2));
    287   Writer.addRecord(std::move(Record3));
    288   Writer.addRecord(std::move(Record4));
    289   Writer.addRecord(std::move(Record5));
    290   Writer.addRecord(std::move(Record6));
    291   auto Profile = Writer.writeBuffer();
    292   readProfile(std::move(Profile));
    293 
    294   ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
    295   ASSERT_TRUE(NoError(R.getError()));
    296   ASSERT_EQ(5U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
    297   ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
    298   ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
    299   ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
    300   ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
    301   ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
    302 
    303   std::unique_ptr<InstrProfValueData[]> VD =
    304       R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
    305   // Now sort the target acording to frequency.
    306   std::sort(&VD[0], &VD[4],
    307             [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
    308               return VD1.Count > VD2.Count;
    309             });
    310   ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2"));
    311   ASSERT_EQ(7U, VD[0].Count);
    312   ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3"));
    313   ASSERT_EQ(6U, VD[1].Count);
    314   ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4"));
    315   ASSERT_EQ(4U, VD[2].Count);
    316   ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1"));
    317   ASSERT_EQ(1U, VD[3].Count);
    318 
    319   std::unique_ptr<InstrProfValueData[]> VD_2(
    320       R.get().getValueForSite(IPVK_IndirectCallTarget, 2));
    321   std::sort(&VD_2[0], &VD_2[4],
    322             [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
    323               return VD1.Count > VD2.Count;
    324             });
    325   ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3"));
    326   ASSERT_EQ(6U, VD_2[0].Count);
    327   ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4"));
    328   ASSERT_EQ(4U, VD_2[1].Count);
    329   ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2"));
    330   ASSERT_EQ(3U, VD_2[2].Count);
    331   ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1"));
    332   ASSERT_EQ(1U, VD_2[3].Count);
    333 
    334   std::unique_ptr<InstrProfValueData[]> VD_3(
    335       R.get().getValueForSite(IPVK_IndirectCallTarget, 3));
    336   ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1"));
    337   ASSERT_EQ(1U, VD_3[0].Count);
    338 
    339   std::unique_ptr<InstrProfValueData[]> VD_4(
    340       R.get().getValueForSite(IPVK_IndirectCallTarget, 4));
    341   std::sort(&VD_4[0], &VD_4[3],
    342             [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
    343               return VD1.Count > VD2.Count;
    344             });
    345   ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3"));
    346   ASSERT_EQ(6U, VD_4[0].Count);
    347   ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2"));
    348   ASSERT_EQ(4U, VD_4[1].Count);
    349   ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1"));
    350   ASSERT_EQ(2U, VD_4[2].Count);
    351 }
    352 
    353 TEST_F(InstrProfTest, get_icall_data_merge1_saturation) {
    354   const uint64_t Max = std::numeric_limits<uint64_t>::max();
    355 
    356   InstrProfRecord Record1("foo", 0x1234, {1});
    357   auto Result1 = Writer.addRecord(std::move(Record1));
    358   ASSERT_EQ(Result1, instrprof_error::success);
    359 
    360   // Verify counter overflow.
    361   InstrProfRecord Record2("foo", 0x1234, {Max});
    362   auto Result2 = Writer.addRecord(std::move(Record2));
    363   ASSERT_EQ(Result2, instrprof_error::counter_overflow);
    364 
    365   InstrProfRecord Record3("bar", 0x9012, {8});
    366   auto Result3 = Writer.addRecord(std::move(Record3));
    367   ASSERT_EQ(Result3, instrprof_error::success);
    368 
    369   InstrProfRecord Record4("baz", 0x5678, {3, 4});
    370   Record4.reserveSites(IPVK_IndirectCallTarget, 1);
    371   InstrProfValueData VD4[] = {{(uint64_t) "bar", 1}};
    372   Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
    373   auto Result4 = Writer.addRecord(std::move(Record4));
    374   ASSERT_EQ(Result4, instrprof_error::success);
    375 
    376   // Verify value data counter overflow.
    377   InstrProfRecord Record5("baz", 0x5678, {5, 6});
    378   Record5.reserveSites(IPVK_IndirectCallTarget, 1);
    379   InstrProfValueData VD5[] = {{(uint64_t) "bar", Max}};
    380   Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
    381   auto Result5 = Writer.addRecord(std::move(Record5));
    382   ASSERT_EQ(Result5, instrprof_error::counter_overflow);
    383 
    384   auto Profile = Writer.writeBuffer();
    385   readProfile(std::move(Profile));
    386 
    387   // Verify saturation of counts.
    388   ErrorOr<InstrProfRecord> ReadRecord1 =
    389       Reader->getInstrProfRecord("foo", 0x1234);
    390   ASSERT_TRUE(NoError(ReadRecord1.getError()));
    391   ASSERT_EQ(Max, ReadRecord1.get().Counts[0]);
    392 
    393   ErrorOr<InstrProfRecord> ReadRecord2 =
    394       Reader->getInstrProfRecord("baz", 0x5678);
    395   ASSERT_EQ(1U, ReadRecord2.get().getNumValueSites(IPVK_IndirectCallTarget));
    396   std::unique_ptr<InstrProfValueData[]> VD =
    397       ReadRecord2.get().getValueForSite(IPVK_IndirectCallTarget, 0);
    398   ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3));
    399   ASSERT_EQ(Max, VD[0].Count);
    400 }
    401 
    402 // Synthesize runtime value profile data.
    403 ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]},
    404                                 {{uint64_t("callee2"), 1000}, &Site1Values[2]},
    405                                 {{uint64_t("callee3"), 500}, &Site1Values[3]},
    406                                 {{uint64_t("callee4"), 300}, &Site1Values[4]},
    407                                 {{uint64_t("callee5"), 100}, 0}};
    408 
    409 ValueProfNode Site2Values[4] = {{{uint64_t("callee5"), 800}, &Site2Values[1]},
    410                                 {{uint64_t("callee3"), 1000}, &Site2Values[2]},
    411                                 {{uint64_t("callee2"), 2500}, &Site2Values[3]},
    412                                 {{uint64_t("callee1"), 1300}, 0}};
    413 
    414 ValueProfNode Site3Values[3] = {{{uint64_t("callee6"), 800}, &Site3Values[1]},
    415                                 {{uint64_t("callee3"), 1000}, &Site3Values[2]},
    416                                 {{uint64_t("callee4"), 5500}, 0}};
    417 
    418 ValueProfNode Site4Values[2] = {{{uint64_t("callee2"), 1800}, &Site4Values[1]},
    419                                 {{uint64_t("callee3"), 2000}, 0}};
    420 
    421 static ValueProfNode *ValueProfNodes[5] = {&Site1Values[0], &Site2Values[0],
    422                                            &Site3Values[0], &Site4Values[0], 0};
    423 static uint16_t NumValueSites[IPVK_Last + 1] = {5};
    424 TEST_F(InstrProfTest, runtime_value_prof_data_read_write) {
    425   ValueProfRuntimeRecord RTRecord;
    426   initializeValueProfRuntimeRecord(&RTRecord, &NumValueSites[0],
    427                                    &ValueProfNodes[0]);
    428 
    429   ValueProfData *VPData = serializeValueProfDataFromRT(&RTRecord, nullptr);
    430 
    431   InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
    432 
    433   VPData->deserializeTo(Record, 0);
    434 
    435   // Now read data from Record and sanity check the data
    436   ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
    437   ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
    438   ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
    439   ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
    440   ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
    441   ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
    442 
    443   auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
    444     return VD1.Count > VD2.Count;
    445   };
    446   std::unique_ptr<InstrProfValueData[]> VD_0(
    447       Record.getValueForSite(IPVK_IndirectCallTarget, 0));
    448   std::sort(&VD_0[0], &VD_0[5], Cmp);
    449   ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2"));
    450   ASSERT_EQ(1000U, VD_0[0].Count);
    451   ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3"));
    452   ASSERT_EQ(500U, VD_0[1].Count);
    453   ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1"));
    454   ASSERT_EQ(400U, VD_0[2].Count);
    455   ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4"));
    456   ASSERT_EQ(300U, VD_0[3].Count);
    457   ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5"));
    458   ASSERT_EQ(100U, VD_0[4].Count);
    459 
    460   std::unique_ptr<InstrProfValueData[]> VD_1(
    461       Record.getValueForSite(IPVK_IndirectCallTarget, 1));
    462   std::sort(&VD_1[0], &VD_1[4], Cmp);
    463   ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2"));
    464   ASSERT_EQ(2500U, VD_1[0].Count);
    465   ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1"));
    466   ASSERT_EQ(1300U, VD_1[1].Count);
    467   ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3"));
    468   ASSERT_EQ(1000U, VD_1[2].Count);
    469   ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5"));
    470   ASSERT_EQ(800U, VD_1[3].Count);
    471 
    472   std::unique_ptr<InstrProfValueData[]> VD_2(
    473       Record.getValueForSite(IPVK_IndirectCallTarget, 2));
    474   std::sort(&VD_2[0], &VD_2[3], Cmp);
    475   ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4"));
    476   ASSERT_EQ(5500U, VD_2[0].Count);
    477   ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3"));
    478   ASSERT_EQ(1000U, VD_2[1].Count);
    479   ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6"));
    480   ASSERT_EQ(800U, VD_2[2].Count);
    481 
    482   std::unique_ptr<InstrProfValueData[]> VD_3(
    483       Record.getValueForSite(IPVK_IndirectCallTarget, 3));
    484   std::sort(&VD_3[0], &VD_3[2], Cmp);
    485   ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3"));
    486   ASSERT_EQ(2000U, VD_3[0].Count);
    487   ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2"));
    488   ASSERT_EQ(1800U, VD_3[1].Count);
    489 
    490   finalizeValueProfRuntimeRecord(&RTRecord);
    491   free(VPData);
    492 }
    493 
    494 TEST_F(InstrProfTest, get_max_function_count) {
    495   InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2});
    496   InstrProfRecord Record2("bar", 0, {1ULL << 63});
    497   InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0});
    498   Writer.addRecord(std::move(Record1));
    499   Writer.addRecord(std::move(Record2));
    500   Writer.addRecord(std::move(Record3));
    501   auto Profile = Writer.writeBuffer();
    502   readProfile(std::move(Profile));
    503 
    504   ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount());
    505 }
    506 
    507 TEST_F(InstrProfTest, get_weighted_function_counts) {
    508   InstrProfRecord Record1("foo", 0x1234, {1, 2});
    509   InstrProfRecord Record2("foo", 0x1235, {3, 4});
    510   Writer.addRecord(std::move(Record1), 3);
    511   Writer.addRecord(std::move(Record2), 5);
    512   auto Profile = Writer.writeBuffer();
    513   readProfile(std::move(Profile));
    514 
    515   std::vector<uint64_t> Counts;
    516   ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts)));
    517   ASSERT_EQ(2U, Counts.size());
    518   ASSERT_EQ(3U, Counts[0]);
    519   ASSERT_EQ(6U, Counts[1]);
    520 
    521   ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts)));
    522   ASSERT_EQ(2U, Counts.size());
    523   ASSERT_EQ(15U, Counts[0]);
    524   ASSERT_EQ(20U, Counts[1]);
    525 }
    526 
    527 TEST_F(InstrProfTest, instr_prof_symtab_test) {
    528   std::vector<StringRef> FuncNames;
    529   FuncNames.push_back("func1");
    530   FuncNames.push_back("func2");
    531   FuncNames.push_back("func3");
    532   FuncNames.push_back("bar1");
    533   FuncNames.push_back("bar2");
    534   FuncNames.push_back("bar3");
    535   InstrProfSymtab Symtab;
    536   Symtab.create(FuncNames);
    537   StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
    538   ASSERT_EQ(StringRef("func1"), R);
    539   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
    540   ASSERT_EQ(StringRef("func2"), R);
    541   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
    542   ASSERT_EQ(StringRef("func3"), R);
    543   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
    544   ASSERT_EQ(StringRef("bar1"), R);
    545   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
    546   ASSERT_EQ(StringRef("bar2"), R);
    547   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
    548   ASSERT_EQ(StringRef("bar3"), R);
    549 
    550   // Now incrementally update the symtab
    551   Symtab.addFuncName("blah_1");
    552   Symtab.addFuncName("blah_2");
    553   Symtab.addFuncName("blah_3");
    554   // Finalize it
    555   Symtab.finalizeSymtab();
    556 
    557   // Check again
    558   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1"));
    559   ASSERT_EQ(StringRef("blah_1"), R);
    560   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2"));
    561   ASSERT_EQ(StringRef("blah_2"), R);
    562   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3"));
    563   ASSERT_EQ(StringRef("blah_3"), R);
    564   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
    565   ASSERT_EQ(StringRef("func1"), R);
    566   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
    567   ASSERT_EQ(StringRef("func2"), R);
    568   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
    569   ASSERT_EQ(StringRef("func3"), R);
    570   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
    571   ASSERT_EQ(StringRef("bar1"), R);
    572   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
    573   ASSERT_EQ(StringRef("bar2"), R);
    574   R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
    575   ASSERT_EQ(StringRef("bar3"), R);
    576 }
    577 
    578 } // end anonymous namespace
    579