#include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
namespace llvm {
cl::opt<unsigned> SampleProfileMaxPropagateIterations(
"sample-profile-max-propagate-iterations", cl::init(100),
cl::desc("Maximum number of iterations to go through when propagating "
"sample block/edge weights through the CFG."));
cl::opt<unsigned> SampleProfileRecordCoverage(
"sample-profile-check-record-coverage", cl::init(0), cl::value_desc("N"),
cl::desc("Emit a warning if less than N% of records in the input profile "
"are matched to the IR."));
cl::opt<unsigned> SampleProfileSampleCoverage(
"sample-profile-check-sample-coverage", cl::init(0), cl::value_desc("N"),
cl::desc("Emit a warning if less than N% of samples in the input profile "
"are matched to the IR."));
cl::opt<bool> NoWarnSampleUnused(
"no-warn-sample-unused", cl::init(false), cl::Hidden,
cl::desc("Use this option to turn off/on warnings about function with "
"samples but without debug information to use those samples. "));
cl::opt<bool> SampleProfileUseProfi(
"sample-profile-use-profi", cl::Hidden,
cl::desc("Use profi to infer block and edge counts."));
cl::opt<bool> SampleProfileInferEntryCount(
"sample-profile-infer-entry-count", cl::init(true), cl::Hidden,
cl::desc("Use profi to infer function entry count."));
namespace sampleprofutil {
bool callsiteIsHot(const FunctionSamples *CallsiteFS, ProfileSummaryInfo *PSI,
bool ProfAccForSymsInList) {
if (!CallsiteFS)
return false;
assert(PSI && "PSI is expected to be non null");
uint64_t CallsiteTotalSamples = CallsiteFS->getTotalSamples();
if (ProfAccForSymsInList)
return !PSI->isColdCount(CallsiteTotalSamples);
else
return PSI->isHotCount(CallsiteTotalSamples);
}
bool SampleCoverageTracker::markSamplesUsed(const FunctionSamples *FS,
uint32_t LineOffset,
uint32_t Discriminator,
uint64_t Samples) {
LineLocation Loc(LineOffset, Discriminator);
unsigned &Count = SampleCoverage[FS][Loc];
bool FirstTime = (++Count == 1);
if (FirstTime)
TotalUsedSamples += Samples;
return FirstTime;
}
unsigned
SampleCoverageTracker::countUsedRecords(const FunctionSamples *FS,
ProfileSummaryInfo *PSI) const {
auto I = SampleCoverage.find(FS);
unsigned Count = (I != SampleCoverage.end()) ? I->second.size() : 0;
for (const auto &I : FS->getCallsiteSamples())
for (const auto &J : I.second) {
const FunctionSamples *CalleeSamples = &J.second;
if (callsiteIsHot(CalleeSamples, PSI, ProfAccForSymsInList))
Count += countUsedRecords(CalleeSamples, PSI);
}
return Count;
}
unsigned
SampleCoverageTracker::countBodyRecords(const FunctionSamples *FS,
ProfileSummaryInfo *PSI) const {
unsigned Count = FS->getBodySamples().size();
for (const auto &I : FS->getCallsiteSamples())
for (const auto &J : I.second) {
const FunctionSamples *CalleeSamples = &J.second;
if (callsiteIsHot(CalleeSamples, PSI, ProfAccForSymsInList))
Count += countBodyRecords(CalleeSamples, PSI);
}
return Count;
}
uint64_t
SampleCoverageTracker::countBodySamples(const FunctionSamples *FS,
ProfileSummaryInfo *PSI) const {
uint64_t Total = 0;
for (const auto &I : FS->getBodySamples())
Total += I.second.getSamples();
for (const auto &I : FS->getCallsiteSamples())
for (const auto &J : I.second) {
const FunctionSamples *CalleeSamples = &J.second;
if (callsiteIsHot(CalleeSamples, PSI, ProfAccForSymsInList))
Total += countBodySamples(CalleeSamples, PSI);
}
return Total;
}
unsigned SampleCoverageTracker::computeCoverage(unsigned Used,
unsigned Total) const {
assert(Used <= Total &&
"number of used records cannot exceed the total number of records");
return Total > 0 ? Used * 100 / Total : 100;
}
void createFSDiscriminatorVariable(Module *M) {
const char *FSDiscriminatorVar = "__llvm_fs_discriminator__";
if (M->getGlobalVariable(FSDiscriminatorVar))
return;
auto &Context = M->getContext();
appendToUsed(*M, {new GlobalVariable(*M, Type::getInt1Ty(Context), true,
GlobalValue::WeakODRLinkage,
ConstantInt::getTrue(Context),
FSDiscriminatorVar)});
}
} }