Skip to content

Commit 343be43

Browse files
committed
[LAA] Make Ptr argument optional in isNoWrap.
Update isNoWrap to make the IR Ptr argument optional. This allows using isNoWrap when dealing with things like pointer-selects, where a select is translated to multiple pointer SCEV expressions, but there is no IR value that can be used. We don't try to retrieve pointer values for the pointer SCEVs and using info from the IR would not be safe. For example, we cannot use inbounds, because the pointer may never be accessed.
1 parent 88e72c4 commit 343be43

File tree

2 files changed

+69
-15
lines changed

2 files changed

+69
-15
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -800,8 +800,13 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
800800
Value *Ptr, PredicatedScalarEvolution &PSE) {
801801
// The access function must stride over the innermost loop.
802802
if (Lp != AR->getLoop()) {
803-
LLVM_DEBUG(dbgs() << "LAA: Bad stride - Not striding over innermost loop "
804-
<< *Ptr << " SCEV: " << *AR << "\n");
803+
LLVM_DEBUG({
804+
dbgs() << "LAA: Bad stride - Not striding over innermost loop ";
805+
if (Ptr)
806+
dbgs() << *Ptr << " ";
807+
808+
dbgs() << "SCEV: " << *AR << "\n";
809+
});
805810
return std::nullopt;
806811
}
807812

@@ -811,8 +816,12 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
811816
// Calculate the pointer stride and check if it is constant.
812817
const SCEVConstant *C = dyn_cast<SCEVConstant>(Step);
813818
if (!C) {
814-
LLVM_DEBUG(dbgs() << "LAA: Bad stride - Not a constant strided " << *Ptr
815-
<< " SCEV: " << *AR << "\n");
819+
LLVM_DEBUG({
820+
dbgs() << "LAA: Bad stride - Not a constant strided ";
821+
if (Ptr)
822+
dbgs() << *Ptr << " ";
823+
dbgs() << "SCEV: " << *AR << "\n";
824+
});
816825
return std::nullopt;
817826
}
818827

@@ -839,8 +848,8 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
839848
static bool isNoWrapGEP(Value *Ptr, PredicatedScalarEvolution &PSE,
840849
const Loop *L);
841850

842-
/// Check whether \p AR is a non-wrapping AddRec, or if \p Ptr is a non-wrapping
843-
/// GEP.
851+
/// Check whether a pointer address cannot wrap. If \p Ptr is not nullptr, use
852+
/// informating from the IR pointer value to determine no-wrap.
844853
static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
845854
Value *Ptr, Type *AccessTy, const Loop *L, bool Assume,
846855
std::optional<int64_t> Stride = std::nullopt) {
@@ -861,7 +870,7 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
861870
// location will be larger than half the pointer index type space. In that
862871
// case, the GEP would be poison and any memory access dependent on it would
863872
// be immediate UB when executed.
864-
if (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
873+
if (auto *GEP = dyn_cast_if_present<GetElementPtrInst>(Ptr);
865874
GEP && GEP->hasNoUnsignedSignedWrap())
866875
return true;
867876

@@ -877,6 +886,9 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
877886
return true;
878887
}
879888

889+
if (!Ptr)
890+
return false;
891+
880892
if (Assume) {
881893
PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW);
882894
LLVM_DEBUG(dbgs() << "LAA: Pointer may wrap:\n"
@@ -1144,13 +1156,10 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
11441156

11451157
// When we run after a failing dependency check we have to make sure
11461158
// we don't have wrapping pointers.
1147-
if (ShouldCheckWrap) {
1148-
// Skip wrap checking when translating pointers.
1149-
if (TranslatedPtrs.size() > 1)
1150-
return false;
1151-
1152-
if (!isNoWrap(PSE, AR, Ptr, AccessTy, TheLoop, Assume))
1153-
return false;
1159+
if (ShouldCheckWrap &&
1160+
!isNoWrap(PSE, AR, TranslatedPtrs.size() == 1 ? Ptr : nullptr, AccessTy,
1161+
TheLoop, Assume)) {
1162+
return false;
11541163
}
11551164
}
11561165

@@ -1457,6 +1466,9 @@ void AccessAnalysis::processMemAccesses() {
14571466
/// Check whether \p Ptr is non-wrapping GEP.
14581467
static bool isNoWrapGEP(Value *Ptr, PredicatedScalarEvolution &PSE,
14591468
const Loop *L) {
1469+
if (PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
1470+
return true;
1471+
14601472
// Scalar evolution does not propagate the non-wrapping flags to values that
14611473
// are derived from a non-wrapping induction variable because non-wrapping
14621474
// could be flow-sensitive.

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
@@ -83,10 +83,52 @@ exit:
8383
define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
8484
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs'
8585
; CHECK-NEXT: loop:
86-
; CHECK-NEXT: Report: cannot check memory dependencies at runtime
86+
; CHECK-NEXT: Memory dependences are safe with run-time checks
8787
; CHECK-NEXT: Dependences:
8888
; CHECK-NEXT: Run-time memory checks:
89+
; CHECK-NEXT: Check 0:
90+
; CHECK-NEXT: Comparing group ([[GRP5:0x[0-9a-f]+]]):
91+
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
92+
; CHECK-NEXT: Against group ([[GRP6:0x[0-9a-f]+]]):
93+
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
94+
; CHECK-NEXT: Check 1:
95+
; CHECK-NEXT: Comparing group ([[GRP5]]):
96+
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
97+
; CHECK-NEXT: Against group ([[GRP7:0x[0-9a-f]+]]):
98+
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
99+
; CHECK-NEXT: Check 2:
100+
; CHECK-NEXT: Comparing group ([[GRP5]]):
101+
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
102+
; CHECK-NEXT: Against group ([[GRP8:0x[0-9a-f]+]]):
103+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
104+
; CHECK-NEXT: Check 3:
105+
; CHECK-NEXT: Comparing group ([[GRP6]]):
106+
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
107+
; CHECK-NEXT: Against group ([[GRP7]]):
108+
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
109+
; CHECK-NEXT: Check 4:
110+
; CHECK-NEXT: Comparing group ([[GRP6]]):
111+
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
112+
; CHECK-NEXT: Against group ([[GRP8]]):
113+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
114+
; CHECK-NEXT: Check 5:
115+
; CHECK-NEXT: Comparing group ([[GRP7]]):
116+
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
117+
; CHECK-NEXT: Against group ([[GRP8]]):
118+
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
89119
; CHECK-NEXT: Grouped accesses:
120+
; CHECK-NEXT: Group [[GRP5]]:
121+
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
122+
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
123+
; CHECK-NEXT: Group [[GRP6]]:
124+
; CHECK-NEXT: (Low: %b High: ((4 * %n) + %b))
125+
; CHECK-NEXT: Member: {%b,+,4}<%loop>
126+
; CHECK-NEXT: Group [[GRP7]]:
127+
; CHECK-NEXT: (Low: %c High: ((4 * %n) + %c))
128+
; CHECK-NEXT: Member: {%c,+,4}<%loop>
129+
; CHECK-NEXT: Group [[GRP8]]:
130+
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
131+
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
90132
; CHECK-EMPTY:
91133
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
92134
; CHECK-NEXT: SCEV assumptions:

0 commit comments

Comments
 (0)