15#ifndef LLVM_TRANSFORMS_UTILS_SAMPLEPROFILELOADERBASEIMPL_H
16#define LLVM_TRANSFORMS_UTILS_SAMPLEPROFILELOADERBASEIMPL_H
48using namespace sampleprof;
49using namespace sampleprofutil;
56#define DEBUG_TYPE "sample-profile-impl"
58namespace afdo_detail {
77 return &
F->getEntryBlock();
95 for (
const auto *Operand : FuncInfo->operands()) {
96 const auto *MD = cast<MDNode>(Operand);
97 auto GUID = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0))
99 auto Hash = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1))
107 auto I = GUIDToProbeDescMap.
find(GUID);
108 return I == GUIDToProbeDescMap.
end() ? nullptr : &
I->second;
131 bool IsAvailableExternallyLinkage =
145 if (IsAvailableExternallyLinkage || !
Desc)
146 return !
F.hasFnAttribute(
"profile-checksum-mismatch");
157 return F.isDeclaration() || !
F.hasFnAttribute(
"use-sample-profile");
162 std::vector<Function *> &FunctionOrderList) {
169 FunctionOrderList.push_back(&
F);
173 std::reverse(FunctionOrderList.begin(), FunctionOrderList.end());
184 using BT = std::remove_pointer_t<NodeRef>;
208 using Edge = std::pair<const BasicBlockT *, const BasicBlockT *>;
307 std::unique_ptr<SampleProfileReader>
Reader;
337template <
typename BT>
339 BlockWeights.clear();
341 VisitedBlocks.clear();
342 VisitedEdges.clear();
343 EquivalenceClass.clear();
349 Predecessors.clear();
351 CoverageTracker.clear();
359template <
typename BT>
361 OS <<
"weight[" <<
E.first->getName() <<
"->" <<
E.second->getName()
362 <<
"]: " << EdgeWeights[
E] <<
"\n";
369template <
typename BT>
373 OS <<
"equivalence[" << BB->getName()
374 <<
"]: " << ((Equiv) ? EquivalenceClass[BB]->
getName() :
"NONE") <<
"\n";
381template <
typename BT>
384 const auto &
I = BlockWeights.find(BB);
385 uint64_t W = (
I == BlockWeights.end() ? 0 :
I->second);
386 OS <<
"weight[" << BB->getName() <<
"]: " << W <<
"\n";
401template <
typename BT>
405 return getProbeWeight(Inst);
406 return getInstWeightImpl(Inst);
409template <
typename BT>
414 return std::error_code();
416 const DebugLoc &DLoc = Inst.getDebugLoc();
418 return std::error_code();
424 Discriminator = DIL->getDiscriminator();
431 CoverageTracker.markSamplesUsed(FS, LineOffset, Discriminator, R.get());
436 Remark <<
" samples from profile (offset: ";
447 << Inst <<
" (line offset: " << LineOffset <<
"."
448 << Discriminator <<
" - weight: " << R.get() <<
")\n");
453template <
typename BT>
457 "Profile is not pseudo probe based");
462 return std::error_code();
470 return std::error_code();
473 auto R = FS->findSamplesAt(Probe->Id, Probe->Discriminator);
475 uint64_t Samples = R.get() * Probe->Factor;
476 bool FirstMark = CoverageTracker.markSamplesUsed(FS, Probe->Id, 0, Samples);
481 Remark <<
" samples from profile (ProbeId=";
483 if (Probe->Discriminator) {
489 Remark <<
", OriginalSamples=";
496 if (Probe->Discriminator)
497 dbgs() <<
"." << Probe->Discriminator;
498 dbgs() <<
":" << Inst <<
" - weight: " << R.get()
499 <<
" - factor: " <<
format(
"%0.2f", Probe->Factor) <<
")\n";});
513template <
typename BT>
517 bool HasWeight =
false;
518 for (
auto &
I : *BB) {
521 Max = std::max(Max, R.get());
534template <
typename BT>
536 bool Changed =
false;
538 for (
const auto &BB :
F) {
541 BlockWeights[&BB] = Weight.
get();
542 VisitedBlocks.insert(&BB);
560template <
typename BT>
567 auto it = DILocation2SampleMap.try_emplace(DIL,
nullptr);
569 it.first->second = Samples->findFunctionSamples(DIL, Reader->getRemapper());
571 return it.first->second;
597template <
typename BT>
603 for (
const auto *BB2 : Descendants) {
604 bool IsDomParent = DomTree->dominates(BB2, BB1);
605 bool IsInSameLoop = LI->getLoopFor(BB1) == LI->getLoopFor(BB2);
606 if (BB1 != BB2 && IsDomParent && IsInSameLoop) {
607 EquivalenceClass[BB2] = EC;
609 if (VisitedBlocks.count(BB2)) {
610 VisitedBlocks.insert(EC);
621 Weight = std::max(Weight, BlockWeights[BB2]);
624 const BasicBlockT *EntryBB = getEntryBB(EC->getParent());
626 BlockWeights[EC] = Samples->getHeadSamples() + 1;
628 BlockWeights[EC] = Weight;
641template <
typename BT>
651 auto [It, Inserted] = EquivalenceClass.try_emplace(BB1, BB1);
667 DominatedBBs.
clear();
669 findEquivalencesFor(BB1, DominatedBBs, &*PDT);
681 dbgs() <<
"\nAssign the same weight to all blocks in the same class\n");
686 BlockWeights[BB] = BlockWeights[EquivBB];
701template <
typename BT>
703 unsigned *NumUnknownEdges,
705 if (!VisitedEdges.count(
E)) {
706 (*NumUnknownEdges)++;
711 return EdgeWeights[
E];
727template <
typename BT>
730 bool Changed =
false;
732 for (
const auto &BI :
F) {
741 for (
unsigned i = 0; i < 2; i++) {
743 unsigned NumUnknownEdges = 0, NumTotalEdges = 0;
744 Edge UnknownEdge, SelfReferentialEdge, SingleEdge;
748 auto &Preds = Predecessors[BB];
749 NumTotalEdges = Preds.size();
750 for (
auto *Pred : Preds) {
751 Edge E = std::make_pair(Pred, BB);
752 TotalWeight += visitEdge(
E, &NumUnknownEdges, &UnknownEdge);
753 if (
E.first ==
E.second)
754 SelfReferentialEdge =
E;
756 if (NumTotalEdges == 1) {
757 SingleEdge = std::make_pair(Predecessors[BB][0], BB);
761 auto &Succs = Successors[BB];
762 NumTotalEdges = Succs.size();
763 for (
auto *Succ : Succs) {
764 Edge E = std::make_pair(BB, Succ);
765 TotalWeight += visitEdge(
E, &NumUnknownEdges, &UnknownEdge);
767 if (NumTotalEdges == 1) {
768 SingleEdge = std::make_pair(BB, Successors[BB][0]);
795 if (NumUnknownEdges <= 1) {
796 uint64_t &BBWeight = BlockWeights[EC];
797 if (NumUnknownEdges == 0) {
798 if (!VisitedBlocks.count(EC)) {
802 if (TotalWeight > BBWeight) {
803 BBWeight = TotalWeight;
806 <<
" known. Set weight for block: ";
807 printBlockWeight(
dbgs(), BB););
809 }
else if (NumTotalEdges == 1 &&
810 EdgeWeights[SingleEdge] < BlockWeights[EC]) {
813 EdgeWeights[SingleEdge] = BlockWeights[EC];
816 }
else if (NumUnknownEdges == 1 && VisitedBlocks.count(EC)) {
819 if (BBWeight >= TotalWeight)
820 EdgeWeights[UnknownEdge] = BBWeight - TotalWeight;
822 EdgeWeights[UnknownEdge] = 0;
825 OtherEC = EquivalenceClass[UnknownEdge.first];
827 OtherEC = EquivalenceClass[UnknownEdge.second];
829 if (VisitedBlocks.count(OtherEC) &&
830 EdgeWeights[UnknownEdge] > BlockWeights[OtherEC])
831 EdgeWeights[UnknownEdge] = BlockWeights[OtherEC];
832 VisitedEdges.insert(UnknownEdge);
835 printEdgeWeight(
dbgs(), UnknownEdge));
837 }
else if (VisitedBlocks.count(EC) && BlockWeights[EC] == 0) {
840 for (
auto *Pred : Predecessors[BB]) {
841 Edge E = std::make_pair(Pred, BB);
843 VisitedEdges.insert(
E);
846 for (
auto *Succ : Successors[BB]) {
847 Edge E = std::make_pair(BB, Succ);
849 VisitedEdges.insert(
E);
852 }
else if (SelfReferentialEdge.first && VisitedBlocks.count(EC)) {
853 uint64_t &BBWeight = BlockWeights[BB];
855 if (BBWeight >= TotalWeight)
856 EdgeWeights[SelfReferentialEdge] = BBWeight - TotalWeight;
858 EdgeWeights[SelfReferentialEdge] = 0;
859 VisitedEdges.insert(SelfReferentialEdge);
862 printEdgeWeight(
dbgs(), SelfReferentialEdge));
864 if (UpdateBlockCount && TotalWeight > 0 &&
865 VisitedBlocks.insert(EC).second) {
866 BlockWeights[EC] = TotalWeight;
879template <
typename BT>
886 auto &Preds = Predecessors[B1];
889 for (
auto *B2 : getPredecessors(B1))
890 if (Visited.
insert(B2).second)
895 auto &Succs = Successors[B1];
898 for (
auto *B2 : getSuccessors(B1))
899 if (Visited.
insert(B2).second)
921template <
typename BT>
928 for (
const auto &BI :
F) {
931 SampleBlockWeights[&BI] = Weight.
get();
934 applyProfi(
F, Successors, SampleBlockWeights, BlockWeights, EdgeWeights);
943 LoopT *L = LI->getLoopFor(BB);
948 if (Header && BlockWeights[BB] > BlockWeights[Header]) {
949 BlockWeights[Header] = BlockWeights[BB];
955 Changed = propagateThroughEdges(
F,
false);
961 VisitedEdges.clear();
964 Changed = propagateThroughEdges(
F,
false);
971 Changed = propagateThroughEdges(
F,
true);
976template <
typename FT>
981 Infer.apply(BlockWeights, EdgeWeights);
1030template <
typename BT>
1033 bool Changed = (InlinedGUIDs.
size() != 0);
1036 Changed |= computeBlockWeights(
F);
1040 initWeightPropagation(
F, InlinedGUIDs);
1043 propagateWeights(
F);
1046 finalizeWeightPropagation(
F, InlinedGUIDs);
1052template <
typename BT>
1066 computeDominanceAndLoopInfo(
F);
1069 findEquivalenceClasses(
F);
1080template <
typename BT>
1092 if (BlockWeights[EntryBB] > 0) {
1100template <
typename BT>
1105 unsigned Used = CoverageTracker.countUsedRecords(Samples, PSI);
1106 unsigned Total = CoverageTracker.countBodyRecords(Samples, PSI);
1107 unsigned Coverage = CoverageTracker.computeCoverage(Used,
Total);
1110 Func.getSubprogram()->getFilename(), getFunctionLoc(
F),
1111 Twine(Used) +
" of " +
Twine(
Total) +
" available profile records (" +
1112 Twine(Coverage) +
"%) were applied",
1118 uint64_t Used = CoverageTracker.getTotalUsedSamples();
1119 uint64_t Total = CoverageTracker.countBodySamples(Samples, PSI);
1120 unsigned Coverage = CoverageTracker.computeCoverage(Used,
Total);
1123 Func.getSubprogram()->getFilename(), getFunctionLoc(
F),
1124 Twine(Used) +
" of " +
Twine(
Total) +
" available profile samples (" +
1125 Twine(Coverage) +
"%) were applied",
1142template <
typename BT>
1146 return S->getLine();
1154 "No debug information found in function " + Func.getName() +
1155 ": Function profile not used",
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file defines a set of templates that efficiently compute a dominator tree over a generic graph.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
This file defines the RefCountedBase, ThreadSafeRefCountedBase, and IntrusiveRefCntPtr classes.
Implements a lazy call graph analysis and related passes for the new pass manager.
static StringRef getName(Value *V)
This file provides the interface for the profile inference algorithm, profi.
This file provides the utility functions for the sampled PGO loader base implementation.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
unsigned getBaseDiscriminator() const
Returns the base discriminator stored in the discriminator.
Subprogram description. Uses SubclassData1.
LLVM_ABI unsigned getLine() const
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Implements a dense probed hash-table based set.
Diagnostic information for the sample profiler.
void getDescendants(NodeT *R, SmallVectorImpl< NodeT * > &Result) const
Get all nodes dominated by R, including R itself.
Represents either an error or a value T.
Class to represent profile counts.
void setEntryCount(ProfileCount Count, const DenseSet< GlobalValue::GUID > *Imports=nullptr)
Set the entry count for this function.
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
A node in the call graph.
A RefSCC of the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
LLVM_ABI void buildRefSCCs()
iterator_range< postorder_ref_scc_iterator > postorder_ref_sccs()
Represents a single loop in the control flow graph.
A Module instance is used to store all the information related to an LLVM module.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
Analysis providing profile information.
uint64_t getFunctionHash() const
const PseudoProbeDescriptor * getDesc(StringRef FProfileName) const
bool profileIsHashMismatched(const PseudoProbeDescriptor &FuncDesc, const FunctionSamples &Samples) const
const PseudoProbeDescriptor * getDesc(const Function &F) const
bool moduleIsProbed(const Module &M) const
bool profileIsValid(const Function &F, const FunctionSamples &Samples) const
PseudoProbeManager(const Module &M)
const PseudoProbeDescriptor * getDesc(uint64_t GUID) const
Sample profile inference pass.
bool computeAndPropagateWeights(FunctionT &F, const DenseSet< GlobalValue::GUID > &InlinedGUIDs)
Generate branch weight metadata for all branches in F.
void computeDominanceAndLoopInfo(FunctionT &F)
typename afdo_detail::IRTraits< BT >::BasicBlockT BasicBlockT
IntrusiveRefCntPtr< vfs::FileSystem > FS
VirtualFileSystem to load profile files from.
typename afdo_detail::IRTraits< BT >::OptRemarkAnalysisT OptRemarkAnalysisT
typename afdo_detail::IRTraits< BT >::SuccRangeT SuccRangeT
EdgeWeightMap EdgeWeights
Map edges to their computed weights.
Function & getFunction(FunctionT &F)
SmallSet< Edge, 32 > VisitedEdges
Set of visited edges during propagation.
std::map< SampleContext, FunctionSamples > OutlineFunctionSamples
Synthetic samples created by duplicating the samples of inlined functions from the original profile a...
OptRemarkEmitterT * ORE
Optimization Remark Emitter used to emit diagnostic remarks.
const BasicBlockT * getEntryBB(const FunctionT *F)
ErrorOr< uint64_t > getBlockWeight(const BasicBlockT *BB)
Compute the weight of a basic block.
unsigned getFunctionLoc(FunctionT &Func)
Get the line number for the function header.
PredRangeT getPredecessors(BasicBlockT *BB)
ErrorOr< uint64_t > getInstWeightImpl(const InstructionT &Inst)
virtual ErrorOr< uint64_t > getInstWeight(const InstructionT &Inst)
Get the weight for an instruction.
SmallPtrSet< const BasicBlockT *, 32 > VisitedBlocks
Set of visited blocks during propagation.
EquivalenceClassMap EquivalenceClass
Equivalence classes for block weights.
typename afdo_detail::IRTraits< BT >::DominatorTreePtrT DominatorTreePtrT
SampleCoverageTracker CoverageTracker
Profile coverage tracker.
typename afdo_detail::IRTraits< BT >::LoopT LoopT
typename GraphTraits< FT * >::NodeRef NodeRef
std::unique_ptr< SampleProfileReader > Reader
Profile reader object.
typename afdo_detail::IRTraits< BT >::OptRemarkEmitterT OptRemarkEmitterT
void printBlockWeight(raw_ostream &OS, const BasicBlockT *BB) const
Print the weight of block BB on stream OS.
DominatorTreePtrT DT
Dominance, post-dominance and loop information.
void printBlockEquivalence(raw_ostream &OS, const BasicBlockT *BB)
Print the equivalence class of block BB on stream OS.
std::remove_pointer_t< NodeRef > BT
SampleProfileLoaderBaseImpl(std::string Name, std::string RemapName, IntrusiveRefCntPtr< vfs::FileSystem > FS)
std::unique_ptr< PseudoProbeManager > ProbeManager
~SampleProfileLoaderBaseImpl()=default
typename afdo_detail::IRTraits< BT >::LoopInfoPtrT LoopInfoPtrT
void emitCoverageRemarks(FunctionT &F)
SuccRangeT getSuccessors(BasicBlockT *BB)
std::string Filename
Name of the profile file to load.
bool propagateThroughEdges(FunctionT &F, bool UpdateBlockCount)
Propagate weights through incoming/outgoing edges.
PostDominatorTreePtrT PDT
typename afdo_detail::IRTraits< BT >::InstructionT InstructionT
uint64_t visitEdge(Edge E, unsigned *NumUnknownEdges, Edge *UnknownEdge)
Visit the given edge to decide if it has a valid weight.
typename afdo_detail::IRTraits< BT >::PostDominatorTreePtrT PostDominatorTreePtrT
void initWeightPropagation(FunctionT &F, const DenseSet< GlobalValue::GUID > &InlinedGUIDs)
BlockEdgeMap Predecessors
Predecessors for each basic block in the CFG.
void finalizeWeightPropagation(FunctionT &F, const DenseSet< GlobalValue::GUID > &InlinedGUIDs)
bool computeBlockWeights(FunctionT &F)
Compute and store the weights of every basic block.
virtual const FunctionSamples * findFunctionSamples(const InstructionT &I) const
Get the FunctionSamples for an instruction.
typename afdo_detail::IRTraits< BT >::PostDominatorTreeT PostDominatorTreeT
virtual ErrorOr< uint64_t > getProbeWeight(const InstructionT &Inst)
std::string RemappingFilename
Name of the profile remapping file to load.
typename afdo_detail::IRTraits< BT >::PredRangeT PredRangeT
void applyProfi(FunctionT &F, BlockEdgeMap &Successors, BlockWeightMap &SampleBlockWeights, BlockWeightMap &BlockWeights, EdgeWeightMap &EdgeWeights)
typename afdo_detail::IRTraits< BT >::BlockFrequencyInfoT BlockFrequencyInfoT
BlockEdgeMap Successors
Successors for each basic block in the CFG.
FunctionSamples * Samples
Samples collected for the body of this function.
void findEquivalenceClasses(FunctionT &F)
Find equivalence classes.
std::pair< const BasicBlockT *, const BasicBlockT * > Edge
ProfileSummaryInfo * PSI
Profile Summary Info computed from sample profile.
void clearFunctionData(bool ResetDT=true)
Clear all the per-function data used to load samples and propagate weights.
DenseMap< const DILocation *, const FunctionSamples * > DILocation2SampleMap
void buildEdges(FunctionT &F)
Build in/out edge lists for each basic block in the CFG.
void findEquivalencesFor(BasicBlockT *BB1, ArrayRef< BasicBlockT * > Descendants, PostDominatorTreeT *DomTree)
Find equivalence classes for the given block.
void printEdgeWeight(raw_ostream &OS, Edge E)
Print the weight of edge E on stream OS.
typename afdo_detail::IRTraits< BT >::FunctionT FunctionT
BlockWeightMap BlockWeights
Map basic blocks to their computed weights.
void propagateWeights(FunctionT &F)
Propagate weights into edges.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Representation of the samples collected for a function.
uint64_t getFunctionHash() const
static LLVM_ABI bool ProfileIsProbeBased
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
static LLVM_ABI unsigned getOffset(const DILocation *DIL)
Returns the line offset to the start line of the subprogram.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
template class LLVM_TEMPLATE_ABI opt< bool >
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
Function::ProfileCount ProfileCount
auto successors(const MachineBasicBlock *BB)
cl::opt< unsigned > SampleProfileSampleCoverage
static void buildTopDownFuncOrder(LazyCallGraph &CG, std::vector< Function * > &FunctionOrderList)
cl::opt< unsigned > SampleProfileRecordCoverage
cl::opt< unsigned > SampleProfileMaxPropagateIterations
cl::opt< bool > SampleProfileUseProfi
LLVM_ABI cl::opt< bool > EnableFSDiscriminator
LLVM_ABI std::optional< PseudoProbe > extractProbe(const Instruction &Inst)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< succ_iterator > succ_range
cl::opt< bool > NoWarnSampleUnused
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
iterator_range< pred_iterator > pred_range
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
static bool skipProfileForFunction(const Function &F)
auto predecessors(const MachineBasicBlock *BB)
constexpr const char * PseudoProbeDescMetadataName
Implement std::hash so that hash_code can be used in STL containers.
Description of the encoding of one expression Op.
typename GraphType::UnknownGraphTypeError NodeRef
std::unique_ptr< LoopInfo > LoopInfoPtrT
std::unique_ptr< PostDominatorTree > PostDominatorTreePtrT
static Function & getFunction(Function &F)
static pred_range getPredecessors(BasicBlock *BB)
static succ_range getSuccessors(BasicBlock *BB)
std::unique_ptr< DominatorTree > DominatorTreePtrT
static const BasicBlock * getEntryBB(const Function *F)