40#define DEBUG_TYPE "pseudo-probe"
43 "Number of probes that have an artificial debug line");
47 cl::desc(
"Do pseudo probe verification"));
51 cl::desc(
"The option to specify the name of the functions to verify."));
55 cl::desc(
"Update pseudo probe distribution factor"));
59 const DILocation *InlinedAt = DIL ? DIL->getInlinedAt() :
nullptr;
61 Hash ^=
MD5Hash(std::to_string(InlinedAt->getLine()));
62 Hash ^=
MD5Hash(std::to_string(InlinedAt->getColumn()));
63 auto Name = InlinedAt->getSubprogramLinkageName();
65 InlinedAt = InlinedAt->getInlinedAt();
74bool PseudoProbeVerifier::shouldVerifyFunction(
const Function *
F) {
76 if (
F->isDeclaration())
80 if (
F->hasAvailableExternallyLinkage())
85 return VerifyFuncNames.empty() || VerifyFuncNames.contains(
F->getName());
90 PIC.registerAfterPassCallback(
100 "\n*** Pseudo Probe Verification After " +
PassID.str() +
" ***\n";
125 if (!shouldVerifyFunction(
F))
128 for (
const auto &BB : *
F)
129 collectProbeFactors(&BB, ProbeFactors);
130 verifyProbeFactors(
F, ProbeFactors);
134 const Function *
F =
L->getHeader()->getParent();
140 for (
const auto &
I : *
Block) {
143 ProbeFactors[{Probe->Id, Hash}] += Probe->Factor;
148void PseudoProbeVerifier::verifyProbeFactors(
150 bool BannerPrinted =
false;
151 auto &PrevProbeFactors = FunctionProbeFactors[
F->getName()];
152 for (
const auto &
I : ProbeFactors) {
153 float CurProbeFactor =
I.second;
154 auto [It,
Inserted] = PrevProbeFactors.try_emplace(
I.first);
156 float PrevProbeFactor = It->second;
157 if (std::abs(CurProbeFactor - PrevProbeFactor) >
158 DistributionFactorVariance) {
159 if (!BannerPrinted) {
160 dbgs() <<
"Function " <<
F->getName() <<
":\n";
161 BannerPrinted =
true;
163 dbgs() <<
"Probe " <<
I.first.first <<
"\tprevious factor "
164 <<
format(
"%0.2f", PrevProbeFactor) <<
"\tcurrent factor "
165 <<
format(
"%0.2f", CurProbeFactor) <<
"\n";
170 It->second =
I.second;
175 BlockProbeIds.clear();
176 CallProbeIds.clear();
181 computeBlocksToIgnore(BlocksToIgnore, BlocksAndCallsToIgnore);
183 computeProbeId(BlocksToIgnore, BlocksAndCallsToIgnore);
184 computeCFGHash(BlocksToIgnore);
196void SampleProfileProber::computeBlocksToIgnore(
201 findUnreachableBlocks(BlocksAndCallsToIgnore);
211 findInvokeNormalDests(BlocksToIgnore);
215void SampleProfileProber::findUnreachableBlocks(
217 for (
auto &BB : *
F) {
218 if (&BB != &
F->getEntryBlock() &&
pred_size(&BB) == 0)
219 BlocksToIgnore.
insert(&BB);
236 OnCurrentPath.
clear();
241 auto CycleStart =
llvm::find(CurrentPath, Cur);
242 assert(CycleStart != CurrentPath.
end() &&
243 "OnCurrentPath must hold exactly the blocks in CurrentPath");
244 CycleBlocks.
insert(CycleStart, CurrentPath.
end());
249 OnCurrentPath.
insert(Cur);
252 Cur =
II->getNormalDest();
263void SampleProfileProber::findInvokeNormalDests(
265 DenseSet<const BasicBlock *> CycleBlocks;
268 for (
auto &BB : *F) {
269 auto *TI = BB.getTerminator();
271 auto *ND =
II->getNormalDest();
274 InvokeNormalDests.
insert(ND);
281 InvokeNormalDests.
insert(Pred);
295const Instruction *SampleProfileProber::getOriginalTerminator(
299 DenseSet<const BasicBlock *> Visited;
306 Next =
II->getNormalDest();
325void SampleProfileProber::computeCFGHash(
327 std::vector<uint8_t> Indexes;
329 for (
auto &BB : *F) {
333 auto *TI = getOriginalTerminator(&BB, BlocksToIgnore);
334 for (
unsigned I = 0,
E = TI->getNumSuccessors();
I !=
E; ++
I) {
335 auto *Succ = TI->getSuccessor(
I);
336 auto Index = getBlockId(Succ);
340 for (
int J = 0; J < 4; J++)
341 Indexes.push_back((uint8_t)(Index >> (J * 8)));
347 FunctionHash = (
uint64_t)CallProbeIds.size() << 48 |
350 FunctionHash &= 0x0FFFFFFFFFFFFFFF;
351 assert(FunctionHash &&
"Function checksum should not be zero");
352 LLVM_DEBUG(
dbgs() <<
"\nFunction Hash Computation for " << F->getName()
354 <<
" CRC = " << JC.
getCRC() <<
", Edges = "
355 << Indexes.size() <<
", ICSites = " << CallProbeIds.size()
356 <<
", Hash = " << FunctionHash <<
"\n");
359void SampleProfileProber::computeProbeId(
362 LLVMContext &Ctx = F->getContext();
365 for (
auto &BB : *F) {
367 BlockProbeIds[&BB] = ++LastProbeId;
369 if (BlocksAndCallsToIgnore.
contains(&BB))
377 if (LastProbeId >= 0xFFFF) {
378 std::string
Msg =
"Pseudo instrumentation incomplete for " +
379 std::string(F->getName()) +
" because it's too large";
381 DiagnosticInfoSampleProfile(
M->getName().data(),
Msg,
DS_Warning));
385 CallProbeIds[&
I] = ++LastProbeId;
390uint32_t SampleProfileProber::getBlockId(
const BasicBlock *BB)
const {
391 auto I = BlockProbeIds.find(
const_cast<BasicBlock *
>(BB));
392 return I == BlockProbeIds.end() ? 0 :
I->second;
395uint32_t SampleProfileProber::getCallsiteId(
const Instruction *
Call)
const {
397 return Iter == CallProbeIds.end() ? 0 : Iter->second;
401 Module *M = F.getParent();
407 if (
auto *SP = F.getSubprogram()) {
408 FName = SP->getLinkageName();
410 FName = SP->getName();
421 "Expecting pseudo probe or call instructions");
422 if (!
I->getDebugLoc()) {
423 if (
auto *SP = F.getSubprogram()) {
428 dbgs() <<
"\nIn Function " << F.getName()
429 <<
" Probe gets an artificial debug line\n";
437 for (
auto &
I : BlockProbeIds) {
447 return !
isa<PHINode>(J) && !J->isLifetimeStartOrEnd() && J->getDebugLoc();
462 if ((CI->isMustTailCall() ||
463 CI->getIntrinsicID() == Intrinsic::experimental_deoptimize) &&
468 assert(Builder.GetInsertPoint() != BB->
end() &&
469 "Cannot get the probing point");
472 Value *Args[] = {Builder.getInt64(
Guid), Builder.getInt64(Index),
475 auto *Probe = Builder.CreateCall(ProbeFn, Args);
476 AssignDebugLoc(Probe);
479 if (
auto DIL = Probe->getDebugLoc()) {
480 if (DIL->getDiscriminator()) {
481 DIL = DIL->cloneWithDiscriminator(0);
482 Probe->setDebugLoc(DIL);
490 for (
auto &
I : CallProbeIds) {
491 auto *
Call =
I.first;
496 AssignDebugLoc(
Call);
497 if (
auto DIL =
Call->getDebugLoc()) {
503 DIL->getBaseDiscriminator());
504 DIL = DIL->cloneWithDiscriminator(V);
505 Call->setDebugLoc(DIL);
514 auto Hash = getFunctionHash();
517 assert(NMD &&
"llvm.pseudo_probe_desc should be pre-created");
529 if (
F.isDeclaration())
538void PseudoProbeUpdatePass::runOnFunction(
Function &
F,
541 auto BBProfileCount = [&BFI](
BasicBlock *BB) {
551 ProbeFactors[{Probe->Id, Hash}] += BBProfileCount(&
Block);
561 float Sum = ProbeFactors[{Probe->Id, Hash}];
573 if (
F.isDeclaration())
577 runOnFunction(
F,
FAM);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
static cl::opt< bool > UpdatePseudoProbe("update-pseudo-probe", cl::init(true), cl::Hidden, cl::desc("Update pseudo probe distribution factor"))
static void findInvokeNormalDestCycles(const Function &F, DenseSet< const BasicBlock * > &CycleBlocks)
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 SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
StringSet - A set-like wrapper for the StringMap.
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; assumes that the block is well-formed.
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
LLVM_ABI std::optional< uint64_t > getBlockProfileCount(const BasicBlock *BB, bool AllowSynthetic=false) const
Returns the estimated profile count of BB.
Implements a dense probed hash-table based set.
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
A type-erased reference to the IR unit a pass or analysis is running on, together with the kind of IR...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
LLVM_ABI void update(ArrayRef< uint8_t > Data)
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.
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
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, IRUnitRef 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)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
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)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
void insert_range(Range &&R)
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.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
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)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
DenseMap< std::pair< uint64_t, uint64_t >, float > ProbeFactorMap
static constexpr uint64_t PseudoProbeFullDistributionFactor
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr from_range_t from_range
auto pred_size(const MachineBasicBlock *BB)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI void setProbeDistributionFactor(Instruction &Inst, float Factor)
auto dyn_cast_or_null(const Y &Val)
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.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
constexpr const char * PseudoProbeDescMetadataName
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)