summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Burgess IV <george.burgess.iv@gmail.com>2018-02-27 07:20:49 +0000
committerGeorge Burgess IV <george.burgess.iv@gmail.com>2018-02-27 07:20:49 +0000
commitdebfbcf86e35f4c142c38c5e1f3f64829d71b5ac (patch)
tree4d48575921a1991b758562b4584eb4502ffe75bc
parent3345c9ac189bc6393bd95a634f1b46d247049dd1 (diff)
downloadbcm5719-llvm-debfbcf86e35f4c142c38c5e1f3f64829d71b5ac.tar.gz
bcm5719-llvm-debfbcf86e35f4c142c38c5e1f3f64829d71b5ac.zip
[MemorySSA] Invalidate def caches on deletion
The only cases I can come up with where this invalidation needs to happen is when there's a deletion somewhere. If we find more creative test-cases, we can probably go with another approach mentioned on PR36529. Fixes PR36529. llvm-svn: 326177
-rw-r--r--llvm/include/llvm/Analysis/MemorySSA.h6
-rw-r--r--llvm/unittests/Analysis/MemorySSA.cpp48
2 files changed, 52 insertions, 2 deletions
diff --git a/llvm/include/llvm/Analysis/MemorySSA.h b/llvm/include/llvm/Analysis/MemorySSA.h
index 93911b7407f..2194e8b10f6 100644
--- a/llvm/include/llvm/Analysis/MemorySSA.h
+++ b/llvm/include/llvm/Analysis/MemorySSA.h
@@ -381,7 +381,9 @@ public:
OptimizedID = getDefiningAccess()->getID();
}
- MemoryAccess *getOptimized() const { return Optimized; }
+ MemoryAccess *getOptimized() const {
+ return cast_or_null<MemoryAccess>(Optimized);
+ }
bool isOptimized() const {
return getOptimized() && getDefiningAccess() &&
@@ -401,7 +403,7 @@ private:
const unsigned ID;
unsigned OptimizedID = INVALID_MEMORYACCESS_ID;
- MemoryAccess *Optimized = nullptr;
+ WeakVH Optimized;
};
template <>
diff --git a/llvm/unittests/Analysis/MemorySSA.cpp b/llvm/unittests/Analysis/MemorySSA.cpp
index 326a62efb44..b255b403914 100644
--- a/llvm/unittests/Analysis/MemorySSA.cpp
+++ b/llvm/unittests/Analysis/MemorySSA.cpp
@@ -951,3 +951,51 @@ TEST_F(MemorySSATest, MoveToBeforeLiveOnEntryInvalidatesCache) {
MSSA.getLiveOnEntryDef())
<< "(DefA = " << DefA << ")";
}
+
+TEST_F(MemorySSATest, RemovingDefInvalidatesCache) {
+ // Create:
+ // %x = alloca i8
+ // %y = alloca i8
+ // ; 1 = MemoryDef(liveOnEntry)
+ // store i8 0, i8* %x
+ // ; 2 = MemoryDef(1)
+ // store i8 0, i8* %y
+ // ; 3 = MemoryDef(2)
+ // store i8 0, i8* %x
+ //
+ // And be sure that MSSA's caching handles the removal of def `1`
+ // appropriately.
+ IRBuilder<> B(C);
+ F = Function::Create(
+ FunctionType::get(B.getVoidTy(), {B.getInt8PtrTy()}, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+
+ BasicBlock *Entry = BasicBlock::Create(C, "if", F);
+ B.SetInsertPoint(Entry);
+
+ Value *X = B.CreateAlloca(B.getInt8Ty());
+ Value *Y = B.CreateAlloca(B.getInt8Ty());
+ StoreInst *StoreX1 = B.CreateStore(B.getInt8(0), X);
+ StoreInst *StoreY = B.CreateStore(B.getInt8(0), Y);
+ StoreInst *StoreX2 = B.CreateStore(B.getInt8(0), X);
+
+ setupAnalyses();
+
+ MemorySSA &MSSA = *Analyses->MSSA;
+
+ auto *DefX1 = cast<MemoryDef>(MSSA.getMemoryAccess(StoreX1));
+ auto *DefY = cast<MemoryDef>(MSSA.getMemoryAccess(StoreY));
+ auto *DefX2 = cast<MemoryDef>(MSSA.getMemoryAccess(StoreX2));
+
+ EXPECT_EQ(DefX2->getDefiningAccess(), DefY);
+ MemoryAccess *X2Clobber = MSSA.getWalker()->getClobberingMemoryAccess(DefX2);
+ ASSERT_EQ(DefX1, X2Clobber);
+
+ MemorySSAUpdater(&MSSA).removeMemoryAccess(DefX1);
+ StoreX1->eraseFromParent();
+
+ EXPECT_EQ(DefX2->getDefiningAccess(), DefY);
+ EXPECT_EQ(MSSA.getWalker()->getClobberingMemoryAccess(DefX2),
+ MSSA.getLiveOnEntryDef())
+ << "(DefX1 = " << DefX1 << ")";
+}
OpenPOWER on IntegriCloud