llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.18k stars 12.04k forks source link

Something wrong in PGOInstrumentationGen pass #74563

Open hungryzzz opened 11 months ago

hungryzzz commented 11 months ago

Description

Hi, I set the -fprofile-generate option to enable the PGOInstrumentationGen pass and collect the function counts when execution.

But I find that a function whose profiling count is zero will be invoked during execution, I think maybe there is something wrong in PGOInstrumentationGen pass.

Steps to reproduce

clang++ -fprofile-generate -O2 bubble_sort.cpp -o bubble
LLVM_PROFILE_FILE=default.profraw ./bubble
llvm-profdata merge -output=default.profdata *.profraw
llvm-profdata show --counts --function=_ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1Ev ./default.profdata

The result of llvm-profdata show is as follows, it shows that the total counts is zero which indicates that the function _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1Ev will not be executed.

Counters:
  _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1Ev:
    Hash: 0x07df0bf914dbeae5
    Counters: 4
    Block counts: [0, 0, 0, 0]
Instrumentation level: IR  entry_first = 0
Functions shown: 1
Total functions: 9
Maximum function count: 795760
Maximum internal block count: 31829604240

Then I use gdb to debug it, and find that the function _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1Ev will be entered.

bash-4.4$ gdb -q ./bubble
Reading symbols from ./bubble...(no debugging symbols found)...done.
(gdb) b _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1Ev
Breakpoint 1 at 0x18e0
(gdb) r
Starting program: path/bubble
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-151.el8.x86_64
path/bubble iteration(ex. 20). Will use default iteration(20)
 iteration = 20
Bubble sorting array of 40000 elements

Breakpoint 1, 0x00007ffff7b34fb0 in std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream() () from /lib64/libstdc++.so.6
Missing separate debuginfos, use: yum debuginfo-install libgcc-8.4.1-1.el8.x86_64 libstdc++-8.4.1-1.el8.x86_64

Environment

The test case is attached here. case.zip

david-xl commented 11 months ago

The function may be inlined into the caller before the instrumentation so that the remaining out of line copy does not have any count. The inline instance will have no zero count.

hungryzzz commented 11 months ago

I dump the LLVM IR and find that the function is invoked explicitly so I don't think it is related to inlining. I've also checked that sort_array is the only one caller to call the _ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1Ev.

# clang++ -fprofile-generate -O2 bubble_sort.cpp -S -emit-llvm -o bubble.ll
; Function Attrs: mustprogress uwtable
define dso_local void @_Z10sort_arrayv() local_unnamed_addr #5 personality ptr @__gxx_personality_v0 {
  %1 = alloca %"class.std::basic_ifstream", align 8
  %2 = tail call i32 (ptr, ...) @printf(ptr noundef nonnull dereferenceable(1) @.str, i32 noundef 40000)
  call void @llvm.lifetime.start.p0(i64 520, ptr nonnull %1) #13
  call void @_ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1Ev(ptr noundef nonnull align 8 dereferenceable(256) %1)
  %3 = getelementptr inbounds %"class.std::basic_ifstream", ptr %1, i64 0, i32 1
  %4 = invoke noundef ptr @_ZNSt13basic_filebufIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode(ptr noundef nonnull align 8 dereferenceable(240) %3, ptr noundef nonnull @.str.1, i32 noundef 8)
          to label %5 unwind label %40
david-xl commented 11 months ago

Given your observation, another possibility is that the actual callee body is defined in the library not instrumented. You can use the linker trace symbol option to see where the function is defined.