[all-commits] [llvm/llvm-project] 890163: [LTO] Make local linkage GlobalValue in non-prevai...

Fangrui Song via All-commits all-commits at lists.llvm.org
Thu Nov 10 21:54:57 PST 2022


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 8901635423cbea4324059a5127657126d2e00ce1
      https://github.com/llvm/llvm-project/commit/8901635423cbea4324059a5127657126d2e00ce1
  Author: Fangrui Song <i at maskray.me>
  Date:   2022-11-10 (Thu, 10 Nov 2022)

  Changed paths:
    M llvm/lib/LTO/LTO.cpp
    M llvm/lib/Transforms/IPO/FunctionImport.cpp
    M llvm/test/LTO/Resolution/X86/comdat-mixed-lto.ll
    M llvm/test/ThinLTO/X86/Inputs/linkonce_resolution_comdat.ll
    A llvm/test/ThinLTO/X86/constructor-alias.ll
    M llvm/test/ThinLTO/X86/linkonce_resolution_comdat.ll
    A llvm/test/ThinLTO/X86/windows-vftable.ll

  Log Message:
  -----------
  [LTO] Make local linkage GlobalValue in non-prevailing COMDAT available_externally

For a local linkage GlobalObject in a non-prevailing COMDAT, it remains defined while its
leader has been made available_externally. This violates the COMDAT rule that
its members must be retained or discarded as a unit.

To fix this, update the regular LTO change D34803 to track local linkage
GlobalValues, and port the code to ThinLTO (GlobalAliases are not handled.)

This fixes two problems.

(a) `__cxx_global_var_init` in a non-prevailing COMDAT group used to
linger around (unreferenced, hence benign), and is now correctly discarded.
```
int foo();
inline int v = foo();
```

(b) Fix https://github.com/llvm/llvm-project/issues/58215:
as a size optimization, we place private `__profd_` in a COMDAT with a
`__profc_` key. When FuncImport.cpp makes `__profc_` available_externally due to
a non-prevailing COMDAT, `__profd_` incorrectly remains private. This change
makes the `__profd_` available_externally.

```
cat > c.h <<'eof'
extern void bar();
inline __attribute__((noinline)) void foo() {}
eof
cat > m1.cc <<'eof'
#include "c.h"
int main() {
  bar();
  foo();
}
eof
cat > m2.cc <<'eof'
#include "c.h"
__attribute__((noinline)) void bar() {
  foo();
}
eof

clang -O2 -fprofile-generate=./t m1.cc m2.cc -flto -fuse-ld=lld -o t_gen
rm -fr t && ./t_gen && llvm-profdata show -function=foo t/default_*.profraw

clang -O2 -fprofile-generate=./t m1.cc m2.cc -flto=thin -fuse-ld=lld -o t_gen
rm -fr t && ./t_gen && llvm-profdata show -function=foo t/default_*.profraw
```

If a GlobalAlias references a GlobalValue which is just changed to
available_externally, change the GlobalAlias as well (e.g. C5/D5 comdats due to
cc1 -mconstructor-aliases). The GlobalAlias may be referenced by other
available_externally functions, so it cannot easily be removed.

Depends on D137441: we use available_externally to mark a GlobalAlias in a
non-prevailing COMDAT, similar to how we handle GlobalVariable/Function.
GlobalAlias may refer to a ConstantExpr, not changing GlobalAlias to
GlobalVariable gives flexibility for future extensions (the use case is niche.
For simplicity we don't handle it yet). In addition, available_externally
GlobalAlias is the most straightforward implementation and retains the aliasee
information to help optimizers.

See windows-vftable.ll: Windows vftable uses an alias pointing to a
private constant where the alias is the COMDAT leader. The COMDAT use case
is skeptical and ThinLTO does not discard the alias in the non-prevailing COMDAT.
This patch retains the behavior.

Reviewed By: tejohnson

Differential Revision: https://reviews.llvm.org/D135427




More information about the All-commits mailing list