Index: include/llvm/Analysis/MemorySSA.h =================================================================== --- include/llvm/Analysis/MemorySSA.h +++ include/llvm/Analysis/MemorySSA.h @@ -703,6 +703,7 @@ ~MemorySSA(); MemorySSAWalker *getWalker(); + MemorySSAWalker *getTransformWalker(); /// Given a memory Mod/Ref'ing instruction, get the MemorySSA /// access associated with it. If passed a basic block gets the memory phi @@ -829,6 +830,7 @@ private: class CachingWalker; + class SkipSelfWalker; class OptimizeUses; CachingWalker *getWalkerImpl(); @@ -883,6 +885,7 @@ // Memory SSA building info std::unique_ptr Walker; + std::unique_ptr TransformWalker; unsigned NextID; }; Index: lib/Analysis/MemorySSA.cpp =================================================================== --- lib/Analysis/MemorySSA.cpp +++ lib/Analysis/MemorySSA.cpp @@ -950,9 +950,10 @@ /// A MemorySSAWalker that does AA walks to disambiguate accesses. It no /// longer does caching on its own, but the name has been retained for the /// moment. -class MemorySSA::CachingWalker final : public MemorySSAWalker { +class MemorySSA::CachingWalker : public MemorySSAWalker { ClobberWalker Walker; +protected: MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, UpwardsMemoryQuery &); public: @@ -972,6 +973,16 @@ } }; +class MemorySSA::SkipSelfWalker final : public MemorySSA::CachingWalker { + public: + SkipSelfWalker(MemorySSA *MSSA, AliasAnalysis *AA, DominatorTree * DT) + : CachingWalker(MSSA,AA, DT) {}; + + using MemorySSA::CachingWalker::getClobberingMemoryAccess; + + MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override; +}; + } // end namespace llvm void MemorySSA::renameSuccessorPhis(BasicBlock *BB, MemoryAccess *IncomingVal, @@ -1107,7 +1118,7 @@ MemorySSA::MemorySSA(Function &Func, AliasAnalysis *AA, DominatorTree *DT) : AA(AA), DT(DT), F(Func), LiveOnEntryDef(nullptr), Walker(nullptr), - NextID(0) { + TransformWalker(nullptr), NextID(0) { buildMemorySSA(); } @@ -1442,6 +1453,14 @@ return Walker.get(); } +MemorySSAWalker *MemorySSA::getTransformWalker() { + if (TransformWalker) + return TransformWalker.get(); + + TransformWalker = llvm::make_unique(this, AA, DT); + return TransformWalker.get(); +}; + // This is a helper function used by the creation routines. It places NewAccess // into the access and defs lists for a given basic block, at the given // insertion point. @@ -2252,6 +2271,87 @@ return Result; } +MemoryAccess * +MemorySSA::SkipSelfWalker::getClobberingMemoryAccess(MemoryAccess *MA) { + LLVM_DEBUG(dbgs() << "Starting Memory SSA clobber for: " << *MA << " is "); + auto *StartingAccess = dyn_cast(MA); + // If this is a MemoryPhi, we can't do anything. + if (!StartingAccess) + return MA; + + bool IsOptimized = false; + + // If this is an already optimized use or def, return the optimized result. + // Note: Currently, we store the optimized def result in a separate field, + // since we can't use the defining access. + if (StartingAccess->isOptimized()) { + if (!isa(StartingAccess)) + return StartingAccess->getOptimized(); + else + IsOptimized = true; + } + + const Instruction *I = StartingAccess->getMemoryInst(); + // We can't sanely do anything with a fence, since they conservatively clobber + // all memory, and have no locations to get pointers from to try to + // disambiguate. + if (!ImmutableCallSite(I) && I->isFenceLike()) + return StartingAccess; + + UpwardsMemoryQuery Q(I, StartingAccess); + + if (isUseTriviallyOptimizableToLiveOnEntry(*MSSA->AA, I)) { + MemoryAccess *LiveOnEntry = MSSA->getLiveOnEntryDef(); + StartingAccess->setOptimized(LiveOnEntry); + StartingAccess->setOptimizedAccessType(None); + return LiveOnEntry; + } + + MemoryAccess *OptimizedAccess; + if (!IsOptimized) { + // Start with the thing we already think clobbers this location + MemoryAccess *DefiningAccess = StartingAccess->getDefiningAccess(); + + // At this point, DefiningAccess may be the live on entry def. + // If it is, we will not get a better result. + if (MSSA->isLiveOnEntryDef(DefiningAccess)) { + StartingAccess->setOptimized(DefiningAccess); + StartingAccess->setOptimizedAccessType(None); + return DefiningAccess; + } + + OptimizedAccess = getClobberingMemoryAccess(DefiningAccess, Q); + StartingAccess->setOptimized(OptimizedAccess); + if (MSSA->isLiveOnEntryDef(OptimizedAccess)) + StartingAccess->setOptimizedAccessType(None); + else if (Q.AR == MustAlias) + StartingAccess->setOptimizedAccessType(MustAlias); + } + else + OptimizedAccess = StartingAccess->getOptimized(); + + LLVM_DEBUG(dbgs() << "Starting Memory SSA clobber for " << *I << " is "); + LLVM_DEBUG(dbgs() << *StartingAccess << "\n"); + LLVM_DEBUG(dbgs() << "Optimized Memory SSA clobber for " << *I << " is "); + LLVM_DEBUG(dbgs() << *OptimizedAccess << "\n"); + + MemoryAccess *Result; + if (isa(OptimizedAccess) && + isa(StartingAccess)) { + Q.SkipSelfAccess = true; + Result = getClobberingMemoryAccess(OptimizedAccess, Q); + } + else + Result = OptimizedAccess; + + LLVM_DEBUG(dbgs() << "***Optimized Memory SSA clobber for " << *I << " is "); + LLVM_DEBUG(dbgs() << *OptimizedAccess << "\n"); + LLVM_DEBUG(dbgs() << "***Final Memory SSA clobber for " << *I << " is "); + LLVM_DEBUG(dbgs() << *Result << "\n"); + + return Result; +} + MemoryAccess * DoNothingMemorySSAWalker::getClobberingMemoryAccess(MemoryAccess *MA) { if (auto *Use = dyn_cast(MA))