[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