summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2016-12-31 22:12:34 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2016-12-31 22:12:34 +0000
commit3bb2dbd66586d03e9586294f0964ec05f3322cd6 (patch)
treee859f82b426760a7fc2d34326e3e23baa04b3ac7 /llvm/lib
parent0945530d4dc3c36a03cbd5c62fdccb870bcb21ab (diff)
downloadbcm5719-llvm-3bb2dbd66586d03e9586294f0964ec05f3322cd6.tar.gz
bcm5719-llvm-3bb2dbd66586d03e9586294f0964ec05f3322cd6.zip
Fix an issue with isGuaranteedToTransferExecutionToSuccessor
I'm not sure if this was intentional, but today isGuaranteedToTransferExecutionToSuccessor returns true for readonly and argmemonly calls that may throw. This commit changes the function to not implicitly infer nounwind this way. Even if we eventually specify readonly calls as not throwing, isGuaranteedToTransferExecutionToSuccessor is not the best place to infer that. We should instead teach FunctionAttrs or some other such pass to tag readonly functions / calls as nounwind instead. llvm-svn: 290794
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp26
1 files changed, 20 insertions, 6 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c39745c72cd..2a77baec6c3 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3657,12 +3657,26 @@ bool llvm::isGuaranteedToTransferExecutionToSuccessor(const Instruction *I) {
// Calls can throw, or contain an infinite loop, or kill the process.
if (auto CS = ImmutableCallSite(I)) {
- // Calls which don't write to arbitrary memory are safe.
- // FIXME: Ignoring infinite loops without any side-effects is too
- // aggressive,
- // but it's consistent with other passes. See http://llvm.org/PR965 .
- // FIXME: This isn't aggressive enough; a call which only writes to a
- // global is guaranteed to return.
+ // Call sites that throw have implicit non-local control flow.
+ if (!CS.doesNotThrow())
+ return false;
+
+ // Non-throwing call sites can loop infinitely, call exit/pthread_exit
+ // etc. and thus not return. However, LLVM already assumes that
+ //
+ // - Thread exiting actions are modeled as writes to memory invisible to
+ // the program.
+ //
+ // - Loops that don't have side effects (side effects are volatile/atomic
+ // stores and IO) always terminate (see http://llvm.org/PR965).
+ // Furthermore IO itself is also modeled as writes to memory invisible to
+ // the program.
+ //
+ // We rely on those assumptions here, and use the memory effects of the call
+ // target as a proxy for checking that it always returns.
+
+ // FIXME: This isn't aggressive enough; a call which only writes to a global
+ // is guaranteed to return.
return CS.onlyReadsMemory() || CS.onlyAccessesArgMemory() ||
match(I, m_Intrinsic<Intrinsic::assume>());
}
OpenPOWER on IntegriCloud