make clients have to know how to call getCallSiteDependencyFrom
[oota-llvm.git] / lib / Analysis / MemoryDependenceAnalysis.cpp
index c47ec0493a5c4643b777c9a24cde1db48b95b0b2..415766a5a15c4f31a6c862f4f2d2f6c5bce64bbd 100644 (file)
@@ -52,11 +52,11 @@ bool MemoryDependenceAnalysis::runOnFunction(Function &) {
 }
 
 
-/// getCallSiteDependency - Private helper for finding the local dependencies
-/// of a call site.
+/// getCallSiteDependencyFrom - Private helper for finding the local
+/// dependencies of a call site.
 MemDepResult MemoryDependenceAnalysis::
-getCallSiteDependency(CallSite C, BasicBlock::iterator ScanIt, BasicBlock *BB) {
-  
+getCallSiteDependencyFrom(CallSite CS, BasicBlock::iterator ScanIt,
+                          BasicBlock *BB) {
   // Walk backwards through the block, looking for dependencies
   while (ScanIt != BB->begin()) {
     Instruction *Inst = --ScanIt;
@@ -76,17 +76,29 @@ getCallSiteDependency(CallSite C, BasicBlock::iterator ScanIt, BasicBlock *BB) {
       // FreeInsts erase the entire structure
       PointerSize = ~0UL;
     } else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
-      if (AA->getModRefBehavior(CallSite::get(Inst)) ==
-            AliasAnalysis::DoesNotAccessMemory)
+      CallSite InstCS = CallSite::get(Inst);
+      // If these two calls do not interfere, look past it.
+      if (AA->getModRefInfo(CS, InstCS) == AliasAnalysis::NoModRef)
         continue;
-      return MemDepResult::get(Inst);
+      
+      // FIXME: If this is a ref/ref result, we should ignore it!
+      //  X = strlen(P);
+      //  Y = strlen(Q);
+      //  Z = strlen(P);  // Z = X
+      
+      // If they interfere, we generally return clobber.  However, if they are
+      // calls to the same read-only functions we return Def.
+      if (!AA->onlyReadsMemory(CS) || CS.getCalledFunction() == 0 ||
+          CS.getCalledFunction() != InstCS.getCalledFunction())
+        return MemDepResult::getClobber(Inst);
+      return MemDepResult::getDef(Inst);
     } else {
       // Non-memory instruction.
       continue;
     }
     
-    if (AA->getModRefInfo(C, Pointer, PointerSize) != AliasAnalysis::NoModRef)
-      return MemDepResult::get(Inst);
+    if (AA->getModRefInfo(CS, Pointer, PointerSize) != AliasAnalysis::NoModRef)
+      return MemDepResult::getClobber(Inst);
   }
   
   // No dependence found.
@@ -98,63 +110,82 @@ getCallSiteDependency(CallSite C, BasicBlock::iterator ScanIt, BasicBlock *BB) {
 MemDepResult MemoryDependenceAnalysis::
 getDependencyFrom(Instruction *QueryInst, BasicBlock::iterator ScanIt, 
                   BasicBlock *BB) {
+  // The first instruction in a block is always non-local.
+  if (ScanIt == BB->begin())
+    return MemDepResult::getNonLocal();
+  
   // Get the pointer value for which dependence will be determined
   Value *MemPtr = 0;
   uint64_t MemSize = 0;
-  bool MemVolatile = false;
   
-  if (StoreInst* S = dyn_cast<StoreInst>(QueryInst)) {
-    MemPtr = S->getPointerOperand();
-    MemSize = TD->getTypeStoreSize(S->getOperand(0)->getType());
-    MemVolatile = S->isVolatile();
-  } else if (LoadInst* L = dyn_cast<LoadInst>(QueryInst)) {
-    MemPtr = L->getPointerOperand();
-    MemSize = TD->getTypeStoreSize(L->getType());
-    MemVolatile = L->isVolatile();
-  } else if (VAArgInst* V = dyn_cast<VAArgInst>(QueryInst)) {
-    MemPtr = V->getOperand(0);
-    MemSize = TD->getTypeStoreSize(V->getType());
-  } else if (FreeInst* F = dyn_cast<FreeInst>(QueryInst)) {
-    MemPtr = F->getPointerOperand();
+  if (StoreInst *SI = dyn_cast<StoreInst>(QueryInst)) {
+    // If this is a volatile store, don't mess around with it.  Just return the
+    // previous instruction as a clobber.
+    if (SI->isVolatile())
+      return MemDepResult::getClobber(--ScanIt);
+
+    MemPtr = SI->getPointerOperand();
+    MemSize = TD->getTypeStoreSize(SI->getOperand(0)->getType());
+  } else if (LoadInst *LI = dyn_cast<LoadInst>(QueryInst)) {
+    // If this is a volatile load, don't mess around with it.  Just return the
+    // previous instruction as a clobber.
+    if (LI->isVolatile())
+      return MemDepResult::getClobber(--ScanIt);
+    
+    MemPtr = LI->getPointerOperand();
+    MemSize = TD->getTypeStoreSize(LI->getType());
+  } else if (FreeInst *FI = dyn_cast<FreeInst>(QueryInst)) {
+    MemPtr = FI->getPointerOperand();
     // FreeInsts erase the entire structure, not just a field.
     MemSize = ~0UL;
-  } else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst))
-    return getCallSiteDependency(CallSite::get(QueryInst), ScanIt, BB);
-  else  // Non-memory instructions depend on nothing.
-    return MemDepResult::getNone();
+  } else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) {
+    assert(0 && "Should use getCallSiteDependencyFrom!");
+    return getCallSiteDependencyFrom(CallSite::get(QueryInst), ScanIt, BB);
+  } else {
+    // Otherwise, this is a vaarg or non-memory instruction, just return a
+    // clobber dependency on the previous inst.
+    return MemDepResult::getClobber(--ScanIt);
+  }
   
   // Walk backwards through the basic block, looking for dependencies
   while (ScanIt != BB->begin()) {
     Instruction *Inst = --ScanIt;
 
-    // If the access is volatile and this is a volatile load/store, return a
-    // dependence.
-    if (MemVolatile &&
-        ((isa<LoadInst>(Inst) && cast<LoadInst>(Inst)->isVolatile()) ||
-         (isa<StoreInst>(Inst) && cast<StoreInst>(Inst)->isVolatile())))
-      return MemDepResult::get(Inst);
-
     // Values depend on loads if the pointers are must aliased.  This means that
     // a load depends on another must aliased load from the same value.
-    if (LoadInst *L = dyn_cast<LoadInst>(Inst)) {
-      Value *Pointer = L->getPointerOperand();
-      uint64_t PointerSize = TD->getTypeStoreSize(L->getType());
+    if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
+      Value *Pointer = LI->getPointerOperand();
+      uint64_t PointerSize = TD->getTypeStoreSize(LI->getType());
       
-      // If we found a pointer, check if it could be the same as our pointer
+      // If we found a pointer, check if it could be the same as our pointer.
       AliasAnalysis::AliasResult R =
         AA->alias(Pointer, PointerSize, MemPtr, MemSize);
-      
       if (R == AliasAnalysis::NoAlias)
         continue;
       
       // May-alias loads don't depend on each other without a dependence.
       if (isa<LoadInst>(QueryInst) && R == AliasAnalysis::MayAlias)
         continue;
-      return MemDepResult::get(Inst);
+      return MemDepResult::getDef(Inst);
+    }
+    
+    if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
+      Value *Pointer = SI->getPointerOperand();
+      uint64_t PointerSize = TD->getTypeStoreSize(SI->getOperand(0)->getType());
+
+      // If we found a pointer, check if it could be the same as our pointer.
+      AliasAnalysis::AliasResult R =
+        AA->alias(Pointer, PointerSize, MemPtr, MemSize);
+      
+      if (R == AliasAnalysis::NoAlias)
+        continue;
+      if (R == AliasAnalysis::MayAlias)
+        return MemDepResult::getClobber(Inst);
+      return MemDepResult::getDef(Inst);
     }
 
     // If this is an allocation, and if we know that the accessed pointer is to
-    // the allocation, return None.  This means that there is no dependence and
+    // the allocation, return Def.  This means that there is no dependence and
     // the access can be optimized based on that.  For example, a load could
     // turn into undef.
     if (AllocationInst *AI = dyn_cast<AllocationInst>(Inst)) {
@@ -162,22 +193,16 @@ getDependencyFrom(Instruction *QueryInst, BasicBlock::iterator ScanIt,
       
       if (AccessPtr == AI ||
           AA->alias(AI, 1, AccessPtr, 1) == AliasAnalysis::MustAlias)
-        return MemDepResult::getNone();
+        return MemDepResult::getDef(AI);
       continue;
     }
     
-    // See if this instruction mod/ref's the pointer.
-    AliasAnalysis::ModRefResult MRR = AA->getModRefInfo(Inst, MemPtr, MemSize);
-
-    if (MRR == AliasAnalysis::NoModRef)
-      continue;
-    
-    // Loads don't depend on read-only instructions.
-    if (isa<LoadInst>(QueryInst) && MRR == AliasAnalysis::Ref)
+    // See if this instruction (e.g. a call or vaarg) mod/ref's the pointer.
+    if (AA->getModRefInfo(Inst, MemPtr, MemSize) == AliasAnalysis::NoModRef)
       continue;
     
     // Otherwise, there is a dependence.
-    return MemDepResult::get(Inst);
+    return MemDepResult::getClobber(Inst);
   }
   
   // If we found nothing, return the non-local flag.
@@ -209,7 +234,11 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) {
   }
   
   // Do the scan.
-  LocalCache = getDependencyFrom(QueryInst, ScanPos, QueryInst->getParent());
+  if (!isa<CallInst>(QueryInst) && !isa<InvokeInst>(QueryInst))
+    LocalCache = getDependencyFrom(QueryInst, ScanPos, QueryInst->getParent());
+  else 
+    LocalCache = getCallSiteDependencyFrom(CallSite::get(QueryInst), ScanPos,
+                                           QueryInst->getParent());
   
   // Remember the result!
   if (Instruction *I = LocalCache.getInst())
@@ -317,7 +346,12 @@ MemoryDependenceAnalysis::getNonLocalDependency(Instruction *QueryInst) {
     }
     
     // Find out if this block has a local dependency for QueryInst.
-    MemDepResult Dep = getDependencyFrom(QueryInst, ScanPos, DirtyBB);
+    MemDepResult Dep;
+    if (!isa<CallInst>(QueryInst) && !isa<InvokeInst>(QueryInst))
+      Dep = getDependencyFrom(QueryInst, ScanPos, DirtyBB);
+    else 
+      Dep = getCallSiteDependencyFrom(CallSite::get(QueryInst), ScanPos,
+                                      DirtyBB);
     
     // If we had a dirty entry for the block, update it.  Otherwise, just add
     // a new entry.
@@ -344,6 +378,7 @@ MemoryDependenceAnalysis::getNonLocalDependency(Instruction *QueryInst) {
   return Cache;
 }
 
+
 /// removeInstruction - Remove an instruction from the dependence analysis,
 /// updating the dependence of instructions that previously depended on it.
 /// This method attempts to keep the cache coherent using the reverse map.