llvm-project/llvm/lib/Transforms/Scalar
Sanjoy Das 5ce3272833 Don't IPO over functions that can be de-refined
Summary:
Fixes PR26774.

If you're aware of the issue, feel free to skip the "Motivation"
section and jump directly to "This patch".

Motivation:

I define "refinement" as discarding behaviors from a program that the
optimizer has license to discard.  So transforming:

```
void f(unsigned x) {
  unsigned t = 5 / x;
  (void)t;
}
```

to

```
void f(unsigned x) { }
```

is refinement, since the behavior went from "if x == 0 then undefined
else nothing" to "nothing" (the optimizer has license to discard
undefined behavior).

Refinement is a fundamental aspect of many mid-level optimizations done
by LLVM.  For instance, transforming `x == (x + 1)` to `false` also
involves refinement since the expression's value went from "if x is
`undef` then { `true` or `false` } else { `false` }" to "`false`" (by
definition, the optimizer has license to fold `undef` to any non-`undef`
value).

Unfortunately, refinement implies that the optimizer cannot assume
that the implementation of a function it can see has all of the
behavior an unoptimized or a differently optimized version of the same
function can have.  This is a problem for functions with comdat
linkage, where a function can be replaced by an unoptimized or a
differently optimized version of the same source level function.

For instance, FunctionAttrs cannot assume a comdat function is
actually `readnone` even if it does not have any loads or stores in
it; since there may have been loads and stores in the "original
function" that were refined out in the currently visible variant, and
at the link step the linker may in fact choose an implementation with
a load or a store.  As an example, consider a function that does two
atomic loads from the same memory location, and writes to memory only
if the two values are not equal.  The optimizer is allowed to refine
this function by first CSE'ing the two loads, and the folding the
comparision to always report that the two values are equal.  Such a
refined variant will look like it is `readonly`.  However, the
unoptimized version of the function can still write to memory (since
the two loads //can// result in different values), and selecting the
unoptimized version at link time will retroactively invalidate
transforms we may have done under the assumption that the function
does not write to memory.

Note: this is not just a problem with atomics or with linking
differently optimized object files.  See PR26774 for more realistic
examples that involved neither.

This patch:

This change introduces a new set of linkage types, predicated as
`GlobalValue::mayBeDerefined` that returns true if the linkage type
allows a function to be replaced by a differently optimized variant at
link time.  It then changes a set of IPO passes to bail out if they see
such a function.

Reviewers: chandlerc, hfinkel, dexonsmith, joker.eph, rnk

Subscribers: mcrosier, llvm-commits

Differential Revision: http://reviews.llvm.org/D18634

llvm-svn: 265762
2016-04-08 00:48:30 +00:00
..
ADCE.cpp ADCE: Remove debug info intrinsics in dead scopes 2016-03-29 22:57:12 +00:00
AlignmentFromAssumptions.cpp [SCEV] Add and use SCEVConstant::getAPInt; NFCI 2015-12-17 20:28:46 +00:00
BDCE.cpp Add GlobalsAA as preserved to a bunch of transforms 2015-09-10 10:22:12 +00:00
CMakeLists.txt Introduce a @llvm.experimental.guard intrinsic 2016-03-31 00:18:46 +00:00
ConstantHoisting.cpp Scalar: Remove some implicit ilist iterator conversions, NFC 2015-10-13 18:26:00 +00:00
ConstantProp.cpp use range loop; NFCI 2016-04-04 23:05:06 +00:00
CorrelatedValuePropagation.cpp [CVP] Replace nonnegative with positive, per Philip's request. NFC. 2016-03-14 13:48:00 +00:00
DCE.cpp Scalar: Remove some implicit ilist iterator conversions, NFC 2015-10-13 18:26:00 +00:00
DeadStoreElimination.cpp [PM] Port memdep to the new pass manager. 2016-03-10 00:55:30 +00:00
EarlyCSE.cpp NFC: make AtomicOrdering an enum class 2016-04-06 21:19:33 +00:00
FlattenCFGPass.cpp Scalar: Remove some implicit ilist iterator conversions, NFC 2015-10-13 18:26:00 +00:00
Float2Int.cpp [Float2Int] Don't operate on vector instructions 2015-12-09 21:08:18 +00:00
GVN.cpp [GVN] Address review comments for D18662 2016-04-07 15:55:11 +00:00
IndVarSimplify.cpp [IndVarSimplify] Don't insert after a catchswitch 2016-03-30 21:12:06 +00:00
InductiveRangeCheckElimination.cpp IR: RF_IgnoreMissingValues => RF_IgnoreMissingLocals, NFC 2016-04-07 00:26:43 +00:00
JumpThreading.cpp [SimlifyCFG] Prevent passes from destroying canonical loop structure, especially for nested loops 2016-03-29 04:08:57 +00:00
LICM.cpp Fix the build 2016-03-09 23:07:53 +00:00
LLVMBuild.txt Update libdeps in LLVMipo and LLVMScalarOpts, corresponding to r245940. 2015-08-25 17:11:17 +00:00
LoadCombine.cpp Remove PreserveNames template parameter from IRBuilder 2016-03-13 21:05:13 +00:00
LoopDataPrefetch.cpp [LoopDataPrefetch] Centralize the tuning cl::opts under the pass 2016-03-29 23:45:52 +00:00
LoopDeletion.cpp [LoopDeletion] Add an assert that verifies LCSSA 2016-02-21 17:11:59 +00:00
LoopDistribute.cpp [LoopVersioning] Annotate versioned loop with noalias metadata 2016-03-17 20:32:32 +00:00
LoopIdiomRecognize.cpp [LPM] Factor all of the loop analysis usage updates into a common helper 2016-02-19 10:45:18 +00:00
LoopInstSimplify.cpp Simplify logic. NFC. 2016-04-06 13:27:13 +00:00
LoopInterchange.cpp LPM: Stop threading `Pass *` through all of the loop utility APIs. NFC 2015-12-15 19:40:57 +00:00
LoopLoadElimination.cpp [LLE] Check for mismatching types between the store and the load earlier 2016-03-24 17:59:26 +00:00
LoopRerollPass.cpp [PATCH] Force LoopReroll to reset the loop trip count value after reroll. 2016-03-22 13:50:57 +00:00
LoopRotation.cpp IR: RF_IgnoreMissingValues => RF_IgnoreMissingLocals, NFC 2016-04-07 00:26:43 +00:00
LoopSimplifyCFG.cpp [LPM] Factor all of the loop analysis usage updates into a common helper 2016-02-19 10:45:18 +00:00
LoopStrengthReduce.cpp [LoopStrengthReduce] Don't hoist into a catchswitch 2016-03-24 21:40:22 +00:00
LoopUnrollPass.cpp Loop Unroll: add options and tweak to make Partial unrolling more useful 2016-04-06 16:57:25 +00:00
LoopUnswitch.cpp IR: RF_IgnoreMissingValues => RF_IgnoreMissingLocals, NFC 2016-04-07 00:26:43 +00:00
LoopVersioningLICM.cpp Fix MSVC 2013 build after rL260504 2016-02-11 11:27:51 +00:00
LowerAtomic.cpp NFC: make AtomicOrdering an enum class 2016-04-06 21:19:33 +00:00
LowerExpectIntrinsic.cpp fix typo; NFC 2015-08-24 20:11:14 +00:00
LowerGuardIntrinsic.cpp Introduce a @llvm.experimental.guard intrinsic 2016-03-31 00:18:46 +00:00
MemCpyOptimizer.cpp Imporove load to store => memcpy 2016-03-14 22:52:27 +00:00
MergedLoadStoreMotion.cpp [PM] Port memdep to the new pass manager. 2016-03-10 00:55:30 +00:00
NaryReassociate.cpp [opaque pointer types] [NFC] GEP: replace get(Pointer)ElementType uses with get{Source,Result}ElementType. 2016-01-19 17:28:00 +00:00
PartiallyInlineLibCalls.cpp Scalar: Remove remaining ilist iterator implicit conversions 2015-10-13 19:26:58 +00:00
PlaceSafepoints.cpp [PlaceSafepoints] Use DEBUG() instead of TraceLSP 2016-01-28 23:49:27 +00:00
Reassociate.cpp ADT: Remove == and != comparisons between ilist iterators and pointers 2016-02-21 20:39:50 +00:00
Reg2Mem.cpp Scalar: Remove remaining ilist iterator implicit conversions 2015-10-13 19:26:58 +00:00
RewriteStatepointsForGC.cpp Add parentheses to silence warning. 2016-04-06 04:22:00 +00:00
SCCP.cpp Don't IPO over functions that can be de-refined 2016-04-08 00:48:30 +00:00
SROA.cpp Don't IPO over functions that can be de-refined 2016-04-08 00:48:30 +00:00
Scalar.cpp Introduce a @llvm.experimental.guard intrinsic 2016-03-31 00:18:46 +00:00
ScalarReplAggregates.cpp [opaque pointer types] [NFC] DataLayout::getIndexedOffset: take source element type instead of pointer type and rename to getIndexedOffsetInType. 2016-01-22 03:08:27 +00:00
Scalarizer.cpp Scalar: Remove remaining ilist iterator implicit conversions 2015-10-13 19:26:58 +00:00
SeparateConstOffsetFromGEP.cpp Bug fix: use dyn_cast_or_null instead of dyn_cast 2016-02-19 02:17:07 +00:00
SimplifyCFGPass.cpp [SimlifyCFG] Prevent passes from destroying canonical loop structure, especially for nested loops 2016-03-29 04:08:57 +00:00
Sink.cpp Remove uses of builtin comma operator. 2016-02-18 22:09:30 +00:00
SpeculativeExecution.cpp Scalar: Remove remaining ilist iterator implicit conversions 2015-10-13 19:26:58 +00:00
StraightLineStrengthReduce.cpp [opaque pointer types] [NFC] GEP: replace get(Pointer)ElementType uses with get{Source,Result}ElementType. 2016-01-19 17:28:00 +00:00
StructurizeCFG.cpp StructurizeCFG: Initialize SkipUniformRegions in the default constructor 2016-02-10 01:10:09 +00:00
TailRecursionElimination.cpp Change isSafeToLoadUnconditionally arguments order. Separated from http://reviews.llvm.org/D10920. 2016-01-15 15:27:46 +00:00