X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=unittests%2FProfileData%2FInstrProfTest.cpp;h=635a5431a5133f62c51ee2eb657451ab7be4d524;hp=a9257fe316e0c8c37d333650e92315081f504546;hb=1c2b998913d05c83a781da1a15738ac4c9379f6f;hpb=0a3cc8fdf572dd4598952013b8d90f6ae6ce87bb diff --git a/unittests/ProfileData/InstrProfTest.cpp b/unittests/ProfileData/InstrProfTest.cpp index a9257fe316e..635a5431a51 100644 --- a/unittests/ProfileData/InstrProfTest.cpp +++ b/unittests/ProfileData/InstrProfTest.cpp @@ -350,6 +350,133 @@ TEST_F(InstrProfTest, get_icall_data_merge1) { ASSERT_EQ(2U, VD_4[2].Count); } +TEST_F(InstrProfTest, get_icall_data_merge1_saturation) { + const uint64_t Max = std::numeric_limits::max(); + + InstrProfRecord Record1("caller", 0x1234, {1}); + InstrProfRecord Record2("caller", 0x1234, {Max}); + InstrProfRecord Record3("callee1", 0x1235, {3, 4}); + + Record1.reserveSites(IPVK_IndirectCallTarget, 1); + InstrProfValueData VD1[] = {{(uint64_t) "callee1", 1}}; + Record1.addValueData(IPVK_IndirectCallTarget, 0, VD1, 1, nullptr); + + Record2.reserveSites(IPVK_IndirectCallTarget, 1); + InstrProfValueData VD2[] = {{(uint64_t) "callee1", Max}}; + Record2.addValueData(IPVK_IndirectCallTarget, 0, VD2, 1, nullptr); + + Writer.addRecord(std::move(Record1)); + Writer.addRecord(std::move(Record2)); + Writer.addRecord(std::move(Record3)); + + auto Profile = Writer.writeBuffer(); + readProfile(std::move(Profile)); + + // Verify saturation of counts. + ErrorOr R = Reader->getInstrProfRecord("caller", 0x1234); + ASSERT_TRUE(NoError(R.getError())); + + ASSERT_EQ(Max, R.get().Counts[0]); + + ASSERT_EQ(1U, R.get().getNumValueSites(IPVK_IndirectCallTarget)); + std::unique_ptr VD = + R.get().getValueForSite(IPVK_IndirectCallTarget, 0); + ASSERT_EQ(StringRef("callee1"), StringRef((const char *)VD[0].Value, 7)); + ASSERT_EQ(Max, VD[0].Count); +} + +// Synthesize runtime value profile data. +ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]}, + {{uint64_t("callee2"), 1000}, &Site1Values[2]}, + {{uint64_t("callee3"), 500}, &Site1Values[3]}, + {{uint64_t("callee4"), 300}, &Site1Values[4]}, + {{uint64_t("callee5"), 100}, 0}}; + +ValueProfNode Site2Values[4] = {{{uint64_t("callee5"), 800}, &Site2Values[1]}, + {{uint64_t("callee3"), 1000}, &Site2Values[2]}, + {{uint64_t("callee2"), 2500}, &Site2Values[3]}, + {{uint64_t("callee1"), 1300}, 0}}; + +ValueProfNode Site3Values[3] = {{{uint64_t("callee6"), 800}, &Site3Values[1]}, + {{uint64_t("callee3"), 1000}, &Site3Values[2]}, + {{uint64_t("callee4"), 5500}, 0}}; + +ValueProfNode Site4Values[2] = {{{uint64_t("callee2"), 1800}, &Site4Values[1]}, + {{uint64_t("callee3"), 2000}, 0}}; + +static ValueProfNode *ValueProfNodes[5] = {&Site1Values[0], &Site2Values[0], + &Site3Values[0], &Site4Values[0], 0}; +static uint16_t NumValueSites[IPVK_Last + 1] = {5}; +TEST_F(InstrProfTest, runtime_value_prof_data_read_write) { + ValueProfRuntimeRecord RTRecord; + initializeValueProfRuntimeRecord(&RTRecord, &NumValueSites[0], + &ValueProfNodes[0]); + + ValueProfData *VPData = serializeValueProfDataFromRT(&RTRecord, nullptr); + + InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2}); + + VPData->deserializeTo(Record, 0); + + // Now read data from Record and sanity check the data + ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget)); + ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); + ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); + ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); + ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); + ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); + + auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { + return VD1.Count > VD2.Count; + }; + std::unique_ptr VD_0( + Record.getValueForSite(IPVK_IndirectCallTarget, 0)); + std::sort(&VD_0[0], &VD_0[5], Cmp); + ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2")); + ASSERT_EQ(1000U, VD_0[0].Count); + ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3")); + ASSERT_EQ(500U, VD_0[1].Count); + ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1")); + ASSERT_EQ(400U, VD_0[2].Count); + ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4")); + ASSERT_EQ(300U, VD_0[3].Count); + ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5")); + ASSERT_EQ(100U, VD_0[4].Count); + + std::unique_ptr VD_1( + Record.getValueForSite(IPVK_IndirectCallTarget, 1)); + std::sort(&VD_1[0], &VD_1[4], Cmp); + ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2")); + ASSERT_EQ(2500U, VD_1[0].Count); + ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1")); + ASSERT_EQ(1300U, VD_1[1].Count); + ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3")); + ASSERT_EQ(1000U, VD_1[2].Count); + ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5")); + ASSERT_EQ(800U, VD_1[3].Count); + + std::unique_ptr VD_2( + Record.getValueForSite(IPVK_IndirectCallTarget, 2)); + std::sort(&VD_2[0], &VD_2[3], Cmp); + ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4")); + ASSERT_EQ(5500U, VD_2[0].Count); + ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3")); + ASSERT_EQ(1000U, VD_2[1].Count); + ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6")); + ASSERT_EQ(800U, VD_2[2].Count); + + std::unique_ptr VD_3( + Record.getValueForSite(IPVK_IndirectCallTarget, 3)); + std::sort(&VD_3[0], &VD_3[2], Cmp); + ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3")); + ASSERT_EQ(2000U, VD_3[0].Count); + ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2")); + ASSERT_EQ(1800U, VD_3[1].Count); + + finalizeValueProfRuntimeRecord(&RTRecord); + free(VPData); +} + TEST_F(InstrProfTest, get_max_function_count) { InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2}); InstrProfRecord Record2("bar", 0, {1ULL << 63});