llvm-project/llvm/lib/Transforms/IPO
Fangrui Song 12050a3fb7 [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.

See new tests ctor-dtor-alias2.ll: depending on whether the complete object
destructor emitted, when ctor/dtor aliases are used, we may see D0/D2 COMDATs in
one TU and D0/D1/D2 in a D5 COMDAT in another TU.
Allow such a mix-and-match with `if (GO->getComdat()->getName() == GO->getName()) NonPrevailingComdats.insert(GO->getComdat());`

GlobalAlias handling in ThinLTO is still weird, but this patch should hopefully
improve the situation for at least all cases I can think of.

Reviewed By: tejohnson

Differential Revision: https://reviews.llvm.org/D135427
2022-11-16 22:13:22 -08:00
..
AlwaysInliner.cpp [IPO] Reorder parameters of InlineFunction (NFC) 2022-09-20 09:09:38 -07:00
Annotation2Metadata.cpp
ArgumentPromotion.cpp [ArgPromotion] Transfer metadata nontemporal to promoted loads 2022-07-26 16:30:08 +08:00
Attributor.cpp [AAPointerInfo] refactor how offsets and Access objects are tracked 2022-11-15 18:52:11 +05:30
AttributorAttributes.cpp [AAPointerInfo] refactor how offsets and Access objects are tracked 2022-11-15 18:52:11 +05:30
BarrierNoopPass.cpp
BlockExtractor.cpp [Transforms] Qualify auto in range-based for loops (NFC) 2022-08-27 21:21:02 -07:00
CMakeLists.txt [NFC][2/n] Remove PrunePH pass 2022-09-26 18:38:04 -07:00
CalledValuePropagation.cpp [IPO] Use default member initialization (NFC) 2022-06-18 12:17:09 -07:00
ConstantMerge.cpp [llvm] Qualify auto (NFC) 2022-08-07 23:55:27 -07:00
CrossDSOCFI.cpp [Transforms] Qualify auto in range-based for loops (NFC) 2022-08-27 21:21:02 -07:00
DeadArgumentElimination.cpp [DeadArgElim] Use structure bindings in foreach loops. NFC 2022-09-01 13:48:46 +03:00
ElimAvailExtern.cpp
ExtractGV.cpp
ForceFunctionAttrs.cpp Cleanup includes: final pass 2022-03-29 09:00:21 +02:00
FunctionAttrs.cpp [IR] Switch everything to use memory attribute 2022-11-04 10:21:38 +01:00
FunctionImport.cpp [LTO] Make local linkage GlobalValue in non-prevailing COMDAT available_externally 2022-11-16 22:13:22 -08:00
FunctionSpecialization.cpp [FuncSpec][NFC] Avoid redundant computations of DominatorTree/LoopInfo 2022-10-28 16:08:41 +01:00
GlobalDCE.cpp [Transforms] Qualify auto in range-based for loops (NFC) 2022-08-27 21:21:02 -07:00
GlobalOpt.cpp [GlobalOpt] Don't remove inalloca from varargs functions 2022-11-01 13:04:05 -07:00
GlobalSplit.cpp [NFC] Switch a few uses of undef to poison as placeholders for unreachble code 2022-06-30 23:01:43 +01:00
HotColdSplitting.cpp Add !nosanitize to FixedMetadataKinds 2022-05-27 09:46:13 +08:00
IPO.cpp [NFC][2/n] Remove PrunePH pass 2022-09-26 18:38:04 -07:00
IROutliner.cpp Remove redundant initialization of Optional (NFC) 2022-08-20 21:18:28 -07:00
InferFunctionAttrs.cpp Reapply "[BuildLibCalls] Introduce getOrInsertLibFunc() for use when building 2022-05-02 19:37:00 +02:00
InlineSimple.cpp
Inliner.cpp [IPO] Reorder parameters of InlineFunction (NFC) 2022-09-20 09:09:38 -07:00
Internalize.cpp [Internalize] Support glob patterns for API lists 2022-07-22 08:24:32 -04:00
LoopExtractor.cpp
LowerTypeTests.cpp [Transform] Use range-based for loops (NFC) 2022-08-27 23:54:32 -07:00
MergeFunctions.cpp [NFC] Switch a few uses of undef to poison as placeholders for unreachble code 2022-07-03 14:34:03 +01:00
ModuleInliner.cpp [IPO] Reorder parameters of InlineFunction (NFC) 2022-09-20 09:09:38 -07:00
OpenMPOpt.cpp [OpenMP][FIX] Do not add custom state machine eagerly in LTO runs 2022-10-26 10:40:11 -07:00
PartialInlining.cpp [IPO] Reorder parameters of InlineFunction (NFC) 2022-09-20 09:09:38 -07:00
PassManagerBuilder.cpp [AggressiveInstCombine] Remove legacy PM pass 2022-11-15 14:35:15 -08:00
SCCP.cpp [FuncSpec][NFC] Avoid redundant computations of DominatorTree/LoopInfo 2022-10-28 16:08:41 +01:00
SampleContextTracker.cpp [llvm] Qualify auto (NFC) 2022-08-07 23:55:27 -07:00
SampleProfile.cpp [SampleFDO] Persist profile staleness metrics into binary 2022-11-09 22:34:33 -08:00
SampleProfileProbe.cpp [llvm] Use value_or instead of getValueOr (NFC) 2022-06-18 23:07:11 -07:00
StripDeadPrototypes.cpp
StripSymbols.cpp [StripDeadDebugInfo] Drop dead CUs 2022-09-11 01:31:03 -07:00
SyntheticCountsPropagation.cpp Remove redundant initialization of Optional (NFC) 2022-08-20 21:18:28 -07:00
ThinLTOBitcodeWriter.cpp [AA] Tracking per-location ModRef info in FunctionModRefBehavior (NFCI) 2022-09-14 16:34:41 +02:00
WholeProgramDevirt.cpp [WPD/LTT] Lower type test feeding assumes via phi correctly 2022-09-16 13:50:01 -07:00