llvm-project/llvm/test/Transforms
Oliver Stannard 9f6a873268 Dead Virtual Function Elimination
Currently, it is hard for the compiler to remove unused C++ virtual
functions, because they are all referenced from vtables, which are referenced
by constructors. This means that if the constructor is called from any live
code, then we keep every virtual function in the final link, even if there
are no call sites which can use it.

This patch allows unused virtual functions to be removed during LTO (and
regular compilation in limited circumstances) by using type metadata to match
virtual function call sites to the vtable slots they might load from. This
information can then be used in the global dead code elimination pass instead
of the references from vtables to virtual functions, to more accurately
determine which functions are reachable.

To make this transformation safe, I have changed clang's code-generation to
always load virtual function pointers using the llvm.type.checked.load
intrinsic, instead of regular load instructions. I originally tried writing
this using clang's existing code-generation, which uses the llvm.type.test
and llvm.assume intrinsics after doing a normal load. However, it is possible
for optimisations to obscure the relationship between the GEP, load and
llvm.type.test, causing GlobalDCE to fail to find virtual function call
sites.

The existing linkage and visibility types don't accurately describe the scope
in which a virtual call could be made which uses a given vtable. This is
wider than the visibility of the type itself, because a virtual function call
could be made using a more-visible base class. I've added a new
!vcall_visibility metadata type to represent this, described in
TypeMetadata.rst. The internalization pass and libLTO have been updated to
change this metadata when linking is performed.

This doesn't currently work with ThinLTO, because it needs to see every call
to llvm.type.checked.load in the linkage unit. It might be possible to
extend this optimisation to be able to use the ThinLTO summary, as was done
for devirtualization, but until then that combination is rejected in the
clang driver.

To test this, I've written a fuzzer which generates random C++ programs with
complex class inheritance graphs, and virtual functions called through object
and function pointers of different types. The programs are spread across
multiple translation units and DSOs to test the different visibility
restrictions.

I've also tried doing bootstrap builds of LLVM to test this. This isn't
ideal, because only classes in anonymous namespaces can be optimised with
-fvisibility=default, and some parts of LLVM (plugins and bugpoint) do not
work correctly with -fvisibility=hidden. However, there are only 12 test
failures when building with -fvisibility=hidden (and an unmodified compiler),
and this change does not cause any new failures for either value of
-fvisibility.

On the 7 C++ sub-benchmarks of SPEC2006, this gives a geomean code-size
reduction of ~6%, over a baseline compiled with "-O2 -flto
-fvisibility=hidden -fwhole-program-vtables". The best cases are reductions
of ~14% in 450.soplex and 483.xalancbmk, and there are no code size
increases.

I've also run this on a set of 8 mbed-os examples compiled for Armv7M, which
show a geomean size reduction of ~3%, again with no size increases.

I had hoped that this would have no effect on performance, which would allow
it to awlays be enabled (when using -fwhole-program-vtables). However, the
changes in clang to use the llvm.type.checked.load intrinsic are causing ~1%
performance regression in the C++ parts of SPEC2006. It should be possible to
recover some of this perf loss by teaching optimisations about the
llvm.type.checked.load intrinsic, which would make it worth turning this on
by default (though it's still dependent on -fwhole-program-vtables).

Differential revision: https://reviews.llvm.org/D63932

llvm-svn: 374539
2019-10-11 11:59:55 +00:00
..
ADCE Add missing test for r366215 2019-07-16 15:28:29 +00:00
AddDiscriminators Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
AggressiveInstCombine [NFC] run specific pass instead of whole -O3 pipeline for popcount recoginzation testcase. 2019-10-11 05:30:18 +00:00
AlignmentFromAssumptions [AlignmentFromAssumptions] getNewAlignmentDiff(): use getURemExpr() 2019-08-23 02:17:04 +00:00
ArgumentPromotion IR: print value numbers for unnamed function arguments 2019-08-03 14:28:34 +00:00
AtomicExpand [lit] Delete empty lines at the end of lit.local.cfg NFC 2019-06-17 09:51:07 +00:00
BDCE Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
BlockExtractor [BlockExtractor] Avoid assert with wrong line format 2019-08-20 14:46:02 +00:00
BranchFolding Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
CallSiteSplitting CallSiteSplitting: Respect convergent and noduplicate 2019-05-29 16:59:48 +00:00
CalledValuePropagation Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
CanonicalizeAliases Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
CodeExtractor [CodeExtractor] Fix sinking of allocas with multiple bitcast uses (PR42451) 2019-07-10 16:32:20 +00:00
CodeGenPrepare [NFC} Updated test 2019-09-17 09:45:52 +00:00
ConstProp [ConstProp] add tests for extractelement with undef index; NFC 2019-10-09 20:14:17 +00:00
ConstantHoisting [RISCV] Fix RISCVTTIImpl::getIntImmCost for immediates where getMinSignedBits() > 64 2019-07-09 10:56:18 +00:00
ConstantMerge Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
Coroutines [coroutine] Fixes "cannot move instruction since its users are not dominated by CoroBegin" problem. 2019-08-15 00:48:51 +00:00
CorrelatedValuePropagation [CVP] Remove a masking operation if range information implies it's a noop 2019-10-11 03:48:56 +00:00
CrossDSOCFI Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
DCE [FPEnv] Strict FP tests should use the requisite function attributes. 2019-10-04 17:03:46 +00:00
DeadArgElim [FunctionAttrs] Annotate "willreturn" for intrinsics 2019-07-28 06:09:56 +00:00
DeadStoreElimination [FunctionAttrs] Annotate "willreturn" for intrinsics 2019-07-28 06:09:56 +00:00
DivRemPairs [DivRemPairs] Don't assert that we won't ever get expanded-form rem pairs in different BB's (PR43500) 2019-09-29 15:25:24 +00:00
EarlyCSE [EarlyCSE] Add support for unary FNeg to EarlyCSE 2019-08-07 14:34:41 +00:00
EliminateAvailableExternally Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
EntryExitInstrumenter Reland "[ARM] push LR before __gnu_mcount_nc" 2019-08-16 23:30:16 +00:00
ExpandMemCmp Revert "Reland "r364412 [ExpandMemCmp][MergeICmps] Move passes out of CodeGen into opt pipeline."" 2019-09-10 10:39:09 +00:00
Float2Int [Float2Int] avoid crashing on unreachable code (PR38502) 2019-09-19 16:31:17 +00:00
ForcedFunctionAttrs Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
FunctionAttrs [Attributor][FIX] Do not replace musstail calls with constant 2019-10-11 01:45:32 +00:00
FunctionImport Reland "Change the X86 datalayout to add three address spaces 2019-09-10 23:15:38 +00:00
GCOVProfiling Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
GVN [GVN] Propagate simple equalities from assumes within the tail of the block 2019-09-03 17:31:19 +00:00
GVNHoist Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
GVNSink [GVNSink] Add unary FNeg support to GVNSink pass 2019-06-28 19:57:31 +00:00
GlobalDCE Dead Virtual Function Elimination 2019-10-11 11:59:55 +00:00
GlobalMerge Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
GlobalOpt [GlobalOpt] prevent crashing on large integer types (PR42932) 2019-08-09 12:43:25 +00:00
GlobalSplit Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
GuardWidening [GuardWidening] Wire up a NPM version of the LoopGuardWidening pass 2019-04-18 19:17:14 +00:00
HardwareLoops [ARM][LowOverheadLoops] Enable by default 2019-07-30 08:14:28 +00:00
HotColdSplit Invalidate assumption cache before outlining. 2019-10-04 22:46:42 +00:00
IPConstantProp Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
IRCE [SCEV] Add smin support to getRangeRef 2019-09-12 21:32:27 +00:00
IndVarSimplify [IndVars] An implementation of loop predication without a need for speculation 2019-10-01 17:03:44 +00:00
IndirectBrExpand Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
InferAddressSpaces AMDGPU: Add intrinsics for address space identification 2019-09-05 02:20:39 +00:00
InferFunctionAttrs [Attributor][MustExec] Deduce dereferenceable and nonnull attribute using MustBeExecutedContextExplorer 2019-10-08 15:25:56 +00:00
Inline [Inliner] Remove incorrect early exit during switch cost computation 2019-09-20 23:29:17 +00:00
InstCombine [InstCombine] Add test case for PR43617 (NFC) 2019-10-10 21:29:10 +00:00
InstMerge [MergedLoadStoreMotion] Sink stores to BB with more than 2 predecessors 2019-09-05 17:00:32 +00:00
InstNamer Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
InstSimplify [InstSimplify] fold fma/fmuladd with a NaN or undef operand 2019-10-02 12:12:02 +00:00
InterleavedAccess Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
Internalize Dead Virtual Function Elimination 2019-10-11 11:59:55 +00:00
JumpThreading IR: print value numbers for unnamed function arguments 2019-08-03 14:28:34 +00:00
LCSSA Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
LICM [MemorySSA] Don't hoist stores if interfering uses (as calls) exist. 2019-10-03 22:20:04 +00:00
LoadStoreVectorizer Handle casts changing pointer size in the vectorizer 2019-08-02 04:03:37 +00:00
LoopDataPrefetch Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
LoopDeletion Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
LoopDistribute Revert "[IRBuilder] Fold consistently for or/and whether constant is LHS or RHS" 2019-07-07 22:12:01 +00:00
LoopFusion [LoopFusion] Add ability to fuse guarded loops 2019-09-26 21:42:45 +00:00
LoopIdiom Revert r370454 "[LoopIdiomRecognize] BCmp loop idiom recognition" 2019-09-03 17:14:56 +00:00
LoopInstSimplify [LoopPassManager + MemorySSA] Only enable use of MemorySSA for LPMs known to preserve it. 2019-08-21 17:00:57 +00:00
LoopInterchange [LoopInterchange] Properly move condition, induction increment and ops to latch. 2019-09-11 08:23:23 +00:00
LoopLoadElim LoopLoadElim: Respect convergent 2019-06-12 13:50:47 +00:00
LoopPredication [LoopPred] Extend LFTR normalization to the inverse EQ case 2019-07-09 01:27:45 +00:00
LoopReroll [SCEV] Use NoWrapFlags when expanding a simple mul 2019-06-17 10:05:18 +00:00
LoopRotate [LoopPassManager + MemorySSA] Only enable use of MemorySSA for LPMs known to preserve it. 2019-08-21 17:00:57 +00:00
LoopSimplify [DebugInfo@O2][LoopVectorize] pr39024: Vectorized code linenos step through loop even after completion 2019-06-19 10:50:47 +00:00
LoopSimplifyCFG Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
LoopStrengthReduce [NFC][LSR] Avoid undefined grep in pr2570.ll 2019-06-19 16:02:54 +00:00
LoopTransformWarning Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
LoopUnroll [Unroll] Do NOT unroll a loop with small runtime upperbound 2019-09-26 21:40:27 +00:00
LoopUnrollAndJam Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
LoopUnswitch [LoopUnroll+LoopUnswitch] do not transform loops containing callbr 2019-07-15 21:16:29 +00:00
LoopVectorize [LV] Emitting SCEV checks with OptForSize 2019-10-09 13:19:41 +00:00
LoopVersioning LoopVersioning: Respect convergent 2019-06-12 14:05:58 +00:00
LoopVersioningLICM LoopVersioningLICM: Respect convergent and noduplicate 2019-05-29 20:47:59 +00:00
LowerAtomic Transforms: lower fadd and fsub atomicrmw instructions 2019-05-23 17:03:43 +00:00
LowerExpectIntrinsic Reland "clang-misexpect: Profile Guided Validation of Performance Annotations in LLVM" 2019-09-11 16:19:50 +00:00
LowerGuardIntrinsic Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
LowerInvoke Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
LowerSwitch Fix a crash when the default of a switch is removed 2019-06-03 17:54:15 +00:00
LowerTypeTests LowerTypeTests: Rename local functions to avoid collisions with identically named functions in ThinLTO modules. 2019-10-03 23:42:44 +00:00
LowerWidenableCondition Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
MakeGuardsExplicit Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
Mem2Reg Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
MemCpyOpt [ValueTracking] Improve pointer offset computation for cases of same base 2019-10-10 21:30:43 +00:00
MergeFunc IR: print value numbers for unnamed function arguments 2019-08-03 14:28:34 +00:00
MergeICmps [MergeICmps] Make the pass compatible with the new pass manager. 2019-05-23 12:35:26 +00:00
MetaRenamer Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
NameAnonGlobals Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
NaryReassociate Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
NewGVN [NFC][NewGVN] Explicitly check fpmath metadata in fpmath.ll 2019-06-28 21:39:08 +00:00
ObjCARC [ObjC][ARC] Skip debug instructions when computing the insert point of 2019-09-19 20:58:51 +00:00
PGOProfile [PGO] Don't group COMDAT variables for compiler generated profile variables in ELF 2019-09-30 18:11:22 +00:00
PartiallyInlineLibCalls Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
PhaseOrdering [NFC][PhaseOrdering] Add end-to-end tests for the 'two shifts by sext' problem 2019-09-27 19:32:43 +00:00
PlaceSafepoints Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
PreISelIntrinsicLowering Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
PruneEH Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
Reassociate [Reassoc] Small fix to support unary FNeg in NegateValue(...) 2019-08-23 15:49:38 +00:00
Reg2Mem Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
RewriteStatepointsForGC Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
SCCP [SCCP] Update condition to avoid overflow. 2019-07-31 18:22:22 +00:00
SLPVectorizer [SLP] respect target register width for GEP vectorization (PR43578) 2019-10-09 16:32:49 +00:00
SROA SROA: Check Total Bits of vector type 2019-09-21 18:16:37 +00:00
SafeStack [SafeStack] Insert the deref before remaining elements 2019-07-24 00:16:23 +00:00
SampleProfile [SampleFDO] Add indexing for function profiles so they can be loaded on demand 2019-10-09 21:36:03 +00:00
ScalarizeMaskedMemIntrin/X86 [ScalarizeMaskedMemIntrin] Add test case for expanding scatter. 2019-08-07 23:16:29 +00:00
Scalarizer [Intrinsic] Add the llvm.umul.fix.sat intrinsic 2019-09-07 12:16:14 +00:00
SeparateConstOffsetFromGEP [lit] Delete empty lines at the end of lit.local.cfg NFC 2019-06-17 09:51:07 +00:00
SimpleLoopUnswitch [LoopPassManager + MemorySSA] Only enable use of MemorySSA for LPMs known to preserve it. 2019-08-21 17:00:57 +00:00
SimplifyCFG [SimplifyCFG] mergeConditionalStoreToAddress(): consider cost, not instruction count 2019-09-18 19:46:57 +00:00
Sink Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
SpeculateAroundPHIs Ignore indirect branches from callbr. 2019-08-14 16:44:07 +00:00
SpeculativeExecution Support FNeg in SpeculativeExecution pass 2019-05-14 16:51:18 +00:00
StraightLineStrengthReduce Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
StripDeadPrototypes Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
StripSymbols Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
StructurizeCFG StructurizeCFG: Relax uniformity checks. 2019-05-24 08:59:17 +00:00
SyntheticCountsPropagation Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
TailCallElim Revert "Temporarily Revert "Add basic loop fusion pass."" 2019-04-17 04:52:47 +00:00
ThinLTOBitcodeWriter cfi-icall: Allow the jump table to be optionally made non-canonical. 2019-08-09 22:31:59 +00:00
Util Handle successor's PHI node correctly when flattening CFG merges two if-regions 2019-09-26 15:20:17 +00:00
WholeProgramDevirt IR: print value numbers for unnamed function arguments 2019-08-03 14:28:34 +00:00