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