@@ -1954,6 +1954,37 @@ static bool areStridedAccessesIndependent(uint64_t Distance, uint64_t Stride,
19541954 return Distance % Stride;
19551955}
19561956
1957+ bool MemoryDepChecker::areAccessesCompletelyBeforeOrAfter (const SCEV *Src,
1958+ Type *SrcTy,
1959+ const SCEV *Sink,
1960+ Type *SinkTy) {
1961+ const SCEV *BTC = PSE.getBackedgeTakenCount ();
1962+ const SCEV *SymbolicMaxBTC = PSE.getSymbolicMaxBackedgeTakenCount ();
1963+ ScalarEvolution &SE = *PSE.getSE ();
1964+ const auto &[SrcStart_, SrcEnd_] = getStartAndEndForAccess (
1965+ InnermostLoop, Src, SrcTy, BTC, SymbolicMaxBTC, &SE, &PointerBounds);
1966+ if (isa<SCEVCouldNotCompute>(SrcStart_) || isa<SCEVCouldNotCompute>(SrcEnd_))
1967+ return false ;
1968+
1969+ const auto &[SinkStart_, SinkEnd_] = getStartAndEndForAccess (
1970+ InnermostLoop, Sink, SinkTy, BTC, SymbolicMaxBTC, &SE, &PointerBounds);
1971+ if (isa<SCEVCouldNotCompute>(SinkStart_) ||
1972+ isa<SCEVCouldNotCompute>(SinkEnd_))
1973+ return false ;
1974+
1975+ if (!LoopGuards)
1976+ LoopGuards.emplace (ScalarEvolution::LoopGuards::collect (InnermostLoop, SE));
1977+
1978+ auto SrcEnd = SE.applyLoopGuards (SrcEnd_, *LoopGuards);
1979+ auto SinkStart = SE.applyLoopGuards (SinkStart_, *LoopGuards);
1980+ if (SE.isKnownPredicate (CmpInst::ICMP_ULE, SrcEnd, SinkStart))
1981+ return true ;
1982+
1983+ auto SinkEnd = SE.applyLoopGuards (SinkEnd_, *LoopGuards);
1984+ auto SrcStart = SE.applyLoopGuards (SrcStart_, *LoopGuards);
1985+ return SE.isKnownPredicate (CmpInst::ICMP_ULE, SinkEnd, SrcStart);
1986+ }
1987+
19571988std::variant<MemoryDepChecker::Dependence::DepType,
19581989 MemoryDepChecker::DepDistanceStrideAndSizeInfo>
19591990MemoryDepChecker::getDependenceDistanceStrideAndSize (
@@ -2001,37 +2032,13 @@ MemoryDepChecker::getDependenceDistanceStrideAndSize(
20012032 LLVM_DEBUG (dbgs () << " LAA: Distance for " << *AInst << " to " << *BInst
20022033 << " : " << *Dist << " \n " );
20032034
2004- // Check if we can prove that Sink only accesses memory after Src's end or
2005- // vice versa. At the moment this is limited to cases where either source or
2035+ // At the moment this is limited to cases where either source or
20062036 // sink are loop invariant to avoid compile-time increases. This is not
20072037 // required for correctness.
20082038 if (SE.isLoopInvariant (Src, InnermostLoop) ||
20092039 SE.isLoopInvariant (Sink, InnermostLoop)) {
2010- const SCEV *BTC = PSE.getBackedgeTakenCount ();
2011- const SCEV *SymbolicMaxBTC = PSE.getSymbolicMaxBackedgeTakenCount ();
2012- const auto &[SrcStart_, SrcEnd_] =
2013- getStartAndEndForAccess (InnermostLoop, Src, ATy, BTC, SymbolicMaxBTC,
2014- PSE.getSE (), &PointerBounds);
2015- const auto &[SinkStart_, SinkEnd_] =
2016- getStartAndEndForAccess (InnermostLoop, Sink, BTy, BTC, SymbolicMaxBTC,
2017- PSE.getSE (), &PointerBounds);
2018- if (!isa<SCEVCouldNotCompute>(SrcStart_) &&
2019- !isa<SCEVCouldNotCompute>(SrcEnd_) &&
2020- !isa<SCEVCouldNotCompute>(SinkStart_) &&
2021- !isa<SCEVCouldNotCompute>(SinkEnd_)) {
2022- if (!LoopGuards)
2023- LoopGuards.emplace (
2024- ScalarEvolution::LoopGuards::collect (InnermostLoop, SE));
2025- auto SrcEnd = SE.applyLoopGuards (SrcEnd_, *LoopGuards);
2026- auto SinkStart = SE.applyLoopGuards (SinkStart_, *LoopGuards);
2027- if (SE.isKnownPredicate (CmpInst::ICMP_ULE, SrcEnd, SinkStart))
2028- return MemoryDepChecker::Dependence::NoDep;
2029-
2030- auto SinkEnd = SE.applyLoopGuards (SinkEnd_, *LoopGuards);
2031- auto SrcStart = SE.applyLoopGuards (SrcStart_, *LoopGuards);
2032- if (SE.isKnownPredicate (CmpInst::ICMP_ULE, SinkEnd, SrcStart))
2033- return MemoryDepChecker::Dependence::NoDep;
2034- }
2040+ if (areAccessesCompletelyBeforeOrAfter (Src, ATy, Sink, BTy))
2041+ return Dependence::NoDep;
20352042 }
20362043
20372044 // Need accesses with constant strides and the same direction for further
0 commit comments