mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
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:
parent
dc5a37bcd2
commit
5807e047c7
129
include/llvm/IR/ProfileSummary.h
Normal file
129
include/llvm/IR/ProfileSummary.h
Normal 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
|
@ -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
|
||||
|
@ -43,6 +43,7 @@ add_llvm_library(LLVMCore
|
||||
Pass.cpp
|
||||
PassManager.cpp
|
||||
PassRegistry.cpp
|
||||
ProfileSummary.cpp
|
||||
Statepoint.cpp
|
||||
Type.cpp
|
||||
TypeFinder.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,
|
@ -2,7 +2,7 @@ add_llvm_library(LLVMProfileData
|
||||
InstrProf.cpp
|
||||
InstrProfReader.cpp
|
||||
InstrProfWriter.cpp
|
||||
ProfileSummary.cpp
|
||||
ProfileSummaryBuilder.cpp
|
||||
SampleProf.cpp
|
||||
SampleProfReader.cpp
|
||||
SampleProfWriter.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;
|
||||
}
|
||||
}
|
||||
|
@ -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[] = {
|
||||
|
113
lib/ProfileData/ProfileSummaryBuilder.cpp
Normal file
113
lib/ProfileData/ProfileSummaryBuilder.cpp
Normal 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;
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user