@@ -1937,6 +1937,27 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
1937
1937
LLVM_DEBUG (dbgs () << " LAA: Distance for " << *AInst << " to " << *BInst
1938
1938
<< " : " << *Dist << " \n " );
1939
1939
1940
+ // Check if we can prove that Sink only accesses memory after Src's end or
1941
+ // vice versa. At the moment this is limited to cases where either source or
1942
+ // sink are loop invariant to avoid compile-time increases. This is not
1943
+ // required for correctness.
1944
+ if (SE.isLoopInvariant (Src, InnermostLoop) ||
1945
+ SE.isLoopInvariant (Sink, InnermostLoop)) {
1946
+ const auto &[SrcStart, SrcEnd] =
1947
+ getStartAndEndForAccess (InnermostLoop, Src, ATy, PSE, PointerBounds);
1948
+ const auto &[SinkStart, SinkEnd] =
1949
+ getStartAndEndForAccess (InnermostLoop, Sink, BTy, PSE, PointerBounds);
1950
+ if (!isa<SCEVCouldNotCompute>(SrcStart) &&
1951
+ !isa<SCEVCouldNotCompute>(SrcEnd) &&
1952
+ !isa<SCEVCouldNotCompute>(SinkStart) &&
1953
+ !isa<SCEVCouldNotCompute>(SinkEnd)) {
1954
+ if (SE.isKnownPredicate (CmpInst::ICMP_ULE, SrcEnd, SinkStart))
1955
+ return MemoryDepChecker::Dependence::NoDep;
1956
+ if (SE.isKnownPredicate (CmpInst::ICMP_ULE, SinkEnd, SrcStart))
1957
+ return MemoryDepChecker::Dependence::NoDep;
1958
+ }
1959
+ }
1960
+
1940
1961
// Need accesses with constant strides and the same direction for further
1941
1962
// dependence analysis. We don't want to vectorize "A[B[i]] += ..." and
1942
1963
// similar code or pointer arithmetic that could wrap in the address space.
@@ -1982,45 +2003,12 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
1982
2003
const MemAccessInfo &B, unsigned BIdx) {
1983
2004
assert (AIdx < BIdx && " Must pass arguments in program order" );
1984
2005
1985
- // Check if we can prove that Sink only accesses memory after Src's end or
1986
- // vice versa. The helper is used to perform the checks only on the exit paths
1987
- // where it helps to improve the analysis result.
1988
- auto CheckCompletelyBeforeOrAfter = [&]() {
1989
- auto *APtr = A.getPointer ();
1990
- auto *BPtr = B.getPointer ();
1991
-
1992
- Type *ATy = getLoadStoreType (InstMap[AIdx]);
1993
- Type *BTy = getLoadStoreType (InstMap[BIdx]);
1994
-
1995
- const SCEV *Src = PSE.getSCEV (APtr);
1996
- const SCEV *Sink = PSE.getSCEV (BPtr);
1997
-
1998
- const auto &[SrcStart, SrcEnd] =
1999
- getStartAndEndForAccess (InnermostLoop, Src, ATy, PSE, PointerBounds);
2000
- if (isa<SCEVCouldNotCompute>(SrcStart) || isa<SCEVCouldNotCompute>(SrcEnd))
2001
- return false ;
2002
-
2003
- const auto &[SinkStart, SinkEnd] =
2004
- getStartAndEndForAccess (InnermostLoop, Sink, BTy, PSE, PointerBounds);
2005
- if (isa<SCEVCouldNotCompute>(SinkStart) ||
2006
- isa<SCEVCouldNotCompute>(SinkEnd))
2007
- return false ;
2008
-
2009
- auto &SE = *PSE.getSE ();
2010
- return SE.isKnownPredicate (CmpInst::ICMP_ULE, SrcEnd, SinkStart) ||
2011
- SE.isKnownPredicate (CmpInst::ICMP_ULE, SinkEnd, SrcStart);
2012
- };
2013
-
2014
2006
// Get the dependence distance, stride, type size and what access writes for
2015
2007
// the dependence between A and B.
2016
2008
auto Res =
2017
2009
getDependenceDistanceStrideAndSize (A, InstMap[AIdx], B, InstMap[BIdx]);
2018
- if (std::holds_alternative<Dependence::DepType>(Res)) {
2019
- if (std::get<Dependence::DepType>(Res) == Dependence::Unknown &&
2020
- CheckCompletelyBeforeOrAfter ())
2021
- return Dependence::NoDep;
2010
+ if (std::holds_alternative<Dependence::DepType>(Res))
2022
2011
return std::get<Dependence::DepType>(Res);
2023
- }
2024
2012
2025
2013
auto &[Dist, StrideA, StrideB, TypeByteSize, AIsWrite, BIsWrite] =
2026
2014
std::get<DepDistanceStrideAndSizeInfo>(Res);
@@ -2029,9 +2017,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
2029
2017
std::optional<uint64_t > CommonStride =
2030
2018
StrideA == StrideB ? std::make_optional (StrideA) : std::nullopt;
2031
2019
if (isa<SCEVCouldNotCompute>(Dist)) {
2032
- if (CheckCompletelyBeforeOrAfter ())
2033
- return Dependence::NoDep;
2034
-
2035
2020
// TODO: Relax requirement that there is a common stride to retry with
2036
2021
// non-constant distance dependencies.
2037
2022
FoundNonConstantDistanceDependence |= CommonStride.has_value ();
@@ -2083,8 +2068,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
2083
2068
// Write to the same location with the same size.
2084
2069
return Dependence::Forward;
2085
2070
}
2086
- assert (!CheckCompletelyBeforeOrAfter () &&
2087
- " unexpectedly proved no dependence" );
2088
2071
LLVM_DEBUG (dbgs () << " LAA: possibly zero dependence difference but "
2089
2072
" different type sizes\n " );
2090
2073
return Dependence::Unknown;
@@ -2106,8 +2089,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
2106
2089
// did not set it when strides were different but there is no inherent
2107
2090
// reason to.
2108
2091
FoundNonConstantDistanceDependence |= CommonStride.has_value ();
2109
- if (CheckCompletelyBeforeOrAfter ())
2110
- return Dependence::NoDep;
2111
2092
return Dependence::Unknown;
2112
2093
}
2113
2094
if (!HasSameSize ||
@@ -2127,9 +2108,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
2127
2108
// Below we only handle strictly positive distances.
2128
2109
if (MinDistance <= 0 ) {
2129
2110
FoundNonConstantDistanceDependence |= CommonStride.has_value ();
2130
- if (CheckCompletelyBeforeOrAfter ())
2131
- return Dependence::NoDep;
2132
-
2133
2111
return Dependence::Unknown;
2134
2112
}
2135
2113
@@ -2146,18 +2124,13 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
2146
2124
}
2147
2125
2148
2126
if (!HasSameSize) {
2149
- if (CheckCompletelyBeforeOrAfter ())
2150
- return Dependence::NoDep;
2151
2127
LLVM_DEBUG (dbgs () << " LAA: ReadWrite-Write positive dependency with "
2152
2128
" different type sizes\n " );
2153
2129
return Dependence::Unknown;
2154
2130
}
2155
2131
2156
- if (!CommonStride) {
2157
- if (CheckCompletelyBeforeOrAfter ())
2158
- return Dependence::NoDep;
2132
+ if (!CommonStride)
2159
2133
return Dependence::Unknown;
2160
- }
2161
2134
2162
2135
// Bail out early if passed-in parameters make vectorization not feasible.
2163
2136
unsigned ForcedFactor = (VectorizerParams::VectorizationFactor ?
@@ -2205,10 +2178,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
2205
2178
// dependence distance and the distance may be larger at runtime (and safe
2206
2179
// for vectorization). Classify it as Unknown, so we re-try with runtime
2207
2180
// checks.
2208
- //
2209
- if (CheckCompletelyBeforeOrAfter ())
2210
- return Dependence::NoDep;
2211
-
2212
2181
return Dependence::Unknown;
2213
2182
}
2214
2183
LLVM_DEBUG (dbgs () << " LAA: Failure because of positive minimum distance "
@@ -2221,8 +2190,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
2221
2190
if (MinDistanceNeeded > MinDepDistBytes) {
2222
2191
LLVM_DEBUG (dbgs () << " LAA: Failure because it needs at least "
2223
2192
<< MinDistanceNeeded << " size in bytes\n " );
2224
- assert (!CheckCompletelyBeforeOrAfter () &&
2225
- " unexpectedly proved no dependence" );
2226
2193
return Dependence::Backward;
2227
2194
}
2228
2195
@@ -2270,8 +2237,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
2270
2237
// For non-constant distances, we checked the lower bound of the dependence
2271
2238
// distance and the distance may be larger at runtime (and safe for
2272
2239
// vectorization). Classify it as Unknown, so we re-try with runtime checks.
2273
- assert (!CheckCompletelyBeforeOrAfter () &&
2274
- " unexpectedly proved no dependence" );
2275
2240
return Dependence::Unknown;
2276
2241
}
2277
2242
0 commit comments