[llvm-branch-commits] [llvm] [DA] Fix the Weak Zero SIV tests when Delta is a signed minimum. (PR #184999)

Ryotaro Kasuga via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Mar 6 06:09:51 PST 2026


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

>From 540ee35f436e8798848f6d2493fd7576e12840d8 Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Fri, 6 Mar 2026 12:07:15 +0000
Subject: [PATCH] [DA] Fix the Weak Zero SIV tests when Delta is a signed
 minimum.

---
 llvm/lib/Analysis/DependenceAnalysis.cpp      | 65 +++++++++++++++----
 .../weak-zero-siv-delta-signed-min.ll         | 12 ++--
 2 files changed, 57 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 56177f11cc870..0ab8a993c02e5 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1153,6 +1153,39 @@ static const SCEV *minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B,
   return nullptr;
 }
 
+/// Returns whether \p A is guaranteed not to be the signed minimum value for
+/// its type.
+static bool isKnownNonSignedMinimum(const SCEV *A, ScalarEvolution &SE) {
+  IntegerType *Ty = cast<IntegerType>(A->getType());
+  if (!Ty)
+    return false;
+
+  const SCEV *SMin =
+      SE.getConstant(APInt::getSignedMinValue(Ty->getBitWidth()));
+  return SE.isKnownPredicate(CmpInst::ICMP_NE, A, SMin);
+}
+
+/// Returns the absolute value of \p A. In the context of dependence analysis,
+/// we need a negative value in a mathematical sense. If \p A is the signed
+/// minimum value, we cannot represent its negative value unless extending the
+/// original type. In that case, nullptr is returned to indicate the failure.
+static const SCEV *negativeSCEVNoSignedOverflow(const SCEV *A,
+                                                ScalarEvolution &SE) {
+  if (!isKnownNonSignedMinimum(A, SE))
+    return nullptr;
+  return SE.getNegativeSCEV(A);
+}
+
+/// Returns the absolute value of \p A. In the context of dependence analysis,
+/// we need an absolute value in a mathematical sense. If \p A is the signed
+/// minimum value, we cannot represent it unless extending the original type.
+/// In that case, nullptr is returned to indicate the failure.
+static const SCEV *absSCEVNoSignedOverflow(const SCEV *A, ScalarEvolution &SE) {
+  if (!isKnownNonSignedMinimum(A, SE))
+    return nullptr;
+  return SE.getAbsExpr(A, /*IsNSW=*/true);
+}
+
 /// Returns true iff \p Test is enabled.
 static bool isDependenceTestEnabled(DependenceTestType Test) {
   if (EnableDependenceTest == DependenceTestType::All)
@@ -1844,13 +1877,15 @@ bool DependenceInfo::weakZeroSrcSIVtest(const SCEV *DstCoeff,
   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;
+  const SCEV *AbsCoeff = absSCEVNoSignedOverflow(ConstCoeff, *SE);
+  if (!AbsCoeff)
+    return false;
+
+  const SCEV *NewDelta = SE->isKnownNegative(ConstCoeff)
+                             ? negativeSCEVNoSignedOverflow(Delta, *SE)
+                             : Delta;
+  if (!NewDelta)
+    return false;
 
   // check that Delta/SrcCoeff < iteration count
   // really check NewDelta < count*AbsCoeff
@@ -1956,13 +1991,15 @@ bool DependenceInfo::weakZeroDstSIVtest(const SCEV *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;
+  const SCEV *AbsCoeff = absSCEVNoSignedOverflow(ConstCoeff, *SE);
+  if (!AbsCoeff)
+    return false;
+
+  const SCEV *NewDelta = SE->isKnownNegative(ConstCoeff)
+                             ? negativeSCEVNoSignedOverflow(Delta, *SE)
+                             : Delta;
+  if (!NewDelta)
+    return false;
 
   // check that Delta/SrcCoeff < iteration count
   // really check NewDelta < count*AbsCoeff
diff --git a/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-delta-signed-min.ll b/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-delta-signed-min.ll
index 90c3477234043..01d4f218a18ec 100644
--- a/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-delta-signed-min.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/weak-zero-siv-delta-signed-min.ll
@@ -11,14 +11,14 @@
 ;     A[-i + (1 << 62)] = 1;
 ; }
 ;
-; FIXME: There is a dependency between the two stores in all directions.
+; There is a dependency between the two stores in all directions.
 ;
 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.0, align 1 --> Dst: store i8 0, ptr %gep.0, align 1
 ; CHECK-ALL-NEXT:    da analyze - output [S]!
 ; CHECK-ALL-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
-; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:    da analyze - output [*|<]!
 ; CHECK-ALL-NEXT:  Src: store i8 1, ptr %gep.1, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
 ; CHECK-ALL-NEXT:    da analyze - none!
 ;
@@ -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.0, align 1 --> Dst: store i8 0, ptr %gep.0, align 1
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [S]!
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.1, 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 %gep.1, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [*]!
 ;
@@ -63,14 +63,14 @@ exit:
 ;   A[-(1 << 62)] = 1;
 ; }
 ;
-; FIXME: There is a dependency between the two stores in all directions.
+; There is a dependency between the two stores in all directions.
 ;
 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 0, ptr %gep.0, align 1 --> Dst: store i8 0, ptr %gep.0, align 1
 ; CHECK-ALL-NEXT:    da analyze - none!
 ; CHECK-ALL-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
-; CHECK-ALL-NEXT:    da analyze - none!
+; CHECK-ALL-NEXT:    da analyze - output [*|<]!
 ; CHECK-ALL-NEXT:  Src: store i8 1, ptr %gep.1, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
 ; CHECK-ALL-NEXT:    da analyze - output [S]!
 ;
@@ -78,7 +78,7 @@ define void @weak_zero_dst_siv_large_btc(ptr %A) {
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 0, ptr %gep.0, align 1
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [*]!
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:  Src: store i8 0, ptr %gep.0, align 1 --> Dst: store i8 1, ptr %gep.1, 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 %gep.1, align 1 --> Dst: store i8 1, ptr %gep.1, align 1
 ; CHECK-WEAK-ZERO-SRC-SIV-NEXT:    da analyze - output [S]!
 ;



More information about the llvm-branch-commits mailing list