34#include <unordered_set>
38#define DEBUG_TYPE "pseudo-probe"
41 "Number of probes that have an artificial debug line");
45 cl::desc(
"Do pseudo probe verification"));
49 cl::desc(
"The option to specify the name of the functions to verify."));
53 cl::desc(
"Update pseudo probe distribution factor"));
57 const DILocation *InlinedAt = DIL ? DIL->getInlinedAt() :
nullptr;
59 Hash ^=
MD5Hash(std::to_string(InlinedAt->getLine()));
60 Hash ^=
MD5Hash(std::to_string(InlinedAt->getColumn()));
61 auto Name = InlinedAt->getSubprogramLinkageName();
63 InlinedAt = InlinedAt->getInlinedAt();
72bool PseudoProbeVerifier::shouldVerifyFunction(
const Function *
F) {
74 if (
F->isDeclaration())
78 if (
F->hasAvailableExternallyLinkage())
81 static std::unordered_set<std::string> VerifyFuncNames(
83 return VerifyFuncNames.empty() || VerifyFuncNames.count(
F->getName().str());
98 "\n*** Pseudo Probe Verification After " + PassID.
str() +
" ***\n";
100 if (
const auto **M = llvm::any_cast<const Module *>(&
IR))
102 else if (
const auto **
F = llvm::any_cast<const Function *>(&
IR))
104 else if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
106 else if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
123 if (!shouldVerifyFunction(
F))
126 for (
const auto &BB : *
F)
127 collectProbeFactors(&BB, ProbeFactors);
128 verifyProbeFactors(
F, ProbeFactors);
132 const Function *
F =
L->getHeader()->getParent();
138 for (
const auto &
I : *
Block) {
141 ProbeFactors[{Probe->Id, Hash}] += Probe->Factor;
146void PseudoProbeVerifier::verifyProbeFactors(
148 bool BannerPrinted =
false;
149 auto &PrevProbeFactors = FunctionProbeFactors[
F->getName()];
150 for (
const auto &
I : ProbeFactors) {
151 float CurProbeFactor =
I.second;
152 if (PrevProbeFactors.count(
I.first)) {
153 float PrevProbeFactor = PrevProbeFactors[
I.first];
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 PrevProbeFactors[
I.first] =
I.second;
172 const std::string &CurModuleUniqueId)
173 :
F(&Func), CurModuleUniqueId(CurModuleUniqueId) {
174 BlockProbeIds.clear();
175 CallProbeIds.clear();
180 computeBlocksToIgnore(BlocksToIgnore, BlocksAndCallsToIgnore);
182 computeProbeId(BlocksToIgnore, BlocksAndCallsToIgnore);
183 computeCFGHash(BlocksToIgnore);
195void SampleProfileProber::computeBlocksToIgnore(
200 findUnreachableBlocks(BlocksAndCallsToIgnore);
202 BlocksToIgnore.
insert(BlocksAndCallsToIgnore.
begin(),
203 BlocksAndCallsToIgnore.
end());
211 findInvokeNormalDests(BlocksToIgnore);
215void SampleProfileProber::findUnreachableBlocks(
217 for (
auto &BB : *F) {
218 if (&BB != &
F->getEntryBlock() &&
pred_size(&BB) == 0)
219 BlocksToIgnore.
insert(&BB);
225void SampleProfileProber::findInvokeNormalDests(
227 for (
auto &BB : *F) {
228 auto *TI = BB.getTerminator();
229 if (
auto *
II = dyn_cast<InvokeInst>(TI)) {
230 auto *ND =
II->getNormalDest();
231 InvokeNormalDests.
insert(ND);
238 InvokeNormalDests.
insert(Pred);
252const Instruction *SampleProfileProber::getOriginalTerminator(
255 if (
auto *
II = dyn_cast<InvokeInst>(TI)) {
256 return getOriginalTerminator(
II->getNormalDest(), BlocksToIgnore);
260 return getOriginalTerminator(*
succ_begin(Head), BlocksToIgnore);
269void SampleProfileProber::computeCFGHash(
271 std::vector<uint8_t> Indexes;
273 for (
auto &BB : *F) {
277 auto *TI = getOriginalTerminator(&BB, BlocksToIgnore);
278 for (
unsigned I = 0, E = TI->getNumSuccessors();
I != E; ++
I) {
279 auto *Succ = TI->getSuccessor(
I);
280 auto Index = getBlockId(Succ);
284 for (
int J = 0; J < 4; J++)
285 Indexes.push_back((uint8_t)(
Index >> (J * 8)));
291 FunctionHash = (
uint64_t)CallProbeIds.size() << 48 |
294 FunctionHash &= 0x0FFFFFFFFFFFFFFF;
295 assert(FunctionHash &&
"Function checksum should not be zero");
296 LLVM_DEBUG(
dbgs() <<
"\nFunction Hash Computation for " <<
F->getName()
298 <<
" CRC = " << JC.
getCRC() <<
", Edges = "
299 << Indexes.size() <<
", ICSites = " << CallProbeIds.size()
300 <<
", Hash = " << FunctionHash <<
"\n");
303void SampleProfileProber::computeProbeId(
309 for (
auto &BB : *F) {
311 BlockProbeIds[&BB] = ++LastProbeId;
313 if (BlocksAndCallsToIgnore.
contains(&BB))
316 if (!isa<CallBase>(
I) || isa<IntrinsicInst>(&
I))
321 if (LastProbeId >= 0xFFFF) {
322 std::string Msg =
"Pseudo instrumentation incomplete for " +
323 std::string(
F->getName()) +
" because it's too large";
329 CallProbeIds[&
I] = ++LastProbeId;
335 auto I = BlockProbeIds.find(
const_cast<BasicBlock *
>(BB));
336 return I == BlockProbeIds.end() ? 0 :
I->second;
340 auto Iter = CallProbeIds.find(
const_cast<Instruction *
>(Call));
341 return Iter == CallProbeIds.end() ? 0 : Iter->second;
351 if (
auto *SP =
F.getSubprogram()) {
352 FName = SP->getLinkageName();
354 FName = SP->getName();
364 assert((isa<PseudoProbeInst>(
I) || isa<CallBase>(
I)) &&
365 "Expecting pseudo probe or call instructions");
366 if (!
I->getDebugLoc()) {
367 if (
auto *SP =
F.getSubprogram()) {
372 dbgs() <<
"\nIn Function " <<
F.getName()
373 <<
" Probe gets an artificial debug line\n";
381 for (
auto &
I : BlockProbeIds) {
391 return !isa<PHINode>(J) && !isa<DbgInfoIntrinsic>(J) &&
392 !J->isLifetimeStartOrEnd() && J->getDebugLoc();
402 "Cannot get the probing point");
408 auto *Probe = Builder.
CreateCall(ProbeFn, Args);
409 AssignDebugLoc(Probe);
412 if (
auto DIL = Probe->getDebugLoc()) {
413 if (DIL->getDiscriminator()) {
414 DIL = DIL->cloneWithDiscriminator(0);
415 Probe->setDebugLoc(DIL);
423 for (
auto &
I : CallProbeIds) {
424 auto *Call =
I.first;
426 uint32_t Type = cast<CallBase>(Call)->getCalledFunction()
429 AssignDebugLoc(Call);
430 if (
auto DIL = Call->getDebugLoc()) {
436 DIL->getBaseDiscriminator());
437 DIL = DIL->cloneWithDiscriminator(V);
438 Call->setDebugLoc(DIL);
447 auto Hash = getFunctionHash();
450 assert(NMD &&
"llvm.pseudo_probe_desc should be pre-created");
463 if (
F.isDeclaration())
472void PseudoProbeUpdatePass::runOnFunction(
Function &
F,
475 auto BBProfileCount = [&BFI](
BasicBlock *BB) {
476 return BFI.getBlockProfileCount(BB).value_or(0);
485 ProbeFactors[{Probe->Id, Hash}] += BBProfileCount(&
Block);
495 float Sum = ProbeFactors[{Probe->Id, Hash}];
507 if (
F.isDeclaration())
511 runOnFunction(
F,
FAM);
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Legalize the Machine IR a function s Machine IR
Module.h This file contains the declarations for the Module class.
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=std::nullopt, 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.
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
void registerAfterPassCallback(CallableT C, bool ToFront=false)
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 * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
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
void setProbeDistributionFactor(Instruction &Inst, float Factor)
pred_iterator pred_begin(BasicBlock *BB)
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.
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)
unsigned succ_size(const MachineBasicBlock *BB)
unsigned pred_size(const MachineBasicBlock *BB)
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)