Skip to content

Commit 2446439

Browse files
[MemProf] Handle profiles with missing column numbers (#70520)
Detect when we are matching a memprof profile with no column numbers, and in that case treat all column numbers as 0 when matching. The profiled binary might have been built with -gno-column-info, for example.
1 parent cc6f9cf commit 2446439

File tree

5 files changed

+60
-2
lines changed

5 files changed

+60
-2
lines changed

llvm/lib/Transforms/Instrumentation/MemProfiler.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,12 @@ static void readMemprof(Module &M, Function &F,
729729
return;
730730
}
731731

732+
// Detect if there are non-zero column numbers in the profile. If not,
733+
// treat all column numbers as 0 when matching (i.e. ignore any non-zero
734+
// columns in the IR). The profiled binary might have been built with
735+
// column numbers disabled, for example.
736+
bool ProfileHasColumns = false;
737+
732738
// Build maps of the location hash to all profile data with that leaf location
733739
// (allocation info and the callsites).
734740
std::map<uint64_t, std::set<const AllocationInfo *>> LocHashToAllocInfo;
@@ -742,6 +748,7 @@ static void readMemprof(Module &M, Function &F,
742748
// of call stack frames.
743749
uint64_t StackId = computeStackId(AI.CallStack[0]);
744750
LocHashToAllocInfo[StackId].insert(&AI);
751+
ProfileHasColumns |= AI.CallStack[0].Column;
745752
}
746753
for (auto &CS : MemProfRec->CallSites) {
747754
// Need to record all frames from leaf up to and including this function,
@@ -750,6 +757,7 @@ static void readMemprof(Module &M, Function &F,
750757
for (auto &StackFrame : CS) {
751758
uint64_t StackId = computeStackId(StackFrame);
752759
LocHashToCallSites[StackId].insert(std::make_pair(&CS, Idx++));
760+
ProfileHasColumns |= StackFrame.Column;
753761
// Once we find this function, we can stop recording.
754762
if (StackFrame.Function == FuncGUID)
755763
break;
@@ -798,8 +806,8 @@ static void readMemprof(Module &M, Function &F,
798806
if (Name.empty())
799807
Name = DIL->getScope()->getSubprogram()->getName();
800808
auto CalleeGUID = Function::getGUID(Name);
801-
auto StackId =
802-
computeStackId(CalleeGUID, GetOffset(DIL), DIL->getColumn());
809+
auto StackId = computeStackId(CalleeGUID, GetOffset(DIL),
810+
ProfileHasColumns ? DIL->getColumn() : 0);
803811
// LeafFound will only be false on the first iteration, since we either
804812
// set it true or break out of the loop below.
805813
if (!LeafFound) {
Binary file not shown.
Binary file not shown.

llvm/test/Transforms/PGOProfile/Inputs/update_memprof_inputs.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ COMMON_FLAGS="-fuse-ld=lld -Wl,--no-rosegment -gmlt -fdebug-info-for-profiling -
8282
${CLANG} ${COMMON_FLAGS} -fmemory-profile ${OUTDIR}/memprof.cc -o ${OUTDIR}/memprof.exe
8383
env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof.exe > ${OUTDIR}/memprof.memprofraw
8484

85+
# Generate another profile without any column numbers.
86+
${CLANG} ${COMMON_FLAGS} -gno-column-info -fmemory-profile ${OUTDIR}/memprof.cc -o ${OUTDIR}/memprof.nocolinfo.exe
87+
env MEMPROF_OPTIONS=log_path=stdout ${OUTDIR}/memprof.nocolinfo.exe > ${OUTDIR}/memprof.nocolinfo.memprofraw
88+
8589
${CLANG} ${COMMON_FLAGS} -fprofile-generate=. \
8690
${OUTDIR}/memprof.cc -o ${OUTDIR}/pgo.exe
8791
env LLVM_PROFILE_FILE=${OUTDIR}/memprof_pgo.profraw ${OUTDIR}/pgo.exe

llvm/test/Transforms/PGOProfile/memprof.ll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
; RUN: llvm-profdata merge %S/Inputs/memprof.memprofraw --profiled-binary %S/Inputs/memprof.exe -o %t.memprofdata
1717
; RUN: llvm-profdata merge %S/Inputs/memprof_pgo.proftext %S/Inputs/memprof.memprofraw --profiled-binary %S/Inputs/memprof.exe -o %t.pgomemprofdata
1818
; RUN: llvm-profdata merge %S/Inputs/memprof_pgo.proftext -o %t.pgoprofdata
19+
; RUN: llvm-profdata merge %S/Inputs/memprof.nocolinfo.memprofraw --profiled-binary %S/Inputs/memprof.nocolinfo.exe -o %t.nocolinfo.memprofdata
1920

2021
;; In all below cases we should not get any messages about missing profile data
2122
;; for any functions. Either we are not performing any matching for a particular
@@ -28,6 +29,12 @@
2829
; There should not be any PGO metadata
2930
; MEMPROFONLY-NOT: !prof
3031

32+
;; Try again but using a profile with missing columns. The memprof matcher
33+
;; should recognize that there are no non-zero columns in the profile and
34+
;; not attempt to include column numbers in the matching (which means that the
35+
;; stack ids will be different).
36+
; RUN: opt < %s -passes='memprof-use<profile-filename=%t.nocolinfo.memprofdata>' -pgo-warn-missing-function -S 2>&1 | FileCheck %s --check-prefixes=MEMPROFNOCOLINFO,ALL,MEMPROFONLY
37+
3138
;; Test the same thing but by passing the memory profile through to a default
3239
;; pipeline via -memory-profile-file=, which should cause the necessary field
3340
;; of the PGOOptions structure to be populated with the profile filename.
@@ -66,6 +73,7 @@ target triple = "x86_64-unknown-linux-gnu"
6673
define dso_local noundef ptr @_Z3foov() #0 !dbg !10 {
6774
entry:
6875
; MEMPROF: call {{.*}} @_Znam{{.*}} !memprof ![[M1:[0-9]+]], !callsite ![[C1:[0-9]+]]
76+
; MEMPROFNOCOLINFO: call {{.*}} @_Znam{{.*}} !memprof ![[M1:[0-9]+]], !callsite ![[C1:[0-9]+]]
6977
%call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #6, !dbg !13
7078
ret ptr %call, !dbg !14
7179
}
@@ -78,6 +86,7 @@ declare noundef nonnull ptr @_Znam(i64 noundef) #1
7886
define dso_local noundef ptr @_Z4foo2v() #0 !dbg !15 {
7987
entry:
8088
; MEMPROF: call {{.*}} @_Z3foov{{.*}} !callsite ![[C2:[0-9]+]]
89+
; MEMPROFNOCOLINFO: call {{.*}} @_Z3foov{{.*}} !callsite ![[C2:[0-9]+]]
8190
%call = call noundef ptr @_Z3foov(), !dbg !16
8291
ret ptr %call, !dbg !17
8392
}
@@ -86,6 +95,7 @@ entry:
8695
define dso_local noundef ptr @_Z3barv() #0 !dbg !18 {
8796
entry:
8897
; MEMPROF: call {{.*}} @_Z4foo2v{{.*}} !callsite ![[C3:[0-9]+]]
98+
; MEMPROFNOCOLINFO: call {{.*}} @_Z4foo2v{{.*}} !callsite ![[C3:[0-9]+]]
8999
%call = call noundef ptr @_Z4foo2v(), !dbg !19
90100
ret ptr %call, !dbg !20
91101
}
@@ -94,6 +104,7 @@ entry:
94104
define dso_local noundef ptr @_Z3bazv() #0 !dbg !21 {
95105
entry:
96106
; MEMPROF: call {{.*}} @_Z4foo2v{{.*}} !callsite ![[C4:[0-9]+]]
107+
; MEMPROFNOCOLINFO: call {{.*}} @_Z4foo2v{{.*}} !callsite ![[C4:[0-9]+]]
97108
%call = call noundef ptr @_Z4foo2v(), !dbg !22
98109
ret ptr %call, !dbg !23
99110
}
@@ -110,6 +121,7 @@ entry:
110121

111122
if.then: ; preds = %entry
112123
; MEMPROF: call {{.*}} @_Z3foov{{.*}} !callsite ![[C5:[0-9]+]]
124+
; MEMPROFNOCOLINFO: call {{.*}} @_Z3foov{{.*}} !callsite ![[C5:[0-9]+]]
113125
%call = call noundef ptr @_Z3foov(), !dbg !27
114126
store ptr %call, ptr %retval, align 8, !dbg !28
115127
br label %return, !dbg !28
@@ -118,6 +130,7 @@ if.end: ; preds = %entry
118130
%1 = load i32, ptr %n.addr, align 4, !dbg !29
119131
%sub = sub i32 %1, 1, !dbg !30
120132
; MEMPROF: call {{.*}} @_Z7recursej{{.*}} !callsite ![[C6:[0-9]+]]
133+
; MEMPROFNOCOLINFO: call {{.*}} @_Z7recursej{{.*}} !callsite ![[C6:[0-9]+]]
121134
%call1 = call noundef ptr @_Z7recursej(i32 noundef %sub), !dbg !31
122135
store ptr %call1, ptr %retval, align 8, !dbg !32
123136
br label %return, !dbg !32
@@ -145,21 +158,27 @@ entry:
145158
store i32 %argc, ptr %argc.addr, align 4
146159
store ptr %argv, ptr %argv.addr, align 8
147160
; MEMPROF: call {{.*}} @_Znam{{.*}} #[[A1:[0-9]+]]
161+
; MEMPROFNOCOLINFO: call {{.*}} @_Znam{{.*}} #[[A1:[0-9]+]]
148162
%call = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #6, !dbg !35
149163
store ptr %call, ptr %a, align 8, !dbg !36
150164
; MEMPROF: call {{.*}} @_Znam{{.*}} #[[A2:[0-9]+]]
165+
; MEMPROFNOCOLINFO: call {{.*}} @_Znam{{.*}} #[[A2:[0-9]+]]
151166
%call1 = call noalias noundef nonnull ptr @_Znam(i64 noundef 10) #6, !dbg !37
152167
store ptr %call1, ptr %b, align 8, !dbg !38
153168
; MEMPROF: call {{.*}} @_Z3foov{{.*}} !callsite ![[C7:[0-9]+]]
169+
; MEMPROFNOCOLINFO: call {{.*}} @_Z3foov{{.*}} !callsite ![[C7:[0-9]+]]
154170
%call2 = call noundef ptr @_Z3foov(), !dbg !39
155171
store ptr %call2, ptr %c, align 8, !dbg !40
156172
; MEMPROF: call {{.*}} @_Z3foov{{.*}} !callsite ![[C8:[0-9]+]]
173+
; MEMPROFNOCOLINFO: call {{.*}} @_Z3foov{{.*}} !callsite ![[C8:[0-9]+]]
157174
%call3 = call noundef ptr @_Z3foov(), !dbg !41
158175
store ptr %call3, ptr %d, align 8, !dbg !42
159176
; MEMPROF: call {{.*}} @_Z3barv{{.*}} !callsite ![[C9:[0-9]+]]
177+
; MEMPROFNOCOLINFO: call {{.*}} @_Z3barv{{.*}} !callsite ![[C9:[0-9]+]]
160178
%call4 = call noundef ptr @_Z3barv(), !dbg !43
161179
store ptr %call4, ptr %e, align 8, !dbg !44
162180
; MEMPROF: call {{.*}} @_Z3bazv{{.*}} !callsite ![[C10:[0-9]+]]
181+
; MEMPROFNOCOLINFO: call {{.*}} @_Z3bazv{{.*}} !callsite ![[C10:[0-9]+]]
163182
%call5 = call noundef ptr @_Z3bazv(), !dbg !45
164183
store ptr %call5, ptr %f, align 8, !dbg !46
165184
%0 = load ptr, ptr %a, align 8, !dbg !47
@@ -241,6 +260,7 @@ for.body: ; preds = %for.cond
241260
%13 = load i32, ptr %i, align 4, !dbg !84
242261
%add = add i32 %13, 3, !dbg !85
243262
; MEMPROF: call {{.*}} @_Z7recursej{{.*}} !callsite ![[C11:[0-9]+]]
263+
; MEMPROFNOCOLINFO: call {{.*}} @_Z7recursej{{.*}} !callsite ![[C11:[0-9]+]]
244264
%call22 = call noundef ptr @_Z7recursej(i32 noundef %add), !dbg !86
245265
store ptr %call22, ptr %g, align 8, !dbg !87
246266
%14 = load ptr, ptr %g, align 8, !dbg !88
@@ -300,6 +320,32 @@ for.end: ; preds = %for.cond
300320
; MEMPROF: ![[C10]] = !{i64 2061451396820446691}
301321
; MEMPROF: ![[C11]] = !{i64 1544787832369987002}
302322

323+
324+
; MEMPROFNOCOLINFO: #[[A1]] = { builtin allocsize(0) "memprof"="notcold" }
325+
; MEMPROFNOCOLINFO: #[[A2]] = { builtin allocsize(0) "memprof"="cold" }
326+
; MEMPROFNOCOLINFO: ![[M1]] = !{![[MIB1:[0-9]+]], ![[MIB2:[0-9]+]], ![[MIB3:[0-9]+]], ![[MIB4:[0-9]+]], ![[MIB5:[0-9]+]]}
327+
; MEMPROFNOCOLINFO: ![[MIB1]] = !{![[STACK1:[0-9]+]], !"cold"}
328+
; MEMPROFNOCOLINFO: ![[STACK1]] = !{i64 5281664982037379640, i64 6362220161075421157, i64 -5772587307814069790, i64 -5772587307814069790, i64 -5772587307814069790, i64 3577763375057267810}
329+
; MEMPROFNOCOLINFO: ![[MIB2]] = !{![[STACK2:[0-9]+]], !"notcold"}
330+
; MEMPROFNOCOLINFO: ![[STACK2]] = !{i64 5281664982037379640, i64 6362220161075421157, i64 -5772587307814069790, i64 -5772587307814069790, i64 -5772587307814069790, i64 -5772587307814069790}
331+
; MEMPROFNOCOLINFO: ![[MIB3]] = !{![[STACK3:[0-9]+]], !"notcold"}
332+
; MEMPROFNOCOLINFO: ![[STACK3]] = !{i64 5281664982037379640, i64 -6896091699916449732}
333+
; MEMPROFNOCOLINFO: ![[MIB4]] = !{![[STACK4:[0-9]+]], !"cold"}
334+
; MEMPROFNOCOLINFO: ![[STACK4]] = !{i64 5281664982037379640, i64 -6871734214936418908}
335+
; MEMPROFNOCOLINFO: ![[MIB5]] = !{![[STACK5:[0-9]+]], !"cold"}
336+
; MEMPROFNOCOLINFO: ![[STACK5]] = !{i64 5281664982037379640, i64 -6201180255894224618}
337+
; MEMPROFNOCOLINFO: ![[C1]] = !{i64 5281664982037379640}
338+
; MEMPROFNOCOLINFO: ![[C2]] = !{i64 -6871734214936418908}
339+
; MEMPROFNOCOLINFO: ![[C3]] = !{i64 -5588766871448036195}
340+
; MEMPROFNOCOLINFO: ![[C4]] = !{i64 -8990226808646054327}
341+
; MEMPROFNOCOLINFO: ![[C5]] = !{i64 6362220161075421157}
342+
; MEMPROFNOCOLINFO: ![[C6]] = !{i64 -5772587307814069790}
343+
; MEMPROFNOCOLINFO: ![[C7]] = !{i64 -6896091699916449732}
344+
; MEMPROFNOCOLINFO: ![[C8]] = !{i64 -6201180255894224618}
345+
; MEMPROFNOCOLINFO: ![[C9]] = !{i64 -962804290746547393}
346+
; MEMPROFNOCOLINFO: ![[C10]] = !{i64 -4535090212904553409}
347+
; MEMPROFNOCOLINFO: ![[C11]] = !{i64 3577763375057267810}
348+
303349
; Function Attrs: argmemonly nofree nounwind willreturn writeonly
304350
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #3
305351

0 commit comments

Comments
 (0)