diff options
-rw-r--r-- | lib/Analysis/MemoryDependenceAnalysis.cpp | 22 | ||||
-rw-r--r-- | test/Transforms/GVN/2008-12-15-CacheVisited.ll | 28 |
2 files changed, 49 insertions, 1 deletions
diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp index a5bfeee7bc..6818da83ba 100644 --- a/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -601,10 +601,30 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize, // If we have valid cached information for exactly the block we are // investigating, just return it with no recomputation. if (CacheInfo->first == BBSkipFirstBlockPair(StartBB, SkipFirstBlock)) { + // We have a fully cached result for this query then we can just return the + // cached results and populate the visited set. However, we have to verify + // that we don't already have conflicting results for these blocks. Check + // to ensure that if a block in the results set is in the visited set that + // it was for the same pointer query. + if (!Visited.empty()) { + for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end(); + I != E; ++I) { + DenseMap<BasicBlock*, Value*>::iterator VI = Visited.find(I->first); + if (VI == Visited.end() || VI->second == Pointer) continue; + + // We have a pointer mismatch in a block. Just return clobber, saying + // that something was clobbered in this result. We could also do a + // non-fully cached query, but there is little point in doing this. + return true; + } + } + for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end(); - I != E; ++I) + I != E; ++I) { + Visited.insert(std::make_pair(I->first, Pointer)); if (!I->second.isNonLocal()) Result.push_back(*I); + } ++NumCacheCompleteNonLocalPtr; return false; } diff --git a/test/Transforms/GVN/2008-12-15-CacheVisited.ll b/test/Transforms/GVN/2008-12-15-CacheVisited.ll new file mode 100644 index 0000000000..b547003b25 --- /dev/null +++ b/test/Transforms/GVN/2008-12-15-CacheVisited.ll @@ -0,0 +1,28 @@ +; RUN: llvm-as < %s | opt -gvn | llvm-dis +; Cached results must be added to and verified against the visited sets. +; PR3217 + +define fastcc void @gen_field_die(i32* %decl) nounwind { +entry: + br i1 false, label %bb203, label %bb202 + +bb202: ; preds = %entry + unreachable + +bb203: ; preds = %entry + %tmp = getelementptr i32* %decl, i32 1 ; <i32*> [#uses=1] + %tmp1 = load i32* %tmp, align 4 ; <i32> [#uses=0] + br i1 false, label %bb207, label %bb204 + +bb204: ; preds = %bb203 + %tmp2 = getelementptr i32* %decl, i32 1 ; <i32*> [#uses=1] + br label %bb208 + +bb207: ; preds = %bb203 + br label %bb208 + +bb208: ; preds = %bb207, %bb204 + %iftmp.1374.0.in = phi i32* [ null, %bb207 ], [ %tmp2, %bb204 ] ; <i32*> [#uses=1] + %iftmp.1374.0 = load i32* %iftmp.1374.0.in ; <i32> [#uses=0] + unreachable +} |