Index: llvm/trunk/include/llvm/IR/ProfileSummary.h =================================================================== --- llvm/trunk/include/llvm/IR/ProfileSummary.h +++ llvm/trunk/include/llvm/IR/ProfileSummary.h @@ -0,0 +1,129 @@ +//===-- ProfileSummary.h - Profile summary data structure. ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the profile summary data structure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PROFILE_SUMMARY_H +#define LLVM_SUPPORT_PROFILE_SUMMARY_H + +#include +#include + +#include "llvm/Support/Casting.h" + +namespace llvm { + +class LLVMContext; +class Metadata; +class MDTuple; +class MDNode; + +// The profile summary is one or more (Cutoff, MinCount, NumCounts) triplets. +// The semantics of counts depend on the type of profile. For instrumentation +// profile, counts are block counts and for sample profile, counts are +// per-line samples. Given a target counts percentile, we compute the minimum +// number of counts needed to reach this target and the minimum among these +// counts. +struct ProfileSummaryEntry { + uint32_t Cutoff; ///< The required percentile of counts. + uint64_t MinCount; ///< The minimum count for this percentile. + uint64_t NumCounts; ///< Number of counts >= the minimum count. + ProfileSummaryEntry(uint32_t TheCutoff, uint64_t TheMinCount, + uint64_t TheNumCounts) + : Cutoff(TheCutoff), MinCount(TheMinCount), NumCounts(TheNumCounts) {} +}; + +typedef std::vector SummaryEntryVector; + +class ProfileSummary { +public: + enum Kind { PSK_Instr, PSK_Sample }; + +private: + const Kind PSK; + static const char *KindStr[2]; + +protected: + SummaryEntryVector DetailedSummary; + uint64_t TotalCount, MaxCount, MaxFunctionCount; + uint32_t NumCounts, NumFunctions; + ProfileSummary(Kind K, SummaryEntryVector DetailedSummary, + uint64_t TotalCount, uint64_t MaxCount, + uint64_t MaxFunctionCount, uint32_t NumCounts, + uint32_t NumFunctions) + : PSK(K), DetailedSummary(DetailedSummary), TotalCount(TotalCount), + MaxCount(MaxCount), MaxFunctionCount(MaxFunctionCount), + NumCounts(NumCounts), NumFunctions(NumFunctions) {} + ~ProfileSummary() = default; + /// \brief Return metadata specific to the profile format. + /// Derived classes implement this method to return a vector of Metadata. + virtual std::vector getFormatSpecificMD(LLVMContext &Context) = 0; + /// \brief Return detailed summary as metadata. + Metadata *getDetailedSummaryMD(LLVMContext &Context); + +public: + static const int Scale = 1000000; + Kind getKind() const { return PSK; } + const char *getKindStr() const { return KindStr[PSK]; } + /// \brief Return summary information as metadata. + Metadata *getMD(LLVMContext &Context); + /// \brief Construct profile summary from metdata. + static ProfileSummary *getFromMD(Metadata *MD); + SummaryEntryVector &getDetailedSummary() { return DetailedSummary; } + uint32_t getNumFunctions() { return NumFunctions; } + uint64_t getMaxFunctionCount() { return MaxFunctionCount; } +}; + +class InstrProfSummary final : public ProfileSummary { + uint64_t MaxInternalBlockCount; + +protected: + std::vector getFormatSpecificMD(LLVMContext &Context) override; + +public: + InstrProfSummary(uint64_t TotalCount, uint64_t MaxBlockCount, + uint64_t MaxInternalBlockCount, uint64_t MaxFunctionCount, + uint32_t NumBlocks, uint32_t NumFunctions, + SummaryEntryVector Summary) + : ProfileSummary(PSK_Instr, Summary, TotalCount, MaxBlockCount, + MaxFunctionCount, NumBlocks, NumFunctions), + MaxInternalBlockCount(MaxInternalBlockCount) {} + static bool classof(const ProfileSummary *PS) { + return PS->getKind() == PSK_Instr; + } + uint32_t getNumBlocks() { return NumCounts; } + uint64_t getTotalCount() { return TotalCount; } + uint64_t getMaxBlockCount() { return MaxCount; } + uint64_t getMaxInternalBlockCount() { return MaxInternalBlockCount; } +}; + +class SampleProfileSummary final : public ProfileSummary { +protected: + std::vector getFormatSpecificMD(LLVMContext &Context) override; + +public: + uint32_t getNumLinesWithSamples() { return NumCounts; } + uint64_t getTotalSamples() { return TotalCount; } + uint64_t getMaxSamplesPerLine() { return MaxCount; } + SampleProfileSummary(uint64_t TotalSamples, uint64_t MaxSamplesPerLine, + uint64_t MaxFunctionCount, int32_t NumLinesWithSamples, + uint32_t NumFunctions, + SummaryEntryVector DetailedSummary) + : ProfileSummary(PSK_Sample, DetailedSummary, TotalSamples, + MaxSamplesPerLine, MaxFunctionCount, NumLinesWithSamples, + NumFunctions) {} + static bool classof(const ProfileSummary *PS) { + return PS->getKind() == PSK_Sample; + } +}; + +} // end namespace llvm +#endif Index: llvm/trunk/include/llvm/ProfileData/ProfileCommon.h =================================================================== --- llvm/trunk/include/llvm/ProfileData/ProfileCommon.h +++ llvm/trunk/include/llvm/ProfileData/ProfileCommon.h @@ -20,7 +20,7 @@ #include #include -#include "llvm/Support/Casting.h" +#include "llvm/IR/ProfileSummary.h" #include "llvm/Support/Error.h" namespace llvm { @@ -40,134 +40,54 @@ inline const char *getHotSectionPrefix() { return ".hot"; } inline const char *getUnlikelySectionPrefix() { return ".unlikely"; } -// The profile summary is one or more (Cutoff, MinCount, NumCounts) triplets. -// The semantics of counts depend on the type of profile. For instrumentation -// profile, counts are block counts and for sample profile, counts are -// per-line samples. Given a target counts percentile, we compute the minimum -// number of counts needed to reach this target and the minimum among these -// counts. -struct ProfileSummaryEntry { - uint32_t Cutoff; ///< The required percentile of counts. - uint64_t MinCount; ///< The minimum count for this percentile. - uint64_t NumCounts; ///< Number of counts >= the minimum count. - ProfileSummaryEntry(uint32_t TheCutoff, uint64_t TheMinCount, - uint64_t TheNumCounts) - : Cutoff(TheCutoff), MinCount(TheMinCount), NumCounts(TheNumCounts) {} -}; - -typedef std::vector SummaryEntryVector; - -class ProfileSummary { -public: - enum Kind { PSK_Instr, PSK_Sample }; +class ProfileSummaryBuilder { private: - const Kind PSK; - static const char *KindStr[2]; // We keep track of the number of times a count (block count or samples) // appears in the profile. The map is kept sorted in the descending order of // counts. std::map> CountFrequencies; + std::vector DetailedSummaryCutoffs; + protected: SummaryEntryVector DetailedSummary; - std::vector DetailedSummaryCutoffs; - uint64_t TotalCount, MaxCount, MaxFunctionCount; - uint32_t NumCounts, NumFunctions; - ProfileSummary(Kind K, std::vector Cutoffs) - : PSK(K), DetailedSummaryCutoffs(Cutoffs), TotalCount(0), MaxCount(0), + ProfileSummaryBuilder(std::vector Cutoffs) + : DetailedSummaryCutoffs(Cutoffs), TotalCount(0), MaxCount(0), MaxFunctionCount(0), NumCounts(0), NumFunctions(0) {} - ProfileSummary(Kind K) - : PSK(K), TotalCount(0), MaxCount(0), MaxFunctionCount(0), NumCounts(0), - NumFunctions(0) {} - ProfileSummary(Kind K, SummaryEntryVector DetailedSummary, - uint64_t TotalCount, uint64_t MaxCount, - uint64_t MaxFunctionCount, uint32_t NumCounts, - uint32_t NumFunctions) - : PSK(K), DetailedSummary(DetailedSummary), TotalCount(TotalCount), - MaxCount(MaxCount), MaxFunctionCount(MaxFunctionCount), - NumCounts(NumCounts), NumFunctions(NumFunctions) {} - ~ProfileSummary() = default; inline void addCount(uint64_t Count); - /// \brief Return metadata specific to the profile format. - /// Derived classes implement this method to return a vector of Metadata. - virtual std::vector getFormatSpecificMD(LLVMContext &Context) = 0; - /// \brief Return detailed summary as metadata. - Metadata *getDetailedSummaryMD(LLVMContext &Context); + ~ProfileSummaryBuilder() = default; + void computeDetailedSummary(); + uint64_t TotalCount, MaxCount, MaxFunctionCount; + uint32_t NumCounts, NumFunctions; public: - static const int Scale = 1000000; - Kind getKind() const { return PSK; } - const char *getKindStr() const { return KindStr[PSK]; } - // \brief Returns true if F is a hot function. - static bool isFunctionHot(const Function *F); - // \brief Returns true if F is unlikley executed. - static bool isFunctionUnlikely(const Function *F); - inline SummaryEntryVector &getDetailedSummary(); - void computeDetailedSummary(); /// \brief A vector of useful cutoff values for detailed summary. static const std::vector DefaultCutoffs; - /// \brief Return summary information as metadata. - Metadata *getMD(LLVMContext &Context); - /// \brief Construct profile summary from metdata. - static ProfileSummary *getFromMD(Metadata *MD); - uint32_t getNumFunctions() { return NumFunctions; } - uint64_t getMaxFunctionCount() { return MaxFunctionCount; } }; -class InstrProfSummary final : public ProfileSummary { +class InstrProfSummaryBuilder final : public ProfileSummaryBuilder { uint64_t MaxInternalBlockCount; inline void addEntryCount(uint64_t Count); inline void addInternalCount(uint64_t Count); -protected: - std::vector getFormatSpecificMD(LLVMContext &Context) override; - public: - InstrProfSummary(std::vector Cutoffs) - : ProfileSummary(PSK_Instr, Cutoffs), MaxInternalBlockCount(0) {} - InstrProfSummary(const IndexedInstrProf::Summary &S); - InstrProfSummary(uint64_t TotalCount, uint64_t MaxBlockCount, - uint64_t MaxInternalBlockCount, uint64_t MaxFunctionCount, - uint32_t NumBlocks, uint32_t NumFunctions, - SummaryEntryVector Summary) - : ProfileSummary(PSK_Instr, Summary, TotalCount, MaxBlockCount, - MaxFunctionCount, NumBlocks, NumFunctions), - MaxInternalBlockCount(MaxInternalBlockCount) {} - static bool classof(const ProfileSummary *PS) { - return PS->getKind() == PSK_Instr; - } + InstrProfSummaryBuilder(std::vector Cutoffs) + : ProfileSummaryBuilder(Cutoffs), MaxInternalBlockCount(0) {} void addRecord(const InstrProfRecord &); - uint32_t getNumBlocks() { return NumCounts; } - uint64_t getTotalCount() { return TotalCount; } - uint64_t getMaxBlockCount() { return MaxCount; } - uint64_t getMaxInternalBlockCount() { return MaxInternalBlockCount; } + InstrProfSummary *getSummary(); }; -class SampleProfileSummary final : public ProfileSummary { -protected: - std::vector getFormatSpecificMD(LLVMContext &Context) override; +class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder { public: - uint32_t getNumLinesWithSamples() { return NumCounts; } - uint64_t getTotalSamples() { return TotalCount; } - uint64_t getMaxSamplesPerLine() { return MaxCount; } void addRecord(const sampleprof::FunctionSamples &FS); - SampleProfileSummary(std::vector Cutoffs) - : ProfileSummary(PSK_Sample, Cutoffs) {} - SampleProfileSummary(uint64_t TotalSamples, uint64_t MaxSamplesPerLine, - uint64_t MaxFunctionCount, int32_t NumLinesWithSamples, - uint32_t NumFunctions, - SummaryEntryVector DetailedSummary) - : ProfileSummary(PSK_Sample, DetailedSummary, TotalSamples, - MaxSamplesPerLine, MaxFunctionCount, NumLinesWithSamples, - NumFunctions) {} - static bool classof(const ProfileSummary *PS) { - return PS->getKind() == PSK_Sample; - } + SampleProfileSummaryBuilder(std::vector Cutoffs) + : ProfileSummaryBuilder(Cutoffs) {} + SampleProfileSummary *getSummary(); }; // This is called when a count is seen in the profile. -void ProfileSummary::addCount(uint64_t Count) { +void ProfileSummaryBuilder::addCount(uint64_t Count) { TotalCount += Count; if (Count > MaxCount) MaxCount = Count; @@ -175,11 +95,6 @@ CountFrequencies[Count]++; } -SummaryEntryVector &ProfileSummary::getDetailedSummary() { - if (!DetailedSummaryCutoffs.empty() && DetailedSummary.empty()) - computeDetailedSummary(); - return DetailedSummary; -} } // end namespace llvm #endif Index: llvm/trunk/lib/IR/CMakeLists.txt =================================================================== --- llvm/trunk/lib/IR/CMakeLists.txt +++ llvm/trunk/lib/IR/CMakeLists.txt @@ -43,6 +43,7 @@ Pass.cpp PassManager.cpp PassRegistry.cpp + ProfileSummary.cpp Statepoint.cpp Type.cpp TypeFinder.cpp Index: llvm/trunk/lib/IR/ProfileSummary.cpp =================================================================== --- llvm/trunk/lib/IR/ProfileSummary.cpp +++ llvm/trunk/lib/IR/ProfileSummary.cpp @@ -0,0 +1,257 @@ +//=-- Profilesummary.cpp - Profile summary support --------------------------=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for converting profile summary data from/to +// metadata. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/ProfileSummary.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Casting.h" + +using namespace llvm; + +const char *ProfileSummary::KindStr[2] = {"InstrProf", "SampleProfile"}; + +// Return an MDTuple with two elements. The first element is a string Key and +// the second is a uint64_t Value. +static Metadata *getKeyValMD(LLVMContext &Context, const char *Key, + uint64_t Val) { + Type *Int64Ty = Type::getInt64Ty(Context); + Metadata *Ops[2] = {MDString::get(Context, Key), + ConstantAsMetadata::get(ConstantInt::get(Int64Ty, 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, + const char *Val) { + Metadata *Ops[2] = {MDString::get(Context, Key), MDString::get(Context, Val)}; + return MDTuple::get(Context, Ops); +} + +// This returns an MDTuple representing the detiled summary. The tuple has two +// elements: a string "DetailedSummary" and an MDTuple representing the value +// of the detailed summary. Each element of this tuple is again an MDTuple whose +// elements are the (Cutoff, MinCount, NumCounts) triplet of the +// DetailedSummaryEntry. +Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) { + std::vector Entries; + Type *Int32Ty = Type::getInt32Ty(Context); + Type *Int64Ty = Type::getInt64Ty(Context); + for (auto &Entry : DetailedSummary) { + Metadata *EntryMD[3] = { + ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.Cutoff)), + ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Entry.MinCount)), + ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.NumCounts))}; + Entries.push_back(MDTuple::get(Context, EntryMD)); + } + Metadata *Ops[2] = {MDString::get(Context, "DetailedSummary"), + MDTuple::get(Context, Entries)}; + return MDTuple::get(Context, Ops); +} + +// This returns an MDTuple representing this ProfileSummary object. The first +// entry of this tuple is another MDTuple of two elements: a string +// "ProfileFormat" and a string representing the format ("InstrProf" or +// "SampleProfile"). The rest of the elements of the outer MDTuple are specific +// to the kind of profile summary as returned by getFormatSpecificMD. +Metadata *ProfileSummary::getMD(LLVMContext &Context) { + std::vector Components; + Components.push_back(getKeyValMD(Context, "ProfileFormat", getKindStr())); + std::vector Res = getFormatSpecificMD(Context); + Components.insert(Components.end(), Res.begin(), Res.end()); + return MDTuple::get(Context, Components); +} + +// Returns a vector of MDTuples specific to InstrProfSummary. The first six +// elements of this vector are (Key, Val) pairs of the six scalar fields of +// InstrProfSummary (TotalCount, MaxBlockCount, MaxInternalBlockCount, +// MaxFunctionCount, NumBlocks, NumFunctions). The last element of this vector +// is an MDTuple returned by getDetailedSummaryMD. +std::vector +InstrProfSummary::getFormatSpecificMD(LLVMContext &Context) { + std::vector Components; + + Components.push_back(getKeyValMD(Context, "TotalCount", getTotalCount())); + Components.push_back( + getKeyValMD(Context, "MaxBlockCount", getMaxBlockCount())); + Components.push_back(getKeyValMD(Context, "MaxInternalBlockCount", + getMaxInternalBlockCount())); + Components.push_back( + getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount())); + Components.push_back(getKeyValMD(Context, "NumBlocks", getNumBlocks())); + Components.push_back(getKeyValMD(Context, "NumFunctions", getNumFunctions())); + + Components.push_back(getDetailedSummaryMD(Context)); + return Components; +} + +std::vector +SampleProfileSummary::getFormatSpecificMD(LLVMContext &Context) { + std::vector Components; + + Components.push_back(getKeyValMD(Context, "TotalSamples", getTotalSamples())); + Components.push_back( + getKeyValMD(Context, "MaxSamplesPerLine", getMaxSamplesPerLine())); + Components.push_back( + getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount())); + Components.push_back( + getKeyValMD(Context, "NumLinesWithSamples", getNumLinesWithSamples())); + Components.push_back(getKeyValMD(Context, "NumFunctions", NumFunctions)); + + Components.push_back(getDetailedSummaryMD(Context)); + return Components; +} + +// Parse an MDTuple representing (Key, Val) pair. +static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) { + if (!MD) + return false; + if (MD->getNumOperands() != 2) + return false; + MDString *KeyMD = dyn_cast(MD->getOperand(0)); + ConstantAsMetadata *ValMD = dyn_cast(MD->getOperand(1)); + if (!KeyMD || !ValMD) + return false; + if (!KeyMD->getString().equals(Key)) + return false; + Val = cast(ValMD->getValue())->getZExtValue(); + return true; +} + +// Check if an MDTuple represents a (Key, Val) pair. +static bool isKeyValuePair(MDTuple *MD, const char *Key, const char *Val) { + if (!MD || MD->getNumOperands() != 2) + return false; + MDString *KeyMD = dyn_cast(MD->getOperand(0)); + MDString *ValMD = dyn_cast(MD->getOperand(1)); + if (!KeyMD || !ValMD) + return false; + if (!KeyMD->getString().equals(Key) || !ValMD->getString().equals(Val)) + return false; + return true; +} + +// Parse an MDTuple representing detailed summary. +static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) { + if (!MD || MD->getNumOperands() != 2) + return false; + MDString *KeyMD = dyn_cast(MD->getOperand(0)); + if (!KeyMD || !KeyMD->getString().equals("DetailedSummary")) + return false; + MDTuple *EntriesMD = dyn_cast(MD->getOperand(1)); + if (!EntriesMD) + return false; + for (auto &&MDOp : EntriesMD->operands()) { + MDTuple *EntryMD = dyn_cast(MDOp); + if (!EntryMD || EntryMD->getNumOperands() != 3) + return false; + ConstantAsMetadata *Op0 = + dyn_cast(EntryMD->getOperand(0)); + ConstantAsMetadata *Op1 = + dyn_cast(EntryMD->getOperand(1)); + ConstantAsMetadata *Op2 = + dyn_cast(EntryMD->getOperand(2)); + + if (!Op0 || !Op1 || !Op2) + return false; + Summary.emplace_back(cast(Op0->getValue())->getZExtValue(), + cast(Op1->getValue())->getZExtValue(), + cast(Op2->getValue())->getZExtValue()); + } + return true; +} + +// Parse an MDTuple representing an InstrProfSummary object. +static ProfileSummary *getInstrProfSummaryFromMD(MDTuple *Tuple) { + uint64_t NumBlocks, TotalCount, NumFunctions, MaxFunctionCount, MaxBlockCount, + MaxInternalBlockCount; + SummaryEntryVector Summary; + + if (Tuple->getNumOperands() != 8) + return nullptr; + + // Skip operand 0 which has been already parsed in the caller + if (!getVal(dyn_cast(Tuple->getOperand(1)), "TotalCount", + TotalCount)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(2)), "MaxBlockCount", + MaxBlockCount)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(3)), "MaxInternalBlockCount", + MaxInternalBlockCount)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(4)), "MaxFunctionCount", + MaxFunctionCount)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(5)), "NumBlocks", NumBlocks)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(6)), "NumFunctions", + NumFunctions)) + return nullptr; + if (!getSummaryFromMD(dyn_cast(Tuple->getOperand(7)), Summary)) + return nullptr; + return new InstrProfSummary(TotalCount, MaxBlockCount, MaxInternalBlockCount, + MaxFunctionCount, NumBlocks, NumFunctions, + Summary); +} + +// Parse an MDTuple representing a SampleProfileSummary object. +static ProfileSummary *getSampleProfileSummaryFromMD(MDTuple *Tuple) { + uint64_t TotalSamples, MaxSamplesPerLine, MaxFunctionCount, + NumLinesWithSamples, NumFunctions; + SummaryEntryVector Summary; + + if (Tuple->getNumOperands() != 7) + return nullptr; + + // Skip operand 0 which has been already parsed in the caller + if (!getVal(dyn_cast(Tuple->getOperand(1)), "TotalSamples", + TotalSamples)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(2)), "MaxSamplesPerLine", + MaxSamplesPerLine)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(3)), "MaxFunctionCount", + MaxFunctionCount)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(4)), "NumLinesWithSamples", + NumLinesWithSamples)) + return nullptr; + if (!getVal(dyn_cast(Tuple->getOperand(5)), "NumFunctions", + NumFunctions)) + return nullptr; + if (!getSummaryFromMD(dyn_cast(Tuple->getOperand(6)), Summary)) + return nullptr; + return new SampleProfileSummary(TotalSamples, MaxSamplesPerLine, + MaxFunctionCount, NumLinesWithSamples, + NumFunctions, Summary); +} + +ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) { + if (!isa(MD)) + return nullptr; + MDTuple *Tuple = cast(MD); + auto &FormatMD = Tuple->getOperand(0); + if (isKeyValuePair(dyn_cast_or_null(FormatMD), "ProfileFormat", + "SampleProfile")) + return getSampleProfileSummaryFromMD(Tuple); + else if (isKeyValuePair(dyn_cast_or_null(FormatMD), "ProfileFormat", + "InstrProf")) + return getInstrProfSummaryFromMD(Tuple); + else + return nullptr; +} Index: llvm/trunk/lib/ProfileData/CMakeLists.txt =================================================================== --- llvm/trunk/lib/ProfileData/CMakeLists.txt +++ llvm/trunk/lib/ProfileData/CMakeLists.txt @@ -2,7 +2,7 @@ InstrProf.cpp InstrProfReader.cpp InstrProfWriter.cpp - ProfileSummary.cpp + ProfileSummaryBuilder.cpp SampleProf.cpp SampleProfReader.cpp SampleProfWriter.cpp Index: llvm/trunk/lib/ProfileData/InstrProfReader.cpp =================================================================== --- llvm/trunk/lib/ProfileData/InstrProfReader.cpp +++ llvm/trunk/lib/ProfileData/InstrProfReader.cpp @@ -576,6 +576,7 @@ const unsigned char * IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, const unsigned char *Cur) { + using namespace IndexedInstrProf; using namespace support; if (Version >= IndexedInstrProf::Version4) { const IndexedInstrProf::Summary *SummaryInLE = @@ -594,15 +595,28 @@ for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++) Dst[I] = endian::byte_swap(Src[I]); + llvm::SummaryEntryVector DetailedSummary; + for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) { + const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I); + DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount, + Ent.NumBlocks); + } // initialize InstrProfSummary using the SummaryData from disk. - this->Summary = llvm::make_unique(*(SummaryData.get())); + this->Summary = llvm::make_unique( + SummaryData->get(Summary::TotalBlockCount), + SummaryData->get(Summary::MaxBlockCount), + SummaryData->get(Summary::MaxInternalBlockCount), + SummaryData->get(Summary::MaxFunctionCount), + SummaryData->get(Summary::TotalNumBlocks), + SummaryData->get(Summary::TotalNumFunctions), DetailedSummary); return Cur + SummarySize; } else { // For older version of profile data, we need to compute on the fly: using namespace IndexedInstrProf; - this->Summary = - llvm::make_unique(ProfileSummary::DefaultCutoffs); - this->Summary->computeDetailedSummary(); + InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); + // FIXME: This only computes an empty summary. Need to call addRecord for + // all InstrProfRecords to get the correct summary. + this->Summary.reset(Builder.getSummary()); return Cur; } } Index: llvm/trunk/lib/ProfileData/InstrProfWriter.cpp =================================================================== --- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp +++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp @@ -84,7 +84,7 @@ typedef uint64_t offset_type; support::endianness ValueProfDataEndianness; - InstrProfSummary *TheProfileSummary; + InstrProfSummaryBuilder *SummaryBuilder; InstrProfRecordWriterTrait() : ValueProfDataEndianness(support::little) {} static hash_value_type ComputeHash(key_type_ref K) { @@ -123,7 +123,7 @@ endian::Writer LE(Out); for (const auto &ProfileData : *V) { const InstrProfRecord &ProfRecord = ProfileData.second; - TheProfileSummary->addRecord(ProfRecord); + SummaryBuilder->addRecord(ProfRecord); LE.write(ProfileData.first); // Function hash LE.write(ProfRecord.Counts.size()); @@ -215,8 +215,8 @@ OnDiskChainedHashTableGenerator Generator; using namespace IndexedInstrProf; - InstrProfSummary PS(ProfileSummary::DefaultCutoffs); - InfoObj->TheProfileSummary = &PS; + InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs); + InfoObj->SummaryBuilder = &ISB; // Populate the hash table generator. for (const auto &I : FunctionData) @@ -245,7 +245,7 @@ OS.write(0); // Reserve space to write profile summary data. - uint32_t NumEntries = ProfileSummary::DefaultCutoffs.size(); + uint32_t NumEntries = ProfileSummaryBuilder::DefaultCutoffs.size(); uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries); // Remember the summary offset. uint64_t SummaryOffset = OS.tell(); @@ -260,8 +260,9 @@ IndexedInstrProf::allocSummary(SummarySize); // Compute the Summary and copy the data to the data // structure to be serialized out (to disk or buffer). - setSummary(TheSummary.get(), PS); - InfoObj->TheProfileSummary = 0; + InstrProfSummary *IPS = ISB.getSummary(); + setSummary(TheSummary.get(), *IPS); + InfoObj->SummaryBuilder = 0; // Now do the final patch: PatchItem PatchItems[] = { Index: llvm/trunk/lib/ProfileData/ProfileSummary.cpp =================================================================== --- llvm/trunk/lib/ProfileData/ProfileSummary.cpp +++ llvm/trunk/lib/ProfileData/ProfileSummary.cpp @@ -1,368 +0,0 @@ -//=-- Profilesummary.cpp - Profile summary computation ----------------------=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains support for computing profile summary data. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/Attributes.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Metadata.h" -#include "llvm/IR/Type.h" -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/ProfileData/ProfileCommon.h" -#include "llvm/ProfileData/SampleProf.h" -#include "llvm/Support/Casting.h" - -using namespace llvm; - -// A set of cutoff values. Each value, when divided by ProfileSummary::Scale -// (which is 1000000) is a desired percentile of total counts. -const std::vector ProfileSummary::DefaultCutoffs( - {10000, /* 1% */ - 100000, /* 10% */ - 200000, 300000, 400000, 500000, 600000, 500000, 600000, 700000, 800000, - 900000, 950000, 990000, 999000, 999900, 999990, 999999}); -const char *ProfileSummary::KindStr[2] = {"InstrProf", "SampleProfile"}; - -void InstrProfSummary::addRecord(const InstrProfRecord &R) { - // The first counter is not necessarily an entry count for IR - // instrumentation profiles. - // Eventually MaxFunctionCount will become obsolete and this can be - // removed. - addEntryCount(R.Counts[0]); - for (size_t I = 1, E = R.Counts.size(); I < E; ++I) - addInternalCount(R.Counts[I]); -} - -// To compute the detailed summary, we consider each line containing samples as -// equivalent to a block with a count in the instrumented profile. -void SampleProfileSummary::addRecord(const sampleprof::FunctionSamples &FS) { - NumFunctions++; - if (FS.getHeadSamples() > MaxFunctionCount) - MaxFunctionCount = FS.getHeadSamples(); - for (const auto &I : FS.getBodySamples()) - addCount(I.second.getSamples()); -} - -// The argument to this method is a vector of cutoff percentages and the return -// value is a vector of (Cutoff, MinCount, NumCounts) triplets. -void ProfileSummary::computeDetailedSummary() { - if (DetailedSummaryCutoffs.empty()) - return; - auto Iter = CountFrequencies.begin(); - auto End = CountFrequencies.end(); - std::sort(DetailedSummaryCutoffs.begin(), DetailedSummaryCutoffs.end()); - - uint32_t CountsSeen = 0; - uint64_t CurrSum = 0, Count = 0; - - for (uint32_t Cutoff : DetailedSummaryCutoffs) { - assert(Cutoff <= 999999); - APInt Temp(128, TotalCount); - APInt N(128, Cutoff); - APInt D(128, ProfileSummary::Scale); - Temp *= N; - Temp = Temp.sdiv(D); - uint64_t DesiredCount = Temp.getZExtValue(); - assert(DesiredCount <= TotalCount); - while (CurrSum < DesiredCount && Iter != End) { - Count = Iter->first; - uint32_t Freq = Iter->second; - CurrSum += (Count * Freq); - CountsSeen += Freq; - Iter++; - } - assert(CurrSum >= DesiredCount); - ProfileSummaryEntry PSE = {Cutoff, Count, CountsSeen}; - DetailedSummary.push_back(PSE); - } -} - -// Returns true if the function is a hot function. -bool ProfileSummary::isFunctionHot(const Function *F) { - // FIXME: update when summary data is stored in module's metadata. - return false; -} - -// Returns true if the function is a cold function. -bool ProfileSummary::isFunctionUnlikely(const Function *F) { - if (F->hasFnAttribute(Attribute::Cold)) { - return true; - } - if (!F->getEntryCount()) { - return false; - } - // FIXME: update when summary data is stored in module's metadata. - return (*F->getEntryCount()) == 0; -} - -InstrProfSummary::InstrProfSummary(const IndexedInstrProf::Summary &S) - : ProfileSummary(PSK_Instr), - MaxInternalBlockCount( - S.get(IndexedInstrProf::Summary::MaxInternalBlockCount)) { - - TotalCount = S.get(IndexedInstrProf::Summary::TotalBlockCount); - MaxCount = S.get(IndexedInstrProf::Summary::MaxBlockCount); - MaxFunctionCount = S.get(IndexedInstrProf::Summary::MaxFunctionCount); - NumCounts = S.get(IndexedInstrProf::Summary::TotalNumBlocks); - NumFunctions = S.get(IndexedInstrProf::Summary::TotalNumFunctions); - - for (unsigned I = 0; I < S.NumCutoffEntries; I++) { - const IndexedInstrProf::Summary::Entry &Ent = S.getEntry(I); - DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount, - Ent.NumBlocks); - } -} - -void InstrProfSummary::addEntryCount(uint64_t Count) { - addCount(Count); - NumFunctions++; - if (Count > MaxFunctionCount) - MaxFunctionCount = Count; -} - -void InstrProfSummary::addInternalCount(uint64_t Count) { - addCount(Count); - if (Count > MaxInternalBlockCount) - MaxInternalBlockCount = Count; -} - -// Return an MDTuple with two elements. The first element is a string Key and -// the second is a uint64_t Value. -static Metadata *getKeyValMD(LLVMContext &Context, const char *Key, - uint64_t Val) { - Type *Int64Ty = Type::getInt64Ty(Context); - Metadata *Ops[2] = {MDString::get(Context, Key), - ConstantAsMetadata::get(ConstantInt::get(Int64Ty, 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, - const char *Val) { - Metadata *Ops[2] = {MDString::get(Context, Key), MDString::get(Context, Val)}; - return MDTuple::get(Context, Ops); -} - -// This returns an MDTuple representing the detiled summary. The tuple has two -// elements: a string "DetailedSummary" and an MDTuple representing the value -// of the detailed summary. Each element of this tuple is again an MDTuple whose -// elements are the (Cutoff, MinCount, NumCounts) triplet of the -// DetailedSummaryEntry. -Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) { - std::vector Entries; - Type *Int32Ty = Type::getInt32Ty(Context); - Type *Int64Ty = Type::getInt64Ty(Context); - for (auto &Entry : DetailedSummary) { - Metadata *EntryMD[3] = { - ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.Cutoff)), - ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Entry.MinCount)), - ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.NumCounts))}; - Entries.push_back(MDTuple::get(Context, EntryMD)); - } - Metadata *Ops[2] = {MDString::get(Context, "DetailedSummary"), - MDTuple::get(Context, Entries)}; - return MDTuple::get(Context, Ops); -} - -// This returns an MDTuple representing this ProfileSummary object. The first -// entry of this tuple is another MDTuple of two elements: a string -// "ProfileFormat" and a string representing the format ("InstrProf" or -// "SampleProfile"). The rest of the elements of the outer MDTuple are specific -// to the kind of profile summary as returned by getFormatSpecificMD. -Metadata *ProfileSummary::getMD(LLVMContext &Context) { - std::vector Components; - Components.push_back(getKeyValMD(Context, "ProfileFormat", getKindStr())); - std::vector Res = getFormatSpecificMD(Context); - Components.insert(Components.end(), Res.begin(), Res.end()); - return MDTuple::get(Context, Components); -} - -// Returns a vector of MDTuples specific to InstrProfSummary. The first six -// elements of this vector are (Key, Val) pairs of the six scalar fields of -// InstrProfSummary (TotalCount, MaxBlockCount, MaxInternalBlockCount, -// MaxFunctionCount, NumBlocks, NumFunctions). The last element of this vector -// is an MDTuple returned by getDetailedSummaryMD. -std::vector -InstrProfSummary::getFormatSpecificMD(LLVMContext &Context) { - std::vector Components; - - Components.push_back(getKeyValMD(Context, "TotalCount", getTotalCount())); - Components.push_back( - getKeyValMD(Context, "MaxBlockCount", getMaxBlockCount())); - Components.push_back(getKeyValMD(Context, "MaxInternalBlockCount", - getMaxInternalBlockCount())); - Components.push_back( - getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount())); - Components.push_back(getKeyValMD(Context, "NumBlocks", getNumBlocks())); - Components.push_back(getKeyValMD(Context, "NumFunctions", getNumFunctions())); - - Components.push_back(getDetailedSummaryMD(Context)); - return Components; -} - -std::vector -SampleProfileSummary::getFormatSpecificMD(LLVMContext &Context) { - std::vector Components; - - Components.push_back(getKeyValMD(Context, "TotalSamples", getTotalSamples())); - Components.push_back( - getKeyValMD(Context, "MaxSamplesPerLine", getMaxSamplesPerLine())); - Components.push_back( - getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount())); - Components.push_back( - getKeyValMD(Context, "NumLinesWithSamples", getNumLinesWithSamples())); - Components.push_back(getKeyValMD(Context, "NumFunctions", NumFunctions)); - - Components.push_back(getDetailedSummaryMD(Context)); - return Components; -} - -// Parse an MDTuple representing (Key, Val) pair. -static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) { - if (!MD) - return false; - if (MD->getNumOperands() != 2) - return false; - MDString *KeyMD = dyn_cast(MD->getOperand(0)); - ConstantAsMetadata *ValMD = dyn_cast(MD->getOperand(1)); - if (!KeyMD || !ValMD) - return false; - if (!KeyMD->getString().equals(Key)) - return false; - Val = cast(ValMD->getValue())->getZExtValue(); - return true; -} - -// Check if an MDTuple represents a (Key, Val) pair. -static bool isKeyValuePair(MDTuple *MD, const char *Key, const char *Val) { - if (!MD || MD->getNumOperands() != 2) - return false; - MDString *KeyMD = dyn_cast(MD->getOperand(0)); - MDString *ValMD = dyn_cast(MD->getOperand(1)); - if (!KeyMD || !ValMD) - return false; - if (!KeyMD->getString().equals(Key) || !ValMD->getString().equals(Val)) - return false; - return true; -} - -// Parse an MDTuple representing detailed summary. -static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) { - if (!MD || MD->getNumOperands() != 2) - return false; - MDString *KeyMD = dyn_cast(MD->getOperand(0)); - if (!KeyMD || !KeyMD->getString().equals("DetailedSummary")) - return false; - MDTuple *EntriesMD = dyn_cast(MD->getOperand(1)); - if (!EntriesMD) - return false; - for (auto &&MDOp : EntriesMD->operands()) { - MDTuple *EntryMD = dyn_cast(MDOp); - if (!EntryMD || EntryMD->getNumOperands() != 3) - return false; - ConstantAsMetadata *Op0 = - dyn_cast(EntryMD->getOperand(0)); - ConstantAsMetadata *Op1 = - dyn_cast(EntryMD->getOperand(1)); - ConstantAsMetadata *Op2 = - dyn_cast(EntryMD->getOperand(2)); - - if (!Op0 || !Op1 || !Op2) - return false; - Summary.emplace_back(cast(Op0->getValue())->getZExtValue(), - cast(Op1->getValue())->getZExtValue(), - cast(Op2->getValue())->getZExtValue()); - } - return true; -} - -// Parse an MDTuple representing an InstrProfSummary object. -static ProfileSummary *getInstrProfSummaryFromMD(MDTuple *Tuple) { - uint64_t NumBlocks, TotalCount, NumFunctions, MaxFunctionCount, MaxBlockCount, - MaxInternalBlockCount; - SummaryEntryVector Summary; - - if (Tuple->getNumOperands() != 8) - return nullptr; - - // Skip operand 0 which has been already parsed in the caller - if (!getVal(dyn_cast(Tuple->getOperand(1)), "TotalCount", - TotalCount)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(2)), "MaxBlockCount", - MaxBlockCount)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(3)), "MaxInternalBlockCount", - MaxInternalBlockCount)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(4)), "MaxFunctionCount", - MaxFunctionCount)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(5)), "NumBlocks", NumBlocks)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(6)), "NumFunctions", - NumFunctions)) - return nullptr; - if (!getSummaryFromMD(dyn_cast(Tuple->getOperand(7)), Summary)) - return nullptr; - return new InstrProfSummary(TotalCount, MaxBlockCount, MaxInternalBlockCount, - MaxFunctionCount, NumBlocks, NumFunctions, - Summary); -} - -// Parse an MDTuple representing a SampleProfileSummary object. -static ProfileSummary *getSampleProfileSummaryFromMD(MDTuple *Tuple) { - uint64_t TotalSamples, MaxSamplesPerLine, MaxFunctionCount, - NumLinesWithSamples, NumFunctions; - SummaryEntryVector Summary; - - if (Tuple->getNumOperands() != 7) - return nullptr; - - // Skip operand 0 which has been already parsed in the caller - if (!getVal(dyn_cast(Tuple->getOperand(1)), "TotalSamples", - TotalSamples)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(2)), "MaxSamplesPerLine", - MaxSamplesPerLine)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(3)), "MaxFunctionCount", - MaxFunctionCount)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(4)), "NumLinesWithSamples", - NumLinesWithSamples)) - return nullptr; - if (!getVal(dyn_cast(Tuple->getOperand(5)), "NumFunctions", - NumFunctions)) - return nullptr; - if (!getSummaryFromMD(dyn_cast(Tuple->getOperand(6)), Summary)) - return nullptr; - return new SampleProfileSummary(TotalSamples, MaxSamplesPerLine, - MaxFunctionCount, NumLinesWithSamples, - NumFunctions, Summary); -} - -ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) { - if (!isa(MD)) - return nullptr; - MDTuple *Tuple = cast(MD); - auto &FormatMD = Tuple->getOperand(0); - if (isKeyValuePair(dyn_cast_or_null(FormatMD), "ProfileFormat", - "SampleProfile")) - return getSampleProfileSummaryFromMD(Tuple); - else if (isKeyValuePair(dyn_cast_or_null(FormatMD), "ProfileFormat", - "InstrProf")) - return getInstrProfSummaryFromMD(Tuple); - else - return nullptr; -} Index: llvm/trunk/lib/ProfileData/ProfileSummaryBuilder.cpp =================================================================== --- llvm/trunk/lib/ProfileData/ProfileSummaryBuilder.cpp +++ llvm/trunk/lib/ProfileData/ProfileSummaryBuilder.cpp @@ -0,0 +1,113 @@ +//=-- ProfilesummaryBuilder.cpp - Profile summary computation ---------------=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for computing profile summary data. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/Attributes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Type.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/ProfileData/SampleProf.h" +#include "llvm/Support/Casting.h" + +using namespace llvm; + +// A set of cutoff values. Each value, when divided by ProfileSummary::Scale +// (which is 1000000) is a desired percentile of total counts. +const std::vector ProfileSummaryBuilder::DefaultCutoffs( + {10000, /* 1% */ + 100000, /* 10% */ + 200000, 300000, 400000, 500000, 600000, 500000, 600000, 700000, 800000, + 900000, 950000, 990000, 999000, 999900, 999990, 999999}); + +void InstrProfSummaryBuilder::addRecord(const InstrProfRecord &R) { + // The first counter is not necessarily an entry count for IR + // instrumentation profiles. + // Eventually MaxFunctionCount will become obsolete and this can be + // removed. + addEntryCount(R.Counts[0]); + for (size_t I = 1, E = R.Counts.size(); I < E; ++I) + addInternalCount(R.Counts[I]); +} + +// To compute the detailed summary, we consider each line containing samples as +// equivalent to a block with a count in the instrumented profile. +void SampleProfileSummaryBuilder::addRecord( + const sampleprof::FunctionSamples &FS) { + NumFunctions++; + if (FS.getHeadSamples() > MaxFunctionCount) + MaxFunctionCount = FS.getHeadSamples(); + for (const auto &I : FS.getBodySamples()) + addCount(I.second.getSamples()); +} + +// The argument to this method is a vector of cutoff percentages and the return +// value is a vector of (Cutoff, MinCount, NumCounts) triplets. +void ProfileSummaryBuilder::computeDetailedSummary() { + if (DetailedSummaryCutoffs.empty()) + return; + auto Iter = CountFrequencies.begin(); + auto End = CountFrequencies.end(); + std::sort(DetailedSummaryCutoffs.begin(), DetailedSummaryCutoffs.end()); + + uint32_t CountsSeen = 0; + uint64_t CurrSum = 0, Count = 0; + + for (uint32_t Cutoff : DetailedSummaryCutoffs) { + assert(Cutoff <= 999999); + APInt Temp(128, TotalCount); + APInt N(128, Cutoff); + APInt D(128, ProfileSummary::Scale); + Temp *= N; + Temp = Temp.sdiv(D); + uint64_t DesiredCount = Temp.getZExtValue(); + assert(DesiredCount <= TotalCount); + while (CurrSum < DesiredCount && Iter != End) { + Count = Iter->first; + uint32_t Freq = Iter->second; + CurrSum += (Count * Freq); + CountsSeen += Freq; + Iter++; + } + assert(CurrSum >= DesiredCount); + ProfileSummaryEntry PSE = {Cutoff, Count, CountsSeen}; + DetailedSummary.push_back(PSE); + } +} + +SampleProfileSummary *SampleProfileSummaryBuilder::getSummary() { + computeDetailedSummary(); + return new SampleProfileSummary(TotalCount, MaxCount, MaxFunctionCount, + NumCounts, NumFunctions, DetailedSummary); +} + +InstrProfSummary *InstrProfSummaryBuilder::getSummary() { + computeDetailedSummary(); + return new InstrProfSummary(TotalCount, MaxCount, MaxInternalBlockCount, + MaxFunctionCount, NumCounts, NumFunctions, + DetailedSummary); +} + +void InstrProfSummaryBuilder::addEntryCount(uint64_t Count) { + addCount(Count); + NumFunctions++; + if (Count > MaxFunctionCount) + MaxFunctionCount = Count; +} + +void InstrProfSummaryBuilder::addInternalCount(uint64_t Count) { + addCount(Count); + if (Count > MaxInternalBlockCount) + MaxInternalBlockCount = Count; +} Index: llvm/trunk/lib/ProfileData/SampleProfReader.cpp =================================================================== --- llvm/trunk/lib/ProfileData/SampleProfReader.cpp +++ llvm/trunk/lib/ProfileData/SampleProfReader.cpp @@ -793,10 +793,10 @@ // For text and GCC file formats, we compute the summary after reading the // profile. Binary format has the profile summary in its header. void SampleProfileReader::computeSummary() { - Summary.reset(new SampleProfileSummary(ProfileSummary::DefaultCutoffs)); + SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); for (const auto &I : Profiles) { const FunctionSamples &Profile = I.second; - Summary->addRecord(Profile); + Builder.addRecord(Profile); } - Summary->computeDetailedSummary(); + Summary.reset(Builder.getSummary()); } Index: llvm/trunk/lib/ProfileData/SampleProfWriter.cpp =================================================================== --- llvm/trunk/lib/ProfileData/SampleProfWriter.cpp +++ llvm/trunk/lib/ProfileData/SampleProfWriter.cpp @@ -255,10 +255,10 @@ void SampleProfileWriter::computeSummary( const StringMap &ProfileMap) { - Summary.reset(new SampleProfileSummary(ProfileSummary::DefaultCutoffs)); + SampleProfileSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); for (const auto &I : ProfileMap) { const FunctionSamples &Profile = I.second; - Summary->addRecord(Profile); + Builder.addRecord(Profile); } - Summary->computeDetailedSummary(); + Summary.reset(Builder.getSummary()); } Index: llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp =================================================================== --- llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp +++ llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp @@ -281,7 +281,7 @@ if (ShowDetailedSummary && DetailedSummaryCutoffs.empty()) { Cutoffs = {800000, 900000, 950000, 990000, 999000, 999900, 999990}; } - InstrProfSummary PS(Cutoffs); + InstrProfSummaryBuilder Builder(Cutoffs); if (Error E = ReaderOrErr.takeError()) exitWithError(std::move(E), Filename); @@ -302,7 +302,7 @@ } assert(Func.Counts.size() > 0 && "function missing entry counter"); - PS.addRecord(Func); + Builder.addRecord(Func); if (Show) { @@ -353,18 +353,19 @@ if (ShowCounts && TextFormat) return 0; - + std::unique_ptr PS(Builder.getSummary()); if (ShowAllFunctions || !ShowFunction.empty()) OS << "Functions shown: " << ShownFunctions << "\n"; - OS << "Total functions: " << PS.getNumFunctions() << "\n"; - OS << "Maximum function count: " << PS.getMaxFunctionCount() << "\n"; - OS << "Maximum internal block count: " << PS.getMaxInternalBlockCount() << "\n"; + OS << "Total functions: " << PS->getNumFunctions() << "\n"; + OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n"; + OS << "Maximum internal block count: " << PS->getMaxInternalBlockCount() + << "\n"; if (ShowDetailedSummary) { OS << "Detailed summary:\n"; - OS << "Total number of blocks: " << PS.getNumBlocks() << "\n"; - OS << "Total count: " << PS.getTotalCount() << "\n"; - for (auto Entry : PS.getDetailedSummary()) { + OS << "Total number of blocks: " << PS->getNumBlocks() << "\n"; + OS << "Total count: " << PS->getTotalCount() << "\n"; + for (auto Entry : PS->getDetailedSummary()) { OS << Entry.NumCounts << " blocks with count >= " << Entry.MinCount << " account for " << format("%0.6g", (float)Entry.Cutoff / ProfileSummary::Scale * 100)