mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 10:58:11 +08:00
[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: https://github.com/llvm/llvm-project/pull/127410
This commit is contained in:
@@ -798,8 +798,13 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
|
||||
Value *Ptr, PredicatedScalarEvolution &PSE) {
|
||||
// The access function must stride over the innermost loop.
|
||||
if (Lp != AR->getLoop()) {
|
||||
LLVM_DEBUG(dbgs() << "LAA: Bad stride - Not striding over innermost loop "
|
||||
<< *Ptr << " SCEV: " << *AR << "\n");
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "LAA: Bad stride - Not striding over innermost loop ";
|
||||
if (Ptr)
|
||||
dbgs() << *Ptr << " ";
|
||||
|
||||
dbgs() << "SCEV: " << *AR << "\n";
|
||||
});
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -809,8 +814,12 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
|
||||
// Calculate the pointer stride and check if it is constant.
|
||||
const SCEVConstant *C = dyn_cast<SCEVConstant>(Step);
|
||||
if (!C) {
|
||||
LLVM_DEBUG(dbgs() << "LAA: Bad stride - Not a constant strided " << *Ptr
|
||||
<< " SCEV: " << *AR << "\n");
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "LAA: Bad stride - Not a constant strided ";
|
||||
if (Ptr)
|
||||
dbgs() << *Ptr << " ";
|
||||
dbgs() << "SCEV: " << *AR << "\n";
|
||||
});
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -837,8 +846,8 @@ getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy,
|
||||
static bool isNoWrapGEP(Value *Ptr, PredicatedScalarEvolution &PSE,
|
||||
const Loop *L);
|
||||
|
||||
/// Check whether \p AR is a non-wrapping AddRec, or if \p Ptr is a non-wrapping
|
||||
/// GEP.
|
||||
/// Check whether \p AR is a non-wrapping AddRec. If \p Ptr is not nullptr, use
|
||||
/// informating from the IR pointer value to determine no-wrap.
|
||||
static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
|
||||
Value *Ptr, Type *AccessTy, const Loop *L, bool Assume,
|
||||
std::optional<int64_t> Stride = std::nullopt) {
|
||||
@@ -846,12 +855,12 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
|
||||
if (AR->getNoWrapFlags(SCEV::NoWrapMask))
|
||||
return true;
|
||||
|
||||
if (PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
|
||||
if (Ptr && PSE.hasNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW))
|
||||
return true;
|
||||
|
||||
// The address calculation must not wrap. Otherwise, a dependence could be
|
||||
// inverted.
|
||||
if (isNoWrapGEP(Ptr, PSE, L))
|
||||
if (Ptr && isNoWrapGEP(Ptr, PSE, L))
|
||||
return true;
|
||||
|
||||
// An nusw getelementptr that is an AddRec cannot wrap. If it would wrap,
|
||||
@@ -859,7 +868,7 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
|
||||
// location will be larger than half the pointer index type space. In that
|
||||
// case, the GEP would be poison and any memory access dependent on it would
|
||||
// be immediate UB when executed.
|
||||
if (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr);
|
||||
if (auto *GEP = dyn_cast_if_present<GetElementPtrInst>(Ptr);
|
||||
GEP && GEP->hasNoUnsignedSignedWrap())
|
||||
return true;
|
||||
|
||||
@@ -875,7 +884,7 @@ static bool isNoWrap(PredicatedScalarEvolution &PSE, const SCEVAddRecExpr *AR,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Assume) {
|
||||
if (Ptr && Assume) {
|
||||
PSE.setNoOverflow(Ptr, SCEVWrapPredicate::IncrementNUSW);
|
||||
LLVM_DEBUG(dbgs() << "LAA: Pointer may wrap:\n"
|
||||
<< "LAA: Pointer: " << *Ptr << "\n"
|
||||
@@ -1117,6 +1126,7 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
|
||||
|
||||
SmallVector<PointerIntPair<const SCEV *, 1, bool>> TranslatedPtrs =
|
||||
findForkedPointer(PSE, StridesMap, Ptr, TheLoop);
|
||||
assert(!TranslatedPtrs.empty() && "must have some translated pointers");
|
||||
|
||||
/// Check whether all pointers can participate in a runtime bounds check. They
|
||||
/// must either be invariant or AddRecs. If ShouldCheckWrap is true, they also
|
||||
@@ -1142,13 +1152,10 @@ bool AccessAnalysis::createCheckForAccess(RuntimePointerChecking &RtCheck,
|
||||
|
||||
// When we run after a failing dependency check we have to make sure
|
||||
// we don't have wrapping pointers.
|
||||
if (ShouldCheckWrap) {
|
||||
// Skip wrap checking when translating pointers.
|
||||
if (TranslatedPtrs.size() > 1)
|
||||
return false;
|
||||
|
||||
if (!isNoWrap(PSE, AR, Ptr, AccessTy, TheLoop, Assume))
|
||||
return false;
|
||||
if (ShouldCheckWrap &&
|
||||
!isNoWrap(PSE, AR, TranslatedPtrs.size() == 1 ? Ptr : nullptr, AccessTy,
|
||||
TheLoop, Assume)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,10 +83,52 @@ exit:
|
||||
define void @dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs(ptr %a, ptr %b, ptr %c, i64 %offset, i64 %n) {
|
||||
; CHECK-LABEL: 'dependency_check_and_runtime_checks_needed_select_of_ptr_add_recs'
|
||||
; CHECK-NEXT: loop:
|
||||
; CHECK-NEXT: Report: cannot check memory dependencies at runtime
|
||||
; CHECK-NEXT: Memory dependences are safe with run-time checks
|
||||
; CHECK-NEXT: Dependences:
|
||||
; CHECK-NEXT: Run-time memory checks:
|
||||
; CHECK-NEXT: Check 0:
|
||||
; CHECK-NEXT: Comparing group ([[GRP5:0x[0-9a-f]+]]):
|
||||
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
|
||||
; CHECK-NEXT: Against group ([[GRP6:0x[0-9a-f]+]]):
|
||||
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
|
||||
; CHECK-NEXT: Check 1:
|
||||
; CHECK-NEXT: Comparing group ([[GRP5]]):
|
||||
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
|
||||
; CHECK-NEXT: Against group ([[GRP7:0x[0-9a-f]+]]):
|
||||
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
|
||||
; CHECK-NEXT: Check 2:
|
||||
; CHECK-NEXT: Comparing group ([[GRP5]]):
|
||||
; CHECK-NEXT: %gep.a.iv = getelementptr inbounds float, ptr %a, i64 %iv
|
||||
; CHECK-NEXT: Against group ([[GRP8:0x[0-9a-f]+]]):
|
||||
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
|
||||
; CHECK-NEXT: Check 3:
|
||||
; CHECK-NEXT: Comparing group ([[GRP6]]):
|
||||
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
|
||||
; CHECK-NEXT: Against group ([[GRP7]]):
|
||||
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
|
||||
; CHECK-NEXT: Check 4:
|
||||
; CHECK-NEXT: Comparing group ([[GRP6]]):
|
||||
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
|
||||
; CHECK-NEXT: Against group ([[GRP8]]):
|
||||
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
|
||||
; CHECK-NEXT: Check 5:
|
||||
; CHECK-NEXT: Comparing group ([[GRP7]]):
|
||||
; CHECK-NEXT: %select = select i1 %cmp, ptr %gep.b, ptr %gep.c
|
||||
; CHECK-NEXT: Against group ([[GRP8]]):
|
||||
; CHECK-NEXT: %gep.a.iv.off = getelementptr inbounds float, ptr %a, i64 %iv.offset
|
||||
; CHECK-NEXT: Grouped accesses:
|
||||
; CHECK-NEXT: Group [[GRP5]]:
|
||||
; CHECK-NEXT: (Low: %a High: ((4 * %n) + %a))
|
||||
; CHECK-NEXT: Member: {%a,+,4}<nuw><%loop>
|
||||
; CHECK-NEXT: Group [[GRP6]]:
|
||||
; CHECK-NEXT: (Low: %b High: ((4 * %n) + %b))
|
||||
; CHECK-NEXT: Member: {%b,+,4}<%loop>
|
||||
; CHECK-NEXT: Group [[GRP7]]:
|
||||
; CHECK-NEXT: (Low: %c High: ((4 * %n) + %c))
|
||||
; CHECK-NEXT: Member: {%c,+,4}<%loop>
|
||||
; CHECK-NEXT: Group [[GRP8]]:
|
||||
; CHECK-NEXT: (Low: ((4 * %offset) + %a) High: ((4 * %offset) + (4 * %n) + %a))
|
||||
; CHECK-NEXT: Member: {((4 * %offset) + %a),+,4}<%loop>
|
||||
; CHECK-EMPTY:
|
||||
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
|
||||
; CHECK-NEXT: SCEV assumptions:
|
||||
|
||||
Reference in New Issue
Block a user