164fa8cceSHongtao Yu //===- SampleProfileProbe.cpp - Pseudo probe Instrumentation -------------===//
264fa8cceSHongtao Yu //
364fa8cceSHongtao Yu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464fa8cceSHongtao Yu // See https://llvm.org/LICENSE.txt for license information.
564fa8cceSHongtao Yu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664fa8cceSHongtao Yu //
764fa8cceSHongtao Yu //===----------------------------------------------------------------------===//
864fa8cceSHongtao Yu //
964fa8cceSHongtao Yu // This file implements the SampleProfileProber transformation.
1064fa8cceSHongtao Yu //
1164fa8cceSHongtao Yu //===----------------------------------------------------------------------===//
1264fa8cceSHongtao Yu 
1364fa8cceSHongtao Yu #include "llvm/Transforms/IPO/SampleProfileProbe.h"
1464fa8cceSHongtao Yu #include "llvm/ADT/Statistic.h"
153d89b3cbSHongtao Yu #include "llvm/Analysis/BlockFrequencyInfo.h"
16f1985a3fSserge-sans-paille #include "llvm/Analysis/LoopInfo.h"
1764fa8cceSHongtao Yu #include "llvm/IR/BasicBlock.h"
1864fa8cceSHongtao Yu #include "llvm/IR/Constants.h"
1964fa8cceSHongtao Yu #include "llvm/IR/DebugInfoMetadata.h"
2064fa8cceSHongtao Yu #include "llvm/IR/IRBuilder.h"
2164fa8cceSHongtao Yu #include "llvm/IR/Instruction.h"
22e188aae4Sserge-sans-paille #include "llvm/IR/IntrinsicInst.h"
2364fa8cceSHongtao Yu #include "llvm/IR/MDBuilder.h"
24f1985a3fSserge-sans-paille #include "llvm/IR/PseudoProbe.h"
2564fa8cceSHongtao Yu #include "llvm/ProfileData/SampleProf.h"
2664fa8cceSHongtao Yu #include "llvm/Support/CRC.h"
273d89b3cbSHongtao Yu #include "llvm/Support/CommandLine.h"
28f1985a3fSserge-sans-paille #include "llvm/Target/TargetMachine.h"
2964fa8cceSHongtao Yu #include "llvm/Transforms/Instrumentation.h"
3064fa8cceSHongtao Yu #include "llvm/Transforms/Utils/ModuleUtils.h"
313d89b3cbSHongtao Yu #include <unordered_set>
3264fa8cceSHongtao Yu #include <vector>
3364fa8cceSHongtao Yu 
3464fa8cceSHongtao Yu using namespace llvm;
3564fa8cceSHongtao Yu #define DEBUG_TYPE "sample-profile-probe"
3664fa8cceSHongtao Yu 
3764fa8cceSHongtao Yu STATISTIC(ArtificialDbgLine,
3864fa8cceSHongtao Yu           "Number of probes that have an artificial debug line");
3964fa8cceSHongtao Yu 
403d89b3cbSHongtao Yu static cl::opt<bool>
413d89b3cbSHongtao Yu     VerifyPseudoProbe("verify-pseudo-probe", cl::init(false), cl::Hidden,
423d89b3cbSHongtao Yu                       cl::desc("Do pseudo probe verification"));
433d89b3cbSHongtao Yu 
443d89b3cbSHongtao Yu static cl::list<std::string> VerifyPseudoProbeFuncList(
453d89b3cbSHongtao Yu     "verify-pseudo-probe-funcs", cl::Hidden,
463d89b3cbSHongtao Yu     cl::desc("The option to specify the name of the functions to verify."));
473d89b3cbSHongtao Yu 
483d89b3cbSHongtao Yu static cl::opt<bool>
493d89b3cbSHongtao Yu     UpdatePseudoProbe("update-pseudo-probe", cl::init(true), cl::Hidden,
503d89b3cbSHongtao Yu                       cl::desc("Update pseudo probe distribution factor"));
513d89b3cbSHongtao Yu 
getCallStackHash(const DILocation * DIL)52f28ee1a2SHongtao Yu static uint64_t getCallStackHash(const DILocation *DIL) {
53f28ee1a2SHongtao Yu   uint64_t Hash = 0;
54f28ee1a2SHongtao Yu   const DILocation *InlinedAt = DIL ? DIL->getInlinedAt() : nullptr;
55f28ee1a2SHongtao Yu   while (InlinedAt) {
56f28ee1a2SHongtao Yu     Hash ^= MD5Hash(std::to_string(InlinedAt->getLine()));
57f28ee1a2SHongtao Yu     Hash ^= MD5Hash(std::to_string(InlinedAt->getColumn()));
58f28ee1a2SHongtao Yu     const DISubprogram *SP = InlinedAt->getScope()->getSubprogram();
59f28ee1a2SHongtao Yu     // Use linkage name for C++ if possible.
60f28ee1a2SHongtao Yu     auto Name = SP->getLinkageName();
61f28ee1a2SHongtao Yu     if (Name.empty())
62f28ee1a2SHongtao Yu       Name = SP->getName();
63f28ee1a2SHongtao Yu     Hash ^= MD5Hash(Name);
64f28ee1a2SHongtao Yu     InlinedAt = InlinedAt->getInlinedAt();
65f28ee1a2SHongtao Yu   }
66f28ee1a2SHongtao Yu   return Hash;
67f28ee1a2SHongtao Yu }
68f28ee1a2SHongtao Yu 
computeCallStackHash(const Instruction & Inst)69f28ee1a2SHongtao Yu static uint64_t computeCallStackHash(const Instruction &Inst) {
70f28ee1a2SHongtao Yu   return getCallStackHash(Inst.getDebugLoc());
71f28ee1a2SHongtao Yu }
72f28ee1a2SHongtao Yu 
shouldVerifyFunction(const Function * F)733d89b3cbSHongtao Yu bool PseudoProbeVerifier::shouldVerifyFunction(const Function *F) {
743d89b3cbSHongtao Yu   // Skip function declaration.
753d89b3cbSHongtao Yu   if (F->isDeclaration())
763d89b3cbSHongtao Yu     return false;
773d89b3cbSHongtao Yu   // Skip function that will not be emitted into object file. The prevailing
783d89b3cbSHongtao Yu   // defintion will be verified instead.
793d89b3cbSHongtao Yu   if (F->hasAvailableExternallyLinkage())
803d89b3cbSHongtao Yu     return false;
813d89b3cbSHongtao Yu   // Do a name matching.
823d89b3cbSHongtao Yu   static std::unordered_set<std::string> VerifyFuncNames(
833d89b3cbSHongtao Yu       VerifyPseudoProbeFuncList.begin(), VerifyPseudoProbeFuncList.end());
843d89b3cbSHongtao Yu   return VerifyFuncNames.empty() || VerifyFuncNames.count(F->getName().str());
853d89b3cbSHongtao Yu }
863d89b3cbSHongtao Yu 
registerCallbacks(PassInstrumentationCallbacks & PIC)873d89b3cbSHongtao Yu void PseudoProbeVerifier::registerCallbacks(PassInstrumentationCallbacks &PIC) {
883d89b3cbSHongtao Yu   if (VerifyPseudoProbe) {
893d89b3cbSHongtao Yu     PIC.registerAfterPassCallback(
903d89b3cbSHongtao Yu         [this](StringRef P, Any IR, const PreservedAnalyses &) {
913d89b3cbSHongtao Yu           this->runAfterPass(P, IR);
923d89b3cbSHongtao Yu         });
933d89b3cbSHongtao Yu   }
943d89b3cbSHongtao Yu }
953d89b3cbSHongtao Yu 
963d89b3cbSHongtao Yu // Callback to run after each transformation for the new pass manager.
runAfterPass(StringRef PassID,Any IR)973d89b3cbSHongtao Yu void PseudoProbeVerifier::runAfterPass(StringRef PassID, Any IR) {
983d89b3cbSHongtao Yu   std::string Banner =
993d89b3cbSHongtao Yu       "\n*** Pseudo Probe Verification After " + PassID.str() + " ***\n";
1003d89b3cbSHongtao Yu   dbgs() << Banner;
1013d89b3cbSHongtao Yu   if (any_isa<const Module *>(IR))
1023d89b3cbSHongtao Yu     runAfterPass(any_cast<const Module *>(IR));
1033d89b3cbSHongtao Yu   else if (any_isa<const Function *>(IR))
1043d89b3cbSHongtao Yu     runAfterPass(any_cast<const Function *>(IR));
1053d89b3cbSHongtao Yu   else if (any_isa<const LazyCallGraph::SCC *>(IR))
1063d89b3cbSHongtao Yu     runAfterPass(any_cast<const LazyCallGraph::SCC *>(IR));
1073d89b3cbSHongtao Yu   else if (any_isa<const Loop *>(IR))
1083d89b3cbSHongtao Yu     runAfterPass(any_cast<const Loop *>(IR));
1093d89b3cbSHongtao Yu   else
1103d89b3cbSHongtao Yu     llvm_unreachable("Unknown IR unit");
1113d89b3cbSHongtao Yu }
1123d89b3cbSHongtao Yu 
runAfterPass(const Module * M)1133d89b3cbSHongtao Yu void PseudoProbeVerifier::runAfterPass(const Module *M) {
1143d89b3cbSHongtao Yu   for (const Function &F : *M)
1153d89b3cbSHongtao Yu     runAfterPass(&F);
1163d89b3cbSHongtao Yu }
1173d89b3cbSHongtao Yu 
runAfterPass(const LazyCallGraph::SCC * C)1183d89b3cbSHongtao Yu void PseudoProbeVerifier::runAfterPass(const LazyCallGraph::SCC *C) {
1193d89b3cbSHongtao Yu   for (const LazyCallGraph::Node &N : *C)
1203d89b3cbSHongtao Yu     runAfterPass(&N.getFunction());
1213d89b3cbSHongtao Yu }
1223d89b3cbSHongtao Yu 
runAfterPass(const Function * F)1233d89b3cbSHongtao Yu void PseudoProbeVerifier::runAfterPass(const Function *F) {
1243d89b3cbSHongtao Yu   if (!shouldVerifyFunction(F))
1253d89b3cbSHongtao Yu     return;
1263d89b3cbSHongtao Yu   ProbeFactorMap ProbeFactors;
1273d89b3cbSHongtao Yu   for (const auto &BB : *F)
1283d89b3cbSHongtao Yu     collectProbeFactors(&BB, ProbeFactors);
1293d89b3cbSHongtao Yu   verifyProbeFactors(F, ProbeFactors);
1303d89b3cbSHongtao Yu }
1313d89b3cbSHongtao Yu 
runAfterPass(const Loop * L)1323d89b3cbSHongtao Yu void PseudoProbeVerifier::runAfterPass(const Loop *L) {
1333d89b3cbSHongtao Yu   const Function *F = L->getHeader()->getParent();
1343d89b3cbSHongtao Yu   runAfterPass(F);
1353d89b3cbSHongtao Yu }
1363d89b3cbSHongtao Yu 
collectProbeFactors(const BasicBlock * Block,ProbeFactorMap & ProbeFactors)1373d89b3cbSHongtao Yu void PseudoProbeVerifier::collectProbeFactors(const BasicBlock *Block,
1383d89b3cbSHongtao Yu                                               ProbeFactorMap &ProbeFactors) {
1393d89b3cbSHongtao Yu   for (const auto &I : *Block) {
140f28ee1a2SHongtao Yu     if (Optional<PseudoProbe> Probe = extractProbe(I)) {
141f28ee1a2SHongtao Yu       uint64_t Hash = computeCallStackHash(I);
142f28ee1a2SHongtao Yu       ProbeFactors[{Probe->Id, Hash}] += Probe->Factor;
143f28ee1a2SHongtao Yu     }
1443d89b3cbSHongtao Yu   }
1453d89b3cbSHongtao Yu }
1463d89b3cbSHongtao Yu 
verifyProbeFactors(const Function * F,const ProbeFactorMap & ProbeFactors)1473d89b3cbSHongtao Yu void PseudoProbeVerifier::verifyProbeFactors(
1483d89b3cbSHongtao Yu     const Function *F, const ProbeFactorMap &ProbeFactors) {
1493d89b3cbSHongtao Yu   bool BannerPrinted = false;
1503d89b3cbSHongtao Yu   auto &PrevProbeFactors = FunctionProbeFactors[F->getName()];
1513d89b3cbSHongtao Yu   for (const auto &I : ProbeFactors) {
1523d89b3cbSHongtao Yu     float CurProbeFactor = I.second;
1533d89b3cbSHongtao Yu     if (PrevProbeFactors.count(I.first)) {
1543d89b3cbSHongtao Yu       float PrevProbeFactor = PrevProbeFactors[I.first];
1553d89b3cbSHongtao Yu       if (std::abs(CurProbeFactor - PrevProbeFactor) >
1563d89b3cbSHongtao Yu           DistributionFactorVariance) {
1573d89b3cbSHongtao Yu         if (!BannerPrinted) {
1583d89b3cbSHongtao Yu           dbgs() << "Function " << F->getName() << ":\n";
1593d89b3cbSHongtao Yu           BannerPrinted = true;
1603d89b3cbSHongtao Yu         }
161f28ee1a2SHongtao Yu         dbgs() << "Probe " << I.first.first << "\tprevious factor "
1623d89b3cbSHongtao Yu                << format("%0.2f", PrevProbeFactor) << "\tcurrent factor "
1633d89b3cbSHongtao Yu                << format("%0.2f", CurProbeFactor) << "\n";
1643d89b3cbSHongtao Yu       }
1653d89b3cbSHongtao Yu     }
1663d89b3cbSHongtao Yu 
1673d89b3cbSHongtao Yu     // Update
1683d89b3cbSHongtao Yu     PrevProbeFactors[I.first] = I.second;
1693d89b3cbSHongtao Yu   }
1703d89b3cbSHongtao Yu }
1713d89b3cbSHongtao Yu 
PseudoProbeManager(const Module & M)172ac068e01SHongtao Yu PseudoProbeManager::PseudoProbeManager(const Module &M) {
173ac068e01SHongtao Yu   if (NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName)) {
174ac068e01SHongtao Yu     for (const auto *Operand : FuncInfo->operands()) {
175ac068e01SHongtao Yu       const auto *MD = cast<MDNode>(Operand);
176ac068e01SHongtao Yu       auto GUID =
177ac068e01SHongtao Yu           mdconst::dyn_extract<ConstantInt>(MD->getOperand(0))->getZExtValue();
178ac068e01SHongtao Yu       auto Hash =
179ac068e01SHongtao Yu           mdconst::dyn_extract<ConstantInt>(MD->getOperand(1))->getZExtValue();
180ac068e01SHongtao Yu       GUIDToProbeDescMap.try_emplace(GUID, PseudoProbeDescriptor(GUID, Hash));
181ac068e01SHongtao Yu     }
182ac068e01SHongtao Yu   }
183ac068e01SHongtao Yu }
184ac068e01SHongtao Yu 
185ac068e01SHongtao Yu const PseudoProbeDescriptor *
getDesc(const Function & F) const186ac068e01SHongtao Yu PseudoProbeManager::getDesc(const Function &F) const {
187ac068e01SHongtao Yu   auto I = GUIDToProbeDescMap.find(
188ac068e01SHongtao Yu       Function::getGUID(FunctionSamples::getCanonicalFnName(F)));
189ac068e01SHongtao Yu   return I == GUIDToProbeDescMap.end() ? nullptr : &I->second;
190ac068e01SHongtao Yu }
191ac068e01SHongtao Yu 
moduleIsProbed(const Module & M) const192ac068e01SHongtao Yu bool PseudoProbeManager::moduleIsProbed(const Module &M) const {
193ac068e01SHongtao Yu   return M.getNamedMetadata(PseudoProbeDescMetadataName);
194ac068e01SHongtao Yu }
195ac068e01SHongtao Yu 
profileIsValid(const Function & F,const FunctionSamples & Samples) const196ac068e01SHongtao Yu bool PseudoProbeManager::profileIsValid(const Function &F,
197ac068e01SHongtao Yu                                         const FunctionSamples &Samples) const {
198ac068e01SHongtao Yu   const auto *Desc = getDesc(F);
199ac068e01SHongtao Yu   if (!Desc) {
200ac068e01SHongtao Yu     LLVM_DEBUG(dbgs() << "Probe descriptor missing for Function " << F.getName()
201ac068e01SHongtao Yu                       << "\n");
202ac068e01SHongtao Yu     return false;
203ac068e01SHongtao Yu   } else {
204ac068e01SHongtao Yu     if (Desc->getFunctionHash() != Samples.getFunctionHash()) {
205ac068e01SHongtao Yu       LLVM_DEBUG(dbgs() << "Hash mismatch for Function " << F.getName()
206ac068e01SHongtao Yu                         << "\n");
207ac068e01SHongtao Yu       return false;
208ac068e01SHongtao Yu     }
209ac068e01SHongtao Yu   }
210ac068e01SHongtao Yu   return true;
211ac068e01SHongtao Yu }
212ac068e01SHongtao Yu 
SampleProfileProber(Function & Func,const std::string & CurModuleUniqueId)213705a4c14SHongtao Yu SampleProfileProber::SampleProfileProber(Function &Func,
214705a4c14SHongtao Yu                                          const std::string &CurModuleUniqueId)
215705a4c14SHongtao Yu     : F(&Func), CurModuleUniqueId(CurModuleUniqueId) {
21664fa8cceSHongtao Yu   BlockProbeIds.clear();
21724d4291cSHongtao Yu   CallProbeIds.clear();
21864fa8cceSHongtao Yu   LastProbeId = (uint32_t)PseudoProbeReservedId::Last;
21964fa8cceSHongtao Yu   computeProbeIdForBlocks();
22024d4291cSHongtao Yu   computeProbeIdForCallsites();
221705a4c14SHongtao Yu   computeCFGHash();
222705a4c14SHongtao Yu }
223705a4c14SHongtao Yu 
224705a4c14SHongtao Yu // Compute Hash value for the CFG: the lower 32 bits are CRC32 of the index
225705a4c14SHongtao Yu // value of each BB in the CFG. The higher 32 bits record the number of edges
226705a4c14SHongtao Yu // preceded by the number of indirect calls.
227705a4c14SHongtao Yu // This is derived from FuncPGOInstrumentation<Edge, BBInfo>::computeCFGHash().
computeCFGHash()228705a4c14SHongtao Yu void SampleProfileProber::computeCFGHash() {
229705a4c14SHongtao Yu   std::vector<uint8_t> Indexes;
230705a4c14SHongtao Yu   JamCRC JC;
231705a4c14SHongtao Yu   for (auto &BB : *F) {
232705a4c14SHongtao Yu     auto *TI = BB.getTerminator();
233705a4c14SHongtao Yu     for (unsigned I = 0, E = TI->getNumSuccessors(); I != E; ++I) {
234705a4c14SHongtao Yu       auto *Succ = TI->getSuccessor(I);
235705a4c14SHongtao Yu       auto Index = getBlockId(Succ);
236705a4c14SHongtao Yu       for (int J = 0; J < 4; J++)
237705a4c14SHongtao Yu         Indexes.push_back((uint8_t)(Index >> (J * 8)));
238705a4c14SHongtao Yu     }
239705a4c14SHongtao Yu   }
240705a4c14SHongtao Yu 
241705a4c14SHongtao Yu   JC.update(Indexes);
242705a4c14SHongtao Yu 
243705a4c14SHongtao Yu   FunctionHash = (uint64_t)CallProbeIds.size() << 48 |
244705a4c14SHongtao Yu                  (uint64_t)Indexes.size() << 32 | JC.getCRC();
245705a4c14SHongtao Yu   // Reserve bit 60-63 for other information purpose.
246705a4c14SHongtao Yu   FunctionHash &= 0x0FFFFFFFFFFFFFFF;
247705a4c14SHongtao Yu   assert(FunctionHash && "Function checksum should not be zero");
248705a4c14SHongtao Yu   LLVM_DEBUG(dbgs() << "\nFunction Hash Computation for " << F->getName()
249705a4c14SHongtao Yu                     << ":\n"
250705a4c14SHongtao Yu                     << " CRC = " << JC.getCRC() << ", Edges = "
251705a4c14SHongtao Yu                     << Indexes.size() << ", ICSites = " << CallProbeIds.size()
252705a4c14SHongtao Yu                     << ", Hash = " << FunctionHash << "\n");
25364fa8cceSHongtao Yu }
25464fa8cceSHongtao Yu 
computeProbeIdForBlocks()25564fa8cceSHongtao Yu void SampleProfileProber::computeProbeIdForBlocks() {
25664fa8cceSHongtao Yu   for (auto &BB : *F) {
25764fa8cceSHongtao Yu     BlockProbeIds[&BB] = ++LastProbeId;
25864fa8cceSHongtao Yu   }
25964fa8cceSHongtao Yu }
26064fa8cceSHongtao Yu 
computeProbeIdForCallsites()26124d4291cSHongtao Yu void SampleProfileProber::computeProbeIdForCallsites() {
26224d4291cSHongtao Yu   for (auto &BB : *F) {
26324d4291cSHongtao Yu     for (auto &I : BB) {
26424d4291cSHongtao Yu       if (!isa<CallBase>(I))
26524d4291cSHongtao Yu         continue;
26624d4291cSHongtao Yu       if (isa<IntrinsicInst>(&I))
26724d4291cSHongtao Yu         continue;
26824d4291cSHongtao Yu       CallProbeIds[&I] = ++LastProbeId;
26924d4291cSHongtao Yu     }
27024d4291cSHongtao Yu   }
27124d4291cSHongtao Yu }
27224d4291cSHongtao Yu 
getBlockId(const BasicBlock * BB) const27364fa8cceSHongtao Yu uint32_t SampleProfileProber::getBlockId(const BasicBlock *BB) const {
27464fa8cceSHongtao Yu   auto I = BlockProbeIds.find(const_cast<BasicBlock *>(BB));
27564fa8cceSHongtao Yu   return I == BlockProbeIds.end() ? 0 : I->second;
27664fa8cceSHongtao Yu }
27764fa8cceSHongtao Yu 
getCallsiteId(const Instruction * Call) const27824d4291cSHongtao Yu uint32_t SampleProfileProber::getCallsiteId(const Instruction *Call) const {
27924d4291cSHongtao Yu   auto Iter = CallProbeIds.find(const_cast<Instruction *>(Call));
28024d4291cSHongtao Yu   return Iter == CallProbeIds.end() ? 0 : Iter->second;
28124d4291cSHongtao Yu }
28224d4291cSHongtao Yu 
instrumentOneFunc(Function & F,TargetMachine * TM)28364fa8cceSHongtao Yu void SampleProfileProber::instrumentOneFunc(Function &F, TargetMachine *TM) {
28464fa8cceSHongtao Yu   Module *M = F.getParent();
28564fa8cceSHongtao Yu   MDBuilder MDB(F.getContext());
28664fa8cceSHongtao Yu   // Compute a GUID without considering the function's linkage type. This is
28764fa8cceSHongtao Yu   // fine since function name is the only key in the profile database.
28864fa8cceSHongtao Yu   uint64_t Guid = Function::getGUID(F.getName());
28964fa8cceSHongtao Yu 
29024d4291cSHongtao Yu   // Assign an artificial debug line to a probe that doesn't come with a real
29124d4291cSHongtao Yu   // line. A probe not having a debug line will get an incomplete inline
29224d4291cSHongtao Yu   // context. This will cause samples collected on the probe to be counted
29324d4291cSHongtao Yu   // into the base profile instead of a context profile. The line number
29424d4291cSHongtao Yu   // itself is not important though.
29524d4291cSHongtao Yu   auto AssignDebugLoc = [&](Instruction *I) {
29624d4291cSHongtao Yu     assert((isa<PseudoProbeInst>(I) || isa<CallBase>(I)) &&
29724d4291cSHongtao Yu            "Expecting pseudo probe or call instructions");
29824d4291cSHongtao Yu     if (!I->getDebugLoc()) {
29924d4291cSHongtao Yu       if (auto *SP = F.getSubprogram()) {
300b5ad32efSFangrui Song         auto DIL = DILocation::get(SP->getContext(), 0, 0, SP);
30124d4291cSHongtao Yu         I->setDebugLoc(DIL);
30224d4291cSHongtao Yu         ArtificialDbgLine++;
30324d4291cSHongtao Yu         LLVM_DEBUG({
30424d4291cSHongtao Yu           dbgs() << "\nIn Function " << F.getName()
30524d4291cSHongtao Yu                  << " Probe gets an artificial debug line\n";
30624d4291cSHongtao Yu           I->dump();
30724d4291cSHongtao Yu         });
30824d4291cSHongtao Yu       }
30924d4291cSHongtao Yu     }
31024d4291cSHongtao Yu   };
31124d4291cSHongtao Yu 
31264fa8cceSHongtao Yu   // Probe basic blocks.
31364fa8cceSHongtao Yu   for (auto &I : BlockProbeIds) {
31464fa8cceSHongtao Yu     BasicBlock *BB = I.first;
31564fa8cceSHongtao Yu     uint32_t Index = I.second;
31664fa8cceSHongtao Yu     // Insert a probe before an instruction with a valid debug line number which
31764fa8cceSHongtao Yu     // will be assigned to the probe. The line number will be used later to
31864fa8cceSHongtao Yu     // model the inline context when the probe is inlined into other functions.
31964fa8cceSHongtao Yu     // Debug instructions, phi nodes and lifetime markers do not have an valid
32064fa8cceSHongtao Yu     // line number. Real instructions generated by optimizations may not come
32164fa8cceSHongtao Yu     // with a line number either.
32264fa8cceSHongtao Yu     auto HasValidDbgLine = [](Instruction *J) {
32364fa8cceSHongtao Yu       return !isa<PHINode>(J) && !isa<DbgInfoIntrinsic>(J) &&
32464fa8cceSHongtao Yu              !J->isLifetimeStartOrEnd() && J->getDebugLoc();
32564fa8cceSHongtao Yu     };
32664fa8cceSHongtao Yu 
32764fa8cceSHongtao Yu     Instruction *J = &*BB->getFirstInsertionPt();
32864fa8cceSHongtao Yu     while (J != BB->getTerminator() && !HasValidDbgLine(J)) {
32964fa8cceSHongtao Yu       J = J->getNextNode();
33064fa8cceSHongtao Yu     }
33164fa8cceSHongtao Yu 
33264fa8cceSHongtao Yu     IRBuilder<> Builder(J);
33364fa8cceSHongtao Yu     assert(Builder.GetInsertPoint() != BB->end() &&
33464fa8cceSHongtao Yu            "Cannot get the probing point");
33564fa8cceSHongtao Yu     Function *ProbeFn =
33664fa8cceSHongtao Yu         llvm::Intrinsic::getDeclaration(M, Intrinsic::pseudoprobe);
33764fa8cceSHongtao Yu     Value *Args[] = {Builder.getInt64(Guid), Builder.getInt64(Index),
3383d89b3cbSHongtao Yu                      Builder.getInt32(0),
3393d89b3cbSHongtao Yu                      Builder.getInt64(PseudoProbeFullDistributionFactor)};
34064fa8cceSHongtao Yu     auto *Probe = Builder.CreateCall(ProbeFn, Args);
34124d4291cSHongtao Yu     AssignDebugLoc(Probe);
34264fa8cceSHongtao Yu   }
34324d4291cSHongtao Yu 
34424d4291cSHongtao Yu   // Probe both direct calls and indirect calls. Direct calls are probed so that
34524d4291cSHongtao Yu   // their probe ID can be used as an call site identifier to represent a
34624d4291cSHongtao Yu   // calling context.
34724d4291cSHongtao Yu   for (auto &I : CallProbeIds) {
34824d4291cSHongtao Yu     auto *Call = I.first;
34924d4291cSHongtao Yu     uint32_t Index = I.second;
35024d4291cSHongtao Yu     uint32_t Type = cast<CallBase>(Call)->getCalledFunction()
35124d4291cSHongtao Yu                         ? (uint32_t)PseudoProbeType::DirectCall
35224d4291cSHongtao Yu                         : (uint32_t)PseudoProbeType::IndirectCall;
35324d4291cSHongtao Yu     AssignDebugLoc(Call);
35424d4291cSHongtao Yu     // Levarge the 32-bit discriminator field of debug data to store the ID and
35524d4291cSHongtao Yu     // type of a callsite probe. This gets rid of the dependency on plumbing a
35624d4291cSHongtao Yu     // customized metadata through the codegen pipeline.
3573d89b3cbSHongtao Yu     uint32_t V = PseudoProbeDwarfDiscriminator::packProbeData(
3583d89b3cbSHongtao Yu         Index, Type, 0, PseudoProbeDwarfDiscriminator::FullDistributionFactor);
35924d4291cSHongtao Yu     if (auto DIL = Call->getDebugLoc()) {
36024d4291cSHongtao Yu       DIL = DIL->cloneWithDiscriminator(V);
36124d4291cSHongtao Yu       Call->setDebugLoc(DIL);
36264fa8cceSHongtao Yu     }
36364fa8cceSHongtao Yu   }
364705a4c14SHongtao Yu 
365705a4c14SHongtao Yu   // Create module-level metadata that contains function info necessary to
366705a4c14SHongtao Yu   // synthesize probe-based sample counts,  which are
367705a4c14SHongtao Yu   // - FunctionGUID
368705a4c14SHongtao Yu   // - FunctionHash.
369705a4c14SHongtao Yu   // - FunctionName
370705a4c14SHongtao Yu   auto Hash = getFunctionHash();
371705a4c14SHongtao Yu   auto *MD = MDB.createPseudoProbeDesc(Guid, Hash, &F);
372705a4c14SHongtao Yu   auto *NMD = M->getNamedMetadata(PseudoProbeDescMetadataName);
373705a4c14SHongtao Yu   assert(NMD && "llvm.pseudo_probe_desc should be pre-created");
374705a4c14SHongtao Yu   NMD->addOperand(MD);
375705a4c14SHongtao Yu 
376705a4c14SHongtao Yu   // Preserve a comdat group to hold all probes materialized later. This
377705a4c14SHongtao Yu   // allows that when the function is considered dead and removed, the
378705a4c14SHongtao Yu   // materialized probes are disposed too.
379705a4c14SHongtao Yu   // Imported functions are defined in another module. They do not need
380705a4c14SHongtao Yu   // the following handling since same care will be taken for them in their
381705a4c14SHongtao Yu   // original module. The pseudo probes inserted into an imported functions
382705a4c14SHongtao Yu   // above will naturally not be emitted since the imported function is free
383705a4c14SHongtao Yu   // from object emission. However they will be emitted together with the
384705a4c14SHongtao Yu   // inliner functions that the imported function is inlined into. We are not
385705a4c14SHongtao Yu   // creating a comdat group for an import function since it's useless anyway.
386705a4c14SHongtao Yu   if (!F.isDeclarationForLinker()) {
387705a4c14SHongtao Yu     if (TM) {
388705a4c14SHongtao Yu       auto Triple = TM->getTargetTriple();
3894d63892aSFangrui Song       if (Triple.supportsCOMDAT() && TM->getFunctionSections())
3904d63892aSFangrui Song         getOrCreateFunctionComdat(F, Triple);
391705a4c14SHongtao Yu     }
392705a4c14SHongtao Yu   }
39364fa8cceSHongtao Yu }
39464fa8cceSHongtao Yu 
run(Module & M,ModuleAnalysisManager & AM)39564fa8cceSHongtao Yu PreservedAnalyses SampleProfileProbePass::run(Module &M,
39664fa8cceSHongtao Yu                                               ModuleAnalysisManager &AM) {
397705a4c14SHongtao Yu   auto ModuleId = getUniqueModuleId(&M);
398705a4c14SHongtao Yu   // Create the pseudo probe desc metadata beforehand.
399705a4c14SHongtao Yu   // Note that modules with only data but no functions will require this to
400705a4c14SHongtao Yu   // be set up so that they will be known as probed later.
401705a4c14SHongtao Yu   M.getOrInsertNamedMetadata(PseudoProbeDescMetadataName);
402705a4c14SHongtao Yu 
40364fa8cceSHongtao Yu   for (auto &F : M) {
40464fa8cceSHongtao Yu     if (F.isDeclaration())
40564fa8cceSHongtao Yu       continue;
406705a4c14SHongtao Yu     SampleProfileProber ProbeManager(F, ModuleId);
40764fa8cceSHongtao Yu     ProbeManager.instrumentOneFunc(F, TM);
40864fa8cceSHongtao Yu   }
40964fa8cceSHongtao Yu 
41064fa8cceSHongtao Yu   return PreservedAnalyses::none();
41164fa8cceSHongtao Yu }
4123d89b3cbSHongtao Yu 
runOnFunction(Function & F,FunctionAnalysisManager & FAM)4133d89b3cbSHongtao Yu void PseudoProbeUpdatePass::runOnFunction(Function &F,
4143d89b3cbSHongtao Yu                                           FunctionAnalysisManager &FAM) {
4153d89b3cbSHongtao Yu   BlockFrequencyInfo &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
4163d89b3cbSHongtao Yu   auto BBProfileCount = [&BFI](BasicBlock *BB) {
417*129b531cSKazu Hirata     return BFI.getBlockProfileCount(BB).value_or(0);
4183d89b3cbSHongtao Yu   };
4193d89b3cbSHongtao Yu 
4203d89b3cbSHongtao Yu   // Collect the sum of execution weight for each probe.
4213d89b3cbSHongtao Yu   ProbeFactorMap ProbeFactors;
4223d89b3cbSHongtao Yu   for (auto &Block : F) {
4233d89b3cbSHongtao Yu     for (auto &I : Block) {
42489855158SHongtao Yu       if (Optional<PseudoProbe> Probe = extractProbe(I)) {
425f28ee1a2SHongtao Yu         uint64_t Hash = computeCallStackHash(I);
426f28ee1a2SHongtao Yu         ProbeFactors[{Probe->Id, Hash}] += BBProfileCount(&Block);
427f28ee1a2SHongtao Yu       }
4283d89b3cbSHongtao Yu     }
4293d89b3cbSHongtao Yu   }
4303d89b3cbSHongtao Yu 
4313d89b3cbSHongtao Yu   // Fix up over-counted probes.
4323d89b3cbSHongtao Yu   for (auto &Block : F) {
4333d89b3cbSHongtao Yu     for (auto &I : Block) {
4343d89b3cbSHongtao Yu       if (Optional<PseudoProbe> Probe = extractProbe(I)) {
435f28ee1a2SHongtao Yu         uint64_t Hash = computeCallStackHash(I);
436f28ee1a2SHongtao Yu         float Sum = ProbeFactors[{Probe->Id, Hash}];
4373d89b3cbSHongtao Yu         if (Sum != 0)
4383d89b3cbSHongtao Yu           setProbeDistributionFactor(I, BBProfileCount(&Block) / Sum);
4393d89b3cbSHongtao Yu       }
4403d89b3cbSHongtao Yu     }
4413d89b3cbSHongtao Yu   }
4423d89b3cbSHongtao Yu }
4433d89b3cbSHongtao Yu 
run(Module & M,ModuleAnalysisManager & AM)4443d89b3cbSHongtao Yu PreservedAnalyses PseudoProbeUpdatePass::run(Module &M,
4453d89b3cbSHongtao Yu                                              ModuleAnalysisManager &AM) {
4463d89b3cbSHongtao Yu   if (UpdatePseudoProbe) {
4473d89b3cbSHongtao Yu     for (auto &F : M) {
4483d89b3cbSHongtao Yu       if (F.isDeclaration())
4493d89b3cbSHongtao Yu         continue;
4503d89b3cbSHongtao Yu       FunctionAnalysisManager &FAM =
4513d89b3cbSHongtao Yu           AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
4523d89b3cbSHongtao Yu       runOnFunction(F, FAM);
4533d89b3cbSHongtao Yu     }
4543d89b3cbSHongtao Yu   }
4553d89b3cbSHongtao Yu   return PreservedAnalyses::none();
4563d89b3cbSHongtao Yu }
457