summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorEaswaran Raman <eraman@google.com>2016-05-19 21:07:12 +0000
committerEaswaran Raman <eraman@google.com>2016-05-19 21:07:12 +0000
commite5a17e3f1d1d620d0793f36f54654951a4440f99 (patch)
tree29453f82d5ec2e7a668a9bbceb7d8bc300ce0e73 /llvm
parentb1d37199ccfad5654d587cb9a81bcfde613315b4 (diff)
downloadbcm5719-llvm-e5a17e3f1d1d620d0793f36f54654951a4440f99.tar.gz
bcm5719-llvm-e5a17e3f1d1d620d0793f36f54654951a4440f99.zip
Move ProfileSummary to IR.
This splits ProfileSummary into two classes: a ProfileSummary class that has methods to convert from/to metadata and a ProfileSummaryBuilder class that computes the profiles summary which is in ProfileData. Differential Revision: http://reviews.llvm.org/D20314 llvm-svn: 270136
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/IR/ProfileSummary.h129
-rw-r--r--llvm/include/llvm/ProfileData/ProfileCommon.h123
-rw-r--r--llvm/lib/IR/CMakeLists.txt1
-rw-r--r--llvm/lib/IR/ProfileSummary.cpp (renamed from llvm/lib/ProfileData/ProfileSummary.cpp)119
-rw-r--r--llvm/lib/ProfileData/CMakeLists.txt2
-rw-r--r--llvm/lib/ProfileData/InstrProfReader.cpp22
-rw-r--r--llvm/lib/ProfileData/InstrProfWriter.cpp15
-rw-r--r--llvm/lib/ProfileData/ProfileSummaryBuilder.cpp113
-rw-r--r--llvm/lib/ProfileData/SampleProfReader.cpp6
-rw-r--r--llvm/lib/ProfileData/SampleProfWriter.cpp6
-rw-r--r--llvm/tools/llvm-profdata/llvm-profdata.cpp19
11 files changed, 309 insertions, 246 deletions
diff --git a/llvm/include/llvm/IR/ProfileSummary.h b/llvm/include/llvm/IR/ProfileSummary.h
new file mode 100644
index 00000000000..5da87f3b5fe
--- /dev/null
+++ b/llvm/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 <cstdint>
+#include <vector>
+
+#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<ProfileSummaryEntry> 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<Metadata *> 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<Metadata *> 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<Metadata *> 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
diff --git a/llvm/include/llvm/ProfileData/ProfileCommon.h b/llvm/include/llvm/ProfileData/ProfileCommon.h
index 2702d6fc6ae..79eee91c3d7 100644
--- a/llvm/include/llvm/ProfileData/ProfileCommon.h
+++ b/llvm/include/llvm/ProfileData/ProfileCommon.h
@@ -20,7 +20,7 @@
#include <map>
#include <vector>
-#include "llvm/Support/Casting.h"
+#include "llvm/IR/ProfileSummary.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -40,134 +40,54 @@ class MDNode;
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<ProfileSummaryEntry> 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<uint64_t, uint32_t, std::greater<uint64_t>> CountFrequencies;
+ std::vector<uint32_t> DetailedSummaryCutoffs;
+
protected:
SummaryEntryVector DetailedSummary;
- std::vector<uint32_t> DetailedSummaryCutoffs;
- uint64_t TotalCount, MaxCount, MaxFunctionCount;
- uint32_t NumCounts, NumFunctions;
- ProfileSummary(Kind K, std::vector<uint32_t> Cutoffs)
- : PSK(K), DetailedSummaryCutoffs(Cutoffs), TotalCount(0), MaxCount(0),
+ ProfileSummaryBuilder(std::vector<uint32_t> 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<Metadata *> 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<uint32_t> 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<Metadata *> getFormatSpecificMD(LLVMContext &Context) override;
-
public:
- InstrProfSummary(std::vector<uint32_t> 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<uint32_t> 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<Metadata *> 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<uint32_t> 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<uint32_t> 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 @@ void ProfileSummary::addCount(uint64_t Count) {
CountFrequencies[Count]++;
}
-SummaryEntryVector &ProfileSummary::getDetailedSummary() {
- if (!DetailedSummaryCutoffs.empty() && DetailedSummary.empty())
- computeDetailedSummary();
- return DetailedSummary;
-}
} // end namespace llvm
#endif
diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt
index f3f87338ca4..07cec97084e 100644
--- a/llvm/lib/IR/CMakeLists.txt
+++ b/llvm/lib/IR/CMakeLists.txt
@@ -43,6 +43,7 @@ add_llvm_library(LLVMCore
Pass.cpp
PassManager.cpp
PassRegistry.cpp
+ ProfileSummary.cpp
Statepoint.cpp
Type.cpp
TypeFinder.cpp
diff --git a/llvm/lib/ProfileData/ProfileSummary.cpp b/llvm/lib/IR/ProfileSummary.cpp
index dfe44e32bbe..51bcd1845c7 100644
--- a/llvm/lib/ProfileData/ProfileSummary.cpp
+++ b/llvm/lib/IR/ProfileSummary.cpp
@@ -1,4 +1,4 @@
-//=-- Profilesummary.cpp - Profile summary computation ----------------------=//
+//=-- Profilesummary.cpp - Profile summary support --------------------------=//
//
// The LLVM Compiler Infrastructure
//
@@ -7,134 +7,23 @@
//
//===----------------------------------------------------------------------===//
//
-// This file contains support for computing profile summary data.
+// 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/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<uint32_t> 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,
diff --git a/llvm/lib/ProfileData/CMakeLists.txt b/llvm/lib/ProfileData/CMakeLists.txt
index e68717c8188..cd65762ae6a 100644
--- a/llvm/lib/ProfileData/CMakeLists.txt
+++ b/llvm/lib/ProfileData/CMakeLists.txt
@@ -2,7 +2,7 @@ add_llvm_library(LLVMProfileData
InstrProf.cpp
InstrProfReader.cpp
InstrProfWriter.cpp
- ProfileSummary.cpp
+ ProfileSummaryBuilder.cpp
SampleProf.cpp
SampleProfReader.cpp
SampleProfWriter.cpp
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 2678ac28561..33535fd8eb6 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -576,6 +576,7 @@ bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
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 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
Dst[I] = endian::byte_swap<uint64_t, little>(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<InstrProfSummary>(*(SummaryData.get()));
+ this->Summary = llvm::make_unique<InstrProfSummary>(
+ 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<InstrProfSummary>(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;
}
}
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 9b01dac313b..1036a10ed8a 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -84,7 +84,7 @@ public:
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 @@ public:
endian::Writer<little> LE(Out);
for (const auto &ProfileData : *V) {
const InstrProfRecord &ProfRecord = ProfileData.second;
- TheProfileSummary->addRecord(ProfRecord);
+ SummaryBuilder->addRecord(ProfRecord);
LE.write<uint64_t>(ProfileData.first); // Function hash
LE.write<uint64_t>(ProfRecord.Counts.size());
@@ -215,8 +215,8 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> 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 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
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 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
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[] = {
diff --git a/llvm/lib/ProfileData/ProfileSummaryBuilder.cpp b/llvm/lib/ProfileData/ProfileSummaryBuilder.cpp
new file mode 100644
index 00000000000..3d32722ab63
--- /dev/null
+++ b/llvm/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<uint32_t> 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;
+}
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index 63f828697d6..14023bbd509 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -793,10 +793,10 @@ SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C) {
// 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());
}
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index 2f6490224c5..56e836c69cd 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -255,10 +255,10 @@ SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
void SampleProfileWriter::computeSummary(
const StringMap<FunctionSamples> &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());
}
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index d45e6afa5a5..1b042be8a3f 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -281,7 +281,7 @@ static int showInstrProfile(std::string Filename, bool ShowCounts,
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 @@ static int showInstrProfile(std::string Filename, bool ShowCounts,
}
assert(Func.Counts.size() > 0 && "function missing entry counter");
- PS.addRecord(Func);
+ Builder.addRecord(Func);
if (Show) {
@@ -353,18 +353,19 @@ static int showInstrProfile(std::string Filename, bool ShowCounts,
if (ShowCounts && TextFormat)
return 0;
-
+ std::unique_ptr<InstrProfSummary> 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)
OpenPOWER on IntegriCloud