diff --git a/llvm/include/llvm/IR/ProfileSummary.h b/llvm/include/llvm/IR/ProfileSummary.h --- 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 @@ /// 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 @@ 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 @@ 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 --- a/llvm/lib/IR/ProfileSummary.cpp +++ b/llvm/lib/IR/ProfileSummary.cpp @@ -31,6 +31,14 @@ 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 @@ // 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 @@ 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 @@ 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 @@ 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 --- a/llvm/test/Transforms/PGOProfile/unreachable_bb.ll +++ b/llvm/test/Transforms/PGOProfile/unreachable_bb.ll @@ -16,7 +16,7 @@ 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 --- a/llvm/unittests/ProfileData/SampleProfTest.cpp +++ b/llvm/unittests/ProfileData/SampleProfTest.cpp @@ -81,10 +81,13 @@ // 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 @@ 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 @@ 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 @@ 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,