summaryrefslogtreecommitdiffstats
path: root/lib/Analysis/MemoryDependenceAnalysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/MemoryDependenceAnalysis.cpp')
-rw-r--r--lib/Analysis/MemoryDependenceAnalysis.cpp76
1 files changed, 64 insertions, 12 deletions
diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp
index d640075..0ec0e74 100644
--- a/lib/Analysis/MemoryDependenceAnalysis.cpp
+++ b/lib/Analysis/MemoryDependenceAnalysis.cpp
@@ -20,7 +20,7 @@
#include "llvm/IntrinsicInst.h"
#include "llvm/Function.h"
#include "llvm/Analysis/AliasAnalysis.h"
-#include "llvm/Analysis/MallocHelper.h"
+#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/PredIteratorCache.h"
@@ -113,10 +113,13 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall,
} else if (VAArgInst *V = dyn_cast<VAArgInst>(Inst)) {
Pointer = V->getOperand(0);
PointerSize = AA->getTypeStoreSize(V->getType());
- } else if (FreeInst *F = dyn_cast<FreeInst>(Inst)) {
- Pointer = F->getPointerOperand();
-
- // FreeInsts erase the entire structure
+ } else if (isFreeCall(Inst)) {
+ Pointer = Inst->getOperand(1);
+ // calls to free() erase the entire structure
+ PointerSize = ~0ULL;
+ } else if (isFreeCall(Inst)) {
+ Pointer = Inst->getOperand(0);
+ // calls to free() erase the entire structure
PointerSize = ~0ULL;
} else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
// Debug intrinsics don't cause dependences.
@@ -168,13 +171,54 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall,
/// location depends. If isLoad is true, this routine ignore may-aliases with
/// read-only operations.
MemDepResult MemoryDependenceAnalysis::
-getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
+getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
BasicBlock::iterator ScanIt, BasicBlock *BB) {
+ Value* invariantTag = 0;
+
// Walk backwards through the basic block, looking for dependencies.
while (ScanIt != BB->begin()) {
Instruction *Inst = --ScanIt;
+ // If we're in an invariant region, no dependencies can be found before
+ // we pass an invariant-begin marker.
+ if (invariantTag == Inst) {
+ invariantTag = 0;
+ continue;
+ } else if (IntrinsicInst* II = dyn_cast<IntrinsicInst>(Inst)) {
+ // If we pass an invariant-end marker, then we've just entered an
+ // invariant region and can start ignoring dependencies.
+ if (II->getIntrinsicID() == Intrinsic::invariant_end) {
+ uint64_t invariantSize = ~0ULL;
+ if (ConstantInt* CI = dyn_cast<ConstantInt>(II->getOperand(2)))
+ invariantSize = CI->getZExtValue();
+
+ AliasAnalysis::AliasResult R =
+ AA->alias(II->getOperand(3), invariantSize, MemPtr, MemSize);
+ if (R == AliasAnalysis::MustAlias) {
+ invariantTag = II->getOperand(1);
+ continue;
+ }
+
+ // If we reach a lifetime begin or end marker, then the query ends here
+ // because the value is undefined.
+ } else if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+ II->getIntrinsicID() == Intrinsic::lifetime_end) {
+ uint64_t invariantSize = ~0ULL;
+ if (ConstantInt* CI = dyn_cast<ConstantInt>(II->getOperand(1)))
+ invariantSize = CI->getZExtValue();
+
+ AliasAnalysis::AliasResult R =
+ AA->alias(II->getOperand(2), invariantSize, MemPtr, MemSize);
+ if (R == AliasAnalysis::MustAlias)
+ return MemDepResult::getDef(II);
+ }
+ }
+
+ // If we're querying on a load and we're in an invariant region, we're done
+ // at this point. Nothing a load depends on can live in an invariant region.
+ if (isLoad && invariantTag) continue;
+
// Debug intrinsics don't cause dependences.
if (isa<DbgInfoIntrinsic>(Inst)) continue;
@@ -199,6 +243,10 @@ getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
}
if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
+ // There can't be stores to the value we care about inside an
+ // invariant region.
+ if (invariantTag) continue;
+
// If alias analysis can tell that this store is guaranteed to not modify
// the query pointer, ignore it. Use getModRefInfo to handle cases where
// the query pointer points to constant memory etc.
@@ -229,7 +277,7 @@ getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
// a subsequent bitcast of the malloc call result. There can be stores to
// the malloced memory between the malloc call and its bitcast uses, and we
// need to continue scanning until the malloc call.
- if (isa<AllocationInst>(Inst) || extractMallocCall(Inst)) {
+ if (isa<AllocaInst>(Inst) || extractMallocCall(Inst)) {
Value *AccessPtr = MemPtr->getUnderlyingObject();
if (AccessPtr == Inst ||
@@ -243,12 +291,16 @@ getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
case AliasAnalysis::NoModRef:
// If the call has no effect on the queried pointer, just ignore it.
continue;
+ case AliasAnalysis::Mod:
+ // If we're in an invariant region, we can ignore calls that ONLY
+ // modify the pointer.
+ if (invariantTag) continue;
+ return MemDepResult::getClobber(Inst);
case AliasAnalysis::Ref:
// If the call is known to never store to the pointer, and if this is a
// load query, we can safely ignore it (scan past it).
if (isLoad)
continue;
- // FALL THROUGH.
default:
// Otherwise, there is a potential dependence. Return a clobber.
return MemDepResult::getClobber(Inst);
@@ -314,15 +366,15 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) {
MemPtr = LI->getPointerOperand();
MemSize = AA->getTypeStoreSize(LI->getType());
}
+ } else if (isFreeCall(QueryInst)) {
+ MemPtr = QueryInst->getOperand(1);
+ // calls to free() erase the entire structure, not just a field.
+ MemSize = ~0UL;
} else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) {
CallSite QueryCS = CallSite::get(QueryInst);
bool isReadOnly = AA->onlyReadsMemory(QueryCS);
LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos,
QueryParent);
- } else if (FreeInst *FI = dyn_cast<FreeInst>(QueryInst)) {
- MemPtr = FI->getPointerOperand();
- // FreeInsts erase the entire structure, not just a field.
- MemSize = ~0UL;
} else {
// Non-memory instruction.
LocalCache = MemDepResult::getClobber(--BasicBlock::iterator(ScanPos));
OpenPOWER on IntegriCloud