#ifndef LLVM_TRANSFORMS_UTILS_SAMPLEPROFILELOADERBASEIMPL_H
#define LLVM_TRANSFORMS_UTILS_SAMPLEPROFILELOADERBASEIMPL_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/ProfileData/SampleProfReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/GenericDomTree.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/SampleProfileInference.h"
#include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
namespace llvm {
using namespace sampleprof;
using namespace sampleprofutil;
using ProfileCount = Function::ProfileCount;
#define DEBUG_TYPE "sample-profile-impl"
namespace afdo_detail {
template <typename BlockT> struct IRTraits;
template <> struct IRTraits<BasicBlock> {
using InstructionT = Instruction;
using BasicBlockT = BasicBlock;
using FunctionT = Function;
using BlockFrequencyInfoT = BlockFrequencyInfo;
using LoopT = Loop;
using LoopInfoPtrT = std::unique_ptr<LoopInfo>;
using DominatorTreePtrT = std::unique_ptr<DominatorTree>;
using PostDominatorTreeT = PostDominatorTree;
using PostDominatorTreePtrT = std::unique_ptr<PostDominatorTree>;
using OptRemarkEmitterT = OptimizationRemarkEmitter;
using OptRemarkAnalysisT = OptimizationRemarkAnalysis;
using PredRangeT = pred_range;
using SuccRangeT = succ_range;
static Function &getFunction(Function &F) { return F; }
static const BasicBlock *getEntryBB(const Function *F) {
return &F->getEntryBlock();
}
static pred_range getPredecessors(BasicBlock *BB) { return predecessors(BB); }
static succ_range getSuccessors(BasicBlock *BB) { return successors(BB); }
};
}
extern cl::opt<bool> SampleProfileUseProfi;
extern cl::opt<bool> SampleProfileInferEntryCount;
template <typename BT> class SampleProfileLoaderBaseImpl {
public:
SampleProfileLoaderBaseImpl(std::string Name, std::string RemapName)
: Filename(Name), RemappingFilename(RemapName) {}
void dump() { Reader->dump(); }
using InstructionT = typename afdo_detail::IRTraits<BT>::InstructionT;
using BasicBlockT = typename afdo_detail::IRTraits<BT>::BasicBlockT;
using BlockFrequencyInfoT =
typename afdo_detail::IRTraits<BT>::BlockFrequencyInfoT;
using FunctionT = typename afdo_detail::IRTraits<BT>::FunctionT;
using LoopT = typename afdo_detail::IRTraits<BT>::LoopT;
using LoopInfoPtrT = typename afdo_detail::IRTraits<BT>::LoopInfoPtrT;
using DominatorTreePtrT =
typename afdo_detail::IRTraits<BT>::DominatorTreePtrT;
using PostDominatorTreePtrT =
typename afdo_detail::IRTraits<BT>::PostDominatorTreePtrT;
using PostDominatorTreeT =
typename afdo_detail::IRTraits<BT>::PostDominatorTreeT;
using OptRemarkEmitterT =
typename afdo_detail::IRTraits<BT>::OptRemarkEmitterT;
using OptRemarkAnalysisT =
typename afdo_detail::IRTraits<BT>::OptRemarkAnalysisT;
using PredRangeT = typename afdo_detail::IRTraits<BT>::PredRangeT;
using SuccRangeT = typename afdo_detail::IRTraits<BT>::SuccRangeT;
using BlockWeightMap = DenseMap<const BasicBlockT *, uint64_t>;
using EquivalenceClassMap =
DenseMap<const BasicBlockT *, const BasicBlockT *>;
using Edge = std::pair<const BasicBlockT *, const BasicBlockT *>;
using EdgeWeightMap = DenseMap<Edge, uint64_t>;
using BlockEdgeMap =
DenseMap<const BasicBlockT *, SmallVector<const BasicBlockT *, 8>>;
protected:
~SampleProfileLoaderBaseImpl() = default;
friend class SampleCoverageTracker;
Function &getFunction(FunctionT &F) {
return afdo_detail::IRTraits<BT>::getFunction(F);
}
const BasicBlockT *getEntryBB(const FunctionT *F) {
return afdo_detail::IRTraits<BT>::getEntryBB(F);
}
PredRangeT getPredecessors(BasicBlockT *BB) {
return afdo_detail::IRTraits<BT>::getPredecessors(BB);
}
SuccRangeT getSuccessors(BasicBlockT *BB) {
return afdo_detail::IRTraits<BT>::getSuccessors(BB);
}
unsigned getFunctionLoc(FunctionT &Func);
virtual ErrorOr<uint64_t> getInstWeight(const InstructionT &Inst);
ErrorOr<uint64_t> getInstWeightImpl(const InstructionT &Inst);
ErrorOr<uint64_t> getBlockWeight(const BasicBlockT *BB);
mutable DenseMap<const DILocation *, const FunctionSamples *>
DILocation2SampleMap;
virtual const FunctionSamples *
findFunctionSamples(const InstructionT &I) const;
void printEdgeWeight(raw_ostream &OS, Edge E);
void printBlockWeight(raw_ostream &OS, const BasicBlockT *BB) const;
void printBlockEquivalence(raw_ostream &OS, const BasicBlockT *BB);
bool computeBlockWeights(FunctionT &F);
void findEquivalenceClasses(FunctionT &F);
void findEquivalencesFor(BasicBlockT *BB1,
ArrayRef<BasicBlockT *> Descendants,
PostDominatorTreeT *DomTree);
void propagateWeights(FunctionT &F);
void applyProfi(FunctionT &F, BlockEdgeMap &Successors,
BlockWeightMap &SampleBlockWeights,
BlockWeightMap &BlockWeights, EdgeWeightMap &EdgeWeights);
uint64_t visitEdge(Edge E, unsigned *NumUnknownEdges, Edge *UnknownEdge);
void buildEdges(FunctionT &F);
bool propagateThroughEdges(FunctionT &F, bool UpdateBlockCount);
void clearFunctionData(bool ResetDT = true);
void computeDominanceAndLoopInfo(FunctionT &F);
bool
computeAndPropagateWeights(FunctionT &F,
const DenseSet<GlobalValue::GUID> &InlinedGUIDs);
void initWeightPropagation(FunctionT &F,
const DenseSet<GlobalValue::GUID> &InlinedGUIDs);
void
finalizeWeightPropagation(FunctionT &F,
const DenseSet<GlobalValue::GUID> &InlinedGUIDs);
void emitCoverageRemarks(FunctionT &F);
BlockWeightMap BlockWeights;
EdgeWeightMap EdgeWeights;
SmallPtrSet<const BasicBlockT *, 32> VisitedBlocks;
SmallSet<Edge, 32> VisitedEdges;
EquivalenceClassMap EquivalenceClass;
DominatorTreePtrT DT;
PostDominatorTreePtrT PDT;
LoopInfoPtrT LI;
BlockEdgeMap Predecessors;
BlockEdgeMap Successors;
SampleCoverageTracker CoverageTracker;
std::unique_ptr<SampleProfileReader> Reader;
FunctionSamples *Samples = nullptr;
std::string Filename;
std::string RemappingFilename;
ProfileSummaryInfo *PSI = nullptr;
OptRemarkEmitterT *ORE = nullptr;
};
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::clearFunctionData(bool ResetDT) {
BlockWeights.clear();
EdgeWeights.clear();
VisitedBlocks.clear();
VisitedEdges.clear();
EquivalenceClass.clear();
if (ResetDT) {
DT = nullptr;
PDT = nullptr;
LI = nullptr;
}
Predecessors.clear();
Successors.clear();
CoverageTracker.clear();
}
#ifndef NDEBUG
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::printEdgeWeight(raw_ostream &OS, Edge E) {
OS << "weight[" << E.first->getName() << "->" << E.second->getName()
<< "]: " << EdgeWeights[E] << "\n";
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::printBlockEquivalence(
raw_ostream &OS, const BasicBlockT *BB) {
const BasicBlockT *Equiv = EquivalenceClass[BB];
OS << "equivalence[" << BB->getName()
<< "]: " << ((Equiv) ? EquivalenceClass[BB]->getName() : "NONE") << "\n";
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::printBlockWeight(
raw_ostream &OS, const BasicBlockT *BB) const {
const auto &I = BlockWeights.find(BB);
uint64_t W = (I == BlockWeights.end() ? 0 : I->second);
OS << "weight[" << BB->getName() << "]: " << W << "\n";
}
#endif
template <typename BT>
ErrorOr<uint64_t>
SampleProfileLoaderBaseImpl<BT>::getInstWeight(const InstructionT &Inst) {
return getInstWeightImpl(Inst);
}
template <typename BT>
ErrorOr<uint64_t>
SampleProfileLoaderBaseImpl<BT>::getInstWeightImpl(const InstructionT &Inst) {
const FunctionSamples *FS = findFunctionSamples(Inst);
if (!FS)
return std::error_code();
const DebugLoc &DLoc = Inst.getDebugLoc();
if (!DLoc)
return std::error_code();
const DILocation *DIL = DLoc;
uint32_t LineOffset = FunctionSamples::getOffset(DIL);
uint32_t Discriminator;
if (EnableFSDiscriminator)
Discriminator = DIL->getDiscriminator();
else
Discriminator = DIL->getBaseDiscriminator();
ErrorOr<uint64_t> R = FS->findSamplesAt(LineOffset, Discriminator);
if (R) {
bool FirstMark =
CoverageTracker.markSamplesUsed(FS, LineOffset, Discriminator, R.get());
if (FirstMark) {
ORE->emit([&]() {
OptRemarkAnalysisT Remark(DEBUG_TYPE, "AppliedSamples", &Inst);
Remark << "Applied " << ore::NV("NumSamples", *R);
Remark << " samples from profile (offset: ";
Remark << ore::NV("LineOffset", LineOffset);
if (Discriminator) {
Remark << ".";
Remark << ore::NV("Discriminator", Discriminator);
}
Remark << ")";
return Remark;
});
}
LLVM_DEBUG(dbgs() << " " << DLoc.getLine() << "." << Discriminator << ":"
<< Inst << " (line offset: " << LineOffset << "."
<< Discriminator << " - weight: " << R.get() << ")\n");
}
return R;
}
template <typename BT>
ErrorOr<uint64_t>
SampleProfileLoaderBaseImpl<BT>::getBlockWeight(const BasicBlockT *BB) {
uint64_t Max = 0;
bool HasWeight = false;
for (auto &I : *BB) {
const ErrorOr<uint64_t> &R = getInstWeight(I);
if (R) {
Max = std::max(Max, R.get());
HasWeight = true;
}
}
return HasWeight ? ErrorOr<uint64_t>(Max) : std::error_code();
}
template <typename BT>
bool SampleProfileLoaderBaseImpl<BT>::computeBlockWeights(FunctionT &F) {
bool Changed = false;
LLVM_DEBUG(dbgs() << "Block weights\n");
for (const auto &BB : F) {
ErrorOr<uint64_t> Weight = getBlockWeight(&BB);
if (Weight) {
BlockWeights[&BB] = Weight.get();
VisitedBlocks.insert(&BB);
Changed = true;
}
LLVM_DEBUG(printBlockWeight(dbgs(), &BB));
}
return Changed;
}
template <typename BT>
const FunctionSamples *SampleProfileLoaderBaseImpl<BT>::findFunctionSamples(
const InstructionT &Inst) const {
const DILocation *DIL = Inst.getDebugLoc();
if (!DIL)
return Samples;
auto it = DILocation2SampleMap.try_emplace(DIL, nullptr);
if (it.second) {
it.first->second = Samples->findFunctionSamples(DIL, Reader->getRemapper());
}
return it.first->second;
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::findEquivalencesFor(
BasicBlockT *BB1, ArrayRef<BasicBlockT *> Descendants,
PostDominatorTreeT *DomTree) {
const BasicBlockT *EC = EquivalenceClass[BB1];
uint64_t Weight = BlockWeights[EC];
for (const auto *BB2 : Descendants) {
bool IsDomParent = DomTree->dominates(BB2, BB1);
bool IsInSameLoop = LI->getLoopFor(BB1) == LI->getLoopFor(BB2);
if (BB1 != BB2 && IsDomParent && IsInSameLoop) {
EquivalenceClass[BB2] = EC;
if (VisitedBlocks.count(BB2)) {
VisitedBlocks.insert(EC);
}
Weight = std::max(Weight, BlockWeights[BB2]);
}
}
const BasicBlockT *EntryBB = getEntryBB(EC->getParent());
if (EC == EntryBB) {
BlockWeights[EC] = Samples->getHeadSamples() + 1;
} else {
BlockWeights[EC] = Weight;
}
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::findEquivalenceClasses(FunctionT &F) {
SmallVector<BasicBlockT *, 8> DominatedBBs;
LLVM_DEBUG(dbgs() << "\nBlock equivalence classes\n");
for (auto &BB : F) {
BasicBlockT *BB1 = &BB;
if (EquivalenceClass.count(BB1)) {
LLVM_DEBUG(printBlockEquivalence(dbgs(), BB1));
continue;
}
EquivalenceClass[BB1] = BB1;
DominatedBBs.clear();
DT->getDescendants(BB1, DominatedBBs);
findEquivalencesFor(BB1, DominatedBBs, &*PDT);
LLVM_DEBUG(printBlockEquivalence(dbgs(), BB1));
}
LLVM_DEBUG(
dbgs() << "\nAssign the same weight to all blocks in the same class\n");
for (auto &BI : F) {
const BasicBlockT *BB = &BI;
const BasicBlockT *EquivBB = EquivalenceClass[BB];
if (BB != EquivBB)
BlockWeights[BB] = BlockWeights[EquivBB];
LLVM_DEBUG(printBlockWeight(dbgs(), BB));
}
}
template <typename BT>
uint64_t SampleProfileLoaderBaseImpl<BT>::visitEdge(Edge E,
unsigned *NumUnknownEdges,
Edge *UnknownEdge) {
if (!VisitedEdges.count(E)) {
(*NumUnknownEdges)++;
*UnknownEdge = E;
return 0;
}
return EdgeWeights[E];
}
template <typename BT>
bool SampleProfileLoaderBaseImpl<BT>::propagateThroughEdges(
FunctionT &F, bool UpdateBlockCount) {
bool Changed = false;
LLVM_DEBUG(dbgs() << "\nPropagation through edges\n");
for (const auto &BI : F) {
const BasicBlockT *BB = &BI;
const BasicBlockT *EC = EquivalenceClass[BB];
for (unsigned i = 0; i < 2; i++) {
uint64_t TotalWeight = 0;
unsigned NumUnknownEdges = 0, NumTotalEdges = 0;
Edge UnknownEdge, SelfReferentialEdge, SingleEdge;
if (i == 0) {
NumTotalEdges = Predecessors[BB].size();
for (auto *Pred : Predecessors[BB]) {
Edge E = std::make_pair(Pred, BB);
TotalWeight += visitEdge(E, &NumUnknownEdges, &UnknownEdge);
if (E.first == E.second)
SelfReferentialEdge = E;
}
if (NumTotalEdges == 1) {
SingleEdge = std::make_pair(Predecessors[BB][0], BB);
}
} else {
NumTotalEdges = Successors[BB].size();
for (auto *Succ : Successors[BB]) {
Edge E = std::make_pair(BB, Succ);
TotalWeight += visitEdge(E, &NumUnknownEdges, &UnknownEdge);
}
if (NumTotalEdges == 1) {
SingleEdge = std::make_pair(BB, Successors[BB][0]);
}
}
if (NumUnknownEdges <= 1) {
uint64_t &BBWeight = BlockWeights[EC];
if (NumUnknownEdges == 0) {
if (!VisitedBlocks.count(EC)) {
if (TotalWeight > BBWeight) {
BBWeight = TotalWeight;
Changed = true;
LLVM_DEBUG(dbgs() << "All edge weights for " << BB->getName()
<< " known. Set weight for block: ";
printBlockWeight(dbgs(), BB););
}
} else if (NumTotalEdges == 1 &&
EdgeWeights[SingleEdge] < BlockWeights[EC]) {
EdgeWeights[SingleEdge] = BlockWeights[EC];
Changed = true;
}
} else if (NumUnknownEdges == 1 && VisitedBlocks.count(EC)) {
if (BBWeight >= TotalWeight)
EdgeWeights[UnknownEdge] = BBWeight - TotalWeight;
else
EdgeWeights[UnknownEdge] = 0;
const BasicBlockT *OtherEC;
if (i == 0)
OtherEC = EquivalenceClass[UnknownEdge.first];
else
OtherEC = EquivalenceClass[UnknownEdge.second];
if (VisitedBlocks.count(OtherEC) &&
EdgeWeights[UnknownEdge] > BlockWeights[OtherEC])
EdgeWeights[UnknownEdge] = BlockWeights[OtherEC];
VisitedEdges.insert(UnknownEdge);
Changed = true;
LLVM_DEBUG(dbgs() << "Set weight for edge: ";
printEdgeWeight(dbgs(), UnknownEdge));
}
} else if (VisitedBlocks.count(EC) && BlockWeights[EC] == 0) {
if (i == 0) {
for (auto *Pred : Predecessors[BB]) {
Edge E = std::make_pair(Pred, BB);
EdgeWeights[E] = 0;
VisitedEdges.insert(E);
}
} else {
for (auto *Succ : Successors[BB]) {
Edge E = std::make_pair(BB, Succ);
EdgeWeights[E] = 0;
VisitedEdges.insert(E);
}
}
} else if (SelfReferentialEdge.first && VisitedBlocks.count(EC)) {
uint64_t &BBWeight = BlockWeights[BB];
if (BBWeight >= TotalWeight)
EdgeWeights[SelfReferentialEdge] = BBWeight - TotalWeight;
else
EdgeWeights[SelfReferentialEdge] = 0;
VisitedEdges.insert(SelfReferentialEdge);
Changed = true;
LLVM_DEBUG(dbgs() << "Set self-referential edge weight to: ";
printEdgeWeight(dbgs(), SelfReferentialEdge));
}
if (UpdateBlockCount && !VisitedBlocks.count(EC) && TotalWeight > 0) {
BlockWeights[EC] = TotalWeight;
VisitedBlocks.insert(EC);
Changed = true;
}
}
}
return Changed;
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::buildEdges(FunctionT &F) {
for (auto &BI : F) {
BasicBlockT *B1 = &BI;
SmallPtrSet<BasicBlockT *, 16> Visited;
if (!Predecessors[B1].empty())
llvm_unreachable("Found a stale predecessors list in a basic block.");
for (auto *B2 : getPredecessors(B1))
if (Visited.insert(B2).second)
Predecessors[B1].push_back(B2);
Visited.clear();
if (!Successors[B1].empty())
llvm_unreachable("Found a stale successors list in a basic block.");
for (auto *B2 : getSuccessors(B1))
if (Visited.insert(B2).second)
Successors[B1].push_back(B2);
}
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::propagateWeights(FunctionT &F) {
if (SampleProfileUseProfi) {
BlockWeightMap SampleBlockWeights;
for (const auto &BI : F) {
ErrorOr<uint64_t> Weight = getBlockWeight(&BI);
if (Weight)
SampleBlockWeights[&BI] = Weight.get();
}
applyProfi(F, Successors, SampleBlockWeights, BlockWeights, EdgeWeights);
} else {
bool Changed = true;
unsigned I = 0;
for (auto &BI : F) {
BasicBlockT *BB = &BI;
LoopT *L = LI->getLoopFor(BB);
if (!L) {
continue;
}
BasicBlockT *Header = L->getHeader();
if (Header && BlockWeights[BB] > BlockWeights[Header]) {
BlockWeights[Header] = BlockWeights[BB];
}
}
while (Changed && I++ < SampleProfileMaxPropagateIterations) {
Changed = propagateThroughEdges(F, false);
}
VisitedEdges.clear();
Changed = true;
while (Changed && I++ < SampleProfileMaxPropagateIterations) {
Changed = propagateThroughEdges(F, false);
}
Changed = true;
while (Changed && I++ < SampleProfileMaxPropagateIterations) {
Changed = propagateThroughEdges(F, true);
}
}
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::applyProfi(
FunctionT &F, BlockEdgeMap &Successors, BlockWeightMap &SampleBlockWeights,
BlockWeightMap &BlockWeights, EdgeWeightMap &EdgeWeights) {
auto Infer = SampleProfileInference<BT>(F, Successors, SampleBlockWeights);
Infer.apply(BlockWeights, EdgeWeights);
}
template <typename BT>
bool SampleProfileLoaderBaseImpl<BT>::computeAndPropagateWeights(
FunctionT &F, const DenseSet<GlobalValue::GUID> &InlinedGUIDs) {
bool Changed = (InlinedGUIDs.size() != 0);
Changed |= computeBlockWeights(F);
if (Changed) {
initWeightPropagation(F, InlinedGUIDs);
propagateWeights(F);
finalizeWeightPropagation(F, InlinedGUIDs);
}
return Changed;
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::initWeightPropagation(
FunctionT &F, const DenseSet<GlobalValue::GUID> &InlinedGUIDs) {
getFunction(F).setEntryCount(
ProfileCount(Samples->getHeadSamples() + 1, Function::PCT_Real),
&InlinedGUIDs);
if (!SampleProfileUseProfi) {
computeDominanceAndLoopInfo(F);
findEquivalenceClasses(F);
}
buildEdges(F);
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::finalizeWeightPropagation(
FunctionT &F, const DenseSet<GlobalValue::GUID> &InlinedGUIDs) {
if (SampleProfileUseProfi) {
const BasicBlockT *EntryBB = getEntryBB(&F);
ErrorOr<uint64_t> EntryWeight = getBlockWeight(EntryBB);
if (BlockWeights[EntryBB] > 0 &&
(SampleProfileInferEntryCount || !EntryWeight)) {
getFunction(F).setEntryCount(
ProfileCount(BlockWeights[EntryBB], Function::PCT_Real),
&InlinedGUIDs);
}
}
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::emitCoverageRemarks(FunctionT &F) {
const Function &Func = getFunction(F);
if (SampleProfileRecordCoverage) {
unsigned Used = CoverageTracker.countUsedRecords(Samples, PSI);
unsigned Total = CoverageTracker.countBodyRecords(Samples, PSI);
unsigned Coverage = CoverageTracker.computeCoverage(Used, Total);
if (Coverage < SampleProfileRecordCoverage) {
Func.getContext().diagnose(DiagnosticInfoSampleProfile(
Func.getSubprogram()->getFilename(), getFunctionLoc(F),
Twine(Used) + " of " + Twine(Total) + " available profile records (" +
Twine(Coverage) + "%) were applied",
DS_Warning));
}
}
if (SampleProfileSampleCoverage) {
uint64_t Used = CoverageTracker.getTotalUsedSamples();
uint64_t Total = CoverageTracker.countBodySamples(Samples, PSI);
unsigned Coverage = CoverageTracker.computeCoverage(Used, Total);
if (Coverage < SampleProfileSampleCoverage) {
Func.getContext().diagnose(DiagnosticInfoSampleProfile(
Func.getSubprogram()->getFilename(), getFunctionLoc(F),
Twine(Used) + " of " + Twine(Total) + " available profile samples (" +
Twine(Coverage) + "%) were applied",
DS_Warning));
}
}
}
template <typename BT>
unsigned SampleProfileLoaderBaseImpl<BT>::getFunctionLoc(FunctionT &F) {
const Function &Func = getFunction(F);
if (DISubprogram *S = Func.getSubprogram())
return S->getLine();
if (NoWarnSampleUnused)
return 0;
Func.getContext().diagnose(DiagnosticInfoSampleProfile(
"No debug information found in function " + Func.getName() +
": Function profile not used",
DS_Warning));
return 0;
}
template <typename BT>
void SampleProfileLoaderBaseImpl<BT>::computeDominanceAndLoopInfo(
FunctionT &F) {
DT.reset(new DominatorTree);
DT->recalculate(F);
PDT.reset(new PostDominatorTree(F));
LI.reset(new LoopInfo);
LI->analyze(*DT);
}
#undef DEBUG_TYPE
} #endif