Skip to content

Commit d897ea3

Browse files
authored
LAA: check nusw on GEP in place of inbounds (#112223)
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 f719cfa commit d897ea3

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
@@ -1407,9 +1407,9 @@ static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR,
14071407
// Look through the potentially overflowing instruction to try to prove
14081408
// non-wrapping for the *specific* value of Ptr.
14091409

1410-
// The arithmetic implied by an inbounds GEP can't overflow.
1410+
// The arithmetic implied by an nusw GEP can't overflow.
14111411
const auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
1412-
if (!GEP || !GEP->isInBounds())
1412+
if (!GEP || !GEP->hasNoUnsignedSignedWrap())
14131413
return false;
14141414

14151415
// Make sure there is only one non-const index and analyze that.
@@ -1511,12 +1511,12 @@ llvm::getPtrStride(PredicatedScalarEvolution &PSE, Type *AccessTy, Value *Ptr,
15111511
if (isNoWrapAddRec(Ptr, AR, PSE, Lp))
15121512
return Stride;
15131513

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

15221522
// 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)