Skip to content

Commit e080366

Browse files
committed
[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.
1 parent 6e94007 commit e080366

File tree

2 files changed

+63
-40
lines changed

2 files changed

+63
-40
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -793,26 +793,6 @@ class AccessAnalysis {
793793

794794
} // end anonymous namespace
795795

796-
/// Check whether a pointer can participate in a runtime bounds check.
797-
/// If \p Assume, try harder to prove that we can compute the bounds of \p Ptr
798-
/// by adding run-time checks (overflow checks) if necessary.
799-
static bool hasComputableBounds(PredicatedScalarEvolution &PSE, Value *Ptr,
800-
const SCEV *PtrScev, Loop *L, bool Assume) {
801-
// The bounds for loop-invariant pointer is trivial.
802-
if (PSE.getSE()->isLoopInvariant(PtrScev, L))
803-
return true;
804-
805-
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrScev);
806-
807-
if (!AR && Assume)
808-
AR = PSE.getAsAddRec(Ptr);
809-
810-
if (!AR)
811-
return false;
812-
813-
return AR->isAffine();
814-
}
815-
816796
/// Try to compute the stride for \p AR. Used by getPtrStride.
817797
static std::optional<int64_t>
818798
getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
@@ -859,21 +839,9 @@ static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR,
859839
PredicatedScalarEvolution &PSE, const Loop *L);
860840

861841
/// Check whether a pointer address cannot wrap.
862-
static bool isNoWrap(PredicatedScalarEvolution &PSE,
863-
const DenseMap<Value *, const SCEV *> &Strides, Value *Ptr,
864-
Type *AccessTy, const Loop *L, bool Assume,
842+
static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
843+
Value *Ptr, Type *AccessTy, const Loop *L, bool Assume,
865844
std::optional<int64_t> Stride = std::nullopt) {
866-
const SCEV *PtrScev = replaceSymbolicStrideSCEV(PSE, Strides, Ptr);
867-
if (PSE.getSE()->isLoopInvariant(PtrScev, L))
868-
return true;
869-
870-
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrScev);
871-
if (!AR) {
872-
if (!Assume)
873-
return false;
874-
AR = PSE.getAsAddRec(Ptr);
875-
}
876-
877845
// The address calculation must not wrap. Otherwise, a dependence could be
878846
// inverted.
879847
if (isNoWrapAddRec(Ptr, AR, PSE, L))
@@ -1143,14 +1111,27 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
11431111
SmallVector<PointerIntPair<const SCEV *, 1, bool>> TranslatedPtrs =
11441112
findForkedPointer(PSE, StridesMap, Ptr, TheLoop);
11451113

1114+
/// Check whether all pointers can participate in a runtime bounds check. They
1115+
/// must either be invariant or AddRecs. If ShouldCheckWrap is true, they also
1116+
/// must not wrap.
11461117
for (auto &P : TranslatedPtrs) {
1147-
if (!hasComputableBounds(PSE, Ptr, P.getPointer(), TheLoop, Assume))
1118+
// The bounds for loop-invariant pointer is trivial.
1119+
if (PSE.getSE()->isLoopInvariant(P.getPointer(), TheLoop))
1120+
continue;
1121+
1122+
const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(P.getPointer());
1123+
if (!AR && Assume)
1124+
AR = PSE.getAsAddRec(Ptr);
1125+
if (!AR || !AR->isAffine())
11481126
return false;
11491127

11501128
// If there's only one option for Ptr, look it up after bounds and wrap
11511129
// checking, because assumptions might have been added to PSE.
1152-
if (TranslatedPtrs.size() == 1)
1153-
P.setPointer(replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr));
1130+
if (TranslatedPtrs.size() == 1) {
1131+
AR =
1132+
cast<SCEVAddRecExpr>(replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr));
1133+
P.setPointer(AR);
1134+
}
11541135

11551136
// When we run after a failing dependency check we have to make sure
11561137
// we don't have wrapping pointers.
@@ -1159,7 +1140,7 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
11591140
if (TranslatedPtrs.size() > 1)
11601141
return false;
11611142

1162-
if (!isNoWrap(PSE, StridesMap, Ptr, AccessTy, TheLoop, Assume))
1143+
if (!isNoWrap(PSE, AR, Ptr, AccessTy, TheLoop, Assume))
11631144
return false;
11641145
}
11651146
}
@@ -1548,7 +1529,7 @@ llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
15481529
if (!ShouldCheckWrap || !Stride)
15491530
return Stride;
15501531

1551-
if (isNoWrap(PSE, StridesMap, Ptr, AccessTy, Lp, Assume, Stride))
1532+
if (isNoWrap(PSE, AR, Ptr, AccessTy, Lp, Assume, Stride))
15521533
return Stride;
15531534

15541535
LLVM_DEBUG(

llvm/test/Analysis/LoopAccessAnalysis/retry-runtime-checks-after-dependence-analysis-forked-pointers.ll

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,52 @@
55
define void @dependency_check_and_runtime_checks_needed_select_of_invariant_ptrs(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
66
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_invariant_ptrs'
77
; CHECK-NEXT: loop:
8-
; CHECK-NEXT: Report: cannot check memory dependencies at runtime
8+
; CHECK-NEXT: Memory dependences are safe with run-time checks
99
; CHECK-NEXT: Dependences:
1010
; CHECK-NEXT: Run-time memory checks:
11+
; CHECK-NEXT: Check 0:
12+
; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]):
13+
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
14+
; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]):
15+
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
16+
; CHECK-NEXT: Check 1:
17+
; CHECK-NEXT: Comparing group ([[GRP1]]):
18+
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
19+
; CHECK-NEXT: Against group ([[GRP3:0x[0-9a-f]+]]):
20+
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
21+
; CHECK-NEXT: Check 2:
22+
; CHECK-NEXT: Comparing group ([[GRP1]]):
23+
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
24+
; CHECK-NEXT: Against group ([[GRP4:0x[0-9a-f]+]]):
25+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
26+
; CHECK-NEXT: Check 3:
27+
; CHECK-NEXT: Comparing group ([[GRP2]]):
28+
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
29+
; CHECK-NEXT: Against group ([[GRP3]]):
30+
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
31+
; CHECK-NEXT: Check 4:
32+
; CHECK-NEXT: Comparing group ([[GRP2]]):
33+
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
34+
; CHECK-NEXT: Against group ([[GRP4]]):
35+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
36+
; CHECK-NEXT: Check 5:
37+
; CHECK-NEXT: Comparing group ([[GRP3]]):
38+
; CHECK-NEXT: %select = select i1 %cmp, ptr %b, ptr %c
39+
; CHECK-NEXT: Against group ([[GRP4]]):
40+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
1141
; CHECK-NEXT: Grouped accesses:
42+
; CHECK-NEXT: Group [[GRP1]]:
43+
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
44+
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
45+
; CHECK-NEXT: Group [[GRP2]]:
46+
; CHECK-NEXT: (Low: %b High: (4 + %b))
47+
; CHECK-NEXT: Member: %b
48+
; CHECK-NEXT: Group [[GRP3]]:
49+
; CHECK-NEXT: (Low: %c High: (4 + %c))
50+
; CHECK-NEXT: Member: %c
51+
; CHECK-NEXT: Group [[GRP4]]:
52+
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
53+
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
1254
; CHECK-EMPTY:
1355
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
1456
; CHECK-NEXT: SCEV assumptions:

0 commit comments

Comments
 (0)