diff options
Diffstat (limited to 'llvm/lib/Analysis/LoopAccessAnalysis.cpp')
-rw-r--r-- | llvm/lib/Analysis/LoopAccessAnalysis.cpp | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index cd1294b..0ee4b83 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -855,16 +855,61 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy, return Stride; } +static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR, + PredicatedScalarEvolution &PSE, const Loop *L); + /// Check whether a pointer address cannot wrap. static bool isNoWrap(PredicatedScalarEvolution &PSE, const DenseMap<Value *, const SCEV *> &Strides, Value *Ptr, - Type *AccessTy, Loop *L, bool Assume) { - const SCEV *PtrScev = PSE.getSCEV(Ptr); + Type *AccessTy, const Loop *L, bool Assume, + std::optional<int64_t> Stride = std::nullopt) { + const SCEV *PtrScev = replaceSymbolicStrideSCEV(PSE, Strides, Ptr); if (PSE.getSE()->isLoopInvariant(PtrScev, L)) return true; - return getPtrStride(PSE, AccessTy, Ptr, L, Strides, Assume).has_value() || - PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW); + const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrScev); + if (!AR) { + if (!Assume) + return false; + AR = PSE.getAsAddRec(Ptr); + } + + // The address calculation must not wrap. Otherwise, a dependence could be + // inverted. + if (isNoWrapAddRec(Ptr, AR, PSE, L)) + return true; + + // An nusw getelementptr that is an AddRec cannot wrap. If it would wrap, + // the distance between the previously accessed location and the wrapped + // location will be larger than half the pointer index type space. In that + // case, the GEP would be poison and any memory access dependent on it would + // be immediate UB when executed. + if (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr); + GEP && GEP->hasNoUnsignedSignedWrap()) + return true; + + if (!Stride) + Stride = getStrideFromAddRec(AR, L, AccessTy, Ptr, PSE); + if (Stride) { + // If the null pointer is undefined, then a access sequence which would + // otherwise access it can be assumed not to unsigned wrap. Note that this + // assumes the object in memory is aligned to the natural alignment. + unsigned AddrSpace = Ptr->getType()->getPointerAddressSpace(); + if (!NullPointerIsDefined(L->getHeader()->getParent(), AddrSpace) && + (Stride == 1 || Stride == -1)) + return true; + } + + if (Assume) { + PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW); + LLVM_DEBUG(dbgs() << "LAA: Pointer may wrap:\n" + << "LAA: Pointer: " << *Ptr << "\n" + << "LAA: SCEV: " << *AR << "\n" + << "LAA: Added an overflow assumption\n"); + return true; + } + + return PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW); } static void visitPointers(Value *StartPtr, const Loop &InnermostLoop, @@ -1505,36 +1550,9 @@ llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr, if (!ShouldCheckWrap || !Stride) return Stride; - // The address calculation must not wrap. Otherwise, a dependence could be - // inverted. - if (isNoWrapAddRec(Ptr, AR, PSE, Lp)) - return Stride; - - // An nusw getelementptr that is an AddRec cannot wrap. If it would wrap, - // the distance between the previously accessed location and the wrapped - // location will be larger than half the pointer index type space. In that - // case, the GEP would be poison and any memory access dependent on it would - // be immediate UB when executed. - if (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr); - GEP && GEP->hasNoUnsignedSignedWrap()) - return Stride; - - // If the null pointer is undefined, then a access sequence which would - // otherwise access it can be assumed not to unsigned wrap. Note that this - // assumes the object in memory is aligned to the natural alignment. - unsigned AddrSpace = Ty->getPointerAddressSpace(); - if (!NullPointerIsDefined(Lp->getHeader()->getParent(), AddrSpace) && - (Stride == 1 || Stride == -1)) + if (isNoWrap(PSE, StridesMap, Ptr, AccessTy, Lp, Assume, Stride)) return Stride; - if (Assume) { - PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW); - LLVM_DEBUG(dbgs() << "LAA: Pointer may wrap:\n" - << "LAA: Pointer: " << *Ptr << "\n" - << "LAA: SCEV: " << *AR << "\n" - << "LAA: Added an overflow assumption\n"); - return Stride; - } LLVM_DEBUG( dbgs() << "LAA: Bad stride - Pointer may wrap in the address space " << *Ptr << " SCEV: " << *AR << "\n"); |