diff options
Diffstat (limited to 'llvm/lib/Analysis')
| -rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 26 | 
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>());    } | 

