aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Utils/Local.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-06-16 17:23:12 +0000
committerChris Lattner <sabre@nondot.org>2009-06-16 17:23:12 +0000
commitbf502249451467d5c16056b97da00f50308484df (patch)
treef9df28ad13a94e2e1eea5c3f79030970c6c75f1b /lib/Transforms/Utils/Local.cpp
parent0600617a2b238eab8a7d4736981e6747a404030e (diff)
downloadexternal_llvm-bf502249451467d5c16056b97da00f50308484df.zip
external_llvm-bf502249451467d5c16056b97da00f50308484df.tar.gz
external_llvm-bf502249451467d5c16056b97da00f50308484df.tar.bz2
Generalize instcombine's isSafeToLoadUnconditionally() function
to ignore readonly calls, and factor it out of instcombine so that it can be used by other passes. Patch by Frits van Bommel! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73506 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils/Local.cpp')
-rw-r--r--lib/Transforms/Utils/Local.cpp45
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp
index 94483b8..c7fff54 100644
--- a/lib/Transforms/Utils/Local.cpp
+++ b/lib/Transforms/Utils/Local.cpp
@@ -14,6 +14,7 @@
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Constants.h"
+#include "llvm/GlobalAlias.h"
#include "llvm/GlobalVariable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
@@ -28,6 +29,50 @@
using namespace llvm;
//===----------------------------------------------------------------------===//
+// Local analysis.
+//
+
+/// isSafeToLoadUnconditionally - Return true if we know that executing a load
+/// from this value cannot trap. If it is not obviously safe to load from the
+/// specified pointer, we do a quick local scan of the basic block containing
+/// ScanFrom, to determine if the address is already accessed.
+bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom) {
+ // If it is an alloca it is always safe to load from.
+ if (isa<AllocaInst>(V)) return true;
+
+ // If it is a global variable it is mostly safe to load from.
+ if (const GlobalValue *GV = dyn_cast<GlobalVariable>(V))
+ // Don't try to evaluate aliases. External weak GV can be null.
+ return !isa<GlobalAlias>(GV) && !GV->hasExternalWeakLinkage();
+
+ // Otherwise, be a little bit agressive by scanning the local block where we
+ // want to check to see if the pointer is already being loaded or stored
+ // from/to. If so, the previous load or store would have already trapped,
+ // so there is no harm doing an extra load (also, CSE will later eliminate
+ // the load entirely).
+ BasicBlock::iterator BBI = ScanFrom, E = ScanFrom->getParent()->begin();
+
+ while (BBI != E) {
+ --BBI;
+
+ // If we see a free or a call which may write to memory (i.e. which might do
+ // a free) the pointer could be marked invalid.
+ if (isa<FreeInst>(BBI) ||
+ (isa<CallInst>(BBI) && BBI->mayWriteToMemory() &&
+ !isa<DbgInfoIntrinsic>(BBI)))
+ return false;
+
+ if (LoadInst *LI = dyn_cast<LoadInst>(BBI)) {
+ if (LI->getOperand(0) == V) return true;
+ } else if (StoreInst *SI = dyn_cast<StoreInst>(BBI)) {
+ if (SI->getOperand(1) == V) return true;
+ }
+ }
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
// Local constant propagation.
//