Skip to content

Commit 224fee8

Browse files
committed
[CSSPGO] Tweaking inlining with pseudo probes.
Fixing up a couple places where `getCallSiteIdentifier` is needed to support pseudo-probe-based callsites. Also fixing an issue in the extbinary profile reader where the metadata section is not fully scanned based on the number of profiles loaded only for the current module. Reviewed By: wmi, wenlei Differential Revision: https://reviews.llvm.org/D95791
1 parent 772eb24 commit 224fee8

File tree

4 files changed

+204
-9
lines changed

4 files changed

+204
-9
lines changed

llvm/lib/ProfileData/SampleProfReader.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ std::error_code SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5) {
883883
std::error_code SampleProfileReaderExtBinaryBase::readFuncMetadata() {
884884
if (!ProfileIsProbeBased)
885885
return sampleprof_error::success;
886-
for (unsigned I = 0; I < Profiles.size(); ++I) {
886+
while (Data < End) {
887887
auto FName(readStringFromTable());
888888
if (std::error_code EC = FName.getError())
889889
return EC;
@@ -893,8 +893,13 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncMetadata() {
893893
return EC;
894894

895895
SampleContext FContext(*FName);
896-
Profiles[FContext].setFunctionHash(*Checksum);
896+
// No need to load metadata for profiles that are not loaded in the current
897+
// module.
898+
if (Profiles.count(FContext))
899+
Profiles[FContext].setFunctionHash(*Checksum);
897900
}
901+
902+
assert(Data == End && "More data is read than expected");
898903
return sampleprof_error::success;
899904
}
900905

llvm/lib/Transforms/IPO/SampleContextTracker.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,7 @@ void SampleContextTracker::promoteMergeContextSamplesTree(
308308
return;
309309

310310
// Get the context that needs to be promoted
311-
LineLocation CallSite(FunctionSamples::getOffset(DIL),
312-
DIL->getBaseDiscriminator());
311+
LineLocation CallSite = FunctionSamples::getCallSiteIdentifier(DIL);
313312
ContextTrieNode *NodeToPromo =
314313
CallerNode->getChildContext(CallSite, CalleeName);
315314
if (!NodeToPromo)
@@ -370,9 +369,7 @@ SampleContextTracker::getCalleeContextFor(const DILocation *DIL,
370369
return nullptr;
371370

372371
return CallContext->getChildContext(
373-
LineLocation(FunctionSamples::getOffset(DIL),
374-
DIL->getBaseDiscriminator()),
375-
CalleeName);
372+
FunctionSamples::getCallSiteIdentifier(DIL), CalleeName);
376373
}
377374

378375
ContextTrieNode *SampleContextTracker::getContextFor(const DILocation *DIL) {
@@ -386,8 +383,8 @@ ContextTrieNode *SampleContextTracker::getContextFor(const DILocation *DIL) {
386383
if (Name.empty())
387384
Name = PrevDIL->getScope()->getSubprogram()->getName();
388385
S.push_back(
389-
std::make_pair(LineLocation(FunctionSamples::getOffset(DIL),
390-
DIL->getBaseDiscriminator()), Name));
386+
std::make_pair(FunctionSamples::getCallSiteIdentifier(DIL),
387+
PrevDIL->getScope()->getSubprogram()->getLinkageName()));
391388
PrevDIL = DIL;
392389
}
393390

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[foo]:23:23
2+
1: 23
3+
2: 23 zen:23
4+
!CFGChecksum: 281479271677951
5+
[foo:2 @ zen]:765858:23
6+
1: 23
7+
2: 382920
8+
3: 382915
9+
!CFGChecksum: 138828622701
10+
[bar]:23:23
11+
1: 23
12+
2: 23 zen:23
13+
!CFGChecksum: 281479271677951
14+
[bar:2 @ zen]:765858:23
15+
1: 23
16+
2: 382920
17+
3: 382915
18+
!CFGChecksum: 138828622701
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
; RUN: opt < %s -passes=pseudo-probe,sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-inline.prof -S -pass-remarks=sample-profile -pass-remarks-output=%t.opt.yaml 2>&1 | FileCheck %s
2+
; RUN: FileCheck %s -check-prefix=YAML < %t.opt.yaml
3+
4+
; RUN: llvm-profdata merge --sample --extbinary %S/Inputs/pseudo-probe-inline.prof -o %t2
5+
; RUN: opt < %s -passes=pseudo-probe,sample-profile -sample-profile-file=%t2 -S -pass-remarks=sample-profile -pass-remarks-output=%t2.opt.yaml 2>&1 | FileCheck %s
6+
; RUN: FileCheck %s -check-prefix=YAML < %t2.opt.yaml
7+
8+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
9+
target triple = "x86_64-unknown-linux-gnu"
10+
11+
@factor = dso_local global i32 3, align 4
12+
13+
define dso_local i32 @foo(i32 %x) #0 !dbg !12 {
14+
entry:
15+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID1:]], i64 1, i32 0)
16+
%add = add nsw i32 %x, 100000, !dbg !19
17+
;; Check zen is fully inlined so there's no call to zen anymore.
18+
;; Check code from the inlining of zen is properly annotated here.
19+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2:]], i64 1, i32 0)
20+
; CHECK: br i1 %cmp.i, label %while.cond.i, label %while.cond2.i, !dbg ![[#]], !prof ![[PD1:[0-9]+]]
21+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 2, i32 0)
22+
; CHECK: br i1 %cmp1.i, label %while.body.i, label %zen.exit, !dbg ![[#]], !prof ![[PD2:[0-9]+]]
23+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 3, i32 0)
24+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 4, i32 0)
25+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 5, i32 0)
26+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 6, i32 0)
27+
; CHECK-NOT: call i32 @zen
28+
%call = call i32 @zen(i32 %add), !dbg !20
29+
ret i32 %call, !dbg !21
30+
}
31+
32+
; CHECK: define dso_local i32 @zen
33+
define dso_local i32 @zen(i32 %x) #0 !dbg !22 {
34+
entry:
35+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 1, i32 0)
36+
%cmp = icmp sgt i32 %x, 0, !dbg !26
37+
br i1 %cmp, label %while.cond, label %while.cond2, !dbg !28
38+
39+
while.cond:
40+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 2, i32 0)
41+
%x.addr.0 = phi i32 [ %x, %entry ], [ %sub, %while.body ]
42+
%cmp1 = icmp sgt i32 %x.addr.0, 0, !dbg !29
43+
br i1 %cmp1, label %while.body, label %if.end, !dbg !31
44+
45+
while.body:
46+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 3, i32 0)
47+
%0 = load volatile i32, i32* @factor, align 4, !dbg !32
48+
%sub = sub nsw i32 %x.addr.0, %0, !dbg !39
49+
br label %while.cond, !dbg !31
50+
51+
while.cond2:
52+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 4, i32 0)
53+
%x.addr.1 = phi i32 [ %x, %entry ], [ %add, %while.body4 ]
54+
%cmp3 = icmp slt i32 %x.addr.1, 0, !dbg !42
55+
br i1 %cmp3, label %while.body4, label %if.end, !dbg !44
56+
57+
while.body4:
58+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 5, i32 0)
59+
%1 = load volatile i32, i32* @factor, align 4, !dbg !45
60+
%add = add nsw i32 %x.addr.1, %1, !dbg !48
61+
br label %while.cond2, !dbg !44
62+
63+
if.end:
64+
; CHECK: call void @llvm.pseudoprobe(i64 [[#GUID2]], i64 6, i32 0)
65+
%x.addr.2 = phi i32 [ %x.addr.0, %while.cond ], [ %x.addr.1, %while.cond2 ]
66+
ret i32 %x.addr.2, !dbg !51
67+
}
68+
69+
; CHECK: !llvm.pseudo_probe_desc = !{![[#DESC0:]], ![[#DESC1:]]}
70+
; CHECK: ![[#DESC0]] = !{i64 [[#GUID1]], i64 [[#HASH1:]], !"foo"}
71+
; CHECK: ![[#DESC1]] = !{i64 [[#GUID2]], i64 [[#HASH2:]], !"zen"}
72+
; CHECK: ![[PD1]] = !{!"branch_weights", i32 25, i32 1}
73+
; CHECK: ![[PD2]] = !{!"branch_weights", i32 382916, i32 25}
74+
75+
; Checking to see if YAML file is generated and contains remarks
76+
;YAML: --- !Passed
77+
;YAML-NEXT: Pass: sample-profile-inline
78+
;YAML-NEXT: Name: Inlined
79+
;YAML-NEXT: DebugLoc: { File: test.cpp, Line: 10, Column: 11 }
80+
;YAML-NEXT: Function: foo
81+
;YAML-NEXT: Args:
82+
;YAML-NEXT: - Callee: zen
83+
;YAML-NEXT: DebugLoc: { File: test.cpp, Line: 38, Column: 0 }
84+
;YAML-NEXT: - String: ' inlined into '
85+
;YAML-NEXT: - Caller: foo
86+
;YAML-NEXT: DebugLoc: { File: test.cpp, Line: 9, Column: 0 }
87+
;YAML-NEXT: - String: ' to match profiling context'
88+
;YAML-NEXT: - String: ' with '
89+
;YAML-NEXT: - String: '(cost='
90+
;YAML-NEXT: - Cost: '15'
91+
;YAML-NEXT: - String: ', threshold='
92+
;YAML-NEXT: - Threshold: '225'
93+
;YAML-NEXT: - String: ')'
94+
;YAML-NEXT: - String: ' at callsite '
95+
;YAML-NEXT: - String: foo
96+
;YAML-NEXT: - String: ':'
97+
;YAML-NEXT: - Line: '1'
98+
;YAML-NEXT: - String: ':'
99+
;YAML-NEXT: - Column: '11'
100+
;YAML-NEXT: - String: ';'
101+
;YAML-NEXT: ...
102+
;YAML: --- !Analysis
103+
;YAML-NEXT: Pass: sample-profile
104+
;YAML-NEXT: Name: AppliedSamples
105+
;YAML-NEXT: DebugLoc: { File: test.cpp, Line: 10, Column: 22 }
106+
;YAML-NEXT: Function: foo
107+
;YAML-NEXT: Args:
108+
;YAML-NEXT: - String: 'Applied '
109+
;YAML-NEXT: - NumSamples: '23'
110+
;YAML-NEXT: - String: ' samples from profile (ProbeId='
111+
;YAML-NEXT: - ProbeId: '1'
112+
;YAML-NEXT: - String: ')'
113+
;YAML-NEXT: ...
114+
;YAML: --- !Analysis
115+
;YAML-NEXT: Pass: sample-profile
116+
;YAML-NEXT: Name: AppliedSamples
117+
;YAML-NEXT: DebugLoc: { File: test.cpp, Line: 39, Column: 9 }
118+
;YAML-NEXT: Function: foo
119+
;YAML-NEXT: Args:
120+
;YAML-NEXT: - String: 'Applied '
121+
;YAML-NEXT: - NumSamples: '23'
122+
;YAML-NEXT: - String: ' samples from profile (ProbeId='
123+
;YAML-NEXT: - ProbeId: '1'
124+
;YAML-NEXT: - String: ')'
125+
;YAML-NEXT: ...
126+
;YAML: --- !Analysis
127+
;YAML-NEXT: Pass: sample-profile
128+
;YAML-NEXT: Name: AppliedSamples
129+
;YAML-NEXT: DebugLoc: { File: test.cpp, Line: 41, Column: 14 }
130+
;YAML-NEXT: Function: foo
131+
;YAML-NEXT: Args:
132+
;YAML-NEXT: - String: 'Applied '
133+
;YAML-NEXT: - NumSamples: '382920'
134+
;YAML-NEXT: - String: ' samples from profile (ProbeId='
135+
;YAML-NEXT: - ProbeId: '2'
136+
;YAML-NEXT: - String: ')'
137+
;YAML-NEXT: ...
138+
139+
attributes #0 = {"use-sample-profile"}
140+
141+
!llvm.module.flags = !{!8, !9}
142+
143+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3)
144+
!3 = !DIFile(filename: "test.cpp", directory: "test")
145+
!4 = !{}
146+
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
147+
!8 = !{i32 7, !"Dwarf Version", i32 4}
148+
!9 = !{i32 2, !"Debug Info Version", i32 3}
149+
!12 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 9, type: !13, scopeLine: 9, unit: !2)
150+
!13 = !DISubroutineType(types: !14)
151+
!14 = !{!7, !7}
152+
!18 = !DILocation(line: 0, scope: !12)
153+
!19 = !DILocation(line: 10, column: 22, scope: !12)
154+
!20 = !DILocation(line: 10, column: 11, scope: !12)
155+
!21 = !DILocation(line: 12, column: 3, scope: !12)
156+
!22 = distinct !DISubprogram(name: "zen", scope: !3, file: !3, line: 37, type: !13, scopeLine: 38, unit: !2)
157+
!25 = !DILocation(line: 0, scope: !22)
158+
!26 = !DILocation(line: 39, column: 9, scope: !27)
159+
!27 = distinct !DILexicalBlock(scope: !22, file: !3, line: 39, column: 7)
160+
!28 = !DILocation(line: 39, column: 7, scope: !22)
161+
!29 = !DILocation(line: 41, column: 14, scope: !30)
162+
!30 = distinct !DILexicalBlock(scope: !27, file: !3, line: 39, column: 14)
163+
!31 = !DILocation(line: 41, column: 5, scope: !30)
164+
!32 = !DILocation(line: 42, column: 16, scope: !33)
165+
!33 = distinct !DILexicalBlock(scope: !30, file: !3, line: 41, column: 19)
166+
!38 = !DILocation(line: 42, column: 12, scope: !33)
167+
!39 = !DILocation(line: 42, column: 9, scope: !33)
168+
!42 = !DILocation(line: 48, column: 14, scope: !43)
169+
!43 = distinct !DILexicalBlock(scope: !27, file: !3, line: 46, column: 8)
170+
!44 = !DILocation(line: 48, column: 5, scope: !43)
171+
!45 = !DILocation(line: 49, column: 16, scope: !46)
172+
!46 = distinct !DILexicalBlock(scope: !43, file: !3, line: 48, column: 19)
173+
!47 = !DILocation(line: 49, column: 12, scope: !46)
174+
!48 = !DILocation(line: 49, column: 9, scope: !46)
175+
!51 = !DILocation(line: 53, column: 3, scope: !22)

0 commit comments

Comments
 (0)