Skip to content

[InstrProf] Duplicated function entries in profile with LTO/ThinLTO enabled in instrumentation build #58215

@xur-llvm

Description

@xur-llvm

We found that there are duplicated function entries in the profile when the instrumentation build with LTO/ThinLTO enabled. For example, in the clang's ThinLTO enabled PGO profile , there are 336 copies of _ZN4llvm2cl6OptionC2ENS0_18NumOccurrencesFlagENS0_12OptionHiddenE with the same hash.
This is wrong.

The root cause is we private the profd variable associated with a COMDAT function if it's renamed (with a hash postfix). This is fine in non-LTO build, since we still have the COMDAT group in place. Linker will choose the prevailing definition and remove other copies all together.

For the LTO build, the COMDAT group (which includes profd and profc etc) might be dissolved. The "profc" variable is fine as it still has a linkonce_odr linkage -- we will have one prevailing copy. The "profd", with a private linkage, will not have any chance to be de-duplicated.

When dumping the raw profile, we iterate all the profd and have duplicated profile counts for the same function.

The following example shows the problem:

> cat c.h
extern void bar();
inline __attribute__((noinline)) void foo() {
}

> cat m1.cc
#include "c.h"
int main() {
  bar();
  foo();
  return 0;
}

> cat m2.cc
#include "c.h"
__attribute__((noinline)) void bar() {
    foo();
}

> clang -O2 -flto=thin m1.cc m2.cc -o t_gen -fuse-ld=lld -fprofile-generate=./t
> ./t_gen && llvm-profdata show -function=foo t/default_*.profraw
Counters:
  _Z3foov:
    Hash: 0x0a4d0ad3efffffff
    Counters: 1
  _Z3foov:
    Hash: 0x0a4d0ad3efffffff
    Counters: 1
Instrumentation level: IR  entry_first = 0
Functions shown: 2
Total functions: 4
Maximum function count: 2
Maximum internal block count: 0

> clang -O2 m1.cc m2.cc -o p_gen -fuse-ld=lld -fprofile-generate=./p
> ./p_gen && llvm-profdata show -function=foo p/default_*.profraw
Counters:
  _Z3foov:
    Hash: 0x0a4d0ad3efffffff
    Counters: 1
    Block counts: [2]
Instrumentation level: IR  entry_first = 0
Functions shown: 1
Total functions: 3
Maximum function count: 2
Maximum internal block count: 0

The profile from LTO build is wrong.

I think the fix would be not marking "profd" variable as private linkage for COMDAT.

Metadata

Metadata

Assignees

Labels

LTOLink time optimization (regular/full LTO or ThinLTO)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions