xref: /llvm-project/llvm/lib/CodeGen/PseudoProbeInserter.cpp (revision ebe09e2a9556c411809f6c27f555299273442664)
124d4291cSHongtao Yu //===- PseudoProbeInserter.cpp - Insert annotation for callsite profiling -===//
224d4291cSHongtao Yu //
324d4291cSHongtao Yu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
424d4291cSHongtao Yu // See https://llvm.org/LICENSE.txt for license information.
524d4291cSHongtao Yu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
624d4291cSHongtao Yu //
724d4291cSHongtao Yu //===----------------------------------------------------------------------===//
824d4291cSHongtao Yu //
924d4291cSHongtao Yu // This file implements PseudoProbeInserter pass, which inserts pseudo probe
1024d4291cSHongtao Yu // annotations for call instructions with a pseudo-probe-specific dwarf
1124d4291cSHongtao Yu // discriminator. such discriminator indicates that the call instruction comes
1224d4291cSHongtao Yu // with a pseudo probe, and the discriminator value holds information to
1324d4291cSHongtao Yu // identify the corresponding counter.
1424d4291cSHongtao Yu //===----------------------------------------------------------------------===//
1524d4291cSHongtao Yu 
1624d4291cSHongtao Yu #include "llvm/CodeGen/MachineBasicBlock.h"
1724d4291cSHongtao Yu #include "llvm/CodeGen/MachineFunctionPass.h"
1824d4291cSHongtao Yu #include "llvm/CodeGen/MachineInstr.h"
1924d4291cSHongtao Yu #include "llvm/CodeGen/TargetInstrInfo.h"
2024d4291cSHongtao Yu #include "llvm/IR/DebugInfoMetadata.h"
21989f1c72Sserge-sans-paille #include "llvm/IR/Module.h"
2224d4291cSHongtao Yu #include "llvm/IR/PseudoProbe.h"
2324d4291cSHongtao Yu #include "llvm/InitializePasses.h"
2424d4291cSHongtao Yu 
2524d4291cSHongtao Yu #define DEBUG_TYPE "pseudo-probe-inserter"
2624d4291cSHongtao Yu 
2724d4291cSHongtao Yu using namespace llvm;
2824d4291cSHongtao Yu 
2924d4291cSHongtao Yu namespace {
3024d4291cSHongtao Yu class PseudoProbeInserter : public MachineFunctionPass {
3124d4291cSHongtao Yu public:
3224d4291cSHongtao Yu   static char ID;
3324d4291cSHongtao Yu 
PseudoProbeInserter()3424d4291cSHongtao Yu   PseudoProbeInserter() : MachineFunctionPass(ID) {
3524d4291cSHongtao Yu     initializePseudoProbeInserterPass(*PassRegistry::getPassRegistry());
3624d4291cSHongtao Yu   }
3724d4291cSHongtao Yu 
getPassName() const3824d4291cSHongtao Yu   StringRef getPassName() const override { return "Pseudo Probe Inserter"; }
3924d4291cSHongtao Yu 
getAnalysisUsage(AnalysisUsage & AU) const4024d4291cSHongtao Yu   void getAnalysisUsage(AnalysisUsage &AU) const override {
4124d4291cSHongtao Yu     AU.setPreservesAll();
4224d4291cSHongtao Yu     MachineFunctionPass::getAnalysisUsage(AU);
4324d4291cSHongtao Yu   }
4424d4291cSHongtao Yu 
doInitialization(Module & M)45d9b511d8SHongtao Yu   bool doInitialization(Module &M) override {
46d9b511d8SHongtao Yu     ShouldRun = M.getNamedMetadata(PseudoProbeDescMetadataName);
47d9b511d8SHongtao Yu     return false;
48d9b511d8SHongtao Yu   }
49d9b511d8SHongtao Yu 
runOnMachineFunction(MachineFunction & MF)5024d4291cSHongtao Yu   bool runOnMachineFunction(MachineFunction &MF) override {
51d9b511d8SHongtao Yu     if (!ShouldRun)
52d9b511d8SHongtao Yu       return false;
5324d4291cSHongtao Yu     const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
5424d4291cSHongtao Yu     bool Changed = false;
5524d4291cSHongtao Yu     for (MachineBasicBlock &MBB : MF) {
56ad2a59f5SHongtao Yu       MachineInstr *FirstInstr = nullptr;
5724d4291cSHongtao Yu       for (MachineInstr &MI : MBB) {
58ad2a59f5SHongtao Yu         if (!MI.isPseudo())
59ad2a59f5SHongtao Yu           FirstInstr = &MI;
6024d4291cSHongtao Yu         if (MI.isCall()) {
6124d4291cSHongtao Yu           if (DILocation *DL = MI.getDebugLoc()) {
6224d4291cSHongtao Yu             auto Value = DL->getDiscriminator();
6324d4291cSHongtao Yu             if (DILocation::isPseudoProbeDiscriminator(Value)) {
6424d4291cSHongtao Yu               BuildMI(MBB, MI, DL, TII->get(TargetOpcode::PSEUDO_PROBE))
6524d4291cSHongtao Yu                   .addImm(getFuncGUID(MF.getFunction().getParent(), DL))
6624d4291cSHongtao Yu                   .addImm(
6724d4291cSHongtao Yu                       PseudoProbeDwarfDiscriminator::extractProbeIndex(Value))
6824d4291cSHongtao Yu                   .addImm(
6924d4291cSHongtao Yu                       PseudoProbeDwarfDiscriminator::extractProbeType(Value))
7024d4291cSHongtao Yu                   .addImm(PseudoProbeDwarfDiscriminator::extractProbeAttributes(
7124d4291cSHongtao Yu                       Value));
7224d4291cSHongtao Yu               Changed = true;
7324d4291cSHongtao Yu             }
7424d4291cSHongtao Yu           }
7524d4291cSHongtao Yu         }
7624d4291cSHongtao Yu       }
77ad2a59f5SHongtao Yu 
78ad2a59f5SHongtao Yu       // Walk the block backwards, move PSEUDO_PROBE before the first real
79ad2a59f5SHongtao Yu       // instruction to fix out-of-order probes. There is a problem with probes
80ad2a59f5SHongtao Yu       // as the terminator of the block. During the offline counts processing,
81ad2a59f5SHongtao Yu       // the samples collected on the first physical instruction following a
82ad2a59f5SHongtao Yu       // probe will be counted towards the probe. This logically equals to
83ad2a59f5SHongtao Yu       // treating the instruction next to a probe as if it is from the same
84ad2a59f5SHongtao Yu       // block of the probe. This is accurate most of the time unless the
85ad2a59f5SHongtao Yu       // instruction can be reached from multiple flows, which means it actually
86ad2a59f5SHongtao Yu       // starts a new block. Samples collected on such probes may cause
87ad2a59f5SHongtao Yu       // imprecision with the counts inference algorithm. Fortunately, if
88ad2a59f5SHongtao Yu       // there are still other native instructions preceding the probe we can
89ad2a59f5SHongtao Yu       // use them as a place holder to collect samples for the probe.
90ad2a59f5SHongtao Yu       if (FirstInstr) {
91ad2a59f5SHongtao Yu         auto MII = MBB.rbegin();
92ad2a59f5SHongtao Yu         while (MII != MBB.rend()) {
93ad2a59f5SHongtao Yu           // Skip all pseudo probes followed by a real instruction since they
94ad2a59f5SHongtao Yu           // are not dangling.
95ad2a59f5SHongtao Yu           if (!MII->isPseudo())
96ad2a59f5SHongtao Yu             break;
97ad2a59f5SHongtao Yu           auto Cur = MII++;
98ad2a59f5SHongtao Yu           if (Cur->getOpcode() != TargetOpcode::PSEUDO_PROBE)
99ad2a59f5SHongtao Yu             continue;
100ad2a59f5SHongtao Yu           // Move the dangling probe before FirstInstr.
101ad2a59f5SHongtao Yu           auto *ProbeInstr = &*Cur;
102ad2a59f5SHongtao Yu           MBB.remove(ProbeInstr);
103ad2a59f5SHongtao Yu           MBB.insert(FirstInstr, ProbeInstr);
104ad2a59f5SHongtao Yu           Changed = true;
105ad2a59f5SHongtao Yu         }
106ad2a59f5SHongtao Yu       } else {
107ad2a59f5SHongtao Yu         // Probes not surrounded by any real instructions in the same block are
108ad2a59f5SHongtao Yu         // called dangling probes. Since there's no good way to pick up a sample
109ad2a59f5SHongtao Yu         // collection point for dangling probes at compile time, they are being
110bd524955SHongtao Yu         // removed so that the profile correlation tool will not report any
111ad2a59f5SHongtao Yu         // samples collected for them and it's up to the counts inference tool
112ad2a59f5SHongtao Yu         // to get them a reasonable count.
113bd524955SHongtao Yu         SmallVector<MachineInstr *, 4> ToBeRemoved;
114ad2a59f5SHongtao Yu         for (MachineInstr &MI : MBB) {
115ad2a59f5SHongtao Yu           if (MI.isPseudoProbe())
116c75da238SHongtao Yu             ToBeRemoved.push_back(&MI);
117c75da238SHongtao Yu         }
118c75da238SHongtao Yu 
119c75da238SHongtao Yu         for (auto *MI : ToBeRemoved)
120c75da238SHongtao Yu           MI->eraseFromParent();
121c75da238SHongtao Yu 
122c75da238SHongtao Yu         Changed |= !ToBeRemoved.empty();
123bd524955SHongtao Yu       }
124bd524955SHongtao Yu     }
125bd524955SHongtao Yu 
12624d4291cSHongtao Yu     return Changed;
12724d4291cSHongtao Yu   }
12824d4291cSHongtao Yu 
12924d4291cSHongtao Yu private:
getFuncGUID(Module * M,DILocation * DL)13024d4291cSHongtao Yu   uint64_t getFuncGUID(Module *M, DILocation *DL) {
131*ebe09e2aSRong Xu     auto Name = DL->getSubprogramLinkageName();
13224d4291cSHongtao Yu     return Function::getGUID(Name);
13324d4291cSHongtao Yu   }
134d9b511d8SHongtao Yu 
135d9b511d8SHongtao Yu   bool ShouldRun = false;
13624d4291cSHongtao Yu };
13724d4291cSHongtao Yu } // namespace
13824d4291cSHongtao Yu 
13924d4291cSHongtao Yu char PseudoProbeInserter::ID = 0;
14024d4291cSHongtao Yu INITIALIZE_PASS_BEGIN(PseudoProbeInserter, DEBUG_TYPE,
14124d4291cSHongtao Yu                       "Insert pseudo probe annotations for value profiling",
14224d4291cSHongtao Yu                       false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)14324d4291cSHongtao Yu INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
14424d4291cSHongtao Yu INITIALIZE_PASS_END(PseudoProbeInserter, DEBUG_TYPE,
14524d4291cSHongtao Yu                     "Insert pseudo probe annotations for value profiling",
14624d4291cSHongtao Yu                     false, false)
14724d4291cSHongtao Yu 
14824d4291cSHongtao Yu FunctionPass *llvm::createPseudoProbeInserter() {
14924d4291cSHongtao Yu   return new PseudoProbeInserter();
15024d4291cSHongtao Yu }
151