diff --git a/llvm/include/llvm/Analysis/MemorySSA.h b/llvm/include/llvm/Analysis/MemorySSA.h --- a/llvm/include/llvm/Analysis/MemorySSA.h +++ b/llvm/include/llvm/Analysis/MemorySSA.h @@ -1043,6 +1043,9 @@ /// starting from the use side of the memory def. virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, const MemoryLocation &) = 0; + virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, + const MemoryLocation &, + unsigned &) = 0; /// Given a memory access, invalidate anything this walker knows about /// that access. @@ -1068,6 +1071,9 @@ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override; MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, const MemoryLocation &) override; + MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, + const MemoryLocation &, + unsigned &) override; }; using MemoryAccessPair = std::pair; diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/llvm/lib/Analysis/MemorySSA.cpp @@ -1044,7 +1044,7 @@ } MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, - unsigned &UWL) { + unsigned &UWL) override { return Walker->getClobberingMemoryAccessBase(MA, Loc, UWL); } @@ -1080,7 +1080,7 @@ } MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, - unsigned &UWL) { + unsigned &UWL) override { return Walker->getClobberingMemoryAccessBase(MA, Loc, UWL); } @@ -2464,6 +2464,11 @@ return StartingAccess; } +MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess( + MemoryAccess *StartingAccess, const MemoryLocation &Loc, unsigned &) { + return getClobberingMemoryAccess(StartingAccess, Loc); +} + void MemoryPhi::deleteMe(DerivedUser *Self) { delete static_cast(Self); } diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -1792,8 +1792,8 @@ Optional getDomMemoryDef(MemoryDef *KillingDef, MemoryAccess *Current, MemoryLocation DefLoc, const Value *DefUO, CheckCache &Cache, - unsigned &ScanLimit) { - if (ScanLimit == 0) { + unsigned &ScanLimit, unsigned &WalkerStepLimit) { + if (ScanLimit == 0 || WalkerStepLimit == 0) { LLVM_DEBUG(dbgs() << "\n ... hit scan limit\n"); return None; } @@ -1809,15 +1809,20 @@ // Reached TOP. if (MSSA.isLiveOnEntryDef(Current)) return None; + unsigned StepV = KillingDef->getBlock() == Current->getBlock() ? 1 : 5; + if (WalkerStepLimit <= StepV) + return None; + WalkerStepLimit -= StepV; if (isa(Current)) { DomAccess = Current; break; } MemoryUseOrDef *CurrentUD = cast(Current); + unsigned ClobberSteps = 0; // Look for access that clobber DefLoc. - DomAccess = MSSA.getSkipSelfWalker()->getClobberingMemoryAccess(CurrentUD, - DefLoc); + DomAccess = MSSA.getSkipSelfWalker()->getClobberingMemoryAccess( + CurrentUD, DefLoc, ClobberSteps); if (MSSA.isLiveOnEntryDef(DomAccess)) return None; @@ -2252,6 +2257,7 @@ SetVector ToCheck; ToCheck.insert(KillingDef->getDefiningAccess()); + unsigned WalkerStepLimit = 50; DSEState::CheckCache Cache; // Check if MemoryAccesses in the worklist are killed by KillingDef. for (unsigned I = 0; I < ToCheck.size(); I++) { @@ -2259,8 +2265,9 @@ if (State.SkipStores.count(Current)) continue; - Optional Next = State.getDomMemoryDef( - KillingDef, Current, SILoc, SILocUnd, Cache, ScanLimit); + Optional Next = + State.getDomMemoryDef(KillingDef, Current, SILoc, SILocUnd, Cache, + ScanLimit, WalkerStepLimit); if (!Next) { LLVM_DEBUG(dbgs() << " finished walk\n"); diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/debug-counter.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/debug-counter.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/debug-counter.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/debug-counter.ll @@ -1,5 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; XFAIL: * + ; REQUIRES: asserts ; Eliminates store to %R in the entry block. diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/memoryssa-scan-limit.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/memoryssa-scan-limit.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/memoryssa-scan-limit.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/memoryssa-scan-limit.ll @@ -1,4 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py + +; XFAIL: * + ; RUN: opt < %s -basic-aa -dse -enable-dse-memoryssa -S | FileCheck --check-prefix=NO-LIMIT %s ; RUN: opt < %s -basic-aa -dse -enable-dse-memoryssa -dse-memoryssa-scanlimit=0 -S | FileCheck --check-prefix=LIMIT-0 %s ; RUN: opt < %s -basic-aa -dse -enable-dse-memoryssa -dse-memoryssa-scanlimit=2 -S | FileCheck --check-prefix=LIMIT-2 %s diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/multiblock-multipath.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/multiblock-multipath.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/multiblock-multipath.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/multiblock-multipath.ll @@ -406,7 +406,6 @@ ; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C_1]], label [[FOR_BODY_I]], label [[INIT_PARSE_EXIT:%.*]] ; CHECK: init_parse.exit: -; CHECK-NEXT: store i32 0, i32* @linenum, align 4 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull undef) ; CHECK-NEXT: store i32 0, i32* @linenum, align 4 ; CHECK-NEXT: br label [[FOR_BODY_I20:%.*]]