[llvm-branch-commits] [llvm] [DA] Fix overflow of calculation in weakCrossingSIVtest (PR #188450)

Ruoyu Qiu via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Mar 26 03:01:48 PDT 2026


https://github.com/cabbaken updated https://github.com/llvm/llvm-project/pull/188450

>From bd5e296a9d8ebf0ef17909ec89c439f91f12c4a9 Mon Sep 17 00:00:00 2001
From: Ruoyu Qiu <cabbaken at outlook.com>
Date: Wed, 25 Mar 2026 09:44:15 +0000
Subject: [PATCH 1/2] [DA] Fix overflow of calculation in weakCrossingSIVtest

This patch fixes a correctness issue where integer overflow in the
upper bound calculation of weakCrossingSIVtest caused the pass to
incorrectly prove independence.

The previous logic used `SCEV::getMulExpr` to calculate
`2 * ConstCoeff * UpperBound` and compared it to `Delta` using
`isKnownPredicate`. In the presence of overflow, this could yield
unsafe results.

This change replaces the SCEV arithmetic with `ConstantRange` and
its operation (`smul_fast`). If the calculation overflows,
`intersectWith(MLRange).isEmptySet()` would be false, ensures we
conservatively assume a dependence if the bounds cannot be proven
safe.

Signed-off-by: Ruoyu Qiu <cabbaken at outlook.com>
---
 llvm/lib/Analysis/DependenceAnalysis.cpp       | 18 ++++++++++++------
 .../weak-crossing-siv-overflow.ll              |  4 ++--
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 6d449ae374400..25d1540ca763c 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1454,17 +1454,23 @@ bool DependenceInfo::weakCrossingSIVtest(const SCEV *Coeff,
   if (const SCEV *UpperBound =
           collectUpperBound(CurSrcLoop, Delta->getType())) {
     LLVM_DEBUG(dbgs() << "\t    UpperBound = " << *UpperBound << "\n");
-    const SCEV *ConstantTwo = SE->getConstant(UpperBound->getType(), 2);
-    const SCEV *ML =
-        SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound), ConstantTwo);
-    LLVM_DEBUG(dbgs() << "\t    ML = " << *ML << "\n");
-    if (SE->isKnownPredicate(CmpInst::ICMP_SGT, Delta, ML)) {
+    ConstantRange UBRange = SE->getSignedRange(UpperBound);
+    ConstantRange MLRange =
+        UBRange.smul_fast(ConstCoeff->getAPInt())
+            .smul_fast(APInt(Distance.getBitWidth(), 2, true));
+    ConstantRange DeltaRange(ConstDelta->getAPInt());
+    LLVM_DEBUG(dbgs() << "\t    UBRange = " << UBRange << "\n");
+    LLVM_DEBUG(dbgs() << "\t    MLRange = " << MLRange << "\n");
+    LLVM_DEBUG(dbgs() << "\t    DeltaRange = " << DeltaRange << "\n");
+
+    if (DeltaRange.intersectWith(MLRange).isEmptySet() &&
+        DeltaRange.getSignedMin().sgt(MLRange.getSignedMax())) {
       // Delta too big, no dependence
       ++WeakCrossingSIVindependence;
       ++WeakCrossingSIVsuccesses;
       return true;
     }
-    if (SE->isKnownPredicate(CmpInst::ICMP_EQ, Delta, ML)) {
+    if (DeltaRange.getSignedMin().eq(MLRange.getSignedMax())) {
       // i = i' = UB
       Result.DV[Level].Direction &= ~Dependence::DVEntry::LT;
       Result.DV[Level].Direction &= ~Dependence::DVEntry::GT;
diff --git a/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll
index acc1c0a69eb0f..a44b8d4a2c533 100644
--- a/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll
@@ -89,7 +89,7 @@ define void @weakcorssing_prod_ovfl(ptr %A) {
 ; CHECK-ALL-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
 ; CHECK-ALL-NEXT:    da analyze - none!
 ; CHECK-ALL-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
-; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:    da analyze - output [*|<]!
 ; CHECK-ALL-NEXT:  Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
 ; CHECK-ALL-NEXT:    da analyze - none!
 ;
@@ -97,7 +97,7 @@ define void @weakcorssing_prod_ovfl(ptr %A) {
 ; CHECK-WEAK-CROSSING-SIV-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
 ; CHECK-WEAK-CROSSING-SIV-NEXT:    da analyze - output [*]!
 ; CHECK-WEAK-CROSSING-SIV-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
-; CHECK-WEAK-CROSSING-SIV-NEXT:    da analyze - none!
+; CHECK-WEAK-CROSSING-SIV-NEXT:    da analyze - output [*|<]!
 ; CHECK-WEAK-CROSSING-SIV-NEXT:  Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
 ; CHECK-WEAK-CROSSING-SIV-NEXT:    da analyze - output [*]!
 ;

>From 6359edd29a86158aefea5fe23d1162e597993607 Mon Sep 17 00:00:00 2001
From: Ruoyu Qiu <cabbaken at outlook.com>
Date: Thu, 26 Mar 2026 10:01:02 +0000
Subject: [PATCH 2/2] update

Signed-off-by: Ruoyu Qiu <cabbaken at outlook.com>
---
 llvm/lib/Analysis/DependenceAnalysis.cpp      | 31 +++++-----
 .../weak-crossing-siv-overflow.ll             | 59 +++++++++++++++++++
 2 files changed, 75 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 25d1540ca763c..08826c96d7b07 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1463,24 +1463,25 @@ bool DependenceInfo::weakCrossingSIVtest(const SCEV *Coeff,
     LLVM_DEBUG(dbgs() << "\t    MLRange = " << MLRange << "\n");
     LLVM_DEBUG(dbgs() << "\t    DeltaRange = " << DeltaRange << "\n");
 
-    if (DeltaRange.intersectWith(MLRange).isEmptySet() &&
-        DeltaRange.getSignedMin().sgt(MLRange.getSignedMax())) {
-      // Delta too big, no dependence
-      ++WeakCrossingSIVindependence;
-      ++WeakCrossingSIVsuccesses;
-      return true;
-    }
-    if (DeltaRange.getSignedMin().eq(MLRange.getSignedMax())) {
-      // i = i' = UB
-      Result.DV[Level].Direction &= ~Dependence::DVEntry::LT;
-      Result.DV[Level].Direction &= ~Dependence::DVEntry::GT;
-      ++WeakCrossingSIVsuccesses;
-      if (!Result.DV[Level].Direction) {
+    if (!MLRange.isFullSet()) {
+      if (APDelta.sgt(MLRange.getSignedMax())) {
+        // Delta too big, no dependence
         ++WeakCrossingSIVindependence;
+        ++WeakCrossingSIVsuccesses;
         return true;
       }
-      Result.DV[Level].Distance = SE->getZero(Delta->getType());
-      return false;
+      if (APDelta.eq(MLRange.getSignedMax())) {
+        // i = i' = UB
+        Result.DV[Level].Direction &= ~Dependence::DVEntry::LT;
+        Result.DV[Level].Direction &= ~Dependence::DVEntry::GT;
+        ++WeakCrossingSIVsuccesses;
+        if (!Result.DV[Level].Direction) {
+          ++WeakCrossingSIVindependence;
+          return true;
+        }
+        Result.DV[Level].Distance = SE->getZero(Delta->getType());
+        return false;
+      }
     }
   }
 
diff --git a/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll b/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll
index a44b8d4a2c533..4d5ab4bf50b7c 100644
--- a/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/weak-crossing-siv-overflow.ll
@@ -118,6 +118,65 @@ loop:
   %ec = icmp sgt i64 %i.inc, 3074457345618258602
   br i1 %ec, label %exit, label %loop
 
+exit:
+  ret void
+}
+
+; max_i = 1ULL << 62 // 4611686018427387904
+; for (long long i = 0; i <= max_i; i++) {
+;   A[i - ((1ULL << 62) - 1)] = 0;
+;   A[-i + (1ULL << 62)] = 1;
+; }
+;
+; There is a dependence between `A[i - ((1ULL << 62) - 1)]`
+; and `A[-i + (1ULL << 62)]`, for example,
+;
+;  memory access              | i == 0                  | i == 1                  | i == max_i - 1 | i == max_i
+; ----------------------------|-------------------------|-------------------------|----------------|------------------
+;  A[i - ((1ULL << 62) - 1)]  | A[-4611686018427387903] | A[-4611686018427387902] | A[0]           | A[1]
+;  A[-i + (1ULL << 62)]       | A[4611686018427387904]  | A[4611686018427387903]  | A[1]           | A[0]
+;
+; The root cause is that the product of the BTC, the coefficient, and 2
+; triggers an overflow.
+
+define void @test_weakcrossing_siv_overflow(ptr %A) {
+; CHECK-ALL-LABEL: 'test_weakcrossing_siv_overflow'
+; CHECK-ALL-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
+; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-ALL-NEXT:    da analyze - output [<>]!
+; CHECK-ALL-NEXT:  Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-ALL-NEXT:    da analyze - none!
+;
+; CHECK-WEAK-CROSSING-SIV-LABEL: 'test_weakcrossing_siv_overflow'
+; CHECK-WEAK-CROSSING-SIV-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT:    da analyze - output [*]!
+; CHECK-WEAK-CROSSING-SIV-NEXT:  Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT:    da analyze - output [<>]!
+; CHECK-WEAK-CROSSING-SIV-NEXT:  Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
+; CHECK-WEAK-CROSSING-SIV-NEXT:    da analyze - output [*]!
+;
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ]
+  %subscript.0 = phi i64 [ -4611686018427387903, %entry ], [ %subscript.0.next, %loop ]
+  %subscript.1 = phi i64 [ 4611686018427387904, %entry ], [ %subscript.1.next, %loop ]
+
+  %idx.0 = getelementptr inbounds i8, ptr %A, i64 %subscript.0
+  store i8 0, ptr %idx.0
+
+  %idx.1 = getelementptr inbounds i8, ptr %A, i64 %subscript.1
+  store i8 1, ptr %idx.1
+
+  %i.inc = add nuw nsw i64 %i, 1
+  %subscript.0.next = add nsw i64 %subscript.0, 1
+  %subscript.1.next = add nsw i64 %subscript.1, -1
+
+  %ec = icmp sgt i64 %i.inc, 4611686018427387904
+  br i1 %ec, label %exit, label %loop
+
 exit:
   ret void
 }



More information about the llvm-branch-commits mailing list