
See https://discourse.llvm.org/t/rfc-keep-globalvalue-guids-stable/84801 for context. This is a non-functional change which just changes the interface of GlobalValue, in preparation for future functional changes. This part touches a fair few users, so is split out for ease of review. Future changes to the GlobalValue implementation can then be focused purely on that class. This does the following: * Rename GlobalValue::getGUID(StringRef) to getGUIDAssumingExternalLinkage. This is simply making explicit at the callsite what is currently implicit. * Where possible, migrate users to directly calling getGUID on a GlobalValue instance. * Otherwise, where possible, have them call the newly renamed getGUIDAssumingExternalLinkage, to make the assumption explicit. There are a few cases where neither of the above are possible, as the caller saves and reconstructs the necessary information to compute the GUID themselves. We want to migrate these callers eventually, but for this first step we leave them be.
151 lines
5.7 KiB
C++
151 lines
5.7 KiB
C++
//===- PseudoProbeInserter.cpp - Insert annotation for callsite profiling -===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements PseudoProbeInserter pass, which inserts pseudo probe
|
|
// annotations for call instructions with a pseudo-probe-specific dwarf
|
|
// discriminator. such discriminator indicates that the call instruction comes
|
|
// with a pseudo probe, and the discriminator value holds information to
|
|
// identify the corresponding counter.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/PseudoProbe.h"
|
|
#include "llvm/InitializePasses.h"
|
|
|
|
#define DEBUG_TYPE "pseudo-probe-inserter"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
class PseudoProbeInserter : public MachineFunctionPass {
|
|
public:
|
|
static char ID;
|
|
|
|
PseudoProbeInserter() : MachineFunctionPass(ID) {
|
|
initializePseudoProbeInserterPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
StringRef getPassName() const override { return "Pseudo Probe Inserter"; }
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
AU.setPreservesAll();
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
}
|
|
|
|
bool doInitialization(Module &M) override {
|
|
ShouldRun = M.getNamedMetadata(PseudoProbeDescMetadataName);
|
|
return false;
|
|
}
|
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override {
|
|
if (!ShouldRun)
|
|
return false;
|
|
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
|
|
bool Changed = false;
|
|
for (MachineBasicBlock &MBB : MF) {
|
|
MachineInstr *FirstInstr = nullptr;
|
|
for (MachineInstr &MI : MBB) {
|
|
if (!MI.isPseudo())
|
|
FirstInstr = &MI;
|
|
if (MI.isCall()) {
|
|
if (DILocation *DL = MI.getDebugLoc()) {
|
|
auto Value = DL->getDiscriminator();
|
|
if (DILocation::isPseudoProbeDiscriminator(Value)) {
|
|
BuildMI(MBB, MI, DL, TII->get(TargetOpcode::PSEUDO_PROBE))
|
|
.addImm(getFuncGUID(MF.getFunction().getParent(), DL))
|
|
.addImm(
|
|
PseudoProbeDwarfDiscriminator::extractProbeIndex(Value))
|
|
.addImm(
|
|
PseudoProbeDwarfDiscriminator::extractProbeType(Value))
|
|
.addImm(PseudoProbeDwarfDiscriminator::extractProbeAttributes(
|
|
Value));
|
|
Changed = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Walk the block backwards, move PSEUDO_PROBE before the first real
|
|
// instruction to fix out-of-order probes. There is a problem with probes
|
|
// as the terminator of the block. During the offline counts processing,
|
|
// the samples collected on the first physical instruction following a
|
|
// probe will be counted towards the probe. This logically equals to
|
|
// treating the instruction next to a probe as if it is from the same
|
|
// block of the probe. This is accurate most of the time unless the
|
|
// instruction can be reached from multiple flows, which means it actually
|
|
// starts a new block. Samples collected on such probes may cause
|
|
// imprecision with the counts inference algorithm. Fortunately, if
|
|
// there are still other native instructions preceding the probe we can
|
|
// use them as a place holder to collect samples for the probe.
|
|
if (FirstInstr) {
|
|
auto MII = MBB.rbegin();
|
|
while (MII != MBB.rend()) {
|
|
// Skip all pseudo probes followed by a real instruction since they
|
|
// are not dangling.
|
|
if (!MII->isPseudo())
|
|
break;
|
|
auto Cur = MII++;
|
|
if (Cur->getOpcode() != TargetOpcode::PSEUDO_PROBE)
|
|
continue;
|
|
// Move the dangling probe before FirstInstr.
|
|
auto *ProbeInstr = &*Cur;
|
|
MBB.remove(ProbeInstr);
|
|
MBB.insert(FirstInstr, ProbeInstr);
|
|
Changed = true;
|
|
}
|
|
} else {
|
|
// Probes not surrounded by any real instructions in the same block are
|
|
// called dangling probes. Since there's no good way to pick up a sample
|
|
// collection point for dangling probes at compile time, they are being
|
|
// removed so that the profile correlation tool will not report any
|
|
// samples collected for them and it's up to the counts inference tool
|
|
// to get them a reasonable count.
|
|
SmallVector<MachineInstr *, 4> ToBeRemoved;
|
|
for (MachineInstr &MI : MBB) {
|
|
if (MI.isPseudoProbe())
|
|
ToBeRemoved.push_back(&MI);
|
|
}
|
|
|
|
for (auto *MI : ToBeRemoved)
|
|
MI->eraseFromParent();
|
|
|
|
Changed |= !ToBeRemoved.empty();
|
|
}
|
|
}
|
|
|
|
return Changed;
|
|
}
|
|
|
|
private:
|
|
uint64_t getFuncGUID(Module *M, DILocation *DL) {
|
|
auto Name = DL->getSubprogramLinkageName();
|
|
return Function::getGUIDAssumingExternalLinkage(Name);
|
|
}
|
|
|
|
bool ShouldRun = false;
|
|
};
|
|
} // namespace
|
|
|
|
char PseudoProbeInserter::ID = 0;
|
|
INITIALIZE_PASS_BEGIN(PseudoProbeInserter, DEBUG_TYPE,
|
|
"Insert pseudo probe annotations for value profiling",
|
|
false, false)
|
|
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
|
|
INITIALIZE_PASS_END(PseudoProbeInserter, DEBUG_TYPE,
|
|
"Insert pseudo probe annotations for value profiling",
|
|
false, false)
|
|
|
|
FunctionPass *llvm::createPseudoProbeInserter() {
|
|
return new PseudoProbeInserter();
|
|
}
|