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
This commit is contained in:
Easwaran Raman 2016-05-19 21:07:12 +00:00
parent dc5a37bcd2
commit 5807e047c7
11 changed files with 309 additions and 246 deletions

View File

@ -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

View File

@ -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;
ProfileSummaryBuilder(std::vector<uint32_t> Cutoffs)
: DetailedSummaryCutoffs(Cutoffs), TotalCount(0), MaxCount(0),
MaxFunctionCount(0), NumCounts(0), NumFunctions(0) {}
inline void addCount(uint64_t Count);
~ProfileSummaryBuilder() = default;
void computeDetailedSummary();
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),
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);
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

View File

@ -43,6 +43,7 @@ add_llvm_library(LLVMCore
Pass.cpp
PassManager.cpp
PassRegistry.cpp
ProfileSummary.cpp
Statepoint.cpp
Type.cpp
TypeFinder.cpp

View File

@ -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,

View File

@ -2,7 +2,7 @@ add_llvm_library(LLVMProfileData
InstrProf.cpp
InstrProfReader.cpp
InstrProfWriter.cpp
ProfileSummary.cpp
ProfileSummaryBuilder.cpp
SampleProf.cpp
SampleProfReader.cpp
SampleProfWriter.cpp

View File

@ -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;
}
}

View File

@ -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[] = {

View File

@ -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;
}

View File

@ -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());
}

View File

@ -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());
}

View File

@ -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)