Skip to content

Commit 34e3b23

Browse files
committed
[LAA] Always require non-wrapping pointers for runtime checks.
Currently we only check if the pointers involved in runtime checks do not wrap if we need to perform dependency checks. If that's not the case, we generate runtime checks, even if the pointers may wrap (see test/Analysis/LoopAccessAnalysis/runtime-checks-may-wrap.ll). I might be missing something, but at least for the test it doesn't seem correct to ignore wrapping pointers. If the pointer wraps, then we swap start and end of the runtime check. An Alive2 proof of what the runtime checks are checking conceptually (on i4 to have it complete in reasonable time) showing the incorrect result should be https://alive2.llvm.org/ce/z/KsHzn8 Depends on #127410 to avoid more regressions.
1 parent 25849ac commit 34e3b23

8 files changed

+153
-101
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -679,16 +679,17 @@ class AccessAnalysis {
679679
const DenseMap<Value *, const SCEV *> &Strides,
680680
DenseMap<Value *, unsigned> &DepSetId,
681681
Loop *TheLoop, unsigned &RunningDepId,
682-
unsigned ASId, bool ShouldCheckStride, bool Assume);
682+
unsigned ASId, bool Assume);
683683

684684
/// Check whether we can check the pointers at runtime for
685685
/// non-intersection.
686686
///
687687
/// Returns true if we need no check or if we do and we can generate them
688688
/// (i.e. the pointers have computable bounds).
689689
bool canCheckPtrAtRT(RuntimePointerChecking &RtCheck, ScalarEvolution *SE,
690-
Loop *TheLoop, const DenseMap<Value *, const SCEV *> &Strides,
691-
Value *&UncomputablePtr, bool ShouldCheckWrap = false);
690+
Loop *TheLoop,
691+
const DenseMap<Value *, const SCEV *> &Strides,
692+
Value *&UncomputablePtr);
692693

693694
/// Goes over all memory accesses, checks whether a RT check is needed
694695
/// and builds sets of dependent accesses.
@@ -1117,13 +1118,11 @@ findForkedPointer(PredicatedScalarEvolution &PSE,
11171118
return {{replaceSymbolicStrideSCEV(PSE, StridesMap, Ptr), false}};
11181119
}
11191120

1120-
bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
1121-
MemAccessInfo Access, Type *AccessTy,
1122-
const DenseMap<Value *, const SCEV *> &StridesMap,
1123-
DenseMap<Value *, unsigned> &DepSetId,
1124-
Loop *TheLoop, unsigned &RunningDepId,
1125-
unsigned ASId, bool ShouldCheckWrap,
1126-
bool Assume) {
1121+
bool AccessAnalysis::createCheckForAccess(
1122+
RuntimePointerChecking &RtCheck, MemAccessInfo Access, Type *AccessTy,
1123+
const DenseMap<Value *, const SCEV *> &StridesMap,
1124+
DenseMap<Value *, unsigned> &DepSetId, Loop *TheLoop,
1125+
unsigned &RunningDepId, unsigned ASId, bool Assume) {
11271126
Value *Ptr = Access.getPointer();
11281127

11291128
SmallVector<PointerIntPair<const SCEV *, 1, bool>> TranslatedPtrs =
@@ -1153,8 +1152,7 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
11531152

11541153
// When we run after a failing dependency check we have to make sure
11551154
// we don't have wrapping pointers.
1156-
if (ShouldCheckWrap &&
1157-
!isNoWrap(PSE, AR, TranslatedPtrs.size() == 1 ? Ptr : nullptr, AccessTy,
1155+
if (!isNoWrap(PSE, AR, TranslatedPtrs.size() == 1 ? Ptr : nullptr, AccessTy,
11581156
TheLoop, Assume)) {
11591157
return false;
11601158
}
@@ -1183,10 +1181,10 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
11831181
return true;
11841182
}
11851183

1186-
bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
1187-
ScalarEvolution *SE, Loop *TheLoop,
1188-
const DenseMap<Value *, const SCEV *> &StridesMap,
1189-
Value *&UncomputablePtr, bool ShouldCheckWrap) {
1184+
bool AccessAnalysis::canCheckPtrAtRT(
1185+
RuntimePointerChecking &RtCheck, ScalarEvolution *SE, Loop *TheLoop,
1186+
const DenseMap<Value *, const SCEV *> &StridesMap,
1187+
Value *&UncomputablePtr) {
11901188
// Find pointers with computable bounds. We are going to use this information
11911189
// to place a runtime bound check.
11921190
bool CanDoRT = true;
@@ -1246,7 +1244,7 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
12461244
for (const auto &AccessTy : Accesses[Access]) {
12471245
if (!createCheckForAccess(RtCheck, Access, AccessTy, StridesMap,
12481246
DepSetId, TheLoop, RunningDepId, ASId,
1249-
ShouldCheckWrap, false)) {
1247+
false)) {
12501248
LLVM_DEBUG(dbgs() << "LAA: Can't find bounds for ptr:"
12511249
<< *Access.getPointer() << '\n');
12521250
Retries.emplace_back(Access, AccessTy);
@@ -1276,7 +1274,7 @@ bool AccessAnalysis::canCheckPtrAtRT(RuntimePointerChecking &RtCheck,
12761274
for (const auto &[Access, AccessTy] : Retries) {
12771275
if (!createCheckForAccess(RtCheck, Access, AccessTy, StridesMap,
12781276
DepSetId, TheLoop, RunningDepId, ASId,
1279-
ShouldCheckWrap, /*Assume=*/true)) {
1277+
/*Assume=*/true)) {
12801278
CanDoAliasSetRT = false;
12811279
UncomputablePtr = Access.getPointer();
12821280
break;
@@ -2646,9 +2644,8 @@ bool LoopAccessInfo::analyzeLoop(AAResults *AA, const LoopInfo *LI,
26462644
// Find pointers with computable bounds. We are going to use this information
26472645
// to place a runtime bound check.
26482646
Value *UncomputablePtr = nullptr;
2649-
bool CanDoRTIfNeeded =
2650-
Accesses.canCheckPtrAtRT(*PtrRtChecking, PSE->getSE(), TheLoop,
2651-
SymbolicStrides, UncomputablePtr, false);
2647+
bool CanDoRTIfNeeded = Accesses.canCheckPtrAtRT(
2648+
*PtrRtChecking, PSE->getSE(), TheLoop, SymbolicStrides, UncomputablePtr);
26522649
if (!CanDoRTIfNeeded) {
26532650
const auto *I = dyn_cast_or_null<Instruction>(UncomputablePtr);
26542651
recordAnalysis("CantIdentifyArrayBounds", I)
@@ -2679,7 +2676,7 @@ bool LoopAccessInfo::analyzeLoop(AAResults *AA, const LoopInfo *LI,
26792676
auto *SE = PSE->getSE();
26802677
UncomputablePtr = nullptr;
26812678
CanDoRTIfNeeded = Accesses.canCheckPtrAtRT(
2682-
*PtrRtChecking, SE, TheLoop, SymbolicStrides, UncomputablePtr, true);
2679+
*PtrRtChecking, SE, TheLoop, SymbolicStrides, UncomputablePtr);
26832680

26842681
// Check that we found the bounds for the pointer.
26852682
if (!CanDoRTIfNeeded) {

llvm/test/Analysis/LoopAccessAnalysis/nusw-predicates.ll

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ define void @int_and_pointer_predicate(ptr %v, i32 %N) {
1515
; CHECK-EMPTY:
1616
; CHECK-NEXT: Run-time memory checks:
1717
; CHECK-NEXT: Grouped accesses:
18+
; CHECK-NEXT: Group [[GRP1:0x[0-9a-f]+]]:
19+
; CHECK-NEXT: (Low: %v High: (2 + %v))
20+
; CHECK-NEXT: Member: %v
21+
; CHECK-NEXT: Group [[GRP2:0x[0-9a-f]+]]:
22+
; CHECK-NEXT: (Low: %v High: (6 + (4 * (trunc i32 %N to i16)) + %v))
23+
; CHECK-NEXT: Member: {%v,+,4}<%loop>
1824
; CHECK-EMPTY:
1925
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
2026
; CHECK-NEXT: SCEV assumptions:
@@ -57,36 +63,36 @@ define void @int_and_multiple_pointer_predicates(ptr %v, ptr %w, i32 %N) {
5763
; CHECK-EMPTY:
5864
; CHECK-NEXT: Run-time memory checks:
5965
; CHECK-NEXT: Check 0:
60-
; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]):
66+
; CHECK-NEXT: Comparing group ([[GRP3:0x[0-9a-f]+]]):
6167
; CHECK-NEXT: ptr %v
62-
; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]):
68+
; CHECK-NEXT: Against group ([[GRP4:0x[0-9a-f]+]]):
6369
; CHECK-NEXT: ptr %w
6470
; CHECK-NEXT: Check 1:
65-
; CHECK-NEXT: Comparing group ([[GRP1]]):
71+
; CHECK-NEXT: Comparing group ([[GRP3]]):
6672
; CHECK-NEXT: ptr %v
67-
; CHECK-NEXT: Against group ([[GRP3:0x[0-9a-f]+]]):
73+
; CHECK-NEXT: Against group ([[GRP5:0x[0-9a-f]+]]):
6874
; CHECK-NEXT: %gep.w = getelementptr { i16, i16 }, ptr %w, i16 %iv.i16
6975
; CHECK-NEXT: Check 2:
70-
; CHECK-NEXT: Comparing group ([[GRP4:0x[0-9a-f]+]]):
76+
; CHECK-NEXT: Comparing group ([[GRP6:0x[0-9a-f]+]]):
7177
; CHECK-NEXT: %gep.v = getelementptr { i16, i16 }, ptr %v, i16 %iv.i16
72-
; CHECK-NEXT: Against group ([[GRP2]]):
78+
; CHECK-NEXT: Against group ([[GRP4]]):
7379
; CHECK-NEXT: ptr %w
7480
; CHECK-NEXT: Check 3:
75-
; CHECK-NEXT: Comparing group ([[GRP4]]):
81+
; CHECK-NEXT: Comparing group ([[GRP6]]):
7682
; CHECK-NEXT: %gep.v = getelementptr { i16, i16 }, ptr %v, i16 %iv.i16
77-
; CHECK-NEXT: Against group ([[GRP3]]):
83+
; CHECK-NEXT: Against group ([[GRP5]]):
7884
; CHECK-NEXT: %gep.w = getelementptr { i16, i16 }, ptr %w, i16 %iv.i16
7985
; CHECK-NEXT: Grouped accesses:
80-
; CHECK-NEXT: Group [[GRP1]]:
86+
; CHECK-NEXT: Group [[GRP3]]:
8187
; CHECK-NEXT: (Low: %v High: (2 + %v))
8288
; CHECK-NEXT: Member: %v
83-
; CHECK-NEXT: Group [[GRP4]]:
89+
; CHECK-NEXT: Group [[GRP6]]:
8490
; CHECK-NEXT: (Low: %v High: (6 + (4 * (trunc i32 %N to i16)) + %v))
8591
; CHECK-NEXT: Member: {%v,+,4}<%loop>
86-
; CHECK-NEXT: Group [[GRP2]]:
92+
; CHECK-NEXT: Group [[GRP4]]:
8793
; CHECK-NEXT: (Low: %w High: (2 + %w))
8894
; CHECK-NEXT: Member: %w
89-
; CHECK-NEXT: Group [[GRP3]]:
95+
; CHECK-NEXT: Group [[GRP5]]:
9096
; CHECK-NEXT: (Low: %w High: (6 + (4 * (trunc i32 %N to i16)) + %w))
9197
; CHECK-NEXT: Member: {%w,+,4}<%loop>
9298
; CHECK-EMPTY:

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ exit:
163163
define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_may_wrap_1(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
164164
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_may_wrap_1'
165165
; CHECK-NEXT: loop:
166-
; CHECK-NEXT: Report: cannot check memory dependencies at runtime
166+
; CHECK-NEXT: Report: cannot identify array bounds
167167
; CHECK-NEXT: Dependences:
168168
; CHECK-NEXT: Run-time memory checks:
169169
; CHECK-NEXT: Grouped accesses:
@@ -204,7 +204,7 @@ exit:
204204
define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_may_wrap_2(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
205205
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs_may_wrap_2'
206206
; CHECK-NEXT: loop:
207-
; CHECK-NEXT: Report: cannot check memory dependencies at runtime
207+
; CHECK-NEXT: Report: cannot identify array bounds
208208
; CHECK-NEXT: Dependences:
209209
; CHECK-NEXT: Run-time memory checks:
210210
; CHECK-NEXT: Grouped accesses:

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,27 +72,27 @@ define void @dependency_check_and_runtime_checks_needed_gepb_not_inbounds_iv2_st
7272
; CHECK-NEXT: Comparing group ([[GRP4:0x[0-9a-f]+]]):
7373
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
7474
; CHECK-NEXT: Against group ([[GRP5:0x[0-9a-f]+]]):
75-
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
75+
; CHECK-NEXT: %gep.b = getelementptr i8, ptr %b, i64 %iv2
7676
; CHECK-NEXT: Check 1:
7777
; CHECK-NEXT: Comparing group ([[GRP4]]):
7878
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
7979
; CHECK-NEXT: Against group ([[GRP6:0x[0-9a-f]+]]):
80-
; CHECK-NEXT: %gep.b = getelementptr i8, ptr %b, i64 %iv2
80+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
8181
; CHECK-NEXT: Check 2:
8282
; CHECK-NEXT: Comparing group ([[GRP5]]):
83-
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
84-
; CHECK-NEXT: Against group ([[GRP6]]):
8583
; CHECK-NEXT: %gep.b = getelementptr i8, ptr %b, i64 %iv2
84+
; CHECK-NEXT: Against group ([[GRP6]]):
85+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
8686
; CHECK-NEXT: Grouped accesses:
8787
; CHECK-NEXT: Group [[GRP4]]:
8888
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
8989
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
9090
; CHECK-NEXT: Group [[GRP5]]:
91-
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
92-
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
93-
; CHECK-NEXT: Group [[GRP6]]:
9491
; CHECK-NEXT: (Low: %b High: (-1 + (5 * %n) + %b))
9592
; CHECK-NEXT: Member: {%b,+,5}<%loop>
93+
; CHECK-NEXT: Group [[GRP6]]:
94+
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
95+
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
9696
; CHECK-EMPTY:
9797
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
9898
; CHECK-NEXT: SCEV assumptions:
@@ -265,27 +265,27 @@ define void @dependency_check_and_runtime_checks_needed_gepb_may_wrap(ptr %a, pt
265265
; CHECK-NEXT: Comparing group ([[GRP13:0x[0-9a-f]+]]):
266266
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
267267
; CHECK-NEXT: Against group ([[GRP14:0x[0-9a-f]+]]):
268-
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
268+
; CHECK-NEXT: %gep.b = getelementptr float, ptr %b, i64 %iv2
269269
; CHECK-NEXT: Check 1:
270270
; CHECK-NEXT: Comparing group ([[GRP13]]):
271271
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
272272
; CHECK-NEXT: Against group ([[GRP15:0x[0-9a-f]+]]):
273-
; CHECK-NEXT: %gep.b = getelementptr float, ptr %b, i64 %iv2
273+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
274274
; CHECK-NEXT: Check 2:
275275
; CHECK-NEXT: Comparing group ([[GRP14]]):
276-
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
277-
; CHECK-NEXT: Against group ([[GRP15]]):
278276
; CHECK-NEXT: %gep.b = getelementptr float, ptr %b, i64 %iv2
277+
; CHECK-NEXT: Against group ([[GRP15]]):
278+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
279279
; CHECK-NEXT: Grouped accesses:
280280
; CHECK-NEXT: Group [[GRP13]]:
281281
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
282282
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
283283
; CHECK-NEXT: Group [[GRP14]]:
284-
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
285-
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
286-
; CHECK-NEXT: Group [[GRP15]]:
287284
; CHECK-NEXT: (Low: %b High: (-4 + (8 * %n) + %b))
288285
; CHECK-NEXT: Member: {%b,+,8}<%loop>
286+
; CHECK-NEXT: Group [[GRP15]]:
287+
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
288+
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
289289
; CHECK-EMPTY:
290290
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
291291
; CHECK-NEXT: SCEV assumptions:

llvm/test/Analysis/LoopAccessAnalysis/runtime-checks-may-wrap.ll

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,21 @@ define void @geps_may_wrap(ptr %a, ptr %b, i64 %N) {
1111
; CHECK-NEXT: Run-time memory checks:
1212
; CHECK-NEXT: Check 0:
1313
; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]):
14-
; CHECK-NEXT: %gep.iv = getelementptr i32, ptr %a, i64 %iv
15-
; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]):
1614
; CHECK-NEXT: ptr %b
15+
; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]):
16+
; CHECK-NEXT: %gep.iv = getelementptr i32, ptr %a, i64 %iv
1717
; CHECK-NEXT: Grouped accesses:
1818
; CHECK-NEXT: Group [[GRP1]]:
19-
; CHECK-NEXT: (Low: %a High: (16 + (12 * (trunc i128 ((zext i64 %N to i128) /u 3) to i16)) + %a))
20-
; CHECK-NEXT: Member: {%a,+,12}<%loop>
21-
; CHECK-NEXT: Group [[GRP2]]:
2219
; CHECK-NEXT: (Low: %b High: (4 + %b))
2320
; CHECK-NEXT: Member: %b
21+
; CHECK-NEXT: Group [[GRP2]]:
22+
; CHECK-NEXT: (Low: %a High: (16 + (12 * (trunc i128 ((zext i64 %N to i128) /u 3) to i16)) + %a))
23+
; CHECK-NEXT: Member: {%a,+,12}<%loop>
2424
; CHECK-EMPTY:
2525
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
2626
; CHECK-NEXT: SCEV assumptions:
2727
; CHECK-NEXT: {0,+,3}<%loop> Added Flags: <nusw>
28+
; CHECK-NEXT: {%a,+,12}<%loop> Added Flags: <nusw>
2829
; CHECK-EMPTY:
2930
; CHECK-NEXT: Expressions re-written:
3031
;

0 commit comments

Comments
 (0)