Skip to content

Commit 8f4953c

Browse files
committed
LAA: check nusw on GEP in place of inbounds
With the introduction of the nusw flag in GEPNoWrapFlags, it should be safe to weaken the check in LoopAccessAnalysis to just check the nusw flag on the GEP, instead of inbounds.
1 parent a705838 commit 8f4953c

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,9 +1412,9 @@ static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR,
14121412
// Look through the potentially overflowing instruction to try to prove
14131413
// non-wrapping for the *specific* value of Ptr.
14141414

1415-
// The arithmetic implied by an inbounds GEP can't overflow.
1415+
// The arithmetic implied by an nusw GEP can't overflow.
14161416
const auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
1417-
if (!GEP || !GEP->isInBounds())
1417+
if (!GEP || !GEP->hasNoUnsignedSignedWrap())
14181418
return false;
14191419

14201420
// Make sure there is only one non-const index and analyze that.
@@ -1516,12 +1516,12 @@ llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
15161516
if (isNoWrapAddRec(Ptr, AR, PSE, Lp))
15171517
return Stride;
15181518

1519-
// An inbounds getelementptr that is a AddRec with a unit stride
1519+
// An nusw getelementptr that is a AddRec with a unit stride
15201520
// cannot wrap per definition. If it did, the result would be poison
15211521
// and any memory access dependent on it would be immediate UB
15221522
// when executed.
15231523
if (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
1524-
GEP && GEP->isInBounds() && (Stride == 1 || Stride == -1))
1524+
GEP && GEP->hasNoUnsignedSignedWrap() && (Stride == 1 || Stride == -1))
15251525
return Stride;
15261526

15271527
// If the null pointer is undefined, then a access sequence which would

llvm/test/Analysis/LoopAccessAnalysis/symbolic-stride.ll

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,51 @@ exit: ; preds = %loop
4848
ret void
4949
}
5050

51+
; A forwarding in the presence of symbolic strides,
52+
; with nusw instead of inbounds on the GEPs.
53+
define void @single_stride_nusw(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {
54+
; CHECK-LABEL: 'single_stride_nusw'
55+
; CHECK-NEXT: loop:
56+
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
57+
; CHECK-NEXT: Backward loop carried data dependence.
58+
; CHECK-NEXT: Dependences:
59+
; CHECK-NEXT: Backward:
60+
; CHECK-NEXT: %load = load i32, ptr %gep.A, align 4 ->
61+
; CHECK-NEXT: store i32 %add, ptr %gep.A.next, align 4
62+
; CHECK-EMPTY:
63+
; CHECK-NEXT: Run-time memory checks:
64+
; CHECK-NEXT: Grouped accesses:
65+
; CHECK-EMPTY:
66+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
67+
; CHECK-NEXT: SCEV assumptions:
68+
; CHECK-NEXT: Equal predicate: %stride == 1
69+
; CHECK-EMPTY:
70+
; CHECK-NEXT: Expressions re-written:
71+
; CHECK-NEXT: [PSE] %gep.A = getelementptr nusw i32, ptr %A, i64 %mul:
72+
; CHECK-NEXT: {%A,+,(4 * %stride)}<%loop>
73+
; CHECK-NEXT: --> {%A,+,4}<%loop>
74+
;
75+
entry:
76+
br label %loop
77+
78+
loop:
79+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
80+
%mul = mul i64 %iv, %stride
81+
%gep.A = getelementptr nusw i32, ptr %A, i64 %mul
82+
%load = load i32, ptr %gep.A, align 4
83+
%gep.B = getelementptr nusw i32, ptr %B, i64 %iv
84+
%load_1 = load i32, ptr %gep.B, align 4
85+
%add = add i32 %load_1, %load
86+
%iv.next = add nuw nsw i64 %iv, 1
87+
%gep.A.next = getelementptr nusw i32, ptr %A, i64 %iv.next
88+
store i32 %add, ptr %gep.A.next, align 4
89+
%exitcond = icmp eq i64 %iv.next, %N
90+
br i1 %exitcond, label %exit, label %loop
91+
92+
exit: ; preds = %loop
93+
ret void
94+
}
95+
5196
; Similar to @single_stride, but with struct types.
5297
define void @single_stride_struct(ptr noalias %A, ptr noalias %B, i64 %N, i64 %stride) {
5398
; CHECK-LABEL: 'single_stride_struct'

0 commit comments

Comments
 (0)