Skip to content

Commit 171135f

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 e080366 commit 171135f

File tree

2 files changed

+69
-14
lines changed

2 files changed

+69
-14
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

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

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

@@ -838,7 +847,8 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
838847
static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR,
839848
PredicatedScalarEvolution &PSE, const Loop *L);
840849

841-
/// Check whether a pointer address cannot wrap.
850+
/// Check whether a pointer address cannot wrap. If \p Ptr is not nullptr, use
851+
/// informating from the IR pointer value to determine no-wrap.
842852
static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
843853
Value *Ptr, Type *AccessTy, const Loop *L, bool Assume,
844854
std::optional<int64_t> Stride = std::nullopt) {
@@ -852,7 +862,7 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
852862
// location will be larger than half the pointer index type space. In that
853863
// case, the GEP would be poison and any memory access dependent on it would
854864
// be immediate UB when executed.
855-
if (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
865+
if (auto *GEP = dyn_cast_if_present<GetElementPtrInst>(Ptr);
856866
GEP && GEP->hasNoUnsignedSignedWrap())
857867
return true;
858868

@@ -868,6 +878,9 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
868878
return true;
869879
}
870880

881+
if (!Ptr)
882+
return false;
883+
871884
if (Assume) {
872885
PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW);
873886
LLVM_DEBUG(dbgs() << "LAA: Pointer may wrap:\n"
@@ -1135,13 +1148,10 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
11351148

11361149
// When we run after a failing dependency check we have to make sure
11371150
// we don't have wrapping pointers.
1138-
if (ShouldCheckWrap) {
1139-
// Skip wrap checking when translating pointers.
1140-
if (TranslatedPtrs.size() > 1)
1141-
return false;
1142-
1143-
if (!isNoWrap(PSE, AR, Ptr, AccessTy, TheLoop, Assume))
1144-
return false;
1151+
if (ShouldCheckWrap &&
1152+
!isNoWrap(PSE, AR, TranslatedPtrs.size() == 1 ? Ptr : nullptr, AccessTy,
1153+
TheLoop, Assume)) {
1154+
return false;
11451155
}
11461156
}
11471157

@@ -1454,6 +1464,9 @@ static bool isNoWrapAddRec(Value *Ptr, const SCEVAddRecExpr *AR,
14541464
if (AR->getNoWrapFlags(SCEV::NoWrapMask))
14551465
return true;
14561466

1467+
if (!Ptr)
1468+
return false;
1469+
14571470
if (PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
14581471
return true;
14591472

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)