Index: include/llvm/Analysis/MemorySSA.h =================================================================== --- include/llvm/Analysis/MemorySSA.h +++ include/llvm/Analysis/MemorySSA.h @@ -702,7 +702,8 @@ MemorySSA(Function &, AliasAnalysis *, DominatorTree *); ~MemorySSA(); - MemorySSAWalker *getWalker(); + MemorySSAWalker *getWalker() const; + AliasAnalysis *getAA() const; /// Given a memory Mod/Ref'ing instruction, get the MemorySSA /// access associated with it. If passed a basic block gets the memory phi @@ -774,6 +775,10 @@ /// all uses, uses appear in the right places). This is used by unit tests. void verifyMemorySSA() const; + /// Check clobber sanity for an instruction or access. + void checkClobberSanityInstruction(Instruction *I); + void checkClobberSanityAccess(const MemoryAccess *MA) const; + /// Used in various insertion functions to specify whether we are talking /// about the beginning or end of a block. enum InsertionPlace { Beginning, End }; @@ -788,6 +793,7 @@ void verifyDomination(Function &F) const; void verifyOrdering(Function &F) const; void verifyDominationNumbers(const Function &F) const; + void verifyClobberSanity(const Function &F) const; // This is used by the use optimizer and updater. AccessList *getWritableBlockAccesses(const BasicBlock *BB) const { @@ -827,7 +833,7 @@ class CachingWalker; class OptimizeUses; - CachingWalker *getWalkerImpl(); + CachingWalker *getWalkerImpl() const; void buildMemorySSA(); void optimizeUses(); @@ -878,7 +884,7 @@ mutable DenseMap BlockNumbering; // Memory SSA building info - std::unique_ptr Walker; + mutable std::unique_ptr Walker; unsigned NextID; }; @@ -976,7 +982,7 @@ /// standardized interface to getting and using that info. class MemorySSAWalker { public: - MemorySSAWalker(MemorySSA *); + MemorySSAWalker(const MemorySSA *); virtual ~MemorySSAWalker() = default; using MemoryAccessSet = SmallVector; @@ -1039,7 +1045,7 @@ protected: friend class MemorySSA; // For updating MSSA pointer in MemorySSA move // constructor. - MemorySSA *MSSA; + const MemorySSA *MSSA; }; /// A MemorySSAWalker that does no alias queries, or anything else. It Index: lib/Analysis/MemorySSA.cpp =================================================================== --- lib/Analysis/MemorySSA.cpp +++ lib/Analysis/MemorySSA.cpp @@ -377,13 +377,14 @@ /// \param Start The MemoryAccess that we want to walk from. /// \param ClobberAt A clobber for Start. /// \param StartLoc The MemoryLocation for Start. -/// \param MSSA The MemorySSA isntance that Start and ClobberAt belong to. +/// \param MSSA The MemorySSA instance that Start and ClobberAt belong to. /// \param Query The UpwardsMemoryQuery we used for our search. /// \param AA The AliasAnalysis we used for our search. -static void LLVM_ATTRIBUTE_UNUSED -checkClobberSanity(MemoryAccess *Start, MemoryAccess *ClobberAt, - const MemoryLocation &StartLoc, const MemorySSA &MSSA, - const UpwardsMemoryQuery &Query, AliasAnalysis &AA) { +static void checkClobberSanity(MemoryAccess *Start, MemoryAccess *ClobberAt, + const MemoryLocation &StartLoc, + const MemorySSA &MSSA, + const UpwardsMemoryQuery &Query, + AliasAnalysis &AA) { assert(MSSA.dominates(ClobberAt, Start) && "Clobber doesn't dominate start?"); if (MSSA.isLiveOnEntryDef(Start)) { @@ -429,6 +430,10 @@ // We should never hit liveOnEntry, unless it's the clobber. assert(!MSSA.isLiveOnEntryDef(MA) && "Hit liveOnEntry before clobber?"); + // If Start is a Def, skip self. + if (MA == Start) + continue; + if (auto *MD = dyn_cast(MA)) { (void)MD; assert(!instructionClobbersQuery(MD, MAP.second, Query.Inst, AA) @@ -448,6 +453,19 @@ "ClobberAt never acted as a clobber"); } +static void LLVM_ATTRIBUTE_UNUSED +checkClobberSanityInstruction(Instruction *I, const MemorySSA &MSSA) { + auto Loc = MemoryLocation::getOrNone(I); + if (Loc == None) + return; + if (auto *UseOrDef = + dyn_cast_or_null(MSSA.getMemoryAccess(I))) { + auto *Clobber = MSSA.getWalker()->getClobberingMemoryAccess(I); + UpwardsMemoryQuery Q(I, UseOrDef); + checkClobberSanity(UseOrDef, Clobber, *Loc, MSSA, Q, *MSSA.getAA()); + } +} + namespace { /// Our algorithm for walking (and trying to optimize) clobbers, all wrapped up @@ -923,7 +941,7 @@ MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, UpwardsMemoryQuery &); public: - CachingWalker(MemorySSA *, AliasAnalysis *, DominatorTree *); + CachingWalker(const MemorySSA *, AliasAnalysis *, DominatorTree *); ~CachingWalker() override = default; using MemorySSAWalker::getClobberingMemoryAccess; @@ -1399,9 +1417,9 @@ markUnreachableAsLiveOnEntry(&BB); } -MemorySSAWalker *MemorySSA::getWalker() { return getWalkerImpl(); } +MemorySSAWalker *MemorySSA::getWalker() const { return getWalkerImpl(); } -MemorySSA::CachingWalker *MemorySSA::getWalkerImpl() { +MemorySSA::CachingWalker *MemorySSA::getWalkerImpl() const { if (Walker) return Walker.get(); @@ -1409,6 +1427,8 @@ return Walker.get(); } +AliasAnalysis *MemorySSA::getAA() const { return AA; } + // 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. @@ -1683,6 +1703,30 @@ verifyOrdering(F); verifyDominationNumbers(F); Walker->verify(this); + verifyClobberSanity(F); +} + +/// Check sanity of the clobbering instruction for I. +void MemorySSA::checkClobberSanityInstruction(Instruction *I) { + ::checkClobberSanityInstruction(I, *this); +} + +/// Check sanity of the clobbering instruction for access MA. +void MemorySSA::checkClobberSanityAccess(const MemoryAccess *MA) const { + if (auto *MUD = dyn_cast(MA)) + ::checkClobberSanityInstruction(MUD->getMemoryInst(), *this); +} + +void MemorySSA::verifyClobberSanity(const Function &F) const { +#if !defined(NDEBUG) && defined(EXPENSIVE_CHECKS) + for (const BasicBlock &BB : F) { + const AccessList *Accesses = getBlockAccesses(&BB); + if (!Accesses) + continue; + for (const MemoryAccess &MA : *Accesses) + checkClobberSanityAccess(&MA); + } +#endif } /// Verify that all of the blocks we believe to have valid domination numbers @@ -2076,9 +2120,9 @@ MSSA->print(OS); } -MemorySSAWalker::MemorySSAWalker(MemorySSA *M) : MSSA(M) {} +MemorySSAWalker::MemorySSAWalker(const MemorySSA *M) : MSSA(M) {} -MemorySSA::CachingWalker::CachingWalker(MemorySSA *M, AliasAnalysis *A, +MemorySSA::CachingWalker::CachingWalker(const MemorySSA *M, AliasAnalysis *A, DominatorTree *D) : MemorySSAWalker(M), Walker(*M, *A, *D) {}