[llvm] 520b168 - [ValueTracking] An or recurrence with a non-zero start value is non-zero (#226155)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 06:51:26 PDT 2026


Author: Konstantin Bogdanov
Date: 2026-09-24T13:51:15Z
New Revision: 520b1687095eaf9dd410fb48ab622205e9fec044

URL: https://github.com/llvm/llvm-project/commit/520b1687095eaf9dd410fb48ab622205e9fec044
DIFF: https://github.com/llvm/llvm-project/commit/520b1687095eaf9dd410fb48ab622205e9fec044.diff

LOG: [ValueTracking] An or recurrence with a non-zero start value is non-zero (#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`.

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ed1e2f7467e19..6a54ec8ecc5d6 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 d80d1704c73d1..a93f149e9c200 100644
--- a/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll
+++ b/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll
@@ -262,3 +262,76 @@ 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:    ret i1 false
+;
+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
+}


        


More information about the llvm-commits mailing list