mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[CSSPGO][llvm-profgen] Pseudo probe based CS profile generation
This change implements profile generation infra for pseudo probe in llvm-profgen. During virtual unwinding, the raw profile is extracted into range counter and branch counter and aggregated to sample counter map indexed by the call stack context. This change introduces the last step and produces the eventual profile. Specifically, the body of function sample is recorded by going through each probe among the range and callsite target sample is recorded by extracting the callsite probe from branch's source. Please refer https://groups.google.com/g/llvm-dev/c/1p1rdYbL93s and https://reviews.llvm.org/D89707 for more context about CSSPGO and llvm-profgen. **Implementation** - Extended `PseudoProbeProfileGenerator` for pseudo probe based profile generation. - `populateBodySamplesWithProbes` reading range counter is responsible for recording function body samples and inferring caller's body samples. - `populateBoundarySamplesWithProbes` reading branch counter is responsible for recording call site target samples. - Each sample is recorded with its calling context(named `ContextId`). Remind that the probe based context key doesn't include the leaf frame probe info, so the `ContextId` string is created from two part: one from the probe stack strings' concatenation and other one from the leaf frame probe. - Added regression test Test Plan: ninja & ninja check-llvm Differential Revision: https://reviews.llvm.org/D92998
This commit is contained in:
parent
fb07198b1d
commit
0adbe76ec7
@ -1,4 +1,21 @@
|
||||
; RUN: llvm-profgen --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --output=%t --show-unwinder-output | FileCheck %s --check-prefix=CHECK-UNWINDER
|
||||
; RUN: FileCheck %s --input-file %t
|
||||
|
||||
; CHECK: [main:2 @ foo]:74:0
|
||||
; CHECK-NEXT: 2: 15
|
||||
; CHECK-NEXT: 3: 15
|
||||
; CHECK-NEXT: 4: 14
|
||||
; CHECK-NEXT: 5: 1
|
||||
; CHECK-NEXT: 6: 15
|
||||
; CHECK-NEXT: 8: 14 bar:14
|
||||
; CHECK-NEXT: !CFGChecksum: 138950591924
|
||||
; CHECK-NEXT:[main:2 @ foo:8 @ bar]:56:14
|
||||
; CHECK-NEXT: 1: 14
|
||||
; CHECK-NEXT: 2: 14
|
||||
; CHECK-NEXT: 3: 14
|
||||
; CHECK-NEXT: 4: 14
|
||||
; CHECK-NEXT: !CFGChecksum: 72617220756
|
||||
|
||||
|
||||
; CHECK-UNWINDER: Binary(inline-cs-pseudoprobe.perfbin)'s Range Counter:
|
||||
; CHECK-UNWINDER-EMPTY:
|
||||
|
@ -1,4 +1,20 @@
|
||||
; RUN: llvm-profgen --perfscript=%S/Inputs/noinline-cs-pseudoprobe.perfscript --binary=%S/Inputs/noinline-cs-pseudoprobe.perfbin --output=%t --show-unwinder-output | FileCheck %s --check-prefix=CHECK-UNWINDER
|
||||
; RUN: FileCheck %s --input-file %t
|
||||
|
||||
; CHECK: [main:2 @ foo]:75:0
|
||||
; CHECK-NEXT: 2: 15
|
||||
; CHECK-NEXT: 3: 15
|
||||
; CHECK-NEXT: 4: 15
|
||||
; CHECK-NEXT: 6: 15
|
||||
; CHECK-NEXT: 8: 15 bar:15
|
||||
; CHECK-NEXT: !CFGChecksum: 138950591924
|
||||
; CHECK-NEXT:[main:2 @ foo:8 @ bar]:60:15
|
||||
; CHECK-NEXT: 1: 15
|
||||
; CHECK-NEXT: 2: 15
|
||||
; CHECK-NEXT: 3: 15
|
||||
; CHECK-NEXT: 4: 15
|
||||
; CHECK-NEXT: !CFGChecksum: 72617220756
|
||||
|
||||
|
||||
; CHECK-UNWINDER: Binary(noinline-cs-pseudoprobe.perfbin)'s Range Counter:
|
||||
; CHECK-UNWINDER-NEXT: main:2
|
||||
|
@ -567,11 +567,7 @@ void PerfReader::checkAndSetPerfType(
|
||||
}
|
||||
|
||||
if (HasHybridPerf) {
|
||||
// Set up ProfileIsCS to enable context-sensitive functionalities
|
||||
// in SampleProf
|
||||
FunctionSamples::ProfileIsCS = true;
|
||||
PerfType = PERF_LBR_STACK;
|
||||
|
||||
} else {
|
||||
// TODO: Support other type of perf script
|
||||
PerfType = PERF_INVILID;
|
||||
|
@ -67,7 +67,7 @@ void ProfileGenerator::findDisjointRanges(RangeSample &DisjointRanges,
|
||||
/*
|
||||
Regions may overlap with each other. Using the boundary info, find all
|
||||
disjoint ranges and their sample count. BoundaryPoint contains the count
|
||||
mutiple samples begin/end at this points.
|
||||
multiple samples begin/end at this points.
|
||||
|
||||
|<--100-->| Sample1
|
||||
|<------200------>| Sample2
|
||||
@ -264,9 +264,12 @@ static FrameLocation getCallerContext(StringRef CalleeContext,
|
||||
StringRef CallerContext = CalleeContext.rsplit(" @ ").first;
|
||||
CallerNameWithContext = CallerContext.rsplit(':').first;
|
||||
auto ContextSplit = CallerContext.rsplit(" @ ");
|
||||
StringRef CallerFrameStr = ContextSplit.second.size() == 0
|
||||
? ContextSplit.first
|
||||
: ContextSplit.second;
|
||||
FrameLocation LeafFrameLoc = {"", {0, 0}};
|
||||
StringRef Funcname;
|
||||
SampleContext::decodeContextString(ContextSplit.second, Funcname,
|
||||
SampleContext::decodeContextString(CallerFrameStr, Funcname,
|
||||
LeafFrameLoc.second);
|
||||
LeafFrameLoc.first = Funcname.str();
|
||||
return LeafFrameLoc;
|
||||
@ -316,5 +319,196 @@ void CSProfileGenerator::populateInferredFunctionSamples() {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to extract context prefix
|
||||
// PrefixContextId is the context id string except for the leaf probe's
|
||||
// context, the final ContextId will be:
|
||||
// ContextId = PrefixContextId + LeafContextId;
|
||||
// Remind that the string in ContextStrStack is in callee-caller order
|
||||
// So process the string vector reversely
|
||||
static std::string
|
||||
extractPrefixContextId(const SmallVector<const PseudoProbe *, 16> &Probes,
|
||||
ProfiledBinary *Binary) {
|
||||
SmallVector<std::string, 16> ContextStrStack;
|
||||
for (const auto *P : Probes) {
|
||||
Binary->getInlineContextForProbe(P, ContextStrStack, true);
|
||||
}
|
||||
std::ostringstream OContextStr;
|
||||
for (auto &CxtStr : ContextStrStack) {
|
||||
if (OContextStr.str().size())
|
||||
OContextStr << " @ ";
|
||||
OContextStr << CxtStr;
|
||||
}
|
||||
return OContextStr.str();
|
||||
}
|
||||
|
||||
void PseudoProbeCSProfileGenerator::generateProfile() {
|
||||
// Enable CS and pseudo probe functionalities in SampleProf
|
||||
FunctionSamples::ProfileIsCS = true;
|
||||
FunctionSamples::ProfileIsProbeBased = true;
|
||||
for (const auto &BI : BinarySampleCounters) {
|
||||
ProfiledBinary *Binary = BI.first;
|
||||
for (const auto &CI : BI.second) {
|
||||
const ProbeBasedCtxKey *CtxKey =
|
||||
dyn_cast<ProbeBasedCtxKey>(CI.first.getPtr());
|
||||
std::string PrefixContextId =
|
||||
extractPrefixContextId(CtxKey->Probes, Binary);
|
||||
// Fill in function body samples from probes, also infer caller's samples
|
||||
// from callee's probe
|
||||
populateBodySamplesWithProbes(CI.second.RangeCounter, PrefixContextId,
|
||||
Binary);
|
||||
// Fill in boundary samples for a call probe
|
||||
populateBoundarySamplesWithProbes(CI.second.BranchCounter,
|
||||
PrefixContextId, Binary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PseudoProbeCSProfileGenerator::extractProbesFromRange(
|
||||
const RangeSample &RangeCounter, ProbeCounterMap &ProbeCounter,
|
||||
ProfiledBinary *Binary) {
|
||||
RangeSample Ranges;
|
||||
findDisjointRanges(Ranges, RangeCounter);
|
||||
for (const auto &Range : Ranges) {
|
||||
uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
|
||||
uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
|
||||
uint64_t Count = Range.second;
|
||||
// Disjoint ranges have introduce zero-filled gap that
|
||||
// doesn't belong to current context, filter them out.
|
||||
if (Count == 0)
|
||||
continue;
|
||||
|
||||
InstructionPointer IP(Binary, RangeBegin, true);
|
||||
|
||||
// Disjoint ranges may have range in the middle of two instr,
|
||||
// e.g. If Instr1 at Addr1, and Instr2 at Addr2, disjoint range
|
||||
// can be Addr1+1 to Addr2-1. We should ignore such range.
|
||||
if (IP.Address > RangeEnd)
|
||||
continue;
|
||||
|
||||
while (IP.Address <= RangeEnd) {
|
||||
const AddressProbesMap &Address2ProbesMap =
|
||||
Binary->getAddress2ProbesMap();
|
||||
auto It = Address2ProbesMap.find(IP.Address);
|
||||
if (It != Address2ProbesMap.end()) {
|
||||
for (const auto &Probe : It->second) {
|
||||
if (!Probe.isBlock())
|
||||
continue;
|
||||
ProbeCounter[&Probe] += Count;
|
||||
}
|
||||
}
|
||||
|
||||
IP.advance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PseudoProbeCSProfileGenerator::populateBodySamplesWithProbes(
|
||||
const RangeSample &RangeCounter, StringRef PrefixContextId,
|
||||
ProfiledBinary *Binary) {
|
||||
ProbeCounterMap ProbeCounter;
|
||||
// Extract the top frame probes by looking up each address among the range in
|
||||
// the Address2ProbeMap
|
||||
extractProbesFromRange(RangeCounter, ProbeCounter, Binary);
|
||||
for (auto PI : ProbeCounter) {
|
||||
const PseudoProbe *Probe = PI.first;
|
||||
uint64_t Count = PI.second;
|
||||
FunctionSamples &FunctionProfile =
|
||||
getFunctionProfileForLeafProbe(PrefixContextId, Probe, Binary);
|
||||
|
||||
FunctionProfile.addBodySamples(Probe->Index, 0, Count);
|
||||
FunctionProfile.addTotalSamples(Count);
|
||||
if (Probe->isEntry()) {
|
||||
FunctionProfile.addHeadSamples(Count);
|
||||
// Look up for the caller's function profile
|
||||
const auto *InlinerDesc = Binary->getInlinerDescForProbe(Probe);
|
||||
if (InlinerDesc != nullptr) {
|
||||
// Since the context id will be compressed, we have to use callee's
|
||||
// context id to infer caller's context id to ensure they share the
|
||||
// same context prefix.
|
||||
StringRef CalleeContextId =
|
||||
FunctionProfile.getContext().getNameWithContext(true);
|
||||
StringRef CallerContextId;
|
||||
FrameLocation &&CallerLeafFrameLoc =
|
||||
getCallerContext(CalleeContextId, CallerContextId);
|
||||
uint64_t CallerIndex = CallerLeafFrameLoc.second.LineOffset;
|
||||
assert(CallerIndex &&
|
||||
"Inferred caller's location index shouldn't be zero!");
|
||||
FunctionSamples &CallerProfile =
|
||||
getFunctionProfileForContext(CallerContextId);
|
||||
CallerProfile.setFunctionHash(InlinerDesc->FuncHash);
|
||||
CallerProfile.addBodySamples(CallerIndex, 0, Count);
|
||||
CallerProfile.addTotalSamples(Count);
|
||||
CallerProfile.addCalledTargetSamples(CallerIndex, 0,
|
||||
FunctionProfile.getName(), Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PseudoProbeCSProfileGenerator::populateBoundarySamplesWithProbes(
|
||||
const BranchSample &BranchCounter, StringRef PrefixContextId,
|
||||
ProfiledBinary *Binary) {
|
||||
for (auto BI : BranchCounter) {
|
||||
uint64_t SourceOffset = BI.first.first;
|
||||
uint64_t TargetOffset = BI.first.second;
|
||||
uint64_t Count = BI.second;
|
||||
uint64_t SourceAddress = Binary->offsetToVirtualAddr(SourceOffset);
|
||||
const PseudoProbe *CallProbe = Binary->getCallProbeForAddr(SourceAddress);
|
||||
if (CallProbe == nullptr)
|
||||
continue;
|
||||
FunctionSamples &FunctionProfile =
|
||||
getFunctionProfileForLeafProbe(PrefixContextId, CallProbe, Binary);
|
||||
FunctionProfile.addBodySamples(CallProbe->Index, 0, Count);
|
||||
FunctionProfile.addTotalSamples(Count);
|
||||
StringRef CalleeName = FunctionSamples::getCanonicalFnName(
|
||||
Binary->getFuncFromStartOffset(TargetOffset));
|
||||
if (CalleeName.size() == 0)
|
||||
continue;
|
||||
FunctionProfile.addCalledTargetSamples(CallProbe->Index, 0, CalleeName,
|
||||
Count);
|
||||
}
|
||||
}
|
||||
|
||||
FunctionSamples &PseudoProbeCSProfileGenerator::getFunctionProfileForLeafProbe(
|
||||
StringRef PrefixContextId, SmallVector<std::string, 16> &LeafInlinedContext,
|
||||
const PseudoProbeFuncDesc *LeafFuncDesc) {
|
||||
assert(LeafInlinedContext.size() &&
|
||||
"Profile context must have the leaf frame");
|
||||
std::ostringstream OContextStr;
|
||||
OContextStr << PrefixContextId.str();
|
||||
|
||||
for (uint32_t I = 0; I < LeafInlinedContext.size() - 1; I++) {
|
||||
if (OContextStr.str().size())
|
||||
OContextStr << " @ ";
|
||||
OContextStr << LeafInlinedContext[I];
|
||||
}
|
||||
// For leaf inlined context with the top frame, we should strip off the top
|
||||
// frame's probe id, like:
|
||||
// Inlined stack: [foo:1, bar:2], the ContextId will be "foo:1 @ bar"
|
||||
if (OContextStr.str().size())
|
||||
OContextStr << " @ ";
|
||||
StringRef LeafLoc = LeafInlinedContext.back();
|
||||
OContextStr << LeafLoc.split(":").first.str();
|
||||
|
||||
FunctionSamples &FunctionProile =
|
||||
getFunctionProfileForContext(OContextStr.str());
|
||||
FunctionProile.setFunctionHash(LeafFuncDesc->FuncHash);
|
||||
return FunctionProile;
|
||||
}
|
||||
|
||||
FunctionSamples &PseudoProbeCSProfileGenerator::getFunctionProfileForLeafProbe(
|
||||
StringRef PrefixContextId, const PseudoProbe *LeafProbe,
|
||||
ProfiledBinary *Binary) {
|
||||
SmallVector<std::string, 16> LeafInlinedContext;
|
||||
Binary->getInlineContextForProbe(LeafProbe, LeafInlinedContext);
|
||||
// Note that the context from probe doesn't include leaf frame,
|
||||
// hence we need to retrieve and append the leaf frame.
|
||||
const auto *FuncDesc = Binary->getFuncDescForGUID(LeafProbe->GUID);
|
||||
LeafInlinedContext.emplace_back(FuncDesc->FuncName + ":" +
|
||||
Twine(LeafProbe->Index).str());
|
||||
return getFunctionProfileForLeafProbe(PrefixContextId, LeafInlinedContext,
|
||||
FuncDesc);
|
||||
}
|
||||
|
||||
} // end namespace sampleprof
|
||||
} // end namespace llvm
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
ProfileGenerator(){};
|
||||
virtual ~ProfileGenerator() = default;
|
||||
static std::unique_ptr<ProfileGenerator>
|
||||
create(const BinarySampleCounterMap &SampleCounters,
|
||||
create(const BinarySampleCounterMap &BinarySampleCounters,
|
||||
enum PerfScriptType SampleType);
|
||||
virtual void generateProfile() = 0;
|
||||
|
||||
@ -50,7 +50,6 @@ protected:
|
||||
*/
|
||||
void findDisjointRanges(RangeSample &DisjointRanges,
|
||||
const RangeSample &Ranges);
|
||||
|
||||
// Used by SampleProfileWriter
|
||||
StringMap<FunctionSamples> ProfileMap;
|
||||
};
|
||||
@ -65,6 +64,8 @@ public:
|
||||
|
||||
public:
|
||||
void generateProfile() override {
|
||||
// Enable context-sensitive functionalities in SampleProf
|
||||
FunctionSamples::ProfileIsCS = true;
|
||||
for (const auto &BI : BinarySampleCounters) {
|
||||
ProfiledBinary *Binary = BI.first;
|
||||
for (const auto &CI : BI.second) {
|
||||
@ -90,14 +91,16 @@ public:
|
||||
populateInferredFunctionSamples();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Lookup or create FunctionSamples for the context
|
||||
FunctionSamples &getFunctionProfileForContext(StringRef ContextId);
|
||||
|
||||
private:
|
||||
// Helper function for updating body sample for a leaf location in
|
||||
// FunctionProfile
|
||||
void updateBodySamplesforFunctionProfile(FunctionSamples &FunctionProfile,
|
||||
const FrameLocation &LeafLoc,
|
||||
uint64_t Count);
|
||||
// Lookup or create FunctionSamples for the context
|
||||
FunctionSamples &getFunctionProfileForContext(StringRef ContextId);
|
||||
void populateFunctionBodySamples(FunctionSamples &FunctionProfile,
|
||||
const RangeSample &RangeCounters,
|
||||
ProfiledBinary *Binary);
|
||||
@ -108,14 +111,38 @@ private:
|
||||
void populateInferredFunctionSamples();
|
||||
};
|
||||
|
||||
using ProbeCounterMap = std::unordered_map<const PseudoProbe *, uint64_t>;
|
||||
|
||||
class PseudoProbeCSProfileGenerator : public CSProfileGenerator {
|
||||
|
||||
public:
|
||||
PseudoProbeCSProfileGenerator(const BinarySampleCounterMap &Counters)
|
||||
: CSProfileGenerator(Counters) {}
|
||||
void generateProfile() override {
|
||||
// TODO
|
||||
}
|
||||
void generateProfile() override;
|
||||
|
||||
private:
|
||||
// Go through each address from range to extract the top frame probe by
|
||||
// looking up in the Address2ProbeMap
|
||||
void extractProbesFromRange(const RangeSample &RangeCounter,
|
||||
ProbeCounterMap &ProbeCounter,
|
||||
ProfiledBinary *Binary);
|
||||
// Fill in function body samples from probes
|
||||
void populateBodySamplesWithProbes(const RangeSample &RangeCounter,
|
||||
StringRef PrefixContextId,
|
||||
ProfiledBinary *Binary);
|
||||
// Fill in boundary samples for a call probe
|
||||
void populateBoundarySamplesWithProbes(const BranchSample &BranchCounter,
|
||||
StringRef PrefixContextId,
|
||||
ProfiledBinary *Binary);
|
||||
// Helper function to get FunctionSamples for the leaf inlined context
|
||||
FunctionSamples &getFunctionProfileForLeafProbe(
|
||||
StringRef PrefixContextId,
|
||||
SmallVector<std::string, 16> &LeafInlinedContext,
|
||||
const PseudoProbeFuncDesc *LeafFuncDesc);
|
||||
// Helper function to get FunctionSamples for the leaf probe
|
||||
FunctionSamples &getFunctionProfileForLeafProbe(StringRef PrefixContextId,
|
||||
const PseudoProbe *LeafProbe,
|
||||
ProfiledBinary *Binary);
|
||||
};
|
||||
|
||||
} // end namespace sampleprof
|
||||
|
@ -244,10 +244,19 @@ public:
|
||||
void
|
||||
getInlineContextForProbe(const PseudoProbe *Probe,
|
||||
SmallVector<std::string, 16> &InlineContextStack,
|
||||
bool IncludeLeaf) const {
|
||||
bool IncludeLeaf = false) const {
|
||||
return ProbeDecoder.getInlineContextForProbe(Probe, InlineContextStack,
|
||||
IncludeLeaf);
|
||||
}
|
||||
const AddressProbesMap &getAddress2ProbesMap() const {
|
||||
return ProbeDecoder.getAddress2ProbesMap();
|
||||
}
|
||||
const PseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) {
|
||||
return ProbeDecoder.getFuncDescForGUID(GUID);
|
||||
}
|
||||
const PseudoProbeFuncDesc *getInlinerDescForProbe(const PseudoProbe *Probe) {
|
||||
return ProbeDecoder.getInlinerDescForProbe(Probe);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace sampleprof
|
||||
|
@ -41,7 +41,7 @@ void PseudoProbe::getInlineContext(SmallVector<std::string, 16> &ContextStack,
|
||||
PseudoProbeInlineTree *Cur = InlineTree;
|
||||
// It will add the string of each node's inline site during iteration.
|
||||
// Note that it won't include the probe's belonging function(leaf location)
|
||||
while (!Cur->hasInlineSite()) {
|
||||
while (Cur->hasInlineSite()) {
|
||||
std::string ContextStr;
|
||||
if (ShowName) {
|
||||
StringRef FuncName =
|
||||
@ -312,22 +312,32 @@ PseudoProbeDecoder::getCallProbeForAddr(uint64_t Address) const {
|
||||
return CallProbe;
|
||||
}
|
||||
|
||||
const PseudoProbeFuncDesc *
|
||||
PseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID) const {
|
||||
auto It = GUID2FuncDescMap.find(GUID);
|
||||
assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");
|
||||
return &It->second;
|
||||
}
|
||||
|
||||
void PseudoProbeDecoder::getInlineContextForProbe(
|
||||
const PseudoProbe *Probe, SmallVector<std::string, 16> &InlineContextStack,
|
||||
bool IncludeLeaf) const {
|
||||
if (IncludeLeaf) {
|
||||
// Note that the context from probe doesn't include leaf frame,
|
||||
// hence we need to retrieve and prepend leaf if requested.
|
||||
auto It = GUID2FuncDescMap.find(Probe->GUID);
|
||||
assert(It != GUID2FuncDescMap.end() &&
|
||||
"Should have function descriptor for a valid GUID");
|
||||
StringRef FuncName = It->second.FuncName;
|
||||
// InlineContextStack is in callee-caller order, so push leaf in the front
|
||||
InlineContextStack.emplace_back(FuncName.str() + ":" +
|
||||
Twine(Probe->Index).str());
|
||||
}
|
||||
|
||||
Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap, true);
|
||||
if (!IncludeLeaf)
|
||||
return;
|
||||
// Note that the context from probe doesn't include leaf frame,
|
||||
// hence we need to retrieve and prepend leaf if requested.
|
||||
const auto *FuncDesc = getFuncDescForGUID(Probe->GUID);
|
||||
InlineContextStack.emplace_back(FuncDesc->FuncName + ":" +
|
||||
Twine(Probe->Index).str());
|
||||
}
|
||||
|
||||
const PseudoProbeFuncDesc *
|
||||
PseudoProbeDecoder::getInlinerDescForProbe(const PseudoProbe *Probe) const {
|
||||
PseudoProbeInlineTree *InlinerNode = Probe->InlineTree;
|
||||
if (!InlinerNode->hasInlineSite())
|
||||
return nullptr;
|
||||
return getFuncDescForGUID(std::get<0>(InlinerNode->ISite));
|
||||
}
|
||||
|
||||
} // end namespace sampleprof
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
|
||||
void addProbes(PseudoProbe *Probe) { ProbeVector.push_back(Probe); }
|
||||
// Return false if it's a dummy inline site
|
||||
bool hasInlineSite() const { return !std::get<0>(ISite); }
|
||||
bool hasInlineSite() const { return std::get<0>(ISite) != 0; }
|
||||
};
|
||||
|
||||
// Function descriptor decoded from .pseudo_probe_desc section
|
||||
@ -203,17 +203,26 @@ public:
|
||||
// Look up the probe of a call for the input address
|
||||
const PseudoProbe *getCallProbeForAddr(uint64_t Address) const;
|
||||
|
||||
const PseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) const;
|
||||
|
||||
// Helper function to populate one probe's inline stack into
|
||||
// \p InlineContextStack.
|
||||
// Current leaf location info will be added if IncludeLeaf is true
|
||||
// Example:
|
||||
// Current probe(bar:3) inlined at foo:2 then inlined at main:1
|
||||
// IncludeLeaf = true, Output: [main:1, foo:2, bar:3]
|
||||
// IncludeLeaf = false, OUtput: [main:1, foo:2]
|
||||
// IncludeLeaf = false, Output: [main:1, foo:2]
|
||||
void
|
||||
getInlineContextForProbe(const PseudoProbe *Probe,
|
||||
SmallVector<std::string, 16> &InlineContextStack,
|
||||
bool IncludeLeaf) const;
|
||||
|
||||
const AddressProbesMap &getAddress2ProbesMap() const {
|
||||
return Address2ProbesMap;
|
||||
}
|
||||
|
||||
const PseudoProbeFuncDesc *
|
||||
getInlinerDescForProbe(const PseudoProbe *Probe) const;
|
||||
};
|
||||
|
||||
} // end namespace sampleprof
|
||||
|
Loading…
x
Reference in New Issue
Block a user