Skip to content

Commit 01d0793

Browse files
authored
[LAA] Make Ptr argument optional in isNoWrap. (#127410)
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. PR: #127410
1 parent 1ac0db4 commit 01d0793

File tree

2 files changed

+67
-18
lines changed

2 files changed

+67
-18
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

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

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

@@ -837,29 +846,29 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
837846
static bool isNoWrapGEP(Value *Ptr, PredicatedScalarEvolution &PSE,
838847
const Loop *L);
839848

840-
/// Check whether \p AR is a non-wrapping AddRec, or if \p Ptr is a non-wrapping
841-
/// GEP.
849+
/// Check whether \p AR is a non-wrapping AddRec. If \p Ptr is not nullptr, use
850+
/// informating from the IR pointer value to determine no-wrap.
842851
static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
843852
Value *Ptr, Type *AccessTy, const Loop *L, bool Assume,
844853
std::optional<int64_t> Stride = std::nullopt) {
845854
// FIXME: This should probably only return true for NUW.
846855
if (AR->getNoWrapFlags(SCEV::NoWrapMask))
847856
return true;
848857

849-
if (PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
858+
if (Ptr && PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
850859
return true;
851860

852861
// The address calculation must not wrap. Otherwise, a dependence could be
853862
// inverted.
854-
if (isNoWrapGEP(Ptr, PSE, L))
863+
if (Ptr && isNoWrapGEP(Ptr, PSE, L))
855864
return true;
856865

857866
// An nusw getelementptr that is an AddRec cannot wrap. If it would wrap,
858867
// the distance between the previously accessed location and the wrapped
859868
// location will be larger than half the pointer index type space. In that
860869
// case, the GEP would be poison and any memory access dependent on it would
861870
// be immediate UB when executed.
862-
if (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
871+
if (auto *GEP = dyn_cast_if_present<GetElementPtrInst>(Ptr);
863872
GEP && GEP->hasNoUnsignedSignedWrap())
864873
return true;
865874

@@ -875,7 +884,7 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
875884
return true;
876885
}
877886

878-
if (Assume) {
887+
if (Ptr && Assume) {
879888
PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW);
880889
LLVM_DEBUG(dbgs() << "LAA: Pointer may wrap:\n"
881890
<< "LAA: Pointer: " << *Ptr << "\n"
@@ -1117,6 +1126,7 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
11171126

11181127
SmallVector<PointerIntPair<const SCEV *, 1, bool>> TranslatedPtrs =
11191128
findForkedPointer(PSE, StridesMap, Ptr, TheLoop);
1129+
assert(!TranslatedPtrs.empty() && "must have some translated pointers");
11201130

11211131
/// Check whether all pointers can participate in a runtime bounds check. They
11221132
/// must either be invariant or AddRecs. If ShouldCheckWrap is true, they also
@@ -1142,13 +1152,10 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
11421152

11431153
// When we run after a failing dependency check we have to make sure
11441154
// we don't have wrapping pointers.
1145-
if (ShouldCheckWrap) {
1146-
// Skip wrap checking when translating pointers.
1147-
if (TranslatedPtrs.size() > 1)
1148-
return false;
1149-
1150-
if (!isNoWrap(PSE, AR, Ptr, AccessTy, TheLoop, Assume))
1151-
return false;
1155+
if (ShouldCheckWrap &&
1156+
!isNoWrap(PSE, AR, TranslatedPtrs.size() == 1 ? Ptr : nullptr, AccessTy,
1157+
TheLoop, Assume)) {
1158+
return false;
11521159
}
11531160
}
11541161

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)