[llvm] [ValueTracking] Recognize non-negative results of NSW additions (PR #219132)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 00:22:44 PDT 2026
https://github.com/VachanVY updated https://github.com/llvm/llvm-project/pull/219132
>From 12405d79b47306f5820c9bba58da1a541e0dc04e Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Thu, 27 Aug 2026 12:41:09 +0530
Subject: [PATCH 1/2] [ValueTracking] Pre-commit tests. NFC
---
llvm/test/Transforms/InstCombine/div.ll | 68 +++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index 2adf6036d4bcf..3df78779fc8ed 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -2033,6 +2033,74 @@ define <2 x i32> @sdiv_select_one_false_poison_vec(<2 x i32> %a, i1 %b) {
ret <2 x i32> %div
}
+define i32 @sdiv_add_nonneg_guard(i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_add_nonneg_guard(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[OR]], -1
+; CHECK-NEXT: br i1 [[CMP]], label %[[CONT:.*]], label %[[UNREACHABLE:.*]]
+; CHECK: [[CONT]]:
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[Y]], [[X]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ADD]], 2
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %c0 = icmp slt i32 %x, 0
+ %c1 = icmp slt i32 %y, 0
+ %or = or i1 %c0, %c1
+ br i1 %or, label %unreachable, label %cont
+
+unreachable:
+ unreachable
+
+cont:
+ %add = add nsw i32 %x, %y
+ %div = sdiv i32 %add, 2
+ ret i32 %div
+}
+
+define i32 @sdiv_add3_nonneg_guard(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: @sdiv_add3_nonneg_guard(
+; CHECK: [[ADD0:%.*]] = add nsw i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD0]], [[Z:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ADD1]], 2
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %or0 = or i32 %x, %y
+ %or1 = or i32 %or0, %z
+ %cmp = icmp sge i32 %or1, 0
+ br i1 %cmp, label %cont, label %unreachable
+
+unreachable:
+ unreachable
+
+cont:
+ %add0 = add nsw i32 %x, %y
+ %add1 = add nsw i32 %add0, %z
+ %div = sdiv i32 %add1, 2
+ ret i32 %div
+}
+
+define i32 @sdiv_add_or_may_be_negative(i32 %x, i32 %y) {
+; CHECK-LABEL: @sdiv_add_or_may_be_negative(
+; CHECK: [[DIV:%.*]] = sdiv i32 {{%.*}}, 2
+; CHECK-NEXT: ret i32 [[DIV]]
+;
+entry:
+ %or = or i32 %x, %y
+ %cmp = icmp sgt i32 %or, -2
+ br i1 %cmp, label %cont, label %unreachable
+
+unreachable:
+ unreachable
+
+cont:
+ %add = add nsw i32 %x, %y
+ %div = sdiv i32 %add, 2
+ ret i32 %div
+}
+
!0 = !{!"function_entry_count", i64 1000}
;.
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
>From d2f8b25e9d0a44f761f56e4ea9a3a7e1a7ddce7d Mon Sep 17 00:00:00 2001
From: Vachan V Y <vachanvy05 at gmail.com>
Date: Thu, 27 Aug 2026 12:41:40 +0530
Subject: [PATCH 2/2] [ValueTracking] Optimization + check diff; fix #212382
---
llvm/lib/Analysis/ValueTracking.cpp | 37 +++++++++++++++++++++++++
llvm/test/Transforms/InstCombine/div.ll | 10 +++----
2 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index efc14f9a639da..4c96aeaee82f7 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -887,6 +887,31 @@ static bool isKnownNonZeroFromAssume(const Value *V, const SimplifyQuery &Q) {
return false;
}
+static bool visitOrTree(Value *Root,
+ function_ref<bool(Value *)> VisitOperand) {
+ SmallVector<Value *, 4> Worklist = {Root};
+ SmallPtrSet<Value *, 4> Visited = {Root};
+ while (!Worklist.empty()) {
+ Value *X, *Y;
+ if (!match(Worklist.pop_back_val(), m_Or(m_Value(X), m_Value(Y))))
+ continue;
+
+ for (Value *Op : {X, Y}) {
+ if (!Visited.insert(Op).second)
+ continue;
+ if (VisitOperand(Op))
+ return true;
+ Worklist.push_back(Op);
+ }
+ }
+ return false;
+}
+
+static bool isValueInOrTree(const Value *V, Value *Root) {
+ return V == Root ||
+ visitOrTree(Root, [V](Value *Op) { return V == Op; });
+}
+
static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
Value *LHS, Value *RHS, KnownBits &Known,
const SimplifyQuery &Q) {
@@ -989,6 +1014,10 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
(*C - (Pred == ICmpInst::ICMP_ULT)).countLeadingZeros());
}
}
+ if (((Pred == ICmpInst::ICMP_SGT && C->isAllOnes()) ||
+ (Pred == ICmpInst::ICMP_SGE && C->isZero())) &&
+ isValueInOrTree(V, LHS))
+ Known.makeNonNegative();
} break;
}
}
@@ -10723,6 +10752,14 @@ void llvm::findValuesAffectedByCondition(
// X nuw- Y u> C -> X u> C
if (match(A, m_NUWSub(m_Value(X), m_Value())))
AddAffected(X);
+ } else if ((Pred == ICmpInst::ICMP_SGT && match(B, m_AllOnes())) ||
+ (Pred == ICmpInst::ICMP_SGE && match(B, m_Zero()))) {
+ // (or X, Y) sgt -1 or (or X, Y) sge 0 implies that all values in
+ // the or tree are non-negative.
+ visitOrTree(A, [&AddAffected](Value *V) {
+ AddAffected(V);
+ return false;
+ });
}
}
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index 3df78779fc8ed..245b50eec5669 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -2040,8 +2040,8 @@ define i32 @sdiv_add_nonneg_guard(i32 %x, i32 %y) {
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[OR]], -1
; CHECK-NEXT: br i1 [[CMP]], label %[[CONT:.*]], label %[[UNREACHABLE:.*]]
; CHECK: [[CONT]]:
-; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[Y]], [[X]]
-; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ADD]], 2
+; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[Y]], [[X]]
+; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[ADD]], 1
; CHECK-NEXT: ret i32 [[DIV]]
;
entry:
@@ -2061,9 +2061,9 @@ cont:
define i32 @sdiv_add3_nonneg_guard(i32 %x, i32 %y, i32 %z) {
; CHECK-LABEL: @sdiv_add3_nonneg_guard(
-; CHECK: [[ADD0:%.*]] = add nsw i32 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD0]], [[Z:%.*]]
-; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ADD1]], 2
+; CHECK: [[ADD0:%.*]] = add nuw nsw i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i32 [[ADD0]], [[Z:%.*]]
+; CHECK-NEXT: [[DIV:%.*]] = lshr i32 [[ADD1]], 1
; CHECK-NEXT: ret i32 [[DIV]]
;
entry:
More information about the llvm-commits
mailing list