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 @@ -1042,8 +1042,9 @@ /// given a MemoryDef that clobbers the pointer as the starting access, it /// will return that MemoryDef, whereas the above would return the clobber /// starting from the use side of the memory def. - virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, - const MemoryLocation &) = 0; + virtual MemoryAccess * + getClobberingMemoryAccess(MemoryAccess *, const MemoryLocation &, + MemoryAccess *S = nullptr) = 0; /// Given a memory access, invalidate anything this walker knows about /// that access. @@ -1068,7 +1069,8 @@ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override; MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, - const MemoryLocation &) override; + const MemoryLocation &, + MemoryAccess *S = nullptr) 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 @@ -953,7 +953,8 @@ /// Finds the nearest clobber for the given query, optimizing phis if /// possible. MemoryAccess *findClobber(MemoryAccess *Start, UpwardsMemoryQuery &Q, - unsigned &UpWalkLimit) { + unsigned &UpWalkLimit, + MemoryAccess *Stop = nullptr) { Query = &Q; UpwardWalkLimit = &UpWalkLimit; // Starting limit must be > 0. @@ -961,6 +962,8 @@ UpWalkLimit++; MemoryAccess *Current = Start; + MemoryAccess *StopAt = + (Stop && MSSA.dominates(Stop, Start)) ? Stop : nullptr; // This walker pretends uses don't exist. If we're handed one, silently grab // its def. (This has the nice side-effect of ensuring we never cache uses) if (auto *MU = dyn_cast(Start)) @@ -969,9 +972,9 @@ DefPath FirstDesc(Q.StartingLoc, Current, Current, None); // Fast path for the overly-common case (no crazy phi optimization // necessary) - UpwardsWalkResult WalkResult = walkToPhiOrClobber(FirstDesc); + UpwardsWalkResult WalkResult = walkToPhiOrClobber(FirstDesc, StopAt); MemoryAccess *Result; - if (WalkResult.IsKnownClobber) { + if (WalkResult.IsKnownClobber || (StopAt && WalkResult.Result == StopAt)) { Result = WalkResult.Result; Q.AR = WalkResult.AR; } else { @@ -983,7 +986,7 @@ } #ifdef EXPENSIVE_CHECKS - if (!Q.SkipSelfAccess && *UpwardWalkLimit > 0) + if (!Q.SkipSelfAccess && *UpwardWalkLimit > 0 && !StopAt) checkClobberSanity(Current, Result, Q.StartingLoc, MSSA, Q, AA); #endif return Result; @@ -1020,7 +1023,7 @@ MemoryAccess *getClobberingMemoryAccessBase(MemoryAccess *, const MemoryLocation &, - unsigned &); + MemoryAccess *, unsigned &); // Third argument (bool), defines whether the clobber search should skip the // original queried access. If true, there will be a follow-up query searching // for a clobber access past "self". Note that the Optimized access is not @@ -1049,18 +1052,19 @@ } MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, - unsigned &UWL) { - return Walker->getClobberingMemoryAccessBase(MA, Loc, UWL); + MemoryAccess *Stop, unsigned &UWL) { + return Walker->getClobberingMemoryAccessBase(MA, Loc, Stop, UWL); } MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA) override { unsigned UpwardWalkLimit = MaxCheckLimit; return getClobberingMemoryAccess(MA, UpwardWalkLimit); } - MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, - const MemoryLocation &Loc) override { + MemoryAccess * + getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, + MemoryAccess *Stop = nullptr) override { unsigned UpwardWalkLimit = MaxCheckLimit; - return getClobberingMemoryAccess(MA, Loc, UpwardWalkLimit); + return getClobberingMemoryAccess(MA, Loc, Stop, UpwardWalkLimit); } void invalidateInfo(MemoryAccess *MA) override { @@ -1085,18 +1089,19 @@ } MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, - unsigned &UWL) { - return Walker->getClobberingMemoryAccessBase(MA, Loc, UWL); + MemoryAccess *Stop, unsigned &UWL) { + return Walker->getClobberingMemoryAccessBase(MA, Loc, Stop, UWL); } MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA) override { unsigned UpwardWalkLimit = MaxCheckLimit; return getClobberingMemoryAccess(MA, UpwardWalkLimit); } - MemoryAccess *getClobberingMemoryAccess(MemoryAccess *MA, - const MemoryLocation &Loc) override { + MemoryAccess * + getClobberingMemoryAccess(MemoryAccess *MA, const MemoryLocation &Loc, + MemoryAccess *Stop = nullptr) override { unsigned UpwardWalkLimit = MaxCheckLimit; - return getClobberingMemoryAccess(MA, Loc, UpwardWalkLimit); + return getClobberingMemoryAccess(MA, Loc, Stop, UpwardWalkLimit); } void invalidateInfo(MemoryAccess *MA) override { @@ -2343,7 +2348,7 @@ MemoryAccess * MemorySSA::ClobberWalkerBase::getClobberingMemoryAccessBase( MemoryAccess *StartingAccess, const MemoryLocation &Loc, - unsigned &UpwardWalkLimit) { + MemoryAccess *StopAccess, unsigned &UpwardWalkLimit) { if (isa(StartingAccess)) return StartingAccess; @@ -2372,7 +2377,7 @@ : StartingUseOrDef; MemoryAccess *Clobber = - Walker.findClobber(DefiningAccess, Q, UpwardWalkLimit); + Walker.findClobber(DefiningAccess, Q, UpwardWalkLimit, StopAccess); LLVM_DEBUG(dbgs() << "Starting Memory SSA clobber for " << *I << " is "); LLVM_DEBUG(dbgs() << *StartingUseOrDef << "\n"); LLVM_DEBUG(dbgs() << "Final Memory SSA clobber for " << *I << " is "); @@ -2466,7 +2471,7 @@ } MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess( - MemoryAccess *StartingAccess, const MemoryLocation &) { + MemoryAccess *StartingAccess, const MemoryLocation &, MemoryAccess *Stop) { if (auto *Use = dyn_cast(StartingAccess)) return Use->getDefiningAccess(); return StartingAccess;