[llvm] e080366 - [LAA] Inline hasComputableBounds in only caller, simplify isNoWrap.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 16 10:57:02 PST 2025
Author: Florian Hahn
Date: 2025-02-16T19:56:13+01:00
New Revision: e080366a76b78a746c53caccf84661b109ccbc20
URL: https://github.com/llvm/llvm-project/commit/e080366a76b78a746c53caccf84661b109ccbc20
DIFF: https://github.com/llvm/llvm-project/commit/e080366a76b78a746c53caccf84661b109ccbc20.diff
LOG: [LAA] Inline hasComputableBounds in only caller, simplify isNoWrap.
Inline hasComputableBounds into createCheckForAccess. This removes a
level of indirection and allows for passing the AddRec directly to
isNoWrap, removing the need to retrieve the AddRec for the pointer
again.
The early continue for invariant SCEVs now also applies to forked
pointers (i.e. when there's more than one entry in TranslatedPtrs) when
ShouldCheckWrap is true, as those trivially won't wrap.
The change is NFC otherwise. replaceSymbolicStrideSCEV is now called
earlier.
Added:
Modified:
llvm/lib/Analysis/LoopAccessAnalysis.cpp
llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index 43380b59ac49f..7d6dbd51a404d 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -793,26 +793,6 @@ class AccessAnalysis {
} // end anonymous namespace
-/// Check whether a pointer can participate in a runtime bounds check.
-/// If \p Assume, try harder to prove that we can compute the bounds of \p Ptr
-/// by adding run-time checks (overflow checks) if necessary.
-static bool hasComputableBounds(PredicatedScalarEvolution &PSE, Value *Ptr,
- const SCEV *PtrScev, Loop *L, bool Assume) {
- // The bounds for loop-invariant pointer is trivial.
- if (PSE.getSE()->isLoopInvariant(PtrScev, L))
- return true;
-
- const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrScev);
-
- if (!AR && Assume)
- AR = PSE.getAsAddRec(Ptr);
-
- if (!AR)
- return false;
-
- return AR->isAffine();
-}
-
/// Try to compute the stride for \p AR. Used by getPtrStride.
static std::optional<int64_t>
getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
@@ -859,21 +839,9 @@ 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, const Loop *L, bool Assume,
+static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
+ Value *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;
-
- 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))
@@ -1143,14 +1111,27 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
SmallVector<PointerIntPair<const SCEV *, 1, bool>> TranslatedPtrs =
findForkedPointer(PSE, StridesMap, Ptr, TheLoop);
+ /// 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) {
- if (!hasComputableBounds(PSE, Ptr, P.getPointer(), TheLoop, Assume))
+ // The bounds for loop-invariant pointer is trivial.
+ if (PSE.getSE()->isLoopInvariant(P.getPointer(), TheLoop))
+ continue;
+
+ const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(P.getPointer());
+ if (!AR && Assume)
+ AR = PSE.getAsAddRec(Ptr);
+ if (!AR || !AR->isAffine())
return false;
// 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)
- P.setPointer(replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr));
+ if (TranslatedPtrs.size() == 1) {
+ AR =
+ cast<SCEVAddRecExpr>(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.
@@ -1159,7 +1140,7 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
if (TranslatedPtrs.size() > 1)
return false;
- if (!isNoWrap(PSE, StridesMap, Ptr, AccessTy, TheLoop, Assume))
+ if (!isNoWrap(PSE, AR, Ptr, AccessTy, TheLoop, Assume))
return false;
}
}
@@ -1548,7 +1529,7 @@ llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
if (!ShouldCheckWrap || !Stride)
return Stride;
- if (isNoWrap(PSE, StridesMap, Ptr, AccessTy, Lp, Assume, Stride))
+ if (isNoWrap(PSE, AR, Ptr, AccessTy, Lp, Assume, Stride))
return Stride;
LLVM_DEBUG(
diff --git a/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll b/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
index 006ce430249fd..5e9dc7f2b91cc 100644
--- a/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
+++ b/llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll
@@ -5,10 +5,52 @@
define void @dependency_check_and_runtime_checks_needed_select_of_invariant_ptrs(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_invariant_ptrs'
; CHECK-NEXT: loop:
-; CHECK-NEXT: Report: cannot check memory dependencies at runtime
+; CHECK-NEXT: Memory dependences are safe with run-time checks
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
+; CHECK-NEXT: Check 0:
+; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]):
+; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
+; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]):
+; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
+; CHECK-NEXT: Check 1:
+; CHECK-NEXT: Comparing group ([[GRP1]]):
+; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
+; CHECK-NEXT: Against group ([[GRP3:0x[0-9a-f]+]]):
+; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
+; CHECK-NEXT: Check 2:
+; CHECK-NEXT: Comparing group ([[GRP1]]):
+; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
+; CHECK-NEXT: Against group ([[GRP4:0x[0-9a-f]+]]):
+; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
+; CHECK-NEXT: Check 3:
+; CHECK-NEXT: Comparing group ([[GRP2]]):
+; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
+; CHECK-NEXT: Against group ([[GRP3]]):
+; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
+; CHECK-NEXT: Check 4:
+; CHECK-NEXT: Comparing group ([[GRP2]]):
+; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
+; CHECK-NEXT: Against group ([[GRP4]]):
+; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
+; CHECK-NEXT: Check 5:
+; CHECK-NEXT: Comparing group ([[GRP3]]):
+; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
+; CHECK-NEXT: Against group ([[GRP4]]):
+; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
; CHECK-NEXT: Grouped accesses:
+; CHECK-NEXT: Group [[GRP1]]:
+; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
+; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
+; CHECK-NEXT: Group [[GRP2]]:
+; CHECK-NEXT: (Low: %b High: (4 + %b))
+; CHECK-NEXT: Member: %b
+; CHECK-NEXT: Group [[GRP3]]:
+; CHECK-NEXT: (Low: %c High: (4 + %c))
+; CHECK-NEXT: Member: %c
+; CHECK-NEXT: Group [[GRP4]]:
+; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
+; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
More information about the llvm-commits
mailing list