@@ -1937,6 +1937,27 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
19371937 LLVM_DEBUG (dbgs () << " LAA: Distance for " << *AInst << " to " << *BInst
19381938 << " : " << *Dist << " \n " );
19391939
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+
19401961 // Need accesses with constant strides and the same direction for further
19411962 // dependence analysis. We don't want to vectorize "A[B[i]] += ..." and
19421963 // similar code or pointer arithmetic that could wrap in the address space.
@@ -1982,45 +2003,12 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
19822003 const MemAccessInfo &B, unsigned BIdx) {
19832004 assert (AIdx < BIdx && " Must pass arguments in program order" );
19842005
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-
20142006 // Get the dependence distance, stride, type size and what access writes for
20152007 // the dependence between A and B.
20162008 auto Res =
20172009 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))
20222011 return std::get<Dependence::DepType>(Res);
2023- }
20242012
20252013 auto &[Dist, StrideA, StrideB, TypeByteSize, AIsWrite, BIsWrite] =
20262014 std::get<DepDistanceStrideAndSizeInfo>(Res);
@@ -2029,9 +2017,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
20292017 std::optional<uint64_t > CommonStride =
20302018 StrideA == StrideB ? std::make_optional (StrideA) : std::nullopt ;
20312019 if (isa<SCEVCouldNotCompute>(Dist)) {
2032- if (CheckCompletelyBeforeOrAfter ())
2033- return Dependence::NoDep;
2034-
20352020 // TODO: Relax requirement that there is a common stride to retry with
20362021 // non-constant distance dependencies.
20372022 FoundNonConstantDistanceDependence |= CommonStride.has_value ();
@@ -2083,8 +2068,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
20832068 // Write to the same location with the same size.
20842069 return Dependence::Forward;
20852070 }
2086- assert (!CheckCompletelyBeforeOrAfter () &&
2087- " unexpectedly proved no dependence" );
20882071 LLVM_DEBUG (dbgs () << " LAA: possibly zero dependence difference but "
20892072 " different type sizes\n " );
20902073 return Dependence::Unknown;
@@ -2106,8 +2089,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
21062089 // did not set it when strides were different but there is no inherent
21072090 // reason to.
21082091 FoundNonConstantDistanceDependence |= CommonStride.has_value ();
2109- if (CheckCompletelyBeforeOrAfter ())
2110- return Dependence::NoDep;
21112092 return Dependence::Unknown;
21122093 }
21132094 if (!HasSameSize ||
@@ -2127,9 +2108,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
21272108 // Below we only handle strictly positive distances.
21282109 if (MinDistance <= 0 ) {
21292110 FoundNonConstantDistanceDependence |= CommonStride.has_value ();
2130- if (CheckCompletelyBeforeOrAfter ())
2131- return Dependence::NoDep;
2132-
21332111 return Dependence::Unknown;
21342112 }
21352113
@@ -2146,18 +2124,13 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
21462124 }
21472125
21482126 if (!HasSameSize) {
2149- if (CheckCompletelyBeforeOrAfter ())
2150- return Dependence::NoDep;
21512127 LLVM_DEBUG (dbgs () << " LAA: ReadWrite-Write positive dependency with "
21522128 " different type sizes\n " );
21532129 return Dependence::Unknown;
21542130 }
21552131
2156- if (!CommonStride) {
2157- if (CheckCompletelyBeforeOrAfter ())
2158- return Dependence::NoDep;
2132+ if (!CommonStride)
21592133 return Dependence::Unknown;
2160- }
21612134
21622135 // Bail out early if passed-in parameters make vectorization not feasible.
21632136 unsigned ForcedFactor = (VectorizerParams::VectorizationFactor ?
@@ -2205,10 +2178,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
22052178 // dependence distance and the distance may be larger at runtime (and safe
22062179 // for vectorization). Classify it as Unknown, so we re-try with runtime
22072180 // checks.
2208- //
2209- if (CheckCompletelyBeforeOrAfter ())
2210- return Dependence::NoDep;
2211-
22122181 return Dependence::Unknown;
22132182 }
22142183 LLVM_DEBUG (dbgs () << " LAA: Failure because of positive minimum distance "
@@ -2221,8 +2190,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
22212190 if (MinDistanceNeeded > MinDepDistBytes) {
22222191 LLVM_DEBUG (dbgs () << " LAA: Failure because it needs at least "
22232192 << MinDistanceNeeded << " size in bytes\n " );
2224- assert (!CheckCompletelyBeforeOrAfter () &&
2225- " unexpectedly proved no dependence" );
22262193 return Dependence::Backward;
22272194 }
22282195
@@ -2270,8 +2237,6 @@ MemoryDepChecker::isDependent(const MemAccessInfo &A, unsigned AIdx,
22702237 // For non-constant distances, we checked the lower bound of the dependence
22712238 // distance and the distance may be larger at runtime (and safe for
22722239 // vectorization). Classify it as Unknown, so we re-try with runtime checks.
2273- assert (!CheckCompletelyBeforeOrAfter () &&
2274- " unexpectedly proved no dependence" );
22752240 return Dependence::Unknown;
22762241 }
22772242
0 commit comments