[llvm] [LAA] hoist setting condition for rt-checks (NFC) (PR #128045)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 20 10:37:59 PST 2025
https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/128045
Strip ShouldRetyWithRuntimeCheck from the DepedenceDistanceStrideAndSizeInfo struct, and free isDependent from the responsibility of setting the condition for when runtime-checks are needed, transferring this responsibility to getDependenceDistanceStrideAndSize. The change is simple enough, but proving that this was the original intent of the code, making the change non-functional is non-trivial.
The proof is as follows. The condition for runtime-checks is only respected when we return a Dependence::DepType of Dependence::Unknown, and the only possible place that could introduce a functional change with this patch is when Dist is possibly zero, but HasSameSize is false. Previously, we weren't checking that the Dist is not a SCEVConstant, and setting the runtime-check condition. Now, with the runtime-check condition hoisted, we do. We note that for a functional change to occur, the distance must be both non-constant, not provably non-positive and non-negative, and this is an impossibility.
>From 537f7ef8c9bb61d6c292f601ff0a549da9c5e833 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Thu, 20 Feb 2025 16:37:03 +0000
Subject: [PATCH] [LAA] hoist setting condition for rt-checks (NFC)
Strip ShouldRetyWithRuntimeCheck from the
DepedenceDistanceStrideAndSizeInfo struct, and free isDependent from the
responsibility of setting the condition for when runtime-checks are
needed, transferring this responsibility to
getDependenceDistanceStrideAndSize. The change is simple enough, but
proving that this was the original intent of the code, making the change
non-functional is non-trivial.
The proof is as follows. The condition for runtime-checks is only
respected when we return a Dependence::DepType of Dependence::Unknown,
and the only possible place that could introduce a functional change
with this patch is when Dist is possibly zero, but HasSameSize is false.
Previously, we weren't checking that the Dist is not a SCEVConstant, and
setting the runtime-check condition. Now, with the runtime-check
condition hoisted, we do. We note that for a functional change to occur,
the distance must be both non-constant, not provably non-positive and
non-negative, and this is an impossibility.
---
.../llvm/Analysis/LoopAccessAnalysis.h | 4 --
llvm/lib/Analysis/LoopAccessAnalysis.cpp | 42 ++++---------------
2 files changed, 9 insertions(+), 37 deletions(-)
diff --git a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
index cb6f47e3a76be..b724078346903 100644
--- a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
+++ b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h
@@ -372,8 +372,6 @@ class MemoryDepChecker {
uint64_t MaxStride;
std::optional<uint64_t> CommonStride;
- bool ShouldRetryWithRuntimeCheck;
-
/// TypeByteSize is either the common store size of both accesses, or 0 when
/// store sizes mismatch.
uint64_t TypeByteSize;
@@ -383,11 +381,9 @@ class MemoryDepChecker {
DepDistanceStrideAndSizeInfo(const SCEV *Dist, uint64_t MaxStride,
std::optional<uint64_t> CommonStride,
- bool ShouldRetryWithRuntimeCheck,
uint64_t TypeByteSize, bool AIsWrite,
bool BIsWrite)
: Dist(Dist), MaxStride(MaxStride), CommonStride(CommonStride),
- ShouldRetryWithRuntimeCheck(ShouldRetryWithRuntimeCheck),
TypeByteSize(TypeByteSize), AIsWrite(AIsWrite), BIsWrite(BIsWrite) {}
};
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
index cab70c5c01a45..5e0302760aeac 100644
--- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp
+++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp
@@ -2006,14 +2006,14 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
if (StrideAScaled == StrideBScaled)
CommonStride = StrideAScaled;
- // TODO: Historically, we don't retry with runtime checks unless the
- // (unscaled) strides are the same. Fix this once the condition for runtime
- // checks in isDependent is fixed.
- bool ShouldRetryWithRuntimeCheck = StrideAPtrInt == StrideBPtrInt;
+ // TODO: FoundNonConstantDistanceDependence is used as a necessary condition
+ // to consider retrying with runtime checks. Historically, we did not set it
+ // when (unscaled) strides were different but there is no inherent reason to.
+ if (!isa<SCEVConstant>(Dist))
+ FoundNonConstantDistanceDependence |= StrideAPtrInt == StrideBPtrInt;
return DepDistanceStrideAndSizeInfo(Dist, MaxStride, CommonStride,
- ShouldRetryWithRuntimeCheck, TypeByteSize,
- AIsWrite, BIsWrite);
+ TypeByteSize, AIsWrite, BIsWrite);
}
MemoryDepChecker::Dependence::DepType
@@ -2028,15 +2028,11 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
if (std::holds_alternative<Dependence::DepType>(Res))
return std::get<Dependence::DepType>(Res);
- auto &[Dist, MaxStride, CommonStride, ShouldRetryWithRuntimeCheck,
- TypeByteSize, AIsWrite, BIsWrite] =
+ auto &[Dist, MaxStride, CommonStride, TypeByteSize, AIsWrite, BIsWrite] =
std::get<DepDistanceStrideAndSizeInfo>(Res);
bool HasSameSize = TypeByteSize > 0;
if (isa<SCEVCouldNotCompute>(Dist)) {
- // TODO: Relax requirement that there is a common unscaled stride to retry
- // with non-constant distance dependencies.
- FoundNonConstantDistanceDependence |= ShouldRetryWithRuntimeCheck;
LLVM_DEBUG(dbgs() << "LAA: Dependence because of uncomputable distance.\n");
return Dependence::Unknown;
}
@@ -2096,14 +2092,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
// forward dependency will allow vectorization using any width.
if (IsTrueDataDependence && EnableForwardingConflictDetection) {
- if (!ConstDist) {
- // TODO: FoundNonConstantDistanceDependence is used as a necessary
- // condition to consider retrying with runtime checks. Historically, we
- // did not set it when strides were different but there is no inherent
- // reason to.
- FoundNonConstantDistanceDependence |= ShouldRetryWithRuntimeCheck;
+ if (!ConstDist)
return Dependence::Unknown;
- }
if (!HasSameSize ||
couldPreventStoreLoadForward(
ConstDist->getAPInt().abs().getZExtValue(), TypeByteSize)) {
@@ -2119,22 +2109,8 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
int64_t MinDistance = SE.getSignedRangeMin(Dist).getSExtValue();
// Below we only handle strictly positive distances.
- if (MinDistance <= 0) {
- FoundNonConstantDistanceDependence |= ShouldRetryWithRuntimeCheck;
+ if (MinDistance <= 0)
return Dependence::Unknown;
- }
-
- if (!ConstDist) {
- // Previously this case would be treated as Unknown, possibly setting
- // FoundNonConstantDistanceDependence to force re-trying with runtime
- // checks. Until the TODO below is addressed, set it here to preserve
- // original behavior w.r.t. re-trying with runtime checks.
- // TODO: FoundNonConstantDistanceDependence is used as a necessary
- // condition to consider retrying with runtime checks. Historically, we
- // did not set it when strides were different but there is no inherent
- // reason to.
- FoundNonConstantDistanceDependence |= ShouldRetryWithRuntimeCheck;
- }
if (!HasSameSize) {
LLVM_DEBUG(dbgs() << "LAA: ReadWrite-Write positive dependency with "
More information about the llvm-commits
mailing list