Skip to content

Commit 610b51c

Browse files
wlei-llvmtstellar
authored andcommitted
[CSSPGO][llvm-profgen] Filter out the instructions without location info for symbolizer
It appears some instructions doesn't have the debug location info and the symbolizer will return an empty call stack for them which will cause some crash later in profile unwinding. Actually we do not record the sample info for them, so this change just filter out those instruction. As those instruction would appears at the begin and end of the instruction list, without them we need to add the boundary check for IP `advance` and `backward`. Also for pseudo probe based profile, we actually don't need the symbolized location info, so here just change to use an empty stack for it. This could save half of the binary loading time. Differential Revision: https://reviews.llvm.org/D96434
1 parent 66873fb commit 610b51c

File tree

7 files changed

+58
-36
lines changed

7 files changed

+58
-36
lines changed

llvm/test/tools/llvm-profgen/inline-cs-noprobe.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
; RUN: llvm-profgen --perfscript=%S/Inputs/inline-cs-noprobe.perfscript --binary=%S/Inputs/inline-cs-noprobe.perfbin --output=%t --show-unwinder-output --csprof-cold-thres=0 | FileCheck %s --check-prefix=CHECK-UNWINDER
22
; RUN: FileCheck %s --input-file %t
33

4-
; CHECK:[main:1 @ foo]:44:0
4+
; CHECK:[main:1 @ foo]:309:0
55
; CHECK: 2.1: 14
66
; CHECK: 3: 15
77
; CHECK: 3.1: 14 bar:14
88
; CHECK: 3.2: 1
9-
; CHECK:[main:1 @ foo:3.1 @ bar]:14:0
9+
; CHECK:[main:1 @ foo:3.1 @ bar]:84:0
1010
; CHECK: 1: 14
1111

1212
; CHECK-UNWINDER: Binary(inline-cs-noprobe.perfbin)'s Range Counter:

llvm/test/tools/llvm-profgen/noinline-cs-noprobe.test

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
; RUN: llvm-profgen --perfscript=%S/Inputs/noinline-cs-noprobe.perfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --show-unwinder-output --csprof-cold-thres=0 | FileCheck %s --check-prefix=CHECK-UNWINDER
22
; RUN: FileCheck %s --input-file %t
33

4-
; CHECK:[main:1 @ foo:3 @ bar]:12:3
4+
; CHECK:[main:1 @ foo]:54:0
5+
; CHECK: 2: 3
6+
; CHECK: 3: 3 bar:3
7+
; CHECK:[main:1 @ foo:3 @ bar]:50:3
58
; CHECK: 0: 3
69
; CHECK: 1: 3
710
; CHECK: 2: 2
811
; CHECK: 4: 1
912
; CHECK: 5: 3
10-
; CHECK:[main:1 @ foo]:6:0
11-
; CHECK: 2: 3
12-
; CHECK: 3: 3 bar:3
1313

1414
; CHECK-UNWINDER: Binary(noinline-cs-noprobe.perfbin)'s Range Counter:
1515
; CHECK-UNWINDER: main:1 @ foo

llvm/test/tools/llvm-profgen/recursion-compression-noprobe.test

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,38 @@
44
; RUN: llvm-profgen --perfscript=%S/Inputs/recursion-compression-noprobe.perfscript --binary=%S/Inputs/recursion-compression-noprobe.perfbin --output=%t --csprof-cold-thres=0
55
; RUN: FileCheck %s --input-file %t
66

7-
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa]:14:0
8-
; CHECK-UNCOMPRESS: 1: 1
9-
; CHECK-UNCOMPRESS: 2: 13 fb:11
10-
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa:2 @ fb]:12:0
7+
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa:2 @ fb]:48:0
118
; CHECK-UNCOMPRESS: 1: 11
129
; CHECK-UNCOMPRESS: 2: 1 fa:1
13-
; CHECK-UNCOMPRESS:[main:1 @ foo]:3:0
10+
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa]:24:0
11+
; CHECK-UNCOMPRESS: 1: 1
12+
; CHECK-UNCOMPRESS: 2: 13 fb:11
13+
; CHECK-UNCOMPRESS:[main:1 @ foo]:7:0
1414
; CHECK-UNCOMPRESS: 2: 1
1515
; CHECK-UNCOMPRESS: 3: 2 fa:1
16-
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa:2 @ fb:2 @ fa]:3:0
16+
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa:2 @ fb:2 @ fa]:7:0
1717
; CHECK-UNCOMPRESS: 1: 1
1818
; CHECK-UNCOMPRESS: 2: 2 fb:1
19-
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa:2 @ fb:2 @ fa:2 @ fb]:1:0
19+
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa:2 @ fb:2 @ fa:2 @ fb]:2:0
2020
; CHECK-UNCOMPRESS: 2: 1 fa:1
21-
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa:2 @ fb:2 @ fa:2 @ fb:2 @ fa]:1:0
21+
; CHECK-UNCOMPRESS:[main:1 @ foo:3 @ fa:2 @ fb:2 @ fa:2 @ fb:2 @ fa]:2:0
2222
; CHECK-UNCOMPRESS: 4: 1
2323

2424

25-
; CHECK: [main:1 @ foo:3 @ fa]:14:0
26-
; CHECK: 1: 1
27-
; CHECK: 2: 13 fb:11
28-
; CHECK: [main:1 @ foo:3 @ fa:2 @ fb]:12:0
25+
; CHECK: [main:1 @ foo:3 @ fa:2 @ fb]:48:0
2926
; CHECK: 1: 11
3027
; CHECK: 2: 1 fa:1
31-
; CHECK: [main:1 @ foo:3 @ fa:2 @ fb:2 @ fa]:4:0
28+
; CHECK: [main:1 @ foo:3 @ fa]:24:0
29+
; CHECK: 1: 1
30+
; CHECK: 2: 13 fb:11
31+
; CHECK: [main:1 @ foo:3 @ fa:2 @ fb:2 @ fa]:9:0
3232
; CHECK: 1: 1
3333
; CHECK: 2: 2 fb:1
3434
; CHECK: 4: 1
35-
; CHECK: [main:1 @ foo]:3:0
35+
; CHECK: [main:1 @ foo]:7:0
3636
; CHECK: 2: 1
3737
; CHECK: 3: 2 fa:1
38-
; CHECK: [main:1 @ foo:3 @ fa:2 @ fb:2 @ fa:2 @ fb]:0:0
38+
; CHECK: [main:1 @ foo:3 @ fa:2 @ fb:2 @ fa:2 @ fb]:1:0
3939

4040

4141
; original code:

llvm/tools/llvm-profgen/PerfReader.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ std::shared_ptr<StringBasedCtxKey> FrameStack::getContextKey() {
9393
std::shared_ptr<StringBasedCtxKey> KeyStr =
9494
std::make_shared<StringBasedCtxKey>();
9595
KeyStr->Context = Binary->getExpandedContextStr(Stack);
96+
if (KeyStr->Context.empty())
97+
return nullptr;
9698
KeyStr->genHashCode();
9799
return KeyStr;
98100
}
@@ -116,6 +118,8 @@ void VirtualUnwinder::collectSamplesFromFrame(UnwindState::ProfiledFrame *Cur,
116118
return;
117119

118120
std::shared_ptr<ContextKey> Key = Stack.getContextKey();
121+
if (Key == nullptr)
122+
return;
119123
auto Ret = CtxCounterMap->emplace(Hashable<ContextKey>(Key), SampleCounter());
120124
SampleCounter &SCounter = Ret.first->second;
121125
for (auto &Item : Cur->RangeSamples) {

llvm/tools/llvm-profgen/ProfileGenerator.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ void CSProfileGenerator::updateBodySamplesforFunctionProfile(
212212
FunctionProfile.addBodySamples(LeafLoc.second.LineOffset,
213213
LeafLoc.second.Discriminator,
214214
Count - PreviousCount);
215-
FunctionProfile.addTotalSamples(Count - PreviousCount);
216215
}
217216
}
218217

@@ -242,9 +241,13 @@ void CSProfileGenerator::populateFunctionBodySamples(
242241

243242
while (IP.Address <= RangeEnd) {
244243
uint64_t Offset = Binary->virtualAddrToOffset(IP.Address);
245-
const FrameLocation &LeafLoc = Binary->getInlineLeafFrameLoc(Offset);
246-
// Recording body sample for this specific context
247-
updateBodySamplesforFunctionProfile(FunctionProfile, LeafLoc, Count);
244+
auto LeafLoc = Binary->getInlineLeafFrameLoc(Offset);
245+
if (LeafLoc.hasValue()) {
246+
// Recording body sample for this specific context
247+
updateBodySamplesforFunctionProfile(FunctionProfile, *LeafLoc, Count);
248+
}
249+
// Accumulate total sample count even it's a line with invalid debug info
250+
FunctionProfile.addTotalSamples(Count);
248251
// Move to next IP within the range
249252
IP.advance();
250253
}
@@ -266,9 +269,11 @@ void CSProfileGenerator::populateFunctionBoundarySamples(
266269
continue;
267270

268271
// Record called target sample and its count
269-
const FrameLocation &LeafLoc = Binary->getInlineLeafFrameLoc(SourceOffset);
270-
FunctionProfile.addCalledTargetSamples(LeafLoc.second.LineOffset,
271-
LeafLoc.second.Discriminator,
272+
auto LeafLoc = Binary->getInlineLeafFrameLoc(SourceOffset);
273+
if (!LeafLoc.hasValue())
274+
continue;
275+
FunctionProfile.addCalledTargetSamples(LeafLoc->second.LineOffset,
276+
LeafLoc->second.Discriminator,
272277
CalleeName, Count);
273278

274279
// Record head sample for called target(callee)
@@ -277,7 +282,7 @@ void CSProfileGenerator::populateFunctionBoundarySamples(
277282
OCalleeCtxStr << ContextId.rsplit(" @ ").first.str();
278283
OCalleeCtxStr << " @ ";
279284
}
280-
OCalleeCtxStr << getCallSite(LeafLoc) << " @ " << CalleeName.str();
285+
OCalleeCtxStr << getCallSite(*LeafLoc) << " @ " << CalleeName.str();
281286

282287
FunctionSamples &CalleeProfile =
283288
getFunctionProfileForContext(OCalleeCtxStr.str());

llvm/tools/llvm-profgen/ProfiledBinary.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ bool ProfiledBinary::inlineContextEqual(uint64_t Address1,
119119
const FrameLocationStack &Context2 = getFrameLocationStack(Offset2);
120120
if (Context1.size() != Context2.size())
121121
return false;
122-
122+
if (Context1.empty())
123+
return false;
123124
// The leaf frame contains location within the leaf, and it
124125
// needs to be remove that as it's not part of the calling context
125126
return std::equal(Context1.begin(), Context1.begin() + Context1.size() - 1,
@@ -134,6 +135,10 @@ std::string ProfiledBinary::getExpandedContextStr(
134135
for (auto Address : Stack) {
135136
uint64_t Offset = virtualAddrToOffset(Address);
136137
const FrameLocationStack &ExpandedContext = getFrameLocationStack(Offset);
138+
// An instruction without a valid debug line will be ignored by sample
139+
// processing
140+
if (ExpandedContext.empty())
141+
return std::string();
137142
for (const auto &Loc : ExpandedContext) {
138143
ContextVec.push_back(getCallSite(Loc));
139144
}
@@ -242,9 +247,14 @@ bool ProfiledBinary::dissassembleSymbol(std::size_t SI, ArrayRef<uint8_t> Bytes,
242247
const MCInstrDesc &MCDesc = MII->get(Inst.getOpcode());
243248

244249
// Populate a vector of the symbolized callsite at this location
245-
InstructionPointer IP(this, Offset);
246-
Offset2LocStackMap[Offset] = symbolize(IP, true);
247-
250+
// We don't need symbolized info for probe-based profile, just use an empty
251+
// stack as an entry to indicate a valid binary offset
252+
FrameLocationStack SymbolizedCallStack;
253+
if (!UsePseudoProbes) {
254+
InstructionPointer IP(this, Offset);
255+
SymbolizedCallStack = symbolize(IP, true);
256+
}
257+
Offset2LocStackMap[Offset] = SymbolizedCallStack;
248258
// Populate address maps.
249259
CodeAddrs.push_back(Offset);
250260
if (MCDesc.isCall())

llvm/tools/llvm-profgen/ProfiledBinary.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "CallContext.h"
1313
#include "PseudoProbe.h"
14+
#include "llvm/ADT/Optional.h"
1415
#include "llvm/ADT/StringRef.h"
1516
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
1617
#include "llvm/MC/MCAsmInfo.h"
@@ -225,9 +226,11 @@ class ProfiledBinary {
225226
return FuncStartAddrMap[Offset];
226227
}
227228

228-
const FrameLocation &getInlineLeafFrameLoc(uint64_t Offset,
229-
bool NameOnly = false) {
230-
return getFrameLocationStack(Offset).back();
229+
Optional<const FrameLocation> getInlineLeafFrameLoc(uint64_t Offset) {
230+
const auto &Stack = getFrameLocationStack(Offset);
231+
if (Stack.empty())
232+
return {};
233+
return Stack.back();
231234
}
232235

233236
// Compare two addresses' inline context

0 commit comments

Comments
 (0)