From d50151b89cbc9fc11ac4b3b2c84e8301129a09d4 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 4 Sep 2025 17:20:42 +0100 Subject: [PATCH 1/3] [LAA] Strip findForkedPointer (NFC) Remove a level of indirection due to findForkedPointer, in an effort to improve code. --- llvm/lib/Analysis/LoopAccessAnalysis.cpp | 71 +++++++++++------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index cfddd9980c86b..30e96d83a107d 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -1231,48 +1231,44 @@ static void findForkedSCEVs( } } -static SmallVector> -findForkedPointer(PredicatedScalarEvolution &PSE, - const DenseMap &StridesMap, Value *Ptr, - const Loop *L) { - ScalarEvolution *SE = PSE.getSE(); - assert(SE->isSCEVable(Ptr->getType()) && "Value is not SCEVable!"); - SmallVector> Scevs; - findForkedSCEVs(SE, L, Ptr, Scevs, MaxForkedSCEVDepth); - - // For now, we will only accept a forked pointer with two possible SCEVs - // that are either SCEVAddRecExprs or loop invariant. - if (Scevs.size() == 2 && - (isa(get<0>(Scevs[0])) || - SE->isLoopInvariant(get<0>(Scevs[0]), L)) && - (isa(get<0>(Scevs[1])) || - SE->isLoopInvariant(get<0>(Scevs[1]), L))) { - LLVM_DEBUG(dbgs() << "LAA: Found forked pointer: " << *Ptr << "\n"); - LLVM_DEBUG(dbgs() << "\t(1) " << *get<0>(Scevs[0]) << "\n"); - LLVM_DEBUG(dbgs() << "\t(2) " << *get<0>(Scevs[1]) << "\n"); - return Scevs; - } - - return {{replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr), false}}; -} - bool AccessAnalysis::createCheckForAccess( RuntimePointerChecking &RtCheck, MemAccessInfo Access, Type *AccessTy, const DenseMap &StridesMap, DenseMap &DepSetId, Loop *TheLoop, unsigned &RunningDepId, unsigned ASId, bool Assume) { Value *Ptr = Access.getPointer(); + ScalarEvolution *SE = PSE.getSE(); + assert(SE->isSCEVable(Ptr->getType()) && "Value is not SCEVable!"); + + SmallVector> RTCheckPtrs; + findForkedSCEVs(SE, TheLoop, Ptr, RTCheckPtrs, MaxForkedSCEVDepth); + assert(!RTCheckPtrs.empty() && + "Must have some runtime-check pointer candidates"); - SmallVector> TranslatedPtrs = - findForkedPointer(PSE, StridesMap, Ptr, TheLoop); - assert(!TranslatedPtrs.empty() && "must have some translated pointers"); + auto IsLoopInvariantOrAR = + [&SE, &TheLoop](const PointerIntPair &P) { + return SE->isLoopInvariant(get<0>(P), TheLoop) || + isa(get<0>(P)); + }; + + // RTCheckPtrs must have size 2 if there are forked pointers. Otherwise, there + // are no forked pointers; replaceSymbolicStridesSCEV in this case. + if (RTCheckPtrs.size() == 2 && all_of(RTCheckPtrs, IsLoopInvariantOrAR)) { + LLVM_DEBUG(dbgs() << "LAA: Found forked pointer: " << *Ptr << "\n"); + for (auto [Idx, Q] : enumerate(RTCheckPtrs)) + LLVM_DEBUG(dbgs() << "\t(" << Idx << ") " << *Q.getPointer() << "\n"); + } else { + RTCheckPtrs.truncate(1); + RTCheckPtrs.front().setPointer( + replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr)); + RTCheckPtrs.front().setInt(false); + } /// Check whether all pointers can participate in a runtime bounds check. They - /// must either be invariant or AddRecs. If ShouldCheckWrap is true, they also - /// must not wrap. - for (auto &P : TranslatedPtrs) { + /// must either be invariant or non-wrapping affine AddRecs. + for (auto &P : RTCheckPtrs) { // The bounds for loop-invariant pointer is trivial. - if (PSE.getSE()->isLoopInvariant(P.getPointer(), TheLoop)) + if (SE->isLoopInvariant(P.getPointer(), TheLoop)) continue; const SCEVAddRecExpr *AR = dyn_cast(P.getPointer()); @@ -1283,21 +1279,18 @@ bool AccessAnalysis::createCheckForAccess( // If there's only one option for Ptr, look it up after bounds and wrap // checking, because assumptions might have been added to PSE. - if (TranslatedPtrs.size() == 1) { + if (RTCheckPtrs.size() == 1) { AR = cast(replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr)); P.setPointer(AR); } - // When we run after a failing dependency check we have to make sure - // we don't have wrapping pointers. - if (!isNoWrap(PSE, AR, TranslatedPtrs.size() == 1 ? Ptr : nullptr, AccessTy, - TheLoop, Assume)) { + if (!isNoWrap(PSE, AR, RTCheckPtrs.size() == 1 ? Ptr : nullptr, AccessTy, + TheLoop, Assume)) return false; - } } - for (auto [PtrExpr, NeedsFreeze] : TranslatedPtrs) { + for (const auto &[PtrExpr, NeedsFreeze] : RTCheckPtrs) { // The id of the dependence set. unsigned DepId; From bc4fc4ef6c678e62964f8faba45a4e0b6f9585da Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Fri, 5 Sep 2025 10:13:58 +0100 Subject: [PATCH 2/3] [LAA] Address review --- llvm/lib/Analysis/LoopAccessAnalysis.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index 30e96d83a107d..da8a15e839a53 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -1245,23 +1245,19 @@ bool AccessAnalysis::createCheckForAccess( assert(!RTCheckPtrs.empty() && "Must have some runtime-check pointer candidates"); + // RTCheckPtrs must have size 2 if there are forked pointers. Otherwise, there + // are no forked pointers; replaceSymbolicStridesSCEV in this case. auto IsLoopInvariantOrAR = [&SE, &TheLoop](const PointerIntPair &P) { return SE->isLoopInvariant(get<0>(P), TheLoop) || isa(get<0>(P)); }; - - // RTCheckPtrs must have size 2 if there are forked pointers. Otherwise, there - // are no forked pointers; replaceSymbolicStridesSCEV in this case. if (RTCheckPtrs.size() == 2 && all_of(RTCheckPtrs, IsLoopInvariantOrAR)) { LLVM_DEBUG(dbgs() << "LAA: Found forked pointer: " << *Ptr << "\n"); for (auto [Idx, Q] : enumerate(RTCheckPtrs)) LLVM_DEBUG(dbgs() << "\t(" << Idx << ") " << *Q.getPointer() << "\n"); } else { - RTCheckPtrs.truncate(1); - RTCheckPtrs.front().setPointer( - replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr)); - RTCheckPtrs.front().setInt(false); + RTCheckPtrs = {{replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr), false}}; } /// Check whether all pointers can participate in a runtime bounds check. They From dc1e6dffde265b877d59e40158756c40eb711ae9 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Tue, 9 Sep 2025 14:31:58 +0100 Subject: [PATCH 3/3] [LAA] Fix some nits --- llvm/lib/Analysis/LoopAccessAnalysis.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index da8a15e839a53..87fae92977cd2 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -1249,13 +1249,13 @@ bool AccessAnalysis::createCheckForAccess( // are no forked pointers; replaceSymbolicStridesSCEV in this case. auto IsLoopInvariantOrAR = [&SE, &TheLoop](const PointerIntPair &P) { - return SE->isLoopInvariant(get<0>(P), TheLoop) || - isa(get<0>(P)); + return SE->isLoopInvariant(P.getPointer(), TheLoop) || + isa(P.getPointer()); }; if (RTCheckPtrs.size() == 2 && all_of(RTCheckPtrs, IsLoopInvariantOrAR)) { - LLVM_DEBUG(dbgs() << "LAA: Found forked pointer: " << *Ptr << "\n"); - for (auto [Idx, Q] : enumerate(RTCheckPtrs)) - LLVM_DEBUG(dbgs() << "\t(" << Idx << ") " << *Q.getPointer() << "\n"); + LLVM_DEBUG(dbgs() << "LAA: Found forked pointer: " << *Ptr << "\n"; + for (const auto &[Idx, Q] : enumerate(RTCheckPtrs)) dbgs() + << "\t(" << Idx << ") " << *Q.getPointer() << "\n"); } else { RTCheckPtrs = {{replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr), false}}; }