[llvm-branch-commits] [llvm] [DA] Consolidate the core logic of the Weak Zero SIV tests (NFCI) (PR #185577)
Ryotaro Kasuga via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Mar 9 23:04:31 PDT 2026
https://github.com/kasuga-fj updated https://github.com/llvm/llvm-project/pull/185577
>From 6907dc19ea641e584aa739eee10b13672fd09122 Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Mon, 9 Mar 2026 13:32:35 +0000
Subject: [PATCH] [DA] Consolidate the core logic of the Weak Zero SIV tests
(NFCI)
---
.../llvm/Analysis/DependenceAnalysis.h | 5 +
llvm/lib/Analysis/DependenceAnalysis.cpp | 199 +++++++-----------
2 files changed, 80 insertions(+), 124 deletions(-)
diff --git a/llvm/include/llvm/Analysis/DependenceAnalysis.h b/llvm/include/llvm/Analysis/DependenceAnalysis.h
index 7ced97c34715b..092280eddbc01 100644
--- a/llvm/include/llvm/Analysis/DependenceAnalysis.h
+++ b/llvm/include/llvm/Analysis/DependenceAnalysis.h
@@ -557,6 +557,11 @@ class DependenceInfo {
const Loop *CurrentSrcLoop, const Loop *CurrentDstLoop,
unsigned Level, FullDependence &Result) const;
+ /// weakZeroSIVtestImpl - Core implementation for weakZeroSrcSIVtest and
+ /// weakZeroDstSIVtest.
+ bool weakZeroSIVtestImpl(const SCEVAddRecExpr *AR, const SCEV *Const,
+ unsigned Level, FullDependence &Result) const;
+
/// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
/// (Src and Dst) for dependence.
/// Things of the form [c1] and [c2 + a*i],
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 29e04e59c414a..ed0a19b3332fd 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1785,77 +1785,32 @@ static bool isRemainderZero(const SCEVConstant *Dividend,
return ConstDividend.srem(ConstDivisor) == 0;
}
-// weakZeroSrcSIVtest -
-// From the paper, Practical Dependence Testing, Section 4.2.2
-//
-// When we have a pair of subscripts of the form [c1] and [c2 + a*i],
-// where i is an induction variable, c1 and c2 are loop invariant,
-// and a is a constant, we can solve it exactly using the
-// Weak-Zero SIV test.
-//
-// Given
-//
-// c1 = c2 + a*i
-//
-// we get
-//
-// (c1 - c2)/a = i
-//
-// If i is not an integer, there's no dependence.
-// If i < 0 or > UB, there's no dependence.
-// If i = 0, the direction is >= and peeling the
-// 1st iteration will break the dependence.
-// If i = UB, the direction is <= and peeling the
-// last iteration will break the dependence.
-// Otherwise, the direction is *.
-//
-// Can prove independence. Failing that, we can sometimes refine
-// the directions. Can sometimes show that first or last
-// iteration carries all the dependences (so worth peeling).
-//
-// (see also weakZeroDstSIVtest)
-//
-// Return true if dependence disproved.
-bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *SrcConst,
- const SCEVAddRecExpr *Dst,
- unsigned Level,
- FullDependence &Result) const {
- if (!isDependenceTestEnabled(DependenceTestType::WeakZeroSIV))
- return false;
-
- // For the WeakSIV test, it's possible the loop isn't common to
- // the Src and Dst loops. If it isn't, then there's no need to
- // record a direction.
- const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
- const SCEV *DstConst = Dst->getStart();
- LLVM_DEBUG(dbgs() << "\tWeak-Zero (src) SIV test\n");
- LLVM_DEBUG(dbgs() << "\t DstCoeff = " << *DstCoeff << "\n");
- LLVM_DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
- LLVM_DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
- ++WeakZeroSIVapplications;
- assert(0 < Level && Level <= MaxLevels && "Level out of range");
- Level--;
+bool DependenceInfo::weakZeroSIVtestImpl(const SCEVAddRecExpr *AR,
+ const SCEV *Const, unsigned Level,
+ FullDependence &Result) const {
+ const SCEV *ARCoeff = AR->getStepRecurrence(*SE);
+ const SCEV *ARConst = AR->getStart();
- ConstantRange SrcRange = SE->getSignedRange(SrcConst);
- ConstantRange DstRange = SE->getSignedRange(Dst);
- if (SrcRange.intersectWith(DstRange).isEmptySet()) {
+ ConstantRange ARRange = SE->getSignedRange(AR);
+ ConstantRange ConstRange = SE->getSignedRange(Const);
+ if (ARRange.intersectWith(ConstRange).isEmptySet()) {
++WeakZeroSIVindependence;
++WeakZeroSIVsuccesses;
return true;
}
- if (SrcConst == DstConst && SE->isKnownNonZero(DstCoeff)) {
+ if (Const == ARConst && SE->isKnownNonZero(ARCoeff)) {
if (Level < CommonLevels) {
- Result.DV[Level].Direction &= Dependence::DVEntry::GE;
+ Result.DV[Level].Direction &= Dependence::DVEntry::LE;
++WeakZeroSIVsuccesses;
}
return false; // dependences caused by first iteration
}
- const SCEV *Delta = minusSCEVNoSignedOverflow(SrcConst, DstConst, *SE);
+
+ const SCEV *Delta = minusSCEVNoSignedOverflow(Const, ARConst, *SE);
if (!Delta)
return false;
- LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
- const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
+ const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(ARCoeff);
if (!ConstCoeff)
return false;
@@ -1868,20 +1823,20 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *SrcConst,
SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
if (const SCEV *UpperBound =
- collectUpperBound(Dst->getLoop(), Delta->getType())) {
+ collectUpperBound(AR->getLoop(), Delta->getType())) {
LLVM_DEBUG(dbgs() << "\t UpperBound = " << *UpperBound << "\n");
const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
if (SE->isKnownPredicate(CmpInst::ICMP_EQ, NewDelta, Product)) {
// dependences caused by last iteration
if (Level < CommonLevels) {
- Result.DV[Level].Direction &= Dependence::DVEntry::LE;
+ Result.DV[Level].Direction &= Dependence::DVEntry::GE;
++WeakZeroSIVsuccesses;
}
return false;
}
}
- // check that Delta/SrcCoeff >= 0
+ // check that Delta/ARCoeff >= 0
// really check that NewDelta >= 0
if (SE->isKnownNegative(NewDelta)) {
// No dependence, newDelta < 0
@@ -1890,7 +1845,7 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *SrcConst,
return true;
}
- // if SrcCoeff doesn't divide Delta, then no dependence
+ // if ARCoeff doesn't divide Delta, then no dependence
if (isa<SCEVConstant>(Delta) &&
!isRemainderZero(cast<SCEVConstant>(Delta), ConstCoeff)) {
++WeakZeroSIVindependence;
@@ -1900,6 +1855,63 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *SrcConst,
return false;
}
+// weakZeroSrcSIVtest -
+// From the paper, Practical Dependence Testing, Section 4.2.2
+//
+// When we have a pair of subscripts of the form [c1] and [c2 + a*i],
+// where i is an induction variable, c1 and c2 are loop invariant,
+// and a is a constant, we can solve it exactly using the
+// Weak-Zero SIV test.
+//
+// Given
+//
+// c1 = c2 + a*i
+//
+// we get
+//
+// (c1 - c2)/a = i
+//
+// If i is not an integer, there's no dependence.
+// If i < 0 or > UB, there's no dependence.
+// If i = 0, the direction is >= and peeling the
+// 1st iteration will break the dependence.
+// If i = UB, the direction is <= and peeling the
+// last iteration will break the dependence.
+// Otherwise, the direction is *.
+//
+// Can prove independence. Failing that, we can sometimes refine
+// the directions. Can sometimes show that first or last
+// iteration carries all the dependences (so worth peeling).
+//
+// (see also weakZeroDstSIVtest)
+//
+// Return true if dependence disproved.
+bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *SrcConst,
+ const SCEVAddRecExpr *Dst,
+ unsigned Level,
+ FullDependence &Result) const {
+ if (!isDependenceTestEnabled(DependenceTestType::WeakZeroSIV))
+ return false;
+
+ // For the WeakSIV test, it's possible the loop isn't common to
+ // the Src and Dst loops. If it isn't, then there's no need to
+ // record a direction.
+ const SCEV *DstCoeff = Dst->getStepRecurrence(*SE);
+ const SCEV *DstConst = Dst->getStart();
+ LLVM_DEBUG(dbgs() << "\tWeak-Zero (src) SIV test\n");
+ LLVM_DEBUG(dbgs() << "\t DstCoeff = " << *DstCoeff << "\n");
+ LLVM_DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
+ LLVM_DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
+ ++WeakZeroSIVapplications;
+ assert(0 < Level && Level <= MaxLevels && "Level out of range");
+ Level--;
+
+ Result.reverse(*SE);
+ bool Res = weakZeroSIVtestImpl(Dst, SrcConst, Level, Result);
+ Result.reverse(*SE);
+ return Res;
+}
+
// weakZeroDstSIVtest -
// From the paper, Practical Dependence Testing, Section 4.2.2
//
@@ -1949,68 +1961,7 @@ bool DependenceInfo::weakZeroDstSIVtest(const SCEVAddRecExpr *Src,
assert(0 < Level && Level <= SrcLevels && "Level out of range");
Level--;
- ConstantRange SrcRange = SE->getSignedRange(Src);
- ConstantRange DstRange = SE->getSignedRange(DstConst);
- if (SrcRange.intersectWith(DstRange).isEmptySet()) {
- ++WeakZeroSIVindependence;
- ++WeakZeroSIVsuccesses;
- return true;
- }
-
- if (DstConst == SrcConst && SE->isKnownNonZero(SrcCoeff)) {
- if (Level < CommonLevels) {
- Result.DV[Level].Direction &= Dependence::DVEntry::LE;
- ++WeakZeroSIVsuccesses;
- }
- return false; // dependences caused by first iteration
- }
- const SCEV *Delta = minusSCEVNoSignedOverflow(DstConst, SrcConst, *SE);
- if (!Delta)
- return false;
- LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
- const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
- if (!ConstCoeff)
- return false;
-
- // Since ConstCoeff is constant, !isKnownNegative means it's non-negative.
- // TODO: Bail out if it's a signed minimum value.
- const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
- ? SE->getNegativeSCEV(ConstCoeff)
- : ConstCoeff;
- const SCEV *NewDelta =
- SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
-
- if (const SCEV *UpperBound =
- collectUpperBound(Src->getLoop(), Delta->getType())) {
- LLVM_DEBUG(dbgs() << "\t UpperBound = " << *UpperBound << "\n");
- const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
- if (SE->isKnownPredicate(CmpInst::ICMP_EQ, NewDelta, Product)) {
- // dependences caused by last iteration
- if (Level < CommonLevels) {
- Result.DV[Level].Direction &= Dependence::DVEntry::GE;
- ++WeakZeroSIVsuccesses;
- }
- return false;
- }
- }
-
- // check that Delta/SrcCoeff >= 0
- // really check that NewDelta >= 0
- if (SE->isKnownNegative(NewDelta)) {
- // No dependence, newDelta < 0
- ++WeakZeroSIVindependence;
- ++WeakZeroSIVsuccesses;
- return true;
- }
-
- // if SrcCoeff doesn't divide Delta, then no dependence
- if (isa<SCEVConstant>(Delta) &&
- !isRemainderZero(cast<SCEVConstant>(Delta), ConstCoeff)) {
- ++WeakZeroSIVindependence;
- ++WeakZeroSIVsuccesses;
- return true;
- }
- return false;
+ return weakZeroSIVtestImpl(Src, DstConst, Level, Result);
}
// exactRDIVtest - Tests the RDIV subscript pair for dependence.
More information about the llvm-branch-commits
mailing list