Skip to content

Commit 9693056

Browse files
committed
[LAA] Move code to check if access are completely before/after (NFC).
Factor out code to check if access are completely before/after each other. This reduces the diff for an upcoming re-commit and moving to a function also helps to reduce the nesting level via early exits.
1 parent 1fdbe69 commit 9693056

File tree

2 files changed

+39
-27
lines changed

2 files changed

+39
-27
lines changed

llvm/include/llvm/Analysis/LoopAccessAnalysis.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,11 @@ class MemoryDepChecker {
423423
getDependenceDistanceStrideAndSize(const MemAccessInfo &A, Instruction *AInst,
424424
const MemAccessInfo &B,
425425
Instruction *BInst);
426+
427+
// Return true if we can prove that \p Sink only accesses memory after \p
428+
// Src's end or vice versa.
429+
bool areAccessesCompletelyBeforeOrAfter(const SCEV *Src, Type *SrcTy,
430+
const SCEV *Sink, Type *SinkTy);
426431
};
427432

428433
class RuntimePointerChecking;

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
19571988
std::variant<MemoryDepChecker::Dependence::DepType,
19581989
MemoryDepChecker::DepDistanceStrideAndSizeInfo>
19591990
MemoryDepChecker::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

Comments
 (0)