From f1da33e4d3fc9797c7fb4f9ea681a2bc2254c281 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sat, 11 Jun 2016 21:48:25 +0000 Subject: [LICM] Make isGuaranteedToExecute more accurate. Summary: Make isGuaranteedToExecute use the isGuaranteedToTransferExecutionToSuccessor helper, and make that helper a bit more accurate. There's a potential performance impact here from assuming that arbitrary calls might not return. This probably has little impact on loads and stores to a pointer because most things alias analysis can reason about are dereferenceable anyway. The other impacts, like less aggressive hoisting of sdiv by a variable and less aggressive hoisting around volatile memory operations, are unlikely to matter for real code. This also impacts SCEV, which uses the same helper. It's a minor improvement there because we can tell that, for example, memcpy always returns normally. Strictly speaking, it's also introducing a bug, but it's not any worse than everywhere else we assume readonly functions terminate. Fixes http://llvm.org/PR27857. Reviewers: hfinkel, reames, chandlerc, sanjoy Subscribers: broune, llvm-commits Differential Revision: http://reviews.llvm.org/D21167 llvm-svn: 272489 --- llvm/lib/Analysis/ValueTracking.cpp | 52 +++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 13 deletions(-) (limited to 'llvm/lib/Analysis/ValueTracking.cpp') diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 323fe83..7e09ec7 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -3444,19 +3444,45 @@ OverflowResult llvm::computeOverflowForSignedAdd(Value *LHS, Value *RHS, } bool llvm::isGuaranteedToTransferExecutionToSuccessor(const Instruction *I) { - // FIXME: This conservative implementation can be relaxed. E.g. most - // atomic operations are guaranteed to terminate on most platforms - // and most functions terminate. - - // Calls can throw and thus not terminate, and invokes may not terminate and - // could throw to non-successor (see bug 24185 for details). - if (isa(I) || isa(I)) - // However, llvm.dbg intrinsics are safe, since they're no-ops. - return isa(I); - - return !I->isAtomic() && // atomics may never succeed on some platforms - !isa(I) && // has no successors - !isa(I); // has no successors + // A memory operation returns normally if it isn't volatile. A volatile + // operation is allowed to trap. + // + // An atomic operation isn't guaranteed to return in a reasonable amount of + // time because it's possible for another thread to interfere with it for an + // arbitrary length of time, but programs aren't allowed to rely on that. + if (const LoadInst *LI = dyn_cast(I)) + return !LI->isVolatile(); + if (const StoreInst *SI = dyn_cast(I)) + return !SI->isVolatile(); + if (const AtomicCmpXchgInst *CXI = dyn_cast(I)) + return !CXI->isVolatile(); + if (const AtomicRMWInst *RMWI = dyn_cast(I)) + return !RMWI->isVolatile(); + if (const MemIntrinsic *MII = dyn_cast(I)) + return !MII->isVolatile(); + + // If there is no successor, then execution can't transfer to it. + if (const auto *CRI = dyn_cast(I)) + return !CRI->unwindsToCaller(); + if (const auto *CatchSwitch = dyn_cast(I)) + return !CatchSwitch->unwindsToCaller(); + if (isa(I)) + return false; + if (isa(I)) + return false; + + // Calls can throw, or contain an infinite loop, or kill the process. + if (CallSite CS = CallSite(const_cast(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. + return CS.onlyReadsMemory() || CS.onlyAccessesArgMemory(); + } + + // Other instructions return normally. + return true; } bool llvm::isGuaranteedToExecuteForEveryIteration(const Instruction *I, -- cgit v1.1