aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2016-06-11 21:48:25 +0000
committerEli Friedman <eli.friedman@gmail.com>2016-06-11 21:48:25 +0000
commitf1da33e4d3fc9797c7fb4f9ea681a2bc2254c281 (patch)
tree32d783ef43cbe5b7a1a6f91ba40f69f6cdb22213 /llvm/lib/Analysis/ValueTracking.cpp
parent2b7c02a04f465c298d008ebf8b7cc616e3d3db89 (diff)
downloadllvm-f1da33e4d3fc9797c7fb4f9ea681a2bc2254c281.zip
llvm-f1da33e4d3fc9797c7fb4f9ea681a2bc2254c281.tar.gz
llvm-f1da33e4d3fc9797c7fb4f9ea681a2bc2254c281.tar.bz2
[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
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp52
1 files changed, 39 insertions, 13 deletions
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<CallInst>(I) || isa<InvokeInst>(I))
- // However, llvm.dbg intrinsics are safe, since they're no-ops.
- return isa<DbgInfoIntrinsic>(I);
-
- return !I->isAtomic() && // atomics may never succeed on some platforms
- !isa<ResumeInst>(I) && // has no successors
- !isa<ReturnInst>(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<LoadInst>(I))
+ return !LI->isVolatile();
+ if (const StoreInst *SI = dyn_cast<StoreInst>(I))
+ return !SI->isVolatile();
+ if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(I))
+ return !CXI->isVolatile();
+ if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I))
+ return !RMWI->isVolatile();
+ if (const MemIntrinsic *MII = dyn_cast<MemIntrinsic>(I))
+ return !MII->isVolatile();
+
+ // If there is no successor, then execution can't transfer to it.
+ if (const auto *CRI = dyn_cast<CleanupReturnInst>(I))
+ return !CRI->unwindsToCaller();
+ if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I))
+ return !CatchSwitch->unwindsToCaller();
+ if (isa<ResumeInst>(I))
+ return false;
+ if (isa<ReturnInst>(I))
+ return false;
+
+ // Calls can throw, or contain an infinite loop, or kill the process.
+ if (CallSite CS = CallSite(const_cast<Instruction*>(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,