diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index ceed0ab5446..8a5b07e48a9 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -243,6 +243,14 @@ namespace llvm { /// updating the dependence of instructions that previously depended on it. void removeInstruction(Instruction *InstToRemove); + /// invalidateCachedPointerInfo - This method is used to invalidate cached + /// information about the specified pointer, because it may be too + /// conservative in memdep. This is an optional call that can be used when + /// the client detects an equivalence between the pointer and some other + /// value and replaces the other value with ptr. This can make Ptr available + /// in more places that cached info does not necessarily keep. + void invalidateCachedPointerInfo(Value *Ptr); + private: MemDepResult getPointerDependencyFrom(Value *Pointer, uint64_t MemSize, bool isLoad, @@ -260,7 +268,6 @@ namespace llvm { NonLocalDepInfo *Cache, unsigned NumSortedEntries); - void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P); /// verifyRemoved - Verify that the specified instruction does not occur diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp index 42114938edf..0b185b1c7cf 100644 --- a/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -698,6 +698,21 @@ RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P) { } +/// invalidateCachedPointerInfo - This method is used to invalidate cached +/// information about the specified pointer, because it may be too +/// conservative in memdep. This is an optional call that can be used when +/// the client detects an equivalence between the pointer and some other +/// value and replaces the other value with ptr. This can make Ptr available +/// in more places that cached info does not necessarily keep. +void MemoryDependenceAnalysis::invalidateCachedPointerInfo(Value *Ptr) { + // If Ptr isn't really a pointer, just ignore it. + if (!isa(Ptr->getType())) return; + // Flush store info for the pointer. + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, false)); + // Flush load info for the pointer. + RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, true)); +} + /// 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. @@ -864,7 +879,6 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) { AA->deleteValue(RemInst); DEBUG(verifyRemoved(RemInst)); } - /// verifyRemoved - Verify that the specified instruction does not occur /// in our internal data structures. void MemoryDependenceAnalysis::verifyRemoved(Instruction *D) const { diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 79a0fc24e30..2081811f0d1 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -842,6 +842,8 @@ Value *GVN::GetValueForBlock(BasicBlock *BB, LoadInst* orig, } PN->replaceAllUsesWith(v); + if (isa(v->getType())) + MD->invalidateCachedPointerInfo(v); for (DenseMap::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) @@ -1015,6 +1017,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI, if ((*I)->getParent() == LI->getParent()) { DEBUG(cerr << "GVN REMOVING NONLOCAL LOAD #1: " << *LI); LI->replaceAllUsesWith(*I); + if (isa((*I)->getType())) + MD->invalidateCachedPointerInfo(*I); toErase.push_back(LI); NumGVNLoad++; return true; @@ -1030,6 +1034,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI, // Perform PHI construction. Value* v = GetValueForBlock(LI->getParent(), LI, BlockReplValues, true); LI->replaceAllUsesWith(v); + if (isa(v->getType())) + MD->invalidateCachedPointerInfo(v); toErase.push_back(LI); NumGVNLoad++; return true; @@ -1124,6 +1130,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI, Value* v = GetValueForBlock(LI->getParent(), LI, BlockReplValues, true); LI->replaceAllUsesWith(v); v->takeName(LI); + if (isa(v->getType())) + MD->invalidateCachedPointerInfo(v); toErase.push_back(LI); NumPRELoad++; return true; @@ -1157,6 +1165,8 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // Remove it! L->replaceAllUsesWith(DepSI->getOperand(0)); + if (isa(DepSI->getOperand(0)->getType())) + MD->invalidateCachedPointerInfo(DepSI->getOperand(0)); toErase.push_back(L); NumGVNLoad++; return true; @@ -1170,6 +1180,8 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // Remove it! L->replaceAllUsesWith(DepLI); + if (isa(DepLI->getType())) + MD->invalidateCachedPointerInfo(DepLI); toErase.push_back(L); NumGVNLoad++; return true; @@ -1241,6 +1253,8 @@ bool GVN::processInstruction(Instruction *I, PI->second.erase(p); p->replaceAllUsesWith(constVal); + if (isa(constVal->getType())) + MD->invalidateCachedPointerInfo(constVal); toErase.push_back(p); } else { localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); @@ -1257,6 +1271,8 @@ bool GVN::processInstruction(Instruction *I, // Remove it! VN.erase(I); I->replaceAllUsesWith(repl); + if (isa(repl->getType())) + MD->invalidateCachedPointerInfo(repl); toErase.push_back(I); return true; } else { @@ -1494,6 +1510,8 @@ bool GVN::performPRE(Function& F) { localAvail[CurrentBlock]->table[valno] = Phi; CurInst->replaceAllUsesWith(Phi); + if (isa(Phi->getType())) + MD->invalidateCachedPointerInfo(Phi); VN.erase(CurInst); DEBUG(cerr << "GVN PRE removed: " << *CurInst);