summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-12-16 07:10:09 +0000
committerChris Lattner <sabre@nondot.org>2008-12-16 07:10:09 +0000
commitf478951b0eeed2f8a9e39254f65458c9325dab91 (patch)
treed2c4899df814822e49ce59b20406dac2ab066c6f
parent812d7506d0c55fbb0eee522cb77b62e4ab777dea (diff)
downloadllvm-f478951b0eeed2f8a9e39254f65458c9325dab91.tar.gz
llvm-f478951b0eeed2f8a9e39254f65458c9325dab91.tar.bz2
llvm-f478951b0eeed2f8a9e39254f65458c9325dab91.tar.xz
fix PR3217: fully cached queries need to be verified against the
visited set before they are used. If used, their blocks need to be added to the visited set so that subsequent queries don't use conflicting pointer values in the cache result blocks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61080 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/MemoryDependenceAnalysis.cpp22
-rw-r--r--test/Transforms/GVN/2008-12-15-CacheVisited.ll28
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
+}