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 @@ -88,6 +88,7 @@ #include "llvm/IR/DerivedUser.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/IR/User.h" @@ -1217,9 +1218,40 @@ BasicBlock *getPhiArgBlock() const { return DefIterator.getPhiArgBlock(); } private: + /// Returns true if \p Ptr is guaranteed to be loop invariant for any possible + /// loop. In particular, this guarantees that it only references a single + /// MemoryLocation during execution of the containing function. + bool IsGuaranteedLoopInvariant(Value *Ptr) const { + auto IsGuaranteedLoopInvariantBase = [](Value *Ptr) { + Ptr = Ptr->stripPointerCasts(); + if (auto *I = dyn_cast(Ptr)) { + if (isa(Ptr)) + return true; + return false; + } + return true; + }; + + Ptr = Ptr->stripPointerCasts(); + if (auto *GEP = dyn_cast(Ptr)) { + return IsGuaranteedLoopInvariantBase(GEP->getPointerOperand()) && + GEP->hasAllConstantIndices(); + } + return IsGuaranteedLoopInvariantBase(Ptr); + } + void fillInCurrentPair() { CurrentPair.first = *DefIterator; + CurrentPair.second = Location; if (WalkingPhi && Location.Ptr) { + // Mark size as unknown, if the location is not guaranteed to be + // loop-invariant for any possible loop in the function. Setting the size + // to unknown guarantees that any memory accesses that access locations + // after the pointer are considered as clobbers, which is important to + // catch loop carried dependences. + if (Location.Ptr && + !IsGuaranteedLoopInvariant(const_cast(Location.Ptr))) + CurrentPair.second = Location.getWithNewSize(LocationSize::unknown()); PHITransAddr Translator( const_cast(Location.Ptr), OriginalAccess->getBlock()->getModule()->getDataLayout(), nullptr); @@ -1227,17 +1259,13 @@ DefIterator.getPhiArgBlock(), DT, true)) { if (Translator.getAddr() != Location.Ptr) { - CurrentPair.second = Location.getWithNewPtr(Translator.getAddr()); + CurrentPair.second = Location.getWithNewPtr(Translator.getAddr()) + .getWithNewSize(LocationSize::unknown()); if (PerformedPhiTranslation) *PerformedPhiTranslation = true; - return; } - } else { - CurrentPair.second = Location.getWithNewSize(LocationSize::unknown()); - return; } } - CurrentPair.second = Location; } MemoryAccessPair CurrentPair; diff --git a/llvm/test/Analysis/MemorySSA/phi-translation.ll b/llvm/test/Analysis/MemorySSA/phi-translation.ll --- a/llvm/test/Analysis/MemorySSA/phi-translation.ll +++ b/llvm/test/Analysis/MemorySSA/phi-translation.ll @@ -481,8 +481,7 @@ ; CHECK-NEXT: ; 4 = MemoryPhi({entry,1},{cond.read,3}) ; CHECK-LABEL: cond.read: -; NOLIMIT: ; MemoryUse(liveOnEntry) -; LIMIT: ; MemoryUse(4) +; CHECK: ; MemoryUse(4) ; CHECK-NEXT: %use = load i32, i32* %ptr.1, align 4 ; CHECK-NEXT: ; 2 = MemoryDef(4) ; CHECK-NEXT: %c.2 = call i1 @cond(i32 %use)