[llvm] [DA] Rewrite formula in the Weak Zero SIV tests (PR #183738)

Ryotaro Kasuga via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 6 02:57:23 PST 2026


https://github.com/kasuga-fj updated https://github.com/llvm/llvm-project/pull/183738

>From cd0f762131401fa518e0bfc6dcf18cc87dfc9dca Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Fri, 27 Feb 2026 12:53:35 +0000
Subject: [PATCH] [DA] Rewrite formula in the Weak Zero SIV tests

---
 .../llvm/Analysis/DependenceAnalysis.h        | 12 ++--
 llvm/lib/Analysis/DependenceAnalysis.cpp      | 67 +++++++++----------
 .../weak-zero-siv-large-btc.ll                | 16 ++---
 .../weak-zero-siv-overflow.ll                 |  8 +--
 4 files changed, 45 insertions(+), 58 deletions(-)

diff --git a/llvm/include/llvm/Analysis/DependenceAnalysis.h b/llvm/include/llvm/Analysis/DependenceAnalysis.h
index 6320caf09dd35..b644af3f2ca4a 100644
--- a/llvm/include/llvm/Analysis/DependenceAnalysis.h
+++ b/llvm/include/llvm/Analysis/DependenceAnalysis.h
@@ -561,10 +561,8 @@ class DependenceInfo {
   /// Sets appropriate direction entry.
   /// Set consistent to false.
   /// If loop peeling will break the dependence, mark appropriately.
-  bool weakZeroSrcSIVtest(const SCEV *DstCoeff, const SCEV *SrcConst,
-                          const SCEV *DstConst, const Loop *CurrentSrcLoop,
-                          const Loop *CurrentDstLoop, unsigned Level,
-                          FullDependence &Result) const;
+  bool weakZeroSrcSIVtest(const SCEV *SrcConst, const SCEVAddRecExpr *Dst,
+                          unsigned Level, FullDependence &Result) const;
 
   /// weakZeroDstSIVtest - Tests the weak-zero SIV subscript pair
   /// (Src and Dst) for dependence.
@@ -576,10 +574,8 @@ class DependenceInfo {
   /// Sets appropriate direction entry.
   /// Set consistent to false.
   /// If loop peeling will break the dependence, mark appropriately.
-  bool weakZeroDstSIVtest(const SCEV *SrcCoeff, const SCEV *SrcConst,
-                          const SCEV *DstConst, const Loop *CurrentSrcLoop,
-                          const Loop *CurrentDstLoop, unsigned Level,
-                          FullDependence &Result) const;
+  bool weakZeroDstSIVtest(const SCEVAddRecExpr *Src, const SCEV *DstConst,
+                          unsigned Level, FullDependence &Result) const;
 
   /// exactRDIVtest - Tests the RDIV subscript pair for dependence.
   /// Things of the form [c1 + a*i] and [c2 + b*j],
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index a9f436c0d32a7..c4940fea46e5e 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1810,11 +1810,9 @@ static bool isRemainderZero(const SCEVConstant *Dividend,
 // (see also weakZeroDstSIVtest)
 //
 // Return true if dependence disproved.
-bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *DstCoeff,
-                                        const SCEV *SrcConst,
-                                        const SCEV *DstConst,
-                                        const Loop *CurSrcLoop,
-                                        const Loop *CurDstLoop, unsigned Level,
+bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *SrcConst,
+                                        const SCEVAddRecExpr *Dst,
+                                        unsigned Level,
                                         FullDependence &Result) const {
   if (!isDependenceTestEnabled(DependenceTestType::WeakZeroSIV))
     return false;
@@ -1822,6 +1820,8 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *DstCoeff,
   // 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");
@@ -1829,6 +1829,15 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *DstCoeff,
   ++WeakZeroSIVapplications;
   assert(0 < Level && Level <= MaxLevels && "Level out of range");
   Level--;
+
+  ConstantRange SrcRange = SE->getSignedRange(SrcConst);
+  ConstantRange DstRange = SE->getSignedRange(Dst);
+  if (SrcRange.intersectWith(DstRange).isEmptySet()) {
+    ++WeakZeroSIVindependence;
+    ++WeakZeroSIVsuccesses;
+    return true;
+  }
+
   const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
   LLVM_DEBUG(dbgs() << "\t    Delta = " << *Delta << "\n");
   if (SrcConst == DstConst && SE->isKnownNonZero(DstCoeff)) {
@@ -1850,17 +1859,10 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *DstCoeff,
   const SCEV *NewDelta =
       SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
 
-  // check that Delta/SrcCoeff < iteration count
-  // really check NewDelta < count*AbsCoeff
   if (const SCEV *UpperBound =
-          collectUpperBound(CurSrcLoop, Delta->getType())) {
+          collectUpperBound(Dst->getLoop(), Delta->getType())) {
     LLVM_DEBUG(dbgs() << "\t    UpperBound = " << *UpperBound << "\n");
     const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
-    if (SE->isKnownPredicate(CmpInst::ICMP_SGT, NewDelta, Product)) {
-      ++WeakZeroSIVindependence;
-      ++WeakZeroSIVsuccesses;
-      return true;
-    }
     if (SE->isKnownPredicate(CmpInst::ICMP_EQ, NewDelta, Product)) {
       // dependences caused by last iteration
       if (Level < CommonLevels) {
@@ -1921,17 +1923,16 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *DstCoeff,
 // (see also weakZeroSrcSIVtest)
 //
 // Return true if dependence disproved.
-bool DependenceInfo::weakZeroDstSIVtest(const SCEV *SrcCoeff,
-                                        const SCEV *SrcConst,
-                                        const SCEV *DstConst,
-                                        const Loop *CurSrcLoop,
-                                        const Loop *CurDstLoop, unsigned Level,
+bool DependenceInfo::weakZeroDstSIVtest(const SCEVAddRecExpr *Src,
+                                        const SCEV *DstConst, 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 *SrcCoeff = Src->getStepRecurrence(*SE);
+  const SCEV *SrcConst = Src->getStart();
   LLVM_DEBUG(dbgs() << "\tWeak-Zero (dst) SIV test\n");
   LLVM_DEBUG(dbgs() << "\t    SrcCoeff = " << *SrcCoeff << "\n");
   LLVM_DEBUG(dbgs() << "\t    SrcConst = " << *SrcConst << "\n");
@@ -1939,6 +1940,15 @@ bool DependenceInfo::weakZeroDstSIVtest(const SCEV *SrcCoeff,
   ++WeakZeroSIVapplications;
   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;
+  }
+
   const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
   LLVM_DEBUG(dbgs() << "\t    Delta = " << *Delta << "\n");
   if (DstConst == SrcConst && SE->isKnownNonZero(SrcCoeff)) {
@@ -1960,17 +1970,10 @@ bool DependenceInfo::weakZeroDstSIVtest(const SCEV *SrcCoeff,
   const SCEV *NewDelta =
       SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
 
-  // check that Delta/SrcCoeff < iteration count
-  // really check NewDelta < count*AbsCoeff
   if (const SCEV *UpperBound =
-          collectUpperBound(CurSrcLoop, Delta->getType())) {
+          collectUpperBound(Src->getLoop(), Delta->getType())) {
     LLVM_DEBUG(dbgs() << "\t    UpperBound = " << *UpperBound << "\n");
     const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
-    if (SE->isKnownPredicate(CmpInst::ICMP_SGT, NewDelta, Product)) {
-      ++WeakZeroSIVindependence;
-      ++WeakZeroSIVsuccesses;
-      return true;
-    }
     if (SE->isKnownPredicate(CmpInst::ICMP_EQ, NewDelta, Product)) {
       // dependences caused by last iteration
       if (Level < CommonLevels) {
@@ -2300,23 +2303,15 @@ bool DependenceInfo::testSIV(const SCEV *Src, const SCEV *Dst, unsigned &Level,
                             CurDstLoop);
   }
   if (SrcAddRec) {
-    const SCEV *SrcConst = SrcAddRec->getStart();
-    const SCEV *SrcCoeff = SrcAddRec->getStepRecurrence(*SE);
-    const SCEV *DstConst = Dst;
     const Loop *CurSrcLoop = SrcAddRec->getLoop();
     Level = mapSrcLoop(CurSrcLoop);
-    return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurSrcLoop,
-                              CurSrcLoop, Level, Result) ||
+    return weakZeroDstSIVtest(SrcAddRec, Dst, Level, Result) ||
            gcdMIVtest(Src, Dst, Result);
   }
   if (DstAddRec) {
-    const SCEV *DstConst = DstAddRec->getStart();
-    const SCEV *DstCoeff = DstAddRec->getStepRecurrence(*SE);
-    const SCEV *SrcConst = Src;
     const Loop *CurDstLoop = DstAddRec->getLoop();
     Level = mapDstLoop(CurDstLoop);
-    return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst, CurDstLoop,
-                              CurDstLoop, Level, Result) ||
+    return weakZeroSrcSIVtest(Src, DstAddRec, Level, Result) ||
            gcdMIVtest(Src, Dst, Result);
   }
   llvm_unreachable("SIV test expected at least one AddRec");
diff --git a/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-large-btc.ll b/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-large-btc.ll
index 144efa45ed2cb..e5aa0cac5a6e3 100644
--- a/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-large-btc.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-large-btc.ll
@@ -10,15 +10,15 @@
 ;   A[0] = 1;
 ; }
 ;
-; FIXME: `A[i] = 0` will be executed (when i == 0), so there is a ; dependency
-; between the ; two stores.
+; `A[i] = 0` will be executed (when i == 0), so there is a dependency between
+; the two stores.
 ;
 define void @weak_zero_src_siv_large_btc(ptr %A) {
 ; CHECK-ALL-LABEL: 'weak_zero_src_siv_large_btc'
 ; CHECK-ALL-NEXT:  Src: store i8 0, ptr %gep, align 1 --> Dst: store i8 0, ptr %gep, align 1
 ; CHECK-ALL-NEXT:    da analyze - none!
 ; CHECK-ALL-NEXT:  Src: store i8 0, ptr %gep, align 1 --> Dst: store i8 1, ptr %A, align 1
-; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:    da analyze - output [*|<]!
 ; CHECK-ALL-NEXT:  Src: store i8 1, ptr %A, align 1 --> Dst: store i8 1, ptr %A, align 1
 ; CHECK-ALL-NEXT:    da analyze - output [S]!
 ;
@@ -26,7 +26,7 @@ define void @weak_zero_src_siv_large_btc(ptr %A) {
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 0, ptr %gep, align 1 --> Dst: store i8 0, ptr %gep, align 1
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [*]!
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 0, ptr %gep, align 1 --> Dst: store i8 1, ptr %A, align 1
-; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - none!
+; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [*|<]!
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 1, ptr %A, align 1 --> Dst: store i8 1, ptr %A, align 1
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [S]!
 ;
@@ -60,15 +60,15 @@ exit:
 ;     A[i] = 0;
 ; }
 ;
-; FIXME: `A[i] = 0` will be executed (when i == 0), so there is a ; dependency
-; between the ; two stores.
+; `A[i] = 0` will be executed (when i == 0), so there is a dependency between
+; the two stores.
 ;
 define void @weak_zero_dst_siv_large_btc(ptr %A) {
 ; CHECK-ALL-LABEL: 'weak_zero_dst_siv_large_btc'
 ; CHECK-ALL-NEXT:  Src: store i8 1, ptr %A, align 1 --> Dst: store i8 1, ptr %A, align 1
 ; CHECK-ALL-NEXT:    da analyze - output [S]!
 ; CHECK-ALL-NEXT:  Src: store i8 1, ptr %A, align 1 --> Dst: store i8 0, ptr %gep, align 1
-; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:    da analyze - output [*|<]!
 ; CHECK-ALL-NEXT:  Src: store i8 0, ptr %gep, align 1 --> Dst: store i8 0, ptr %gep, align 1
 ; CHECK-ALL-NEXT:    da analyze - none!
 ;
@@ -76,7 +76,7 @@ define void @weak_zero_dst_siv_large_btc(ptr %A) {
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 1, ptr %A, align 1 --> Dst: store i8 1, ptr %A, align 1
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [S]!
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 1, ptr %A, align 1 --> Dst: store i8 0, ptr %gep, align 1
-; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - none!
+; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [*|<]!
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 0, ptr %gep, align 1 --> Dst: store i8 0, ptr %gep, align 1
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [*]!
 ;
diff --git a/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-overflow.ll
index f388502ac2a43..63a295cca35cd 100644
--- a/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-overflow.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-overflow.ll
@@ -10,16 +10,12 @@
 ;   A[2] = 2;
 ; }
 ;
-; FIXME: DependenceAnalysis currently detects no dependency between the two
-; stores, but it does exist. The root cause is that the product of the BTC and
-; the coefficient ((1LL << 62) - 1 and 2) overflows in a signed sense.
-;
 define void @weakzero_dst_siv_prod_ovfl(ptr %A) {
 ; CHECK-ALL-LABEL: 'weakzero_dst_siv_prod_ovfl'
 ; CHECK-ALL-NEXT:  Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
 ; CHECK-ALL-NEXT:    da analyze - none!
 ; CHECK-ALL-NEXT:  Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
-; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:    da analyze - output [*|<]!
 ; CHECK-ALL-NEXT:  Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
 ; CHECK-ALL-NEXT:    da analyze - output [S]!
 ;
@@ -27,7 +23,7 @@ define void @weakzero_dst_siv_prod_ovfl(ptr %A) {
 ; CHECK-WEAK-ZERO-SIV-NEXT:  Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.0, align 1
 ; CHECK-WEAK-ZERO-SIV-NEXT:    da analyze - output [*]!
 ; CHECK-WEAK-ZERO-SIV-NEXT:  Src: store i8 1, ptr %gep.0, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
-; CHECK-WEAK-ZERO-SIV-NEXT:    da analyze - none!
+; CHECK-WEAK-ZERO-SIV-NEXT:    da analyze - output [*|<]!
 ; CHECK-WEAK-ZERO-SIV-NEXT:  Src: store i8 2, ptr %gep.1, align 1 --> Dst: store i8 2, ptr %gep.1, align 1
 ; CHECK-WEAK-ZERO-SIV-NEXT:    da analyze - output [S]!
 ;



More information about the llvm-commits mailing list