1e8d8bef9SDimitry Andric //===- SampleProfileProbe.cpp - Pseudo probe Instrumentation -------------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric //
9e8d8bef9SDimitry Andric // This file implements the SampleProfileProber transformation.
10e8d8bef9SDimitry Andric //
11e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
12e8d8bef9SDimitry Andric 
13e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/SampleProfileProbe.h"
14e8d8bef9SDimitry Andric #include "llvm/ADT/Statistic.h"
15e8d8bef9SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
16e8d8bef9SDimitry Andric #include "llvm/IR/BasicBlock.h"
17e8d8bef9SDimitry Andric #include "llvm/IR/CFG.h"
18e8d8bef9SDimitry Andric #include "llvm/IR/Constant.h"
19e8d8bef9SDimitry Andric #include "llvm/IR/Constants.h"
20e8d8bef9SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
21e8d8bef9SDimitry Andric #include "llvm/IR/GlobalValue.h"
22e8d8bef9SDimitry Andric #include "llvm/IR/GlobalVariable.h"
23e8d8bef9SDimitry Andric #include "llvm/IR/IRBuilder.h"
24e8d8bef9SDimitry Andric #include "llvm/IR/Instruction.h"
25e8d8bef9SDimitry Andric #include "llvm/IR/MDBuilder.h"
26e8d8bef9SDimitry Andric #include "llvm/ProfileData/SampleProf.h"
27e8d8bef9SDimitry Andric #include "llvm/Support/CRC.h"
28e8d8bef9SDimitry Andric #include "llvm/Transforms/Instrumentation.h"
29e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
30e8d8bef9SDimitry Andric #include <vector>
31e8d8bef9SDimitry Andric 
32e8d8bef9SDimitry Andric using namespace llvm;
33e8d8bef9SDimitry Andric #define DEBUG_TYPE "sample-profile-probe"
34e8d8bef9SDimitry Andric 
35e8d8bef9SDimitry Andric STATISTIC(ArtificialDbgLine,
36e8d8bef9SDimitry Andric           "Number of probes that have an artificial debug line");
37e8d8bef9SDimitry Andric 
38e8d8bef9SDimitry Andric PseudoProbeManager::PseudoProbeManager(const Module &M) {
39e8d8bef9SDimitry Andric   if (NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName)) {
40e8d8bef9SDimitry Andric     for (const auto *Operand : FuncInfo->operands()) {
41e8d8bef9SDimitry Andric       const auto *MD = cast<MDNode>(Operand);
42e8d8bef9SDimitry Andric       auto GUID =
43e8d8bef9SDimitry Andric           mdconst::dyn_extract<ConstantInt>(MD->getOperand(0))->getZExtValue();
44e8d8bef9SDimitry Andric       auto Hash =
45e8d8bef9SDimitry Andric           mdconst::dyn_extract<ConstantInt>(MD->getOperand(1))->getZExtValue();
46e8d8bef9SDimitry Andric       GUIDToProbeDescMap.try_emplace(GUID, PseudoProbeDescriptor(GUID, Hash));
47e8d8bef9SDimitry Andric     }
48e8d8bef9SDimitry Andric   }
49e8d8bef9SDimitry Andric }
50e8d8bef9SDimitry Andric 
51e8d8bef9SDimitry Andric const PseudoProbeDescriptor *
52e8d8bef9SDimitry Andric PseudoProbeManager::getDesc(const Function &F) const {
53e8d8bef9SDimitry Andric   auto I = GUIDToProbeDescMap.find(
54e8d8bef9SDimitry Andric       Function::getGUID(FunctionSamples::getCanonicalFnName(F)));
55e8d8bef9SDimitry Andric   return I == GUIDToProbeDescMap.end() ? nullptr : &I->second;
56e8d8bef9SDimitry Andric }
57e8d8bef9SDimitry Andric 
58e8d8bef9SDimitry Andric bool PseudoProbeManager::moduleIsProbed(const Module &M) const {
59e8d8bef9SDimitry Andric   return M.getNamedMetadata(PseudoProbeDescMetadataName);
60e8d8bef9SDimitry Andric }
61e8d8bef9SDimitry Andric 
62e8d8bef9SDimitry Andric bool PseudoProbeManager::profileIsValid(const Function &F,
63e8d8bef9SDimitry Andric                                         const FunctionSamples &Samples) const {
64e8d8bef9SDimitry Andric   const auto *Desc = getDesc(F);
65e8d8bef9SDimitry Andric   if (!Desc) {
66e8d8bef9SDimitry Andric     LLVM_DEBUG(dbgs() << "Probe descriptor missing for Function " << F.getName()
67e8d8bef9SDimitry Andric                       << "\n");
68e8d8bef9SDimitry Andric     return false;
69e8d8bef9SDimitry Andric   } else {
70e8d8bef9SDimitry Andric     if (Desc->getFunctionHash() != Samples.getFunctionHash()) {
71e8d8bef9SDimitry Andric       LLVM_DEBUG(dbgs() << "Hash mismatch for Function " << F.getName()
72e8d8bef9SDimitry Andric                         << "\n");
73e8d8bef9SDimitry Andric       return false;
74e8d8bef9SDimitry Andric     }
75e8d8bef9SDimitry Andric   }
76e8d8bef9SDimitry Andric   return true;
77e8d8bef9SDimitry Andric }
78e8d8bef9SDimitry Andric 
79e8d8bef9SDimitry Andric SampleProfileProber::SampleProfileProber(Function &Func,
80e8d8bef9SDimitry Andric                                          const std::string &CurModuleUniqueId)
81e8d8bef9SDimitry Andric     : F(&Func), CurModuleUniqueId(CurModuleUniqueId) {
82e8d8bef9SDimitry Andric   BlockProbeIds.clear();
83e8d8bef9SDimitry Andric   CallProbeIds.clear();
84e8d8bef9SDimitry Andric   LastProbeId = (uint32_t)PseudoProbeReservedId::Last;
85e8d8bef9SDimitry Andric   computeProbeIdForBlocks();
86e8d8bef9SDimitry Andric   computeProbeIdForCallsites();
87e8d8bef9SDimitry Andric   computeCFGHash();
88e8d8bef9SDimitry Andric }
89e8d8bef9SDimitry Andric 
90e8d8bef9SDimitry Andric // Compute Hash value for the CFG: the lower 32 bits are CRC32 of the index
91e8d8bef9SDimitry Andric // value of each BB in the CFG. The higher 32 bits record the number of edges
92e8d8bef9SDimitry Andric // preceded by the number of indirect calls.
93e8d8bef9SDimitry Andric // This is derived from FuncPGOInstrumentation<Edge, BBInfo>::computeCFGHash().
94e8d8bef9SDimitry Andric void SampleProfileProber::computeCFGHash() {
95e8d8bef9SDimitry Andric   std::vector<uint8_t> Indexes;
96e8d8bef9SDimitry Andric   JamCRC JC;
97e8d8bef9SDimitry Andric   for (auto &BB : *F) {
98e8d8bef9SDimitry Andric     auto *TI = BB.getTerminator();
99e8d8bef9SDimitry Andric     for (unsigned I = 0, E = TI->getNumSuccessors(); I != E; ++I) {
100e8d8bef9SDimitry Andric       auto *Succ = TI->getSuccessor(I);
101e8d8bef9SDimitry Andric       auto Index = getBlockId(Succ);
102e8d8bef9SDimitry Andric       for (int J = 0; J < 4; J++)
103e8d8bef9SDimitry Andric         Indexes.push_back((uint8_t)(Index >> (J * 8)));
104e8d8bef9SDimitry Andric     }
105e8d8bef9SDimitry Andric   }
106e8d8bef9SDimitry Andric 
107e8d8bef9SDimitry Andric   JC.update(Indexes);
108e8d8bef9SDimitry Andric 
109e8d8bef9SDimitry Andric   FunctionHash = (uint64_t)CallProbeIds.size() << 48 |
110e8d8bef9SDimitry Andric                  (uint64_t)Indexes.size() << 32 | JC.getCRC();
111e8d8bef9SDimitry Andric   // Reserve bit 60-63 for other information purpose.
112e8d8bef9SDimitry Andric   FunctionHash &= 0x0FFFFFFFFFFFFFFF;
113e8d8bef9SDimitry Andric   assert(FunctionHash && "Function checksum should not be zero");
114e8d8bef9SDimitry Andric   LLVM_DEBUG(dbgs() << "\nFunction Hash Computation for " << F->getName()
115e8d8bef9SDimitry Andric                     << ":\n"
116e8d8bef9SDimitry Andric                     << " CRC = " << JC.getCRC() << ", Edges = "
117e8d8bef9SDimitry Andric                     << Indexes.size() << ", ICSites = " << CallProbeIds.size()
118e8d8bef9SDimitry Andric                     << ", Hash = " << FunctionHash << "\n");
119e8d8bef9SDimitry Andric }
120e8d8bef9SDimitry Andric 
121e8d8bef9SDimitry Andric void SampleProfileProber::computeProbeIdForBlocks() {
122e8d8bef9SDimitry Andric   for (auto &BB : *F) {
123e8d8bef9SDimitry Andric     BlockProbeIds[&BB] = ++LastProbeId;
124e8d8bef9SDimitry Andric   }
125e8d8bef9SDimitry Andric }
126e8d8bef9SDimitry Andric 
127e8d8bef9SDimitry Andric void SampleProfileProber::computeProbeIdForCallsites() {
128e8d8bef9SDimitry Andric   for (auto &BB : *F) {
129e8d8bef9SDimitry Andric     for (auto &I : BB) {
130e8d8bef9SDimitry Andric       if (!isa<CallBase>(I))
131e8d8bef9SDimitry Andric         continue;
132e8d8bef9SDimitry Andric       if (isa<IntrinsicInst>(&I))
133e8d8bef9SDimitry Andric         continue;
134e8d8bef9SDimitry Andric       CallProbeIds[&I] = ++LastProbeId;
135e8d8bef9SDimitry Andric     }
136e8d8bef9SDimitry Andric   }
137e8d8bef9SDimitry Andric }
138e8d8bef9SDimitry Andric 
139e8d8bef9SDimitry Andric uint32_t SampleProfileProber::getBlockId(const BasicBlock *BB) const {
140e8d8bef9SDimitry Andric   auto I = BlockProbeIds.find(const_cast<BasicBlock *>(BB));
141e8d8bef9SDimitry Andric   return I == BlockProbeIds.end() ? 0 : I->second;
142e8d8bef9SDimitry Andric }
143e8d8bef9SDimitry Andric 
144e8d8bef9SDimitry Andric uint32_t SampleProfileProber::getCallsiteId(const Instruction *Call) const {
145e8d8bef9SDimitry Andric   auto Iter = CallProbeIds.find(const_cast<Instruction *>(Call));
146e8d8bef9SDimitry Andric   return Iter == CallProbeIds.end() ? 0 : Iter->second;
147e8d8bef9SDimitry Andric }
148e8d8bef9SDimitry Andric 
149e8d8bef9SDimitry Andric void SampleProfileProber::instrumentOneFunc(Function &F, TargetMachine *TM) {
150e8d8bef9SDimitry Andric   Module *M = F.getParent();
151e8d8bef9SDimitry Andric   MDBuilder MDB(F.getContext());
152e8d8bef9SDimitry Andric   // Compute a GUID without considering the function's linkage type. This is
153e8d8bef9SDimitry Andric   // fine since function name is the only key in the profile database.
154e8d8bef9SDimitry Andric   uint64_t Guid = Function::getGUID(F.getName());
155e8d8bef9SDimitry Andric 
156e8d8bef9SDimitry Andric   // Assign an artificial debug line to a probe that doesn't come with a real
157e8d8bef9SDimitry Andric   // line. A probe not having a debug line will get an incomplete inline
158e8d8bef9SDimitry Andric   // context. This will cause samples collected on the probe to be counted
159e8d8bef9SDimitry Andric   // into the base profile instead of a context profile. The line number
160e8d8bef9SDimitry Andric   // itself is not important though.
161e8d8bef9SDimitry Andric   auto AssignDebugLoc = [&](Instruction *I) {
162e8d8bef9SDimitry Andric     assert((isa<PseudoProbeInst>(I) || isa<CallBase>(I)) &&
163e8d8bef9SDimitry Andric            "Expecting pseudo probe or call instructions");
164e8d8bef9SDimitry Andric     if (!I->getDebugLoc()) {
165e8d8bef9SDimitry Andric       if (auto *SP = F.getSubprogram()) {
166e8d8bef9SDimitry Andric         auto DIL = DILocation::get(SP->getContext(), 0, 0, SP);
167e8d8bef9SDimitry Andric         I->setDebugLoc(DIL);
168e8d8bef9SDimitry Andric         ArtificialDbgLine++;
169e8d8bef9SDimitry Andric         LLVM_DEBUG({
170e8d8bef9SDimitry Andric           dbgs() << "\nIn Function " << F.getName()
171e8d8bef9SDimitry Andric                  << " Probe gets an artificial debug line\n";
172e8d8bef9SDimitry Andric           I->dump();
173e8d8bef9SDimitry Andric         });
174e8d8bef9SDimitry Andric       }
175e8d8bef9SDimitry Andric     }
176e8d8bef9SDimitry Andric   };
177e8d8bef9SDimitry Andric 
178e8d8bef9SDimitry Andric   // Probe basic blocks.
179e8d8bef9SDimitry Andric   for (auto &I : BlockProbeIds) {
180e8d8bef9SDimitry Andric     BasicBlock *BB = I.first;
181e8d8bef9SDimitry Andric     uint32_t Index = I.second;
182e8d8bef9SDimitry Andric     // Insert a probe before an instruction with a valid debug line number which
183e8d8bef9SDimitry Andric     // will be assigned to the probe. The line number will be used later to
184e8d8bef9SDimitry Andric     // model the inline context when the probe is inlined into other functions.
185e8d8bef9SDimitry Andric     // Debug instructions, phi nodes and lifetime markers do not have an valid
186e8d8bef9SDimitry Andric     // line number. Real instructions generated by optimizations may not come
187e8d8bef9SDimitry Andric     // with a line number either.
188e8d8bef9SDimitry Andric     auto HasValidDbgLine = [](Instruction *J) {
189e8d8bef9SDimitry Andric       return !isa<PHINode>(J) && !isa<DbgInfoIntrinsic>(J) &&
190e8d8bef9SDimitry Andric              !J->isLifetimeStartOrEnd() && J->getDebugLoc();
191e8d8bef9SDimitry Andric     };
192e8d8bef9SDimitry Andric 
193e8d8bef9SDimitry Andric     Instruction *J = &*BB->getFirstInsertionPt();
194e8d8bef9SDimitry Andric     while (J != BB->getTerminator() && !HasValidDbgLine(J)) {
195e8d8bef9SDimitry Andric       J = J->getNextNode();
196e8d8bef9SDimitry Andric     }
197e8d8bef9SDimitry Andric 
198e8d8bef9SDimitry Andric     IRBuilder<> Builder(J);
199e8d8bef9SDimitry Andric     assert(Builder.GetInsertPoint() != BB->end() &&
200e8d8bef9SDimitry Andric            "Cannot get the probing point");
201e8d8bef9SDimitry Andric     Function *ProbeFn =
202e8d8bef9SDimitry Andric         llvm::Intrinsic::getDeclaration(M, Intrinsic::pseudoprobe);
203e8d8bef9SDimitry Andric     Value *Args[] = {Builder.getInt64(Guid), Builder.getInt64(Index),
204e8d8bef9SDimitry Andric                      Builder.getInt32(0)};
205e8d8bef9SDimitry Andric     auto *Probe = Builder.CreateCall(ProbeFn, Args);
206e8d8bef9SDimitry Andric     AssignDebugLoc(Probe);
207e8d8bef9SDimitry Andric   }
208e8d8bef9SDimitry Andric 
209e8d8bef9SDimitry Andric   // Probe both direct calls and indirect calls. Direct calls are probed so that
210e8d8bef9SDimitry Andric   // their probe ID can be used as an call site identifier to represent a
211e8d8bef9SDimitry Andric   // calling context.
212e8d8bef9SDimitry Andric   for (auto &I : CallProbeIds) {
213e8d8bef9SDimitry Andric     auto *Call = I.first;
214e8d8bef9SDimitry Andric     uint32_t Index = I.second;
215e8d8bef9SDimitry Andric     uint32_t Type = cast<CallBase>(Call)->getCalledFunction()
216e8d8bef9SDimitry Andric                         ? (uint32_t)PseudoProbeType::DirectCall
217e8d8bef9SDimitry Andric                         : (uint32_t)PseudoProbeType::IndirectCall;
218e8d8bef9SDimitry Andric     AssignDebugLoc(Call);
219e8d8bef9SDimitry Andric     // Levarge the 32-bit discriminator field of debug data to store the ID and
220e8d8bef9SDimitry Andric     // type of a callsite probe. This gets rid of the dependency on plumbing a
221e8d8bef9SDimitry Andric     // customized metadata through the codegen pipeline.
222e8d8bef9SDimitry Andric     uint32_t V = PseudoProbeDwarfDiscriminator::packProbeData(Index, Type);
223e8d8bef9SDimitry Andric     if (auto DIL = Call->getDebugLoc()) {
224e8d8bef9SDimitry Andric       DIL = DIL->cloneWithDiscriminator(V);
225e8d8bef9SDimitry Andric       Call->setDebugLoc(DIL);
226e8d8bef9SDimitry Andric     }
227e8d8bef9SDimitry Andric   }
228e8d8bef9SDimitry Andric 
229e8d8bef9SDimitry Andric   // Create module-level metadata that contains function info necessary to
230e8d8bef9SDimitry Andric   // synthesize probe-based sample counts,  which are
231e8d8bef9SDimitry Andric   // - FunctionGUID
232e8d8bef9SDimitry Andric   // - FunctionHash.
233e8d8bef9SDimitry Andric   // - FunctionName
234e8d8bef9SDimitry Andric   auto Hash = getFunctionHash();
235e8d8bef9SDimitry Andric   auto *MD = MDB.createPseudoProbeDesc(Guid, Hash, &F);
236e8d8bef9SDimitry Andric   auto *NMD = M->getNamedMetadata(PseudoProbeDescMetadataName);
237e8d8bef9SDimitry Andric   assert(NMD && "llvm.pseudo_probe_desc should be pre-created");
238e8d8bef9SDimitry Andric   NMD->addOperand(MD);
239e8d8bef9SDimitry Andric 
240e8d8bef9SDimitry Andric   // Preserve a comdat group to hold all probes materialized later. This
241e8d8bef9SDimitry Andric   // allows that when the function is considered dead and removed, the
242e8d8bef9SDimitry Andric   // materialized probes are disposed too.
243e8d8bef9SDimitry Andric   // Imported functions are defined in another module. They do not need
244e8d8bef9SDimitry Andric   // the following handling since same care will be taken for them in their
245e8d8bef9SDimitry Andric   // original module. The pseudo probes inserted into an imported functions
246e8d8bef9SDimitry Andric   // above will naturally not be emitted since the imported function is free
247e8d8bef9SDimitry Andric   // from object emission. However they will be emitted together with the
248e8d8bef9SDimitry Andric   // inliner functions that the imported function is inlined into. We are not
249e8d8bef9SDimitry Andric   // creating a comdat group for an import function since it's useless anyway.
250e8d8bef9SDimitry Andric   if (!F.isDeclarationForLinker()) {
251e8d8bef9SDimitry Andric     if (TM) {
252e8d8bef9SDimitry Andric       auto Triple = TM->getTargetTriple();
253e8d8bef9SDimitry Andric       if (Triple.supportsCOMDAT() && TM->getFunctionSections()) {
254e8d8bef9SDimitry Andric         GetOrCreateFunctionComdat(F, Triple, CurModuleUniqueId);
255e8d8bef9SDimitry Andric       }
256e8d8bef9SDimitry Andric     }
257e8d8bef9SDimitry Andric   }
258e8d8bef9SDimitry Andric }
259e8d8bef9SDimitry Andric 
260e8d8bef9SDimitry Andric PreservedAnalyses SampleProfileProbePass::run(Module &M,
261e8d8bef9SDimitry Andric                                               ModuleAnalysisManager &AM) {
262e8d8bef9SDimitry Andric   auto ModuleId = getUniqueModuleId(&M);
263e8d8bef9SDimitry Andric   // Create the pseudo probe desc metadata beforehand.
264e8d8bef9SDimitry Andric   // Note that modules with only data but no functions will require this to
265e8d8bef9SDimitry Andric   // be set up so that they will be known as probed later.
266e8d8bef9SDimitry Andric   M.getOrInsertNamedMetadata(PseudoProbeDescMetadataName);
267e8d8bef9SDimitry Andric 
268e8d8bef9SDimitry Andric   for (auto &F : M) {
269e8d8bef9SDimitry Andric     if (F.isDeclaration())
270e8d8bef9SDimitry Andric       continue;
271e8d8bef9SDimitry Andric     SampleProfileProber ProbeManager(F, ModuleId);
272e8d8bef9SDimitry Andric     ProbeManager.instrumentOneFunc(F, TM);
273e8d8bef9SDimitry Andric   }
274e8d8bef9SDimitry Andric 
275e8d8bef9SDimitry Andric   return PreservedAnalyses::none();
276e8d8bef9SDimitry Andric }
277