From b5c59d77c3a0aad21d7dccfa2c3989e627e9f1bd Mon Sep 17 00:00:00 2001 From: Hiroshi Yamauchi Date: Thu, 14 May 2020 10:21:53 -0700 Subject: [PATCH] [ProfileSummary] Add the PartialProfileRatio field in ProfileSummary metadata. Summary: PartialProfileRatio approximately represents the ratio of the number of profile counters of the program being built to the number of profile counters in the partial sample profile. It is used to scale the working set size under the partial sample profile to reflect the size of the program being built and to improve the working set size heuristics. This is a split from D79831. Reviewers: davidxl Subscribers: eraman, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D79951 --- llvm/include/llvm/IR/ProfileSummary.h | 18 +++++- llvm/lib/IR/ProfileSummary.cpp | 56 +++++++++++++++---- .../Transforms/PGOProfile/unreachable_bb.ll | 2 +- llvm/unittests/ProfileData/SampleProfTest.cpp | 22 +++++--- 4 files changed, 76 insertions(+), 22 deletions(-) diff --git a/llvm/include/llvm/IR/ProfileSummary.h b/llvm/include/llvm/IR/ProfileSummary.h index 425ee2f1c16d..00af0c5e05c8 100644 --- a/llvm/include/llvm/IR/ProfileSummary.h +++ b/llvm/include/llvm/IR/ProfileSummary.h @@ -14,6 +14,7 @@ #define LLVM_IR_PROFILESUMMARY_H #include +#include #include #include @@ -56,6 +57,10 @@ private: /// code. The common profile is usually merged from profiles collected /// from running other targets. bool Partial = false; + /// This approximately represents the ratio of the number of profile counters + /// of the program being built to the number of profile counters in the + /// partial sample profile. When 'Partial' is false, it is undefined. + double PartialProfileRatio = 0; /// Return detailed summary as metadata. Metadata *getDetailedSummaryMD(LLVMContext &Context); @@ -66,15 +71,17 @@ public: uint64_t TotalCount, uint64_t MaxCount, uint64_t MaxInternalCount, uint64_t MaxFunctionCount, uint32_t NumCounts, uint32_t NumFunctions, - bool Partial = false) + bool Partial = false, double PartialProfileRatio = 0) : PSK(K), DetailedSummary(std::move(DetailedSummary)), TotalCount(TotalCount), MaxCount(MaxCount), MaxInternalCount(MaxInternalCount), MaxFunctionCount(MaxFunctionCount), - NumCounts(NumCounts), NumFunctions(NumFunctions), Partial(Partial) {} + NumCounts(NumCounts), NumFunctions(NumFunctions), Partial(Partial), + PartialProfileRatio(PartialProfileRatio) {} Kind getKind() const { return PSK; } /// Return summary information as metadata. - Metadata *getMD(LLVMContext &Context, bool AddPartialField = true); + Metadata *getMD(LLVMContext &Context, bool AddPartialField = true, + bool AddPartialProfileRatioField = true); /// Construct profile summary from metdata. static ProfileSummary *getFromMD(Metadata *MD); SummaryEntryVector &getDetailedSummary() { return DetailedSummary; } @@ -86,6 +93,11 @@ public: uint64_t getMaxInternalCount() { return MaxInternalCount; } void setPartialProfile(bool PP) { Partial = PP; } bool isPartialProfile() { return Partial; } + double getPartialProfileRatio() { return PartialProfileRatio; } + void setPartialProfileRatio(double R) { + assert(isPartialProfile() && "Unexpected when not partial profile"); + PartialProfileRatio = R; + } void printSummary(raw_ostream &OS); void printDetailedSummary(raw_ostream &OS); }; diff --git a/llvm/lib/IR/ProfileSummary.cpp b/llvm/lib/IR/ProfileSummary.cpp index 4f01879b1fb6..fbd2fa5ed8a7 100644 --- a/llvm/lib/IR/ProfileSummary.cpp +++ b/llvm/lib/IR/ProfileSummary.cpp @@ -31,6 +31,14 @@ static Metadata *getKeyValMD(LLVMContext &Context, const char *Key, return MDTuple::get(Context, Ops); } +static Metadata *getKeyFPValMD(LLVMContext &Context, const char *Key, + double Val) { + Type *DoubleTy = Type::getDoubleTy(Context); + Metadata *Ops[2] = {MDString::get(Context, Key), + ConstantAsMetadata::get(ConstantFP::get(DoubleTy, Val))}; + return MDTuple::get(Context, Ops); +} + // Return an MDTuple with two elements. The first element is a string Key and // the second is a string Value. static Metadata *getKeyValMD(LLVMContext &Context, const char *Key, @@ -67,7 +75,10 @@ Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) { // to the kind of profile summary as returned by getFormatSpecificMD. // IsPartialProfile is an optional field and \p AddPartialField will decide // whether to add a field for it. -Metadata *ProfileSummary::getMD(LLVMContext &Context, bool AddPartialField) { +// PartialProfileRatio is an optional field and \p AddPartialProfileRatioField +// will decide whether to add a field for it. +Metadata *ProfileSummary::getMD(LLVMContext &Context, bool AddPartialField, + bool AddPartialProfileRatioField) { const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"}; SmallVector Components; Components.push_back(getKeyValMD(Context, "ProfileFormat", KindStr[PSK])); @@ -82,24 +93,43 @@ Metadata *ProfileSummary::getMD(LLVMContext &Context, bool AddPartialField) { if (AddPartialField) Components.push_back( getKeyValMD(Context, "IsPartialProfile", isPartialProfile())); + if (AddPartialProfileRatioField) + Components.push_back(getKeyFPValMD(Context, "PartialProfileRatio", + getPartialProfileRatio())); Components.push_back(getDetailedSummaryMD(Context)); return MDTuple::get(Context, Components); } -// Parse an MDTuple representing (Key, Val) pair. -static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) { +// Get the value metadata for the input MD/Key. +static ConstantAsMetadata *getValMD(MDTuple *MD, const char *Key) { if (!MD) - return false; + return nullptr; if (MD->getNumOperands() != 2) - return false; + return nullptr; MDString *KeyMD = dyn_cast(MD->getOperand(0)); ConstantAsMetadata *ValMD = dyn_cast(MD->getOperand(1)); if (!KeyMD || !ValMD) - return false; + return nullptr; if (!KeyMD->getString().equals(Key)) - return false; - Val = cast(ValMD->getValue())->getZExtValue(); - return true; + return nullptr; + return ValMD; +} + +// Parse an MDTuple representing (Key, Val) pair. +static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) { + if (auto *ValMD = getValMD(MD, Key)) { + Val = cast(ValMD->getValue())->getZExtValue(); + return true; + } + return false; +} + +static bool getVal(MDTuple *MD, const char *Key, double &Val) { + if (auto *ValMD = getValMD(MD, Key)) { + Val = cast(ValMD->getValue())->getValueAPF().convertToDouble(); + return true; + } + return false; } // Check if an MDTuple represents a (Key, Val) pair. @@ -163,7 +193,7 @@ static bool getOptionalVal(MDTuple *Tuple, unsigned &Idx, const char *Key, ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) { MDTuple *Tuple = dyn_cast_or_null(MD); - if (!Tuple || Tuple->getNumOperands() < 8 || Tuple->getNumOperands() > 9) + if (!Tuple || Tuple->getNumOperands() < 8 || Tuple->getNumOperands() > 10) return nullptr; unsigned I = 0; @@ -205,13 +235,17 @@ ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) { uint64_t IsPartialProfile = 0; if (!getOptionalVal(Tuple, I, "IsPartialProfile", IsPartialProfile)) return nullptr; + double PartialProfileRatio = 0; + if (!getOptionalVal(Tuple, I, "PartialProfileRatio", PartialProfileRatio)) + return nullptr; SummaryEntryVector Summary; if (!getSummaryFromMD(dyn_cast(Tuple->getOperand(I++)), Summary)) return nullptr; return new ProfileSummary(SummaryKind, std::move(Summary), TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount, - NumCounts, NumFunctions, IsPartialProfile); + NumCounts, NumFunctions, IsPartialProfile, + PartialProfileRatio); } void ProfileSummary::printSummary(raw_ostream &OS) { diff --git a/llvm/test/Transforms/PGOProfile/unreachable_bb.ll b/llvm/test/Transforms/PGOProfile/unreachable_bb.ll index 96aca895ac44..8b3162d2b832 100644 --- a/llvm/test/Transforms/PGOProfile/unreachable_bb.ll +++ b/llvm/test/Transforms/PGOProfile/unreachable_bb.ll @@ -16,7 +16,7 @@ return: declare void @bar() ;USE: !0 = !{i32 1, !"ProfileSummary", !1} -;USE: !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10} +;USE: !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10, !11} ;USE: !2 = !{!"ProfileFormat", !"InstrProf"} ;USE: !3 = !{!"TotalCount", i64 0} diff --git a/llvm/unittests/ProfileData/SampleProfTest.cpp b/llvm/unittests/ProfileData/SampleProfTest.cpp index 62273740c91a..26b01e4b2849 100644 --- a/llvm/unittests/ProfileData/SampleProfTest.cpp +++ b/llvm/unittests/ProfileData/SampleProfTest.cpp @@ -81,10 +81,13 @@ struct SampleProfTest : ::testing::Test { // Metadata. \p AddPartialField is to choose whether the Metadata // contains the IsPartialProfile field which is optional. void verifyProfileSummary(ProfileSummary &Summary, Module &M, - const bool AddPartialField) { + const bool AddPartialField, + const bool AddPartialProfileRatioField) { LLVMContext &Context = M.getContext(); const bool IsPartialProfile = Summary.isPartialProfile(); - auto VerifySummary = [IsPartialProfile](ProfileSummary &Summary) mutable { + const double PartialProfileRatio = Summary.getPartialProfileRatio(); + auto VerifySummary = [IsPartialProfile, PartialProfileRatio]( + ProfileSummary &Summary) mutable { ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind()); ASSERT_EQ(137392u, Summary.getTotalCount()); ASSERT_EQ(8u, Summary.getNumCounts()); @@ -92,6 +95,7 @@ struct SampleProfTest : ::testing::Test { ASSERT_EQ(1437u, Summary.getMaxFunctionCount()); ASSERT_EQ(60351u, Summary.getMaxCount()); ASSERT_EQ(IsPartialProfile, Summary.isPartialProfile()); + ASSERT_EQ(PartialProfileRatio, Summary.getPartialProfileRatio()); uint32_t Cutoff = 800000; auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) { @@ -113,7 +117,8 @@ struct SampleProfTest : ::testing::Test { VerifySummary(Summary); // Test that conversion of summary to and from Metadata works. - Metadata *MD = Summary.getMD(Context, AddPartialField); + Metadata *MD = + Summary.getMD(Context, AddPartialField, AddPartialProfileRatioField); ASSERT_TRUE(MD); ProfileSummary *PS = ProfileSummary::getFromMD(MD); ASSERT_TRUE(PS); @@ -271,13 +276,16 @@ struct SampleProfTest : ::testing::Test { ProfileSummary &Summary = Reader->getSummary(); Summary.setPartialProfile(true); - verifyProfileSummary(Summary, M, true); + verifyProfileSummary(Summary, M, true, false); Summary.setPartialProfile(false); - verifyProfileSummary(Summary, M, true); + verifyProfileSummary(Summary, M, true, false); - Summary.setPartialProfile(false); - verifyProfileSummary(Summary, M, false); + verifyProfileSummary(Summary, M, false, false); + + Summary.setPartialProfile(true); + Summary.setPartialProfileRatio(0.5); + verifyProfileSummary(Summary, M, true, true); } void addFunctionSamples(StringMap *Smap, const char *Fname,