[llvm] [ValueTracking] Have sub and xor in KnownNonZero take the same exact path (PR #146975)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 5 08:35:32 PDT 2025


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/146975

>From aa21780c91e16425617d31a7b494025714d3b0d1 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Sat, 5 Jul 2025 10:59:29 -0400
Subject: [PATCH 1/2] Pre-commit test (NFC)

---
 .../test/Transforms/InstCombine/ctpop-cttz.ll | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/ctpop-cttz.ll b/llvm/test/Transforms/InstCombine/ctpop-cttz.ll
index 4c5d7a7dc011b..b469a82a2af23 100644
--- a/llvm/test/Transforms/InstCombine/ctpop-cttz.ll
+++ b/llvm/test/Transforms/InstCombine/ctpop-cttz.ll
@@ -127,3 +127,24 @@ define <2 x i32> @ctpop3v_poison(<2 x i32> %0) {
   %5 = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %4)
   ret <2 x i32> %5
 }
+
+define i32 @ctpop_xor(i32 %x, i32 %y) {
+; CHECK-LABEL: @ctpop_xor(
+; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
+; CHECK:       true:
+; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[RET:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[XOR]])
+; CHECK-NEXT:    ret i32 [[RET]]
+; CHECK:       false:
+; CHECK-NEXT:    ret i32 0
+;
+  %cmp = icmp ne i32 %x, %y
+  br i1 %cmp, label %true, label %false
+true:
+  %xor = xor i32 %x, %y
+  %ret = call i32 @llvm.ctpop.i32(i32 %xor)
+  ret i32 %ret
+false:
+  ret i32 0
+}

>From 93bf56e68116daad627242f60cd3ff87aa90188e Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Thu, 3 Jul 2025 19:55:09 -0400
Subject: [PATCH 2/2] [ValueTracking] Have sub and xor in KnownNonZero take the
 same exact path

If x - y == 0, then x ^ y == 0. Therefore, we can do the exact same checks.

https://alive2.llvm.org/ce/z/MtBRoj
---
 llvm/lib/Analysis/ValueTracking.cpp            | 8 +++-----
 llvm/test/Transforms/InstCombine/ctpop-cttz.ll | 2 +-
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 09745ed6eac6a..5e80ddcfc0dd9 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3036,14 +3036,12 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
         return isKnownNonZero(TI->getOperand(0), DemandedElts, Q, Depth);
     break;
 
+  // Iff x - y == 0, then x ^ y == 0
+  // Therefore we can do the same exact checks
+  case Instruction::Xor:
   case Instruction::Sub:
     return isNonZeroSub(DemandedElts, Q, BitWidth, I->getOperand(0),
                         I->getOperand(1), Depth);
-  case Instruction::Xor:
-    // (X ^ (X != 0)) is non zero
-    if (matchOpWithOpEqZero(I->getOperand(0), I->getOperand(1)))
-      return true;
-    break;
   case Instruction::Or:
     // (X | (X != 0)) is non zero
     if (matchOpWithOpEqZero(I->getOperand(0), I->getOperand(1)))
diff --git a/llvm/test/Transforms/InstCombine/ctpop-cttz.ll b/llvm/test/Transforms/InstCombine/ctpop-cttz.ll
index b469a82a2af23..a1f0f01e2c470 100644
--- a/llvm/test/Transforms/InstCombine/ctpop-cttz.ll
+++ b/llvm/test/Transforms/InstCombine/ctpop-cttz.ll
@@ -134,7 +134,7 @@ define i32 @ctpop_xor(i32 %x, i32 %y) {
 ; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
 ; CHECK:       true:
 ; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X]], [[Y]]
-; CHECK-NEXT:    [[RET:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[XOR]])
+; CHECK-NEXT:    [[RET:%.*]] = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[XOR]])
 ; CHECK-NEXT:    ret i32 [[RET]]
 ; CHECK:       false:
 ; CHECK-NEXT:    ret i32 0



More information about the llvm-commits mailing list