[llvm] [ValueTracking] For NUW, X + Y are not 0 if they are nonequal (PR #148101)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 10 19:15:21 PDT 2025


https://github.com/AZero13 created https://github.com/llvm/llvm-project/pull/148101

In NUW, X + Y is not 0 if X and Y are nonequal.

>From dc653c4466b6b188af18fb39d6249ebe6548d9e0 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Thu, 10 Jul 2025 22:05:10 -0400
Subject: [PATCH] [ValueTracking] For NUW, X + Y are not 0 if they are nonequal

In NUW, X + Y is not 0 if X and Y are nonequal.
---
 llvm/lib/Analysis/ValueTracking.cpp            | 15 +++++++++++++--
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  7 ++++++-
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 21f844c4d2f45..154dce6f1dfd5 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2833,19 +2833,27 @@ static bool isNonZeroAdd(const APInt &DemandedElts, const SimplifyQuery &Q,
   if (matchOpWithOpEqZero(X, Y))
     return true;
 
-  if (NUW)
+  if (NUW) {
+    // X + Y != 0 if X != Y, and X + Y is NUW.
+    if (isKnownNonEqual(X, Y, DemandedElts, Q, Depth))
+      return true;
     return isKnownNonZero(Y, DemandedElts, Q, Depth) ||
            isKnownNonZero(X, DemandedElts, Q, Depth);
+  }
 
   KnownBits XKnown = computeKnownBits(X, DemandedElts, Q, Depth);
   KnownBits YKnown = computeKnownBits(Y, DemandedElts, Q, Depth);
 
   // If X and Y are both non-negative (as signed values) then their sum is not
   // zero unless both X and Y are zero.
-  if (XKnown.isNonNegative() && YKnown.isNonNegative())
+  if (XKnown.isNonNegative() && YKnown.isNonNegative()) {
     if (isKnownNonZero(Y, DemandedElts, Q, Depth) ||
         isKnownNonZero(X, DemandedElts, Q, Depth))
       return true;
+    // X + Y != 0 if X != Y, and X + Y are both nonnegative.
+    if (isKnownNonEqual(X, Y, DemandedElts, Q, Depth))
+      return true;
+  }
 
   // If X and Y are both negative (as signed values) then their sum is not
   // zero unless both X and Y equal INT_MIN.
@@ -2859,6 +2867,9 @@ static bool isNonZeroAdd(const APInt &DemandedElts, const SimplifyQuery &Q,
     // to INT_MIN.
     if (YKnown.One.intersects(Mask))
       return true;
+    // X + Y != 0 because if they are not equal, they cannot both be INT_MIN.
+    if (isKnownNonEqual(X, Y, DemandedElts, Q, Depth))
+      return true;
   }
 
   // The sum of a non-negative number and a power of two is not zero.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index c1356239ad206..bd17b1d570858 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6015,10 +6015,15 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
     break;
 
   case ISD::ADD:
-    if (Op->getFlags().hasNoUnsignedWrap())
+    if (Op->getFlags().hasNoUnsignedWrap()) {
       if (isKnownNeverZero(Op.getOperand(1), Depth + 1) ||
           isKnownNeverZero(Op.getOperand(0), Depth + 1))
         return true;
+      std::optional<bool> ne =
+          KnownBits::ne(computeKnownBits(Op.getOperand(0), Depth + 1),
+                        computeKnownBits(Op.getOperand(1), Depth + 1));
+      return ne && *ne;
+    }
     // TODO: There are a lot more cases we can prove for add.
     break;
 



More information about the llvm-commits mailing list