Convert the library-internal function keep into a local array that references the dummy variables that we want to retain.
This achieves two things:
- The function keep is no longer an external, which was causing problems when a shared library, that has PGO, is linked into an executable with PGO. The symbol keep is seen as duplicate, and one copy is thrown away; we want both to stay as this function is creating a reference to other internal symbols that we want the linker to keep.
- Associate the liveness of the dummy variables with that of the __start_/__stop_ symbols of the 4 named sections used in PGO.
Since the fake volatile reference causes an unnecessary load inside function __llvm_profile_end_vnodes, I picked that function because it gets called the least (twice) number of times, during a train run, compared to the other 3 functions (which get called 3 times) based on running SPEC 2017 benchmarks.
Reproduced on AIX:
$ cat build.sh #!/bin/bash cat <<EOF > foo.c void foo() {} EOF cat << EOF > user.c void foo(); int main() { foo(); } EOF touch empty.exp FLAGS=-fprofile-generate clang foo.c $FLAGS -c clang -shared -bE:empty.exp foo.o $FLAGS -o libfoo.so -bexpall clang user.c libfoo.so $FLAGS -o user1 LIBPATH=$PWD ./user1 $ ./build.sh ld: 0711-224 WARNING: Duplicate symbol: keep ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information. ./build.sh: line 16: 20382302 Illegal instruction (core dumped) LIBPATH=$PWD ./user1
Just noting that I am not familiar with whether this function is always referenced whenever any one of the __start_* or __stop_* symbols would be.