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