diff options
author | David Sherwood <david.sherwood@arm.com> | 2025-01-15 13:56:42 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-15 13:56:42 +0000 |
commit | a00938eedd4246c4252ce3e69a05c4b6760983a3 (patch) | |
tree | 4d737409ae08539c7a7b9630eae20b5d3d633d1b /llvm/lib/Analysis/Loads.cpp | |
parent | 6ca560a9092e29c9f9817db6d6da09edd5f0ded7 (diff) | |
download | llvm-a00938eedd4246c4252ce3e69a05c4b6760983a3.zip llvm-a00938eedd4246c4252ce3e69a05c4b6760983a3.tar.gz llvm-a00938eedd4246c4252ce3e69a05c4b6760983a3.tar.bz2 |
Revert "[LoopVectorize] Add support for reverse loops in isDereferenceableAndAlignedInLoop (#96752)" (#123057)
This reverts commit bfedf6460c2cad6e6f966b457d8d27084579dcd8.
Diffstat (limited to 'llvm/lib/Analysis/Loads.cpp')
-rw-r--r-- | llvm/lib/Analysis/Loads.cpp | 109 |
1 files changed, 52 insertions, 57 deletions
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index cc67602..7bbd469 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -13,7 +13,6 @@ #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumeBundleQueries.h" -#include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/MemoryLocation.h" @@ -276,88 +275,84 @@ static bool AreEquivalentAddressValues(const Value *A, const Value *B) { bool llvm::isDereferenceableAndAlignedInLoop( LoadInst *LI, Loop *L, ScalarEvolution &SE, DominatorTree &DT, AssumptionCache *AC, SmallVectorImpl<const SCEVPredicate *> *Predicates) { - const Align Alignment = LI->getAlign(); auto &DL = LI->getDataLayout(); Value *Ptr = LI->getPointerOperand(); + APInt EltSize(DL.getIndexTypeSizeInBits(Ptr->getType()), DL.getTypeStoreSize(LI->getType()).getFixedValue()); + const Align Alignment = LI->getAlign(); + + Instruction *HeaderFirstNonPHI = L->getHeader()->getFirstNonPHI(); // If given a uniform (i.e. non-varying) address, see if we can prove the // access is safe within the loop w/o needing predication. if (L->isLoopInvariant(Ptr)) - return isDereferenceableAndAlignedPointer( - Ptr, Alignment, EltSize, DL, L->getHeader()->getFirstNonPHI(), AC, &DT); - - const SCEV *PtrScev = SE.getSCEV(Ptr); - auto *AddRec = dyn_cast<SCEVAddRecExpr>(PtrScev); + return isDereferenceableAndAlignedPointer(Ptr, Alignment, EltSize, DL, + HeaderFirstNonPHI, AC, &DT); - // Check to see if we have a repeating access pattern and it's possible - // to prove all accesses are well aligned. + // Otherwise, check to see if we have a repeating access pattern where we can + // prove that all accesses are well aligned and dereferenceable. + auto *AddRec = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(Ptr)); if (!AddRec || AddRec->getLoop() != L || !AddRec->isAffine()) return false; - auto* Step = dyn_cast<SCEVConstant>(AddRec->getStepRecurrence(SE)); if (!Step) return false; - // For the moment, restrict ourselves to the case where the access size is a - // multiple of the requested alignment and the base is aligned. - // TODO: generalize if a case found which warrants - if (EltSize.urem(Alignment.value()) != 0) + auto TC = SE.getSmallConstantMaxTripCount(L, Predicates); + if (!TC) return false; // TODO: Handle overlapping accesses. - if (EltSize.ugt(Step->getAPInt().abs())) - return false; - - const SCEV *MaxBECount = - SE.getPredicatedConstantMaxBackedgeTakenCount(L, *Predicates); - if (isa<SCEVCouldNotCompute>(MaxBECount)) - return false; - - const auto &[AccessStart, AccessEnd] = getStartAndEndForAccess( - L, PtrScev, LI->getType(), MaxBECount, &SE, nullptr); - if (isa<SCEVCouldNotCompute>(AccessStart) || - isa<SCEVCouldNotCompute>(AccessEnd)) + // We should be computing AccessSize as (TC - 1) * Step + EltSize. + if (EltSize.sgt(Step->getAPInt())) return false; - // Try to get the access size. - const SCEV *PtrDiff = SE.getMinusSCEV(AccessEnd, AccessStart); - APInt MaxPtrDiff = SE.getUnsignedRangeMax(PtrDiff); + // Compute the total access size for access patterns with unit stride and + // patterns with gaps. For patterns with unit stride, Step and EltSize are the + // same. + // For patterns with gaps (i.e. non unit stride), we are + // accessing EltSize bytes at every Step. + APInt AccessSize = TC * Step->getAPInt(); + assert(SE.isLoopInvariant(AddRec->getStart(), L) && + "implied by addrec definition"); Value *Base = nullptr; - APInt AccessSize; - if (const SCEVUnknown *NewBase = dyn_cast<SCEVUnknown>(AccessStart)) { - Base = NewBase->getValue(); - AccessSize = MaxPtrDiff; - } else if (auto *MinAdd = dyn_cast<SCEVAddExpr>(AccessStart)) { - if (MinAdd->getNumOperands() != 2) - return false; - - const auto *Offset = dyn_cast<SCEVConstant>(MinAdd->getOperand(0)); - const auto *NewBase = dyn_cast<SCEVUnknown>(MinAdd->getOperand(1)); - if (!Offset || !NewBase) - return false; - - // The following code below assumes the offset is unsigned, but GEP - // offsets are treated as signed so we can end up with a signed value - // here too. For example, suppose the initial PHI value is (i8 255), - // the offset will be treated as (i8 -1) and sign-extended to (i64 -1). - if (Offset->getAPInt().isNegative()) - return false; + if (auto *StartS = dyn_cast<SCEVUnknown>(AddRec->getStart())) { + Base = StartS->getValue(); + } else if (auto *StartS = dyn_cast<SCEVAddExpr>(AddRec->getStart())) { + // Handle (NewBase + offset) as start value. + const auto *Offset = dyn_cast<SCEVConstant>(StartS->getOperand(0)); + const auto *NewBase = dyn_cast<SCEVUnknown>(StartS->getOperand(1)); + if (StartS->getNumOperands() == 2 && Offset && NewBase) { + // The following code below assumes the offset is unsigned, but GEP + // offsets are treated as signed so we can end up with a signed value + // here too. For example, suppose the initial PHI value is (i8 255), + // the offset will be treated as (i8 -1) and sign-extended to (i64 -1). + if (Offset->getAPInt().isNegative()) + return false; - // For the moment, restrict ourselves to the case where the offset is a - // multiple of the requested alignment and the base is aligned. - // TODO: generalize if a case found which warrants - if (Offset->getAPInt().urem(Alignment.value()) != 0) - return false; + // For the moment, restrict ourselves to the case where the offset is a + // multiple of the requested alignment and the base is aligned. + // TODO: generalize if a case found which warrants + if (Offset->getAPInt().urem(Alignment.value()) != 0) + return false; + Base = NewBase->getValue(); + bool Overflow = false; + AccessSize = AccessSize.uadd_ov(Offset->getAPInt(), Overflow); + if (Overflow) + return false; + } + } - AccessSize = MaxPtrDiff + Offset->getAPInt(); - Base = NewBase->getValue(); - } else + if (!Base) return false; - Instruction *HeaderFirstNonPHI = L->getHeader()->getFirstNonPHI(); + // For the moment, restrict ourselves to the case where the access size is a + // multiple of the requested alignment and the base is aligned. + // TODO: generalize if a case found which warrants + if (EltSize.urem(Alignment.value()) != 0) + return false; return isDereferenceableAndAlignedPointer(Base, Alignment, AccessSize, DL, HeaderFirstNonPHI, AC, &DT); } |