[llvm] [ValueTracking] An or recurrence with a non-zero start value is non-zero (PR #226155)
Konstantin Bogdanov via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 06:08:58 PDT 2026
https://github.com/thevar1able created https://github.com/llvm/llvm-project/pull/226155
Or-ing anything into a non-zero value keeps it non-zero, so `isNonZeroRecurrence` can accept a simple `%iv = or %iv, %step` recurrence with a non-zero constant start value, regardless of the step.
The first commit precommits the tests in `phi-known-nonzero.ll`.
This is split out of #222334. Together with a follow-up that stops limiting the recursion depth for single-incoming (LCSSA) phis in `isKnownNonZero`, it lets LoopIdiomRecognize (#222373) form `llvm.ctlz` for the clz loop in ffmpeg's `sbc_calc_scalefactors`.
>From e124c4a826d17d00f2ccc27cce41b2dde3e9e532 Mon Sep 17 00:00:00 2001
From: Konstantin Bogdanov <konstantin at clickhouse.com>
Date: Thu, 24 Sep 2026 13:23:57 +0200
Subject: [PATCH 1/2] [ValueTracking] Precommit tests for non-zero or
recurrences (NFC)
---
.../ValueTracking/phi-known-nonzero.ll | 74 +++++++++++++++++++
1 file changed, 74 insertions(+)
diff --git a/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll b/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll
index d80d1704c73d1d..ed77b9d3586529 100644
--- a/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll
+++ b/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll
@@ -262,3 +262,77 @@ T:
F:
br label %T
}
+
+; An or recurrence with a non-zero start value is never zero.
+define i1 @or_recurrence_nonzero_start(ptr %p, i64 %n) {
+;
+; CHECK-LABEL: @or_recurrence_nonzero_start(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 32768, [[ENTRY]] ], [ [[ACC_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IV]]
+; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[GEP]], align 4
+; CHECK-NEXT: [[ACC_NEXT]] = or i32 [[X]], [[ACC]]
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK: exit:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ACC_NEXT]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %acc = phi i32 [ 32768, %entry ], [ %acc.next, %loop ]
+ %gep = getelementptr i32, ptr %p, i64 %iv
+ %x = load i32, ptr %gep
+ %acc.next = or i32 %x, %acc
+ %iv.next = add i64 %iv, 1
+ %ec = icmp eq i64 %iv.next, %n
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ %cmp = icmp eq i32 %acc.next, 0
+ ret i1 %cmp
+}
+
+; Negative test: the start value is zero.
+define i1 @or_recurrence_zero_start(ptr %p, i64 %n) {
+;
+; CHECK-LABEL: @or_recurrence_zero_start(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ACC_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IV]]
+; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[GEP]], align 4
+; CHECK-NEXT: [[ACC_NEXT]] = or i32 [[X]], [[ACC]]
+; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1
+; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
+; CHECK: exit:
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ACC_NEXT]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %acc = phi i32 [ 0, %entry ], [ %acc.next, %loop ]
+ %gep = getelementptr i32, ptr %p, i64 %iv
+ %x = load i32, ptr %gep
+ %acc.next = or i32 %x, %acc
+ %iv.next = add i64 %iv, 1
+ %ec = icmp eq i64 %iv.next, %n
+ br i1 %ec, label %exit, label %loop
+
+exit:
+ %cmp = icmp eq i32 %acc.next, 0
+ ret i1 %cmp
+}
>From cb8ec8e24de65013a4fead6b90469a70e1324d48 Mon Sep 17 00:00:00 2001
From: Konstantin Bogdanov <konstantin at clickhouse.com>
Date: Thu, 24 Sep 2026 15:07:05 +0200
Subject: [PATCH 2/2] [ValueTracking] An or recurrence with a non-zero start
value is non-zero
Or-ing anything into a non-zero value keeps it non-zero, so a simple
`%iv = or %iv, %step` recurrence with a non-zero constant start value is
never zero.
---
llvm/lib/Analysis/ValueTracking.cpp | 2 ++
llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll | 3 +--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ed1e2f7467e197..6a54ec8ecc5d69 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3182,6 +3182,8 @@ static bool isNonZeroRecurrence(const PHINode *PN) {
case Instruction::AShr:
case Instruction::LShr:
return BO->isExact();
+ case Instruction::Or:
+ return true;
default:
return false;
}
diff --git a/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll b/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll
index ed77b9d3586529..a93f149e9c200d 100644
--- a/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll
+++ b/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll
@@ -279,8 +279,7 @@ define i1 @or_recurrence_nonzero_start(ptr %p, i64 %n) {
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ACC_NEXT]], 0
-; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK-NEXT: ret i1 false
;
entry:
br label %loop
More information about the llvm-commits
mailing list