[PGO] Context sensitive PGO (part 2)
Part 2 of CSPGO changes (mostly related to ProfileSummary). Note that I use a default parameter in setProfileSummary() and getSummary(). This is to break the dependency in clang. I will make the parameter explicit after changing clang in a separated patch. Differential Revision: https://reviews.llvm.org/D54175 llvm-svn: 355131
This commit is contained in:
parent
7fc6ef7dd7
commit
a6ff69f6dd
|
@ -226,6 +226,10 @@ OPTIONS
|
|||
Only output names of functions whose max count value are below the cutoff
|
||||
value.
|
||||
|
||||
.. option:: -showcs
|
||||
Only show context sensitive profile counts. The default is to filter all
|
||||
context sensitive profile counts.
|
||||
|
||||
EXIT STATUS
|
||||
-----------
|
||||
|
||||
|
|
|
@ -73,6 +73,12 @@ public:
|
|||
Summary->getKind() == ProfileSummary::PSK_Instr;
|
||||
}
|
||||
|
||||
/// Returns true if module \c M has context sensitive instrumentation profile.
|
||||
bool hasCSInstrumentationProfile() {
|
||||
return hasProfileSummary() &&
|
||||
Summary->getKind() == ProfileSummary::PSK_CSInstr;
|
||||
}
|
||||
|
||||
/// Handle the invalidation of this information.
|
||||
///
|
||||
/// When used as a result of \c ProfileSummaryAnalysis this method will be
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "llvm/IR/GlobalIFunc.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/ProfileSummary.h"
|
||||
#include "llvm/IR/SymbolTableListTraits.h"
|
||||
#include "llvm/Support/CBindingWrapping.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
|
@ -868,10 +869,13 @@ public:
|
|||
/// @{
|
||||
|
||||
/// Attach profile summary metadata to this module.
|
||||
void setProfileSummary(Metadata *M);
|
||||
// TODO: Remove the default paramter.
|
||||
void setProfileSummary(Metadata *M,
|
||||
ProfileSummary::Kind Kind = ProfileSummary::PSK_Instr);
|
||||
|
||||
/// Returns profile summary metadata
|
||||
Metadata *getProfileSummary();
|
||||
/// Returns profile summary metadata. When IsCS is true, use the context
|
||||
/// sensitive profile summary.
|
||||
Metadata *getProfileSummary(bool IsCS);
|
||||
/// @}
|
||||
|
||||
/// Returns true if PLT should be avoided for RTLib calls.
|
||||
|
|
|
@ -42,11 +42,10 @@ using SummaryEntryVector = std::vector<ProfileSummaryEntry>;
|
|||
|
||||
class ProfileSummary {
|
||||
public:
|
||||
enum Kind { PSK_Instr, PSK_Sample };
|
||||
enum Kind { PSK_Instr, PSK_CSInstr, PSK_Sample };
|
||||
|
||||
private:
|
||||
const Kind PSK;
|
||||
static const char *KindStr[2];
|
||||
SummaryEntryVector DetailedSummary;
|
||||
uint64_t TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount;
|
||||
uint32_t NumCounts, NumFunctions;
|
||||
|
|
|
@ -77,6 +77,8 @@ public:
|
|||
|
||||
virtual bool isIRLevelProfile() const = 0;
|
||||
|
||||
virtual bool hasCSIRLevelProfile() const = 0;
|
||||
|
||||
/// Return the PGO symtab. There are three different readers:
|
||||
/// Raw, Text, and Indexed profile readers. The first two types
|
||||
/// of readers are used only by llvm-profdata tool, while the indexed
|
||||
|
@ -142,6 +144,7 @@ private:
|
|||
/// Iterator over the profile data.
|
||||
line_iterator Line;
|
||||
bool IsIRLevelProfile = false;
|
||||
bool HasCSIRLevelProfile = false;
|
||||
|
||||
Error readValueProfileData(InstrProfRecord &Record);
|
||||
|
||||
|
@ -156,6 +159,8 @@ public:
|
|||
|
||||
bool isIRLevelProfile() const override { return IsIRLevelProfile; }
|
||||
|
||||
bool hasCSIRLevelProfile() const override { return HasCSIRLevelProfile; }
|
||||
|
||||
/// Read the header.
|
||||
Error readHeader() override;
|
||||
|
||||
|
@ -212,6 +217,10 @@ public:
|
|||
return (Version & VARIANT_MASK_IR_PROF) != 0;
|
||||
}
|
||||
|
||||
bool hasCSIRLevelProfile() const override {
|
||||
return (Version & VARIANT_MASK_CSIR_PROF) != 0;
|
||||
}
|
||||
|
||||
InstrProfSymtab &getSymtab() override {
|
||||
assert(Symtab.get());
|
||||
return *Symtab.get();
|
||||
|
@ -341,6 +350,7 @@ struct InstrProfReaderIndexBase {
|
|||
virtual void setValueProfDataEndianness(support::endianness Endianness) = 0;
|
||||
virtual uint64_t getVersion() const = 0;
|
||||
virtual bool isIRLevelProfile() const = 0;
|
||||
virtual bool hasCSIRLevelProfile() const = 0;
|
||||
virtual Error populateSymtab(InstrProfSymtab &) = 0;
|
||||
};
|
||||
|
||||
|
@ -385,6 +395,10 @@ public:
|
|||
return (FormatVersion & VARIANT_MASK_IR_PROF) != 0;
|
||||
}
|
||||
|
||||
bool hasCSIRLevelProfile() const override {
|
||||
return (FormatVersion & VARIANT_MASK_CSIR_PROF) != 0;
|
||||
}
|
||||
|
||||
Error populateSymtab(InstrProfSymtab &Symtab) override {
|
||||
return Symtab.create(HashTable->keys());
|
||||
}
|
||||
|
@ -412,13 +426,16 @@ private:
|
|||
std::unique_ptr<InstrProfReaderRemapper> Remapper;
|
||||
/// Profile summary data.
|
||||
std::unique_ptr<ProfileSummary> Summary;
|
||||
/// Context sensitive profile summary data.
|
||||
std::unique_ptr<ProfileSummary> CS_Summary;
|
||||
// Index to the current record in the record array.
|
||||
unsigned RecordIndex;
|
||||
|
||||
// Read the profile summary. Return a pointer pointing to one byte past the
|
||||
// end of the summary data if it exists or the input \c Cur.
|
||||
// \c UseCS indicates whether to use the context-sensitive profile summary.
|
||||
const unsigned char *readSummary(IndexedInstrProf::ProfVersion Version,
|
||||
const unsigned char *Cur);
|
||||
const unsigned char *Cur, bool UseCS);
|
||||
|
||||
public:
|
||||
IndexedInstrProfReader(
|
||||
|
@ -432,6 +449,9 @@ public:
|
|||
/// Return the profile version.
|
||||
uint64_t getVersion() const { return Index->getVersion(); }
|
||||
bool isIRLevelProfile() const override { return Index->isIRLevelProfile(); }
|
||||
bool hasCSIRLevelProfile() const override {
|
||||
return Index->hasCSIRLevelProfile();
|
||||
}
|
||||
|
||||
/// Return true if the given buffer is in an indexed instrprof format.
|
||||
static bool hasFormat(const MemoryBuffer &DataBuffer);
|
||||
|
@ -450,7 +470,16 @@ public:
|
|||
std::vector<uint64_t> &Counts);
|
||||
|
||||
/// Return the maximum of all known function counts.
|
||||
uint64_t getMaximumFunctionCount() { return Summary->getMaxFunctionCount(); }
|
||||
/// \c UseCS indicates whether to use the context-sensitive count.
|
||||
uint64_t getMaximumFunctionCount(bool UseCS) {
|
||||
if (UseCS) {
|
||||
assert(CS_Summary && "No context sensitive profile summary");
|
||||
return CS_Summary->getMaxFunctionCount();
|
||||
} else {
|
||||
assert(Summary && "No profile summary");
|
||||
return Summary->getMaxFunctionCount();
|
||||
}
|
||||
}
|
||||
|
||||
/// Factory method to create an indexed reader.
|
||||
static Expected<std::unique_ptr<IndexedInstrProfReader>>
|
||||
|
@ -469,7 +498,19 @@ public:
|
|||
// to be used by llvm-profdata (for dumping). Avoid using this when
|
||||
// the client is the compiler.
|
||||
InstrProfSymtab &getSymtab() override;
|
||||
ProfileSummary &getSummary() { return *(Summary.get()); }
|
||||
|
||||
/// Return the profile summary.
|
||||
/// \c UseCS indicates whether to use the context-sensitive summary.
|
||||
// TODO: removed the defualt parameter.
|
||||
ProfileSummary &getSummary(bool UseCS = false) {
|
||||
if (UseCS) {
|
||||
assert(CS_Summary && "No context sensitive summary");
|
||||
return *(CS_Summary.get());
|
||||
} else {
|
||||
assert(Summary && "No profile summary");
|
||||
return *(Summary.get());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -33,7 +33,8 @@ class raw_fd_ostream;
|
|||
class InstrProfWriter {
|
||||
public:
|
||||
using ProfilingData = SmallDenseMap<uint64_t, InstrProfRecord>;
|
||||
enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
|
||||
// PF_IRLevelWithCS is the profile from context sensitive IR instrumentation.
|
||||
enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel, PF_IRLevelWithCS };
|
||||
|
||||
private:
|
||||
bool Sparse;
|
||||
|
@ -74,15 +75,26 @@ public:
|
|||
std::unique_ptr<MemoryBuffer> writeBuffer();
|
||||
|
||||
/// Set the ProfileKind. Report error if mixing FE and IR level profiles.
|
||||
Error setIsIRLevelProfile(bool IsIRLevel) {
|
||||
/// \c WithCS indicates if this is for contenxt sensitive instrumentation.
|
||||
Error setIsIRLevelProfile(bool IsIRLevel, bool WithCS) {
|
||||
if (ProfileKind == PF_Unknown) {
|
||||
ProfileKind = IsIRLevel ? PF_IRLevel: PF_FE;
|
||||
if (IsIRLevel)
|
||||
ProfileKind = WithCS ? PF_IRLevelWithCS : PF_IRLevel;
|
||||
else
|
||||
ProfileKind = PF_FE;
|
||||
return Error::success();
|
||||
}
|
||||
return (IsIRLevel == (ProfileKind == PF_IRLevel))
|
||||
? Error::success()
|
||||
: make_error<InstrProfError>(
|
||||
instrprof_error::unsupported_version);
|
||||
|
||||
if (((ProfileKind != PF_FE) && !IsIRLevel) ||
|
||||
((ProfileKind == PF_FE) && IsIRLevel))
|
||||
return make_error<InstrProfError>(instrprof_error::unsupported_version);
|
||||
|
||||
// When merging a context-sensitive profile (WithCS == true) with an IRLevel
|
||||
// profile, set the kind to PF_IRLevelWithCS.
|
||||
if (ProfileKind == PF_IRLevel && WithCS)
|
||||
ProfileKind = PF_IRLevelWithCS;
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
// Internal interface for testing purpose only.
|
||||
|
|
|
@ -79,7 +79,14 @@ static const ProfileSummaryEntry &getEntryForPercentile(SummaryEntryVector &DS,
|
|||
bool ProfileSummaryInfo::computeSummary() {
|
||||
if (Summary)
|
||||
return true;
|
||||
auto *SummaryMD = M.getProfileSummary();
|
||||
// First try to get context sensitive ProfileSummary.
|
||||
auto *SummaryMD = M.getProfileSummary(/* IsCS */ true);
|
||||
if (SummaryMD) {
|
||||
Summary.reset(ProfileSummary::getFromMD(SummaryMD));
|
||||
return true;
|
||||
}
|
||||
// This will actually return PSK_Instr or PSK_Sample summary.
|
||||
SummaryMD = M.getProfileSummary(/* IsCS */ false);
|
||||
if (!SummaryMD)
|
||||
return false;
|
||||
Summary.reset(ProfileSummary::getFromMD(SummaryMD));
|
||||
|
|
|
@ -531,12 +531,16 @@ void Module::setCodeModel(CodeModel::Model CL) {
|
|||
addModuleFlag(ModFlagBehavior::Error, "Code Model", CL);
|
||||
}
|
||||
|
||||
void Module::setProfileSummary(Metadata *M) {
|
||||
addModuleFlag(ModFlagBehavior::Error, "ProfileSummary", M);
|
||||
void Module::setProfileSummary(Metadata *M, ProfileSummary::Kind Kind) {
|
||||
if (Kind == ProfileSummary::PSK_CSInstr)
|
||||
addModuleFlag(ModFlagBehavior::Error, "CSProfileSummary", M);
|
||||
else
|
||||
addModuleFlag(ModFlagBehavior::Error, "ProfileSummary", M);
|
||||
}
|
||||
|
||||
Metadata *Module::getProfileSummary() {
|
||||
return getModuleFlag("ProfileSummary");
|
||||
Metadata *Module::getProfileSummary(bool IsCS) {
|
||||
return (IsCS ? getModuleFlag("CSProfileSummary")
|
||||
: getModuleFlag("ProfileSummary"));
|
||||
}
|
||||
|
||||
void Module::setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB) {
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
|
||||
using namespace llvm;
|
||||
|
||||
const char *ProfileSummary::KindStr[2] = {"InstrProf", "SampleProfile"};
|
||||
|
||||
// Return an MDTuple with two elements. The first element is a string Key and
|
||||
// the second is a uint64_t Value.
|
||||
static Metadata *getKeyValMD(LLVMContext &Context, const char *Key,
|
||||
|
@ -68,6 +66,7 @@ Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) {
|
|||
// "SampleProfile"). The rest of the elements of the outer MDTuple are specific
|
||||
// to the kind of profile summary as returned by getFormatSpecificMD.
|
||||
Metadata *ProfileSummary::getMD(LLVMContext &Context) {
|
||||
const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"};
|
||||
Metadata *Components[] = {
|
||||
getKeyValMD(Context, "ProfileFormat", KindStr[PSK]),
|
||||
getKeyValMD(Context, "TotalCount", getTotalCount()),
|
||||
|
@ -153,6 +152,9 @@ ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) {
|
|||
else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
|
||||
"InstrProf"))
|
||||
SummaryKind = PSK_Instr;
|
||||
else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
|
||||
"CSInstrProf"))
|
||||
SummaryKind = PSK_CSInstr;
|
||||
else
|
||||
return nullptr;
|
||||
|
||||
|
|
|
@ -162,7 +162,10 @@ Error TextInstrProfReader::readHeader() {
|
|||
IsIRInstr = true;
|
||||
else if (Str.equals_lower("fe"))
|
||||
IsIRInstr = false;
|
||||
else
|
||||
else if (Str.equals_lower("csir")) {
|
||||
IsIRInstr = true;
|
||||
HasCSIRLevelProfile = true;
|
||||
} else
|
||||
return error(instrprof_error::bad_header);
|
||||
|
||||
++Line;
|
||||
|
@ -733,7 +736,7 @@ bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
|
|||
|
||||
const unsigned char *
|
||||
IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
|
||||
const unsigned char *Cur) {
|
||||
const unsigned char *Cur, bool UseCS) {
|
||||
using namespace IndexedInstrProf;
|
||||
using namespace support;
|
||||
|
||||
|
@ -760,10 +763,13 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
|
|||
DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
|
||||
Ent.NumBlocks);
|
||||
}
|
||||
std::unique_ptr<llvm::ProfileSummary> &Summary =
|
||||
UseCS ? this->CS_Summary : this->Summary;
|
||||
|
||||
// initialize InstrProfSummary using the SummaryData from disk.
|
||||
this->Summary = llvm::make_unique<ProfileSummary>(
|
||||
ProfileSummary::PSK_Instr, DetailedSummary,
|
||||
SummaryData->get(Summary::TotalBlockCount),
|
||||
Summary = llvm::make_unique<ProfileSummary>(
|
||||
UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr,
|
||||
DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
|
||||
SummaryData->get(Summary::MaxBlockCount),
|
||||
SummaryData->get(Summary::MaxInternalBlockCount),
|
||||
SummaryData->get(Summary::MaxFunctionCount),
|
||||
|
@ -805,7 +811,11 @@ Error IndexedInstrProfReader::readHeader() {
|
|||
IndexedInstrProf::ProfVersion::CurrentVersion)
|
||||
return error(instrprof_error::unsupported_version);
|
||||
|
||||
Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur);
|
||||
Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
|
||||
/* UseCS */ false);
|
||||
if (Header->Version & VARIANT_MASK_CSIR_PROF)
|
||||
Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur,
|
||||
/* UseCS */ true);
|
||||
|
||||
// Read the hash type and start offset.
|
||||
IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
|
||||
|
|
|
@ -101,6 +101,7 @@ public:
|
|||
|
||||
support::endianness ValueProfDataEndianness = support::little;
|
||||
InstrProfSummaryBuilder *SummaryBuilder;
|
||||
InstrProfSummaryBuilder *CSSummaryBuilder;
|
||||
|
||||
InstrProfRecordWriterTrait() = default;
|
||||
|
||||
|
@ -142,7 +143,10 @@ public:
|
|||
endian::Writer LE(Out, little);
|
||||
for (const auto &ProfileData : *V) {
|
||||
const InstrProfRecord &ProfRecord = ProfileData.second;
|
||||
SummaryBuilder->addRecord(ProfRecord);
|
||||
if (NamedInstrProfRecord::hasCSFlagInHash(ProfileData.first))
|
||||
CSSummaryBuilder->addRecord(ProfRecord);
|
||||
else
|
||||
SummaryBuilder->addRecord(ProfRecord);
|
||||
|
||||
LE.write<uint64_t>(ProfileData.first); // Function hash
|
||||
LE.write<uint64_t>(ProfRecord.Counts.size());
|
||||
|
@ -253,6 +257,8 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
|
|||
|
||||
InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs);
|
||||
InfoObj->SummaryBuilder = &ISB;
|
||||
InstrProfSummaryBuilder CSISB(ProfileSummaryBuilder::DefaultCutoffs);
|
||||
InfoObj->CSSummaryBuilder = &CSISB;
|
||||
|
||||
// Populate the hash table generator.
|
||||
for (const auto &I : FunctionData)
|
||||
|
@ -264,6 +270,10 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
|
|||
Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion;
|
||||
if (ProfileKind == PF_IRLevel)
|
||||
Header.Version |= VARIANT_MASK_IR_PROF;
|
||||
if (ProfileKind == PF_IRLevelWithCS) {
|
||||
Header.Version |= VARIANT_MASK_IR_PROF;
|
||||
Header.Version |= VARIANT_MASK_CSIR_PROF;
|
||||
}
|
||||
Header.Unused = 0;
|
||||
Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
|
||||
Header.HashOffset = 0;
|
||||
|
@ -287,6 +297,14 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
|
|||
uint64_t SummaryOffset = OS.tell();
|
||||
for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
|
||||
OS.write(0);
|
||||
uint64_t CSSummaryOffset = 0;
|
||||
uint64_t CSSummarySize = 0;
|
||||
if (ProfileKind == PF_IRLevelWithCS) {
|
||||
CSSummaryOffset = OS.tell();
|
||||
CSSummarySize = SummarySize / sizeof(uint64_t);
|
||||
for (unsigned I = 0; I < CSSummarySize; I++)
|
||||
OS.write(0);
|
||||
}
|
||||
|
||||
// Write the hash table.
|
||||
uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj);
|
||||
|
@ -300,13 +318,25 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
|
|||
setSummary(TheSummary.get(), *PS);
|
||||
InfoObj->SummaryBuilder = nullptr;
|
||||
|
||||
// For Context Sensitive summary.
|
||||
std::unique_ptr<IndexedInstrProf::Summary> TheCSSummary = nullptr;
|
||||
if (ProfileKind == PF_IRLevelWithCS) {
|
||||
TheCSSummary = IndexedInstrProf::allocSummary(SummarySize);
|
||||
std::unique_ptr<ProfileSummary> CSPS = CSISB.getSummary();
|
||||
setSummary(TheCSSummary.get(), *CSPS);
|
||||
}
|
||||
InfoObj->CSSummaryBuilder = nullptr;
|
||||
|
||||
// Now do the final patch:
|
||||
PatchItem PatchItems[] = {
|
||||
// Patch the Header.HashOffset field.
|
||||
{HashTableStartFieldOffset, &HashTableStart, 1},
|
||||
// Patch the summary data.
|
||||
{SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()),
|
||||
(int)(SummarySize / sizeof(uint64_t))}};
|
||||
(int)(SummarySize / sizeof(uint64_t))},
|
||||
{CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()),
|
||||
(int)CSSummarySize}};
|
||||
|
||||
OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems));
|
||||
}
|
||||
|
||||
|
@ -375,6 +405,8 @@ void InstrProfWriter::writeRecordInText(StringRef Name, uint64_t Hash,
|
|||
Error InstrProfWriter::writeText(raw_fd_ostream &OS) {
|
||||
if (ProfileKind == PF_IRLevel)
|
||||
OS << "# IR level Instrumentation Flag\n:ir\n";
|
||||
else if (ProfileKind == PF_IRLevelWithCS)
|
||||
OS << "# CSIR level Instrumentation Flag\n:csir\n";
|
||||
InstrProfSymtab Symtab;
|
||||
for (const auto &I : FunctionData)
|
||||
if (shouldEncodeData(I.getValue()))
|
||||
|
|
|
@ -664,7 +664,7 @@ bool HotColdSplitting::outlineColdRegions(Function &F, bool HasProfileSummary) {
|
|||
|
||||
bool HotColdSplitting::run(Module &M) {
|
||||
bool Changed = false;
|
||||
bool HasProfileSummary = M.getProfileSummary();
|
||||
bool HasProfileSummary = (M.getProfileSummary(/* IsCS */ false) != nullptr);
|
||||
for (auto It = M.begin(), End = M.end(); It != End; ++It) {
|
||||
Function &F = *It;
|
||||
|
||||
|
|
|
@ -1595,8 +1595,9 @@ bool SampleProfileLoader::runOnModule(Module &M, ModuleAnalysisManager *AM,
|
|||
return false;
|
||||
|
||||
PSI = _PSI;
|
||||
if (M.getProfileSummary() == nullptr)
|
||||
M.setProfileSummary(Reader->getSummary().getMD(M.getContext()));
|
||||
if (M.getProfileSummary(/* IsCS */ false) == nullptr)
|
||||
M.setProfileSummary(Reader->getSummary().getMD(M.getContext()),
|
||||
ProfileSummary::PSK_Sample);
|
||||
|
||||
// Compute the total number of samples collected in this profile.
|
||||
for (const auto &I : Reader->getProfiles())
|
||||
|
|
|
@ -1147,7 +1147,7 @@ bool PGOUseFunc::readCounters(IndexedInstrProfReader *PGOReader, bool &AllZeros)
|
|||
getBBInfo(nullptr).UnknownCountInEdge = 2;
|
||||
|
||||
setInstrumentedCounts(CountFromProfile);
|
||||
ProgramMaxCount = PGOReader->getMaximumFunctionCount();
|
||||
ProgramMaxCount = PGOReader->getMaximumFunctionCount(IsCS);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1531,6 +1531,8 @@ static bool annotateAllFunctions(
|
|||
StringRef("Cannot get PGOReader")));
|
||||
return false;
|
||||
}
|
||||
if (!PGOReader->hasCSIRLevelProfile() && IsCS)
|
||||
return false;
|
||||
|
||||
// TODO: might need to change the warning once the clang option is finalized.
|
||||
if (!PGOReader->isIRLevelProfile()) {
|
||||
|
@ -1599,7 +1601,9 @@ static bool annotateAllFunctions(
|
|||
}
|
||||
}
|
||||
}
|
||||
M.setProfileSummary(PGOReader->getSummary().getMD(M.getContext()));
|
||||
M.setProfileSummary(PGOReader->getSummary(IsCS).getMD(M.getContext()),
|
||||
IsCS ? ProfileSummary::PSK_CSInstr
|
||||
: ProfileSummary::PSK_Instr);
|
||||
|
||||
// Set function hotness attribute from the profile.
|
||||
// We have to apply these attributes at the end because their presence
|
||||
|
|
|
@ -225,7 +225,8 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
|
|||
|
||||
auto Reader = std::move(ReaderOrErr.get());
|
||||
bool IsIRProfile = Reader->isIRLevelProfile();
|
||||
if (WC->Writer.setIsIRLevelProfile(IsIRProfile)) {
|
||||
bool HasCSIRProfile = Reader->hasCSIRLevelProfile();
|
||||
if (WC->Writer.setIsIRLevelProfile(IsIRProfile, HasCSIRProfile)) {
|
||||
WC->Err = make_error<StringError>(
|
||||
"Merge IR generated profile with Clang generated profile.",
|
||||
std::error_code());
|
||||
|
@ -669,9 +670,10 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
|
|||
uint32_t TopN, bool ShowIndirectCallTargets,
|
||||
bool ShowMemOPSizes, bool ShowDetailedSummary,
|
||||
std::vector<uint32_t> DetailedSummaryCutoffs,
|
||||
bool ShowAllFunctions, uint64_t ValueCutoff,
|
||||
bool OnlyListBelow, const std::string &ShowFunction,
|
||||
bool TextFormat, raw_fd_ostream &OS) {
|
||||
bool ShowAllFunctions, bool ShowCS,
|
||||
uint64_t ValueCutoff, bool OnlyListBelow,
|
||||
const std::string &ShowFunction, bool TextFormat,
|
||||
raw_fd_ostream &OS) {
|
||||
auto ReaderOrErr = InstrProfReader::create(Filename);
|
||||
std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
|
||||
if (ShowDetailedSummary && Cutoffs.empty()) {
|
||||
|
@ -708,6 +710,11 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
|
|||
OS << ":ir\n";
|
||||
|
||||
for (const auto &Func : *Reader) {
|
||||
if (Reader->isIRLevelProfile()) {
|
||||
bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
|
||||
if (FuncIsCS != ShowCS)
|
||||
continue;
|
||||
}
|
||||
bool Show =
|
||||
ShowAllFunctions || (!ShowFunction.empty() &&
|
||||
Func.Name.find(ShowFunction) != Func.Name.npos);
|
||||
|
@ -899,6 +906,8 @@ static int show_main(int argc, const char *argv[]) {
|
|||
cl::value_desc("800000,901000,999999"));
|
||||
cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
|
||||
cl::desc("Details for every function"));
|
||||
cl::opt<bool> ShowCS("showcs", cl::init(false),
|
||||
cl::desc("Show context sensitive counts"));
|
||||
cl::opt<std::string> ShowFunction("function",
|
||||
cl::desc("Details for matching functions"));
|
||||
|
||||
|
@ -940,8 +949,8 @@ static int show_main(int argc, const char *argv[]) {
|
|||
return showInstrProfile(Filename, ShowCounts, TopNFunctions,
|
||||
ShowIndirectCallTargets, ShowMemOPSizes,
|
||||
ShowDetailedSummary, DetailedSummaryCutoffs,
|
||||
ShowAllFunctions, ValueCutoff, OnlyListBelow,
|
||||
ShowFunction, TextFormat, OS);
|
||||
ShowAllFunctions, ShowCS, ValueCutoff,
|
||||
OnlyListBelow, ShowFunction, TextFormat, OS);
|
||||
else
|
||||
return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
|
||||
ShowFunction, OS);
|
||||
|
|
|
@ -175,7 +175,7 @@ TEST_F(InstrProfTest, get_profile_summary) {
|
|||
ASSERT_EQ(288230376151711744U, NinetyFivePerc->MinCount);
|
||||
ASSERT_EQ(72057594037927936U, NinetyNinePerc->MinCount);
|
||||
};
|
||||
ProfileSummary &PS = Reader->getSummary();
|
||||
ProfileSummary &PS = Reader->getSummary(/* IsCS */ false);
|
||||
VerifySummary(PS);
|
||||
|
||||
// Test that conversion of summary to and from Metadata works.
|
||||
|
@ -189,8 +189,8 @@ TEST_F(InstrProfTest, get_profile_summary) {
|
|||
|
||||
// Test that summary can be attached to and read back from module.
|
||||
Module M("my_module", Context);
|
||||
M.setProfileSummary(MD);
|
||||
MD = M.getProfileSummary();
|
||||
M.setProfileSummary(MD, ProfileSummary::PSK_Instr);
|
||||
MD = M.getProfileSummary(/* IsCS */ false);
|
||||
ASSERT_TRUE(MD);
|
||||
PSFromMD = ProfileSummary::getFromMD(MD);
|
||||
ASSERT_TRUE(PSFromMD);
|
||||
|
@ -801,7 +801,7 @@ TEST_P(MaybeSparseInstrProfTest, get_max_function_count) {
|
|||
auto Profile = Writer.writeBuffer();
|
||||
readProfile(std::move(Profile));
|
||||
|
||||
ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount());
|
||||
ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount(/* IsCS */ false));
|
||||
}
|
||||
|
||||
TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) {
|
||||
|
|
|
@ -191,8 +191,8 @@ struct SampleProfTest : ::testing::Test {
|
|||
delete PS;
|
||||
|
||||
// Test that summary can be attached to and read back from module.
|
||||
M.setProfileSummary(MD);
|
||||
MD = M.getProfileSummary();
|
||||
M.setProfileSummary(MD, ProfileSummary::PSK_Sample);
|
||||
MD = M.getProfileSummary(/* IsCS */ false);
|
||||
ASSERT_TRUE(MD);
|
||||
PS = ProfileSummary::getFromMD(MD);
|
||||
ASSERT_TRUE(PS);
|
||||
|
|
Loading…
Reference in New Issue