diff options
Diffstat (limited to 'lib/Analysis/MemoryDependenceAnalysis.cpp')
| -rw-r--r-- | lib/Analysis/MemoryDependenceAnalysis.cpp | 76 | 
1 files changed, 64 insertions, 12 deletions
diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp index d6400757a513..0ec0e74233b3 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));  | 
