diff options
author | George Burgess IV <george.burgess.iv@gmail.com> | 2018-02-27 07:20:49 +0000 |
---|---|---|
committer | George Burgess IV <george.burgess.iv@gmail.com> | 2018-02-27 07:20:49 +0000 |
commit | debfbcf86e35f4c142c38c5e1f3f64829d71b5ac (patch) | |
tree | 4d48575921a1991b758562b4584eb4502ffe75bc | |
parent | 3345c9ac189bc6393bd95a634f1b46d247049dd1 (diff) | |
download | bcm5719-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.h | 6 | ||||
-rw-r--r-- | llvm/unittests/Analysis/MemorySSA.cpp | 48 |
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 << ")"; +} |