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 if (PrevProbeFactors.count(
I.first)) {
152 float PrevProbeFactor = PrevProbeFactors[
I.first];
153 if (std::abs(CurProbeFactor - PrevProbeFactor) >
154 DistributionFactorVariance) {
155 if (!BannerPrinted) {
156 dbgs() <<
"Function " <<
F->getName() <<
":\n";
157 BannerPrinted =
true;
159 dbgs() <<
"Probe " <<
I.first.first <<
"\tprevious factor "
160 <<
format(
"%0.2f", PrevProbeFactor) <<
"\tcurrent factor "
161 <<
format(
"%0.2f", CurProbeFactor) <<
"\n";
166 PrevProbeFactors[
I.first] =
I.second;
171 const std::string &CurModuleUniqueId)
172 :
F(&Func), CurModuleUniqueId(CurModuleUniqueId) {
173 BlockProbeIds.clear();
174 CallProbeIds.clear();
179 computeBlocksToIgnore(BlocksToIgnore, BlocksAndCallsToIgnore);
181 computeProbeId(BlocksToIgnore, BlocksAndCallsToIgnore);
182 computeCFGHash(BlocksToIgnore);
194void SampleProfileProber::computeBlocksToIgnore(
199 findUnreachableBlocks(BlocksAndCallsToIgnore);
201 BlocksToIgnore.
insert(BlocksAndCallsToIgnore.
begin(),
202 BlocksAndCallsToIgnore.
end());
210 findInvokeNormalDests(BlocksToIgnore);
214void SampleProfileProber::findUnreachableBlocks(
216 for (
auto &BB : *F) {
217 if (&BB != &
F->getEntryBlock() &&
pred_size(&BB) == 0)
218 BlocksToIgnore.
insert(&BB);
224void SampleProfileProber::findInvokeNormalDests(
226 for (
auto &BB : *F) {
227 auto *TI = BB.getTerminator();
228 if (
auto *
II = dyn_cast<InvokeInst>(TI)) {
229 auto *ND =
II->getNormalDest();
230 InvokeNormalDests.
insert(ND);
237 InvokeNormalDests.
insert(Pred);
251const Instruction *SampleProfileProber::getOriginalTerminator(
254 if (
auto *
II = dyn_cast<InvokeInst>(TI)) {
255 return getOriginalTerminator(
II->getNormalDest(), BlocksToIgnore);
259 return getOriginalTerminator(*
succ_begin(Head), BlocksToIgnore);
268void SampleProfileProber::computeCFGHash(
270 std::vector<uint8_t> Indexes;
272 for (
auto &BB : *F) {
276 auto *TI = getOriginalTerminator(&BB, BlocksToIgnore);
277 for (
unsigned I = 0, E = TI->getNumSuccessors();
I != E; ++
I) {
278 auto *Succ = TI->getSuccessor(
I);
279 auto Index = getBlockId(Succ);
283 for (
int J = 0; J < 4; J++)
284 Indexes.push_back((
uint8_t)(Index >> (J * 8)));
290 FunctionHash = (
uint64_t)CallProbeIds.size() << 48 |
293 FunctionHash &= 0x0FFFFFFFFFFFFFFF;
294 assert(FunctionHash &&
"Function checksum should not be zero");
295 LLVM_DEBUG(
dbgs() <<
"\nFunction Hash Computation for " <<
F->getName()
297 <<
" CRC = " << JC.
getCRC() <<
", Edges = "
298 << Indexes.size() <<
", ICSites = " << CallProbeIds.size()
299 <<
", Hash = " << FunctionHash <<
"\n");
302void SampleProfileProber::computeProbeId(
308 for (
auto &BB : *F) {
310 BlockProbeIds[&BB] = ++LastProbeId;
312 if (BlocksAndCallsToIgnore.
contains(&BB))
315 if (!isa<CallBase>(
I) || isa<IntrinsicInst>(&
I))
320 if (LastProbeId >= 0xFFFF) {
321 std::string Msg =
"Pseudo instrumentation incomplete for " +
322 std::string(
F->getName()) +
" because it's too large";
328 CallProbeIds[&
I] = ++LastProbeId;
334 auto I = BlockProbeIds.find(
const_cast<BasicBlock *
>(BB));
335 return I == BlockProbeIds.end() ? 0 :
I->second;
339 auto Iter = CallProbeIds.find(
const_cast<Instruction *
>(Call));
340 return Iter == CallProbeIds.end() ? 0 : Iter->second;
350 if (
auto *SP =
F.getSubprogram()) {
351 FName = SP->getLinkageName();
353 FName = SP->getName();
363 assert((isa<PseudoProbeInst>(
I) || isa<CallBase>(
I)) &&
364 "Expecting pseudo probe or call instructions");
365 if (!
I->getDebugLoc()) {
366 if (
auto *SP =
F.getSubprogram()) {
371 dbgs() <<
"\nIn Function " <<
F.getName()
372 <<
" Probe gets an artificial debug line\n";
380 for (
auto &
I : BlockProbeIds) {
390 return !isa<PHINode>(J) && !isa<DbgInfoIntrinsic>(J) &&
391 !J->isLifetimeStartOrEnd() && J->getDebugLoc();
401 "Cannot get the probing point");
407 auto *Probe = Builder.
CreateCall(ProbeFn, Args);
408 AssignDebugLoc(Probe);
411 if (
auto DIL = Probe->getDebugLoc()) {
412 if (DIL->getDiscriminator()) {
413 DIL = DIL->cloneWithDiscriminator(0);
414 Probe->setDebugLoc(DIL);
422 for (
auto &
I : CallProbeIds) {
423 auto *Call =
I.first;
425 uint32_t Type = cast<CallBase>(Call)->getCalledFunction()
428 AssignDebugLoc(Call);
429 if (
auto DIL = Call->getDebugLoc()) {
435 DIL->getBaseDiscriminator());
436 DIL = DIL->cloneWithDiscriminator(V);
437 Call->setDebugLoc(DIL);
446 auto Hash = getFunctionHash();
449 assert(NMD &&
"llvm.pseudo_probe_desc should be pre-created");
462 if (
F.isDeclaration())
471void PseudoProbeUpdatePass::runOnFunction(
Function &
F,
474 auto BBProfileCount = [&BFI](
BasicBlock *BB) {
475 return BFI.getBlockProfileCount(BB).value_or(0);
484 ProbeFactors[{Probe->Id, Hash}] += BBProfileCount(&
Block);
494 float Sum = ProbeFactors[{Probe->Id, Hash}];
506 if (
F.isDeclaration())
510 runOnFunction(
F,
FAM);
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
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.
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
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.
void update(ArrayRef< uint8_t > Data)
This is an important class for using LLVM in a threaded context.
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.
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.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void runAfterPass(StringRef PassID, Any IR)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Sample profile pseudo prober.
SampleProfileProber(Function &F, const std::string &CurModuleUniqueId)
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)
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.
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)
void setProbeDistributionFactor(Instruction &Inst, float Factor)
std::string getUniqueModuleId(Module *M)
Produce a unique identifier for this module by taking the MD5 sum of the names of the module's strong...
std::optional< PseudoProbe > extractProbe(const Instruction &Inst)
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)