33#include <unordered_set>
37#define DEBUG_TYPE "pseudo-probe"
40 "Number of probes that have an artificial debug line");
44 cl::desc(
"Do pseudo probe verification"));
48 cl::desc(
"The option to specify the name of the functions to verify."));
52 cl::desc(
"Update pseudo probe distribution factor"));
56 const DILocation *InlinedAt = DIL ? DIL->getInlinedAt() :
nullptr;
58 Hash ^=
MD5Hash(std::to_string(InlinedAt->getLine()));
59 Hash ^=
MD5Hash(std::to_string(InlinedAt->getColumn()));
60 auto Name = InlinedAt->getSubprogramLinkageName();
62 InlinedAt = InlinedAt->getInlinedAt();
71bool PseudoProbeVerifier::shouldVerifyFunction(
const Function *
F) {
73 if (
F->isDeclaration())
77 if (
F->hasAvailableExternallyLinkage())
80 static std::unordered_set<std::string> VerifyFuncNames(
82 return VerifyFuncNames.empty() || VerifyFuncNames.count(
F->getName().str());
97 "\n*** Pseudo Probe Verification After " + PassID.
str() +
" ***\n";
99 if (
const auto **M = llvm::any_cast<const Module *>(&
IR))
101 else if (
const auto **
F = llvm::any_cast<const Function *>(&
IR))
103 else if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
105 else if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
122 if (!shouldVerifyFunction(
F))
125 for (
const auto &BB : *
F)
126 collectProbeFactors(&BB, ProbeFactors);
127 verifyProbeFactors(
F, ProbeFactors);
131 const Function *
F =
L->getHeader()->getParent();
137 for (
const auto &
I : *
Block) {
140 ProbeFactors[{Probe->Id, Hash}] += Probe->Factor;
145void PseudoProbeVerifier::verifyProbeFactors(
147 bool BannerPrinted =
false;
148 auto &PrevProbeFactors = FunctionProbeFactors[
F->getName()];
149 for (
const auto &
I : ProbeFactors) {
150 float CurProbeFactor =
I.second;
151 auto [It,
Inserted] = PrevProbeFactors.try_emplace(
I.first);
153 float PrevProbeFactor = It->second;
154 if (std::abs(CurProbeFactor - PrevProbeFactor) >
155 DistributionFactorVariance) {
156 if (!BannerPrinted) {
157 dbgs() <<
"Function " <<
F->getName() <<
":\n";
158 BannerPrinted =
true;
160 dbgs() <<
"Probe " <<
I.first.first <<
"\tprevious factor "
161 <<
format(
"%0.2f", PrevProbeFactor) <<
"\tcurrent factor "
162 <<
format(
"%0.2f", CurProbeFactor) <<
"\n";
167 It->second =
I.second;
172 BlockProbeIds.clear();
173 CallProbeIds.clear();
178 computeBlocksToIgnore(BlocksToIgnore, BlocksAndCallsToIgnore);
180 computeProbeId(BlocksToIgnore, BlocksAndCallsToIgnore);
181 computeCFGHash(BlocksToIgnore);
193void SampleProfileProber::computeBlocksToIgnore(
198 findUnreachableBlocks(BlocksAndCallsToIgnore);
208 findInvokeNormalDests(BlocksToIgnore);
212void SampleProfileProber::findUnreachableBlocks(
214 for (
auto &BB : *F) {
215 if (&BB != &
F->getEntryBlock() &&
pred_size(&BB) == 0)
216 BlocksToIgnore.
insert(&BB);
222void SampleProfileProber::findInvokeNormalDests(
224 for (
auto &BB : *F) {
225 auto *TI = BB.getTerminator();
226 if (
auto *
II = dyn_cast<InvokeInst>(TI)) {
227 auto *ND =
II->getNormalDest();
228 InvokeNormalDests.
insert(ND);
235 InvokeNormalDests.
insert(Pred);
249const Instruction *SampleProfileProber::getOriginalTerminator(
252 if (
auto *
II = dyn_cast<InvokeInst>(TI)) {
253 return getOriginalTerminator(
II->getNormalDest(), BlocksToIgnore);
257 return getOriginalTerminator(*
succ_begin(Head), BlocksToIgnore);
266void SampleProfileProber::computeCFGHash(
268 std::vector<uint8_t> Indexes;
270 for (
auto &BB : *F) {
274 auto *TI = getOriginalTerminator(&BB, BlocksToIgnore);
275 for (
unsigned I = 0, E = TI->getNumSuccessors();
I != E; ++
I) {
276 auto *Succ = TI->getSuccessor(
I);
277 auto Index = getBlockId(Succ);
281 for (
int J = 0; J < 4; J++)
282 Indexes.push_back((
uint8_t)(Index >> (J * 8)));
288 FunctionHash = (
uint64_t)CallProbeIds.size() << 48 |
291 FunctionHash &= 0x0FFFFFFFFFFFFFFF;
292 assert(FunctionHash &&
"Function checksum should not be zero");
293 LLVM_DEBUG(
dbgs() <<
"\nFunction Hash Computation for " <<
F->getName()
295 <<
" CRC = " << JC.
getCRC() <<
", Edges = "
296 << Indexes.size() <<
", ICSites = " << CallProbeIds.size()
297 <<
", Hash = " << FunctionHash <<
"\n");
300void SampleProfileProber::computeProbeId(
306 for (
auto &BB : *F) {
308 BlockProbeIds[&BB] = ++LastProbeId;
310 if (BlocksAndCallsToIgnore.
contains(&BB))
313 if (!isa<CallBase>(
I) || isa<IntrinsicInst>(&
I))
318 if (LastProbeId >= 0xFFFF) {
319 std::string Msg =
"Pseudo instrumentation incomplete for " +
320 std::string(
F->getName()) +
" because it's too large";
326 CallProbeIds[&
I] = ++LastProbeId;
332 auto I = BlockProbeIds.find(
const_cast<BasicBlock *
>(BB));
333 return I == BlockProbeIds.end() ? 0 :
I->second;
337 auto Iter = CallProbeIds.find(
const_cast<Instruction *
>(Call));
338 return Iter == CallProbeIds.end() ? 0 : Iter->second;
348 if (
auto *SP =
F.getSubprogram()) {
349 FName = SP->getLinkageName();
351 FName = SP->getName();
361 assert((isa<PseudoProbeInst>(
I) || isa<CallBase>(
I)) &&
362 "Expecting pseudo probe or call instructions");
363 if (!
I->getDebugLoc()) {
364 if (
auto *SP =
F.getSubprogram()) {
369 dbgs() <<
"\nIn Function " <<
F.getName()
370 <<
" Probe gets an artificial debug line\n";
378 for (
auto &
I : BlockProbeIds) {
388 return !isa<PHINode>(J) && !J->isLifetimeStartOrEnd() && J->getDebugLoc();
398 "Cannot get the probing point");
404 auto *Probe = Builder.
CreateCall(ProbeFn, Args);
405 AssignDebugLoc(Probe);
408 if (
auto DIL = Probe->getDebugLoc()) {
409 if (DIL->getDiscriminator()) {
410 DIL = DIL->cloneWithDiscriminator(0);
411 Probe->setDebugLoc(DIL);
419 for (
auto &
I : CallProbeIds) {
420 auto *Call =
I.first;
422 uint32_t Type = cast<CallBase>(Call)->getCalledFunction()
425 AssignDebugLoc(Call);
426 if (
auto DIL = Call->getDebugLoc()) {
432 DIL->getBaseDiscriminator());
433 DIL = DIL->cloneWithDiscriminator(V);
434 Call->setDebugLoc(DIL);
443 auto Hash = getFunctionHash();
446 assert(NMD &&
"llvm.pseudo_probe_desc should be pre-created");
458 if (
F.isDeclaration())
467void PseudoProbeUpdatePass::runOnFunction(
Function &
F,
470 auto BBProfileCount = [&BFI](
BasicBlock *BB) {
471 return BFI.getBlockProfileCount(BB).value_or(0);
480 ProbeFactors[{Probe->Id, Hash}] += BBProfileCount(&
Block);
490 float Sum = ProbeFactors[{Probe->Id, Hash}];
502 if (
F.isDeclaration())
506 runOnFunction(
F,
FAM);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Module.h This file contains the declarations for the Module class.
Legalize the Machine IR a function s Machine IR
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
PassInstrumentationCallbacks PIC
static cl::opt< bool > UpdatePseudoProbe("update-pseudo-probe", cl::init(true), cl::Hidden, cl::desc("Update pseudo probe distribution factor"))
static cl::opt< bool > VerifyPseudoProbe("verify-pseudo-probe", cl::init(false), cl::Hidden, cl::desc("Do pseudo probe verification"))
static cl::list< std::string > VerifyPseudoProbeFuncList("verify-pseudo-probe-funcs", cl::Hidden, cl::desc("The option to specify the name of the functions to verify."))
static uint64_t computeCallStackHash(const Instruction &Inst)
static uint64_t getCallStackHash(const DILocation *DIL)
This file provides the interface for the pseudo probe implementation for AutoFDO.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Implements a dense probed hash-table based set.
Diagnostic information for the sample profiler.
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
BasicBlock::iterator GetInsertPoint() const
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
This is an important class for using LLVM in a threaded context.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
A node in the call graph.
An SCC of the call graph.
Represents a single loop in the control flow graph.
LLVM_ABI MDNode * createPseudoProbeDesc(uint64_t GUID, uint64_t Hash, StringRef FName)
Return metadata containing the pseudo probe descriptor for a function.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void runAfterPass(StringRef PassID, Any IR)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Sample profile pseudo prober.
LLVM_ABI SampleProfileProber(Function &F)
LLVM_ABI void instrumentOneFunc(Function &F, TargetMachine *TM)
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
Primary interface to the complete machine description for the target machine.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
std::pair< iterator, bool > insert(const ValueT &V)
void insert_range(Range &&R)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
initializer< Ty > init(const Ty &Val)
uint64_t MD5Hash(const FunctionId &Obj)
This is an optimization pass for GlobalISel generic memory operations.
static constexpr uint64_t PseudoProbeFullDistributionFactor
auto pred_size(const MachineBasicBlock *BB)
LLVM_ABI void setProbeDistributionFactor(Instruction &Inst, float Factor)
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.
auto succ_size(const MachineBasicBlock *BB)
static void computeEHOnlyBlocks(FunctionT &F, DenseSet< BlockT * > &EHBlocks)
Compute a list of blocks that are only reachable via EH paths.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
std::unordered_map< std::pair< uint64_t, uint64_t >, float, pair_hash< uint64_t, uint64_t > > ProbeFactorMap
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
auto pred_begin(const MachineBasicBlock *BB)
constexpr const char * PseudoProbeDescMetadataName
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
void registerAfterPassCallback(CallableT C, bool ToFront=false)
static constexpr uint8_t FullDistributionFactor
static uint32_t packProbeData(uint32_t Index, uint32_t Type, uint32_t Flags, uint32_t Factor, std::optional< uint32_t > DwarfBaseDiscriminator)