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());
87 PIC.registerAfterPassCallback(
97 "\n*** Pseudo Probe Verification After " + PassID.
str() +
" ***\n";
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();
227 auto *ND =
II->getNormalDest();
228 InvokeNormalDests.
insert(ND);
235 InvokeNormalDests.
insert(Pred);
249const Instruction *SampleProfileProber::getOriginalTerminator(
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 |
289 (uint64_t)Indexes.size() << 32 | JC.
getCRC();
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(
303 LLVMContext &Ctx = F->getContext();
306 for (
auto &BB : *F) {
308 BlockProbeIds[&BB] = ++LastProbeId;
310 if (BlocksAndCallsToIgnore.
contains(&BB))
318 if (LastProbeId >= 0xFFFF) {
319 std::string Msg =
"Pseudo instrumentation incomplete for " +
320 std::string(F->getName()) +
" because it's too large";
322 DiagnosticInfoSampleProfile(
M->getName().data(), Msg,
DS_Warning));
326 CallProbeIds[&
I] = ++LastProbeId;
331uint32_t SampleProfileProber::getBlockId(
const BasicBlock *BB)
const {
332 auto I = BlockProbeIds.find(
const_cast<BasicBlock *
>(BB));
333 return I == BlockProbeIds.end() ? 0 :
I->second;
336uint32_t SampleProfileProber::getCallsiteId(
const Instruction *
Call)
const {
338 return Iter == CallProbeIds.end() ? 0 : Iter->second;
342 Module *M = F.getParent();
348 if (
auto *SP = F.getSubprogram()) {
349 FName = SP->getLinkageName();
351 FName = SP->getName();
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();
397 assert(Builder.GetInsertPoint() != BB->
end() &&
398 "Cannot get the probing point");
401 Value *Args[] = {Builder.getInt64(
Guid), Builder.getInt64(Index),
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;
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) {
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!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Module.h This file contains the declarations for the Module class.
Legalize the Machine IR a function s Machine IR
Machine Check Debug Module
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)
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...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
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, 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.
@ BasicBlock
Various leaf nodes.
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)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
T any_cast(const Any &Value)
static constexpr uint64_t PseudoProbeFullDistributionFactor
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto pred_size(const MachineBasicBlock *BB)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
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.
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.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
constexpr const char * PseudoProbeDescMetadataName
std::unordered_map< std::pair< uint64_t, uint64_t >, float, pair_hash< uint64_t, uint64_t > > ProbeFactorMap
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)