[llvm] [SCEV] Set BTC to zero, if constant max BTC < BECountIfTaken. (PR #226098)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 03:04:40 PDT 2026


https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/226098

If ConstantMaxBECount < BECountIfTaken, we know that the backedge is
never taken and BTC is zero.

No changes in https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/1426.
The main motivation is to remove another difference between howManyLessThans
and howManyGreaterThans, which does not have the BECountIfBackedgeTaken
logic and would compute tighter bounds for backedges never taken.

No compile-time impact: https://llvm-compile-time-tracker.com/compare.php?from=022fdfa1e5a0b85dc785d30b17be3880768b22dc&to=475eeff40ba520620a406a3f615d660ed7c3eec0&stat=instructions:u

>From b0a7ce020fb7dd44cd336f3c07a2575c0fe4a5ed Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 23 Sep 2026 12:06:30 +0100
Subject: [PATCH 1/2] [SCEV] Add test where the range bound is tighter than
 MaxOrZero (NFC)

---
 .../Analysis/ScalarEvolution/trip-count13.ll  | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/llvm/test/Analysis/ScalarEvolution/trip-count13.ll b/llvm/test/Analysis/ScalarEvolution/trip-count13.ll
index e3e17a97da639..98bdcb092b5d0 100644
--- a/llvm/test/Analysis/ScalarEvolution/trip-count13.ll
+++ b/llvm/test/Analysis/ScalarEvolution/trip-count13.ll
@@ -124,3 +124,29 @@ loop:
 leave:
   ret void
 }
+
+; %start is in [-1, 127], which bounds the backedge-taken count by 128. That is
+; tighter than the backedge-taken count if the backedge is taken at all (241).
+define void @s_3(i8 %n) {
+; CHECK-LABEL: 's_3'
+; CHECK-NEXT:  Determining loop execution counts for: @s_3
+; CHECK-NEXT:  Loop %loop: backedge-taken count is (-127 + (-1 * %n) + ((112 + %n) smax (127 + %n)<nsw>))
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i8 -15, actual taken count either this or zero.
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is (-127 + (-1 * %n) + ((112 + %n) smax (127 + %n)<nsw>)), actual taken count either this or zero.
+; CHECK-NEXT:  Loop %loop: Trip multiple is 1
+;
+entry:
+  %start = add nsw i8 %n, 127
+  %rhs = add i8 %n, 112
+  %g = icmp sgt i8 %start, %rhs
+  br i1 %g, label %loop, label %leave
+
+loop:
+  %iv = phi i8 [ %start, %entry ], [ %iv.inc, %loop ]
+  %iv.inc = add i8 %iv, 1
+  %iv.cmp = icmp slt i8 %iv, %rhs
+  br i1 %iv.cmp, label %loop, label %leave
+
+leave:
+  ret void
+}

>From 4b36ee1d88cb83e65f189b47a682da9f13012a67 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 23 Sep 2026 12:20:40 +0100
Subject: [PATCH 2/2] [SCEV] Set BTC to zero, if constant max BTC <
 BECountIfTaken.

If ConstantMaxBECount < BECountIfTaken, we know that the backedge is
never taken and BTC is zero.

This removes another difference between howManyLessThans and
howManyGreaterThans, which does not have the BECountIfBackedgeTaken
logic and would compute tighter bounds for backedges never taken.
---
 llvm/lib/Analysis/ScalarEvolution.cpp         | 20 +++++++++++++------
 .../Analysis/ScalarEvolution/trip-count13.ll  | 11 +++++-----
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index b822b7a5d3927..7b3b822f5939a 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -13824,16 +13824,24 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
   bool MaxOrZero = false;
   if (isa<SCEVConstant>(BECount)) {
     ConstantMaxBECount = BECount;
-  } else if (isa<SCEVConstant>(BECountIfBackedgeTaken)) {
-    // If we know exactly how many times the backedge will be taken if it's
-    // taken at least once, then the backedge count will either be that or
-    // zero.
-    ConstantMaxBECount = BECountIfBackedgeTaken;
-    MaxOrZero = true;
   } else {
     ConstantMaxBECount = computeMaxBECountForLT(
         Start, Stride, RHS, getTypeSizeInBits(LHS->getType()), IsSigned,
         /*Invert=*/false);
+    // If we know exactly how many times the backedge will be taken if it's
+    // taken at least once, then the backedge count will either be that or
+    // zero. If that count exceeds the range-based bound, the backedge can
+    // never be taken.
+    const APInt *IfTaken, *RangeMax;
+    if (match(BECountIfBackedgeTaken, m_scev_APInt(IfTaken))) {
+      if (match(ConstantMaxBECount, m_scev_APInt(RangeMax)) &&
+          IfTaken->ugt(*RangeMax)) {
+        ConstantMaxBECount = getZero(BECountIfBackedgeTaken->getType());
+      } else {
+        ConstantMaxBECount = BECountIfBackedgeTaken;
+        MaxOrZero = true;
+      }
+    }
   }
 
   if (isa<SCEVCouldNotCompute>(ConstantMaxBECount) &&
diff --git a/llvm/test/Analysis/ScalarEvolution/trip-count13.ll b/llvm/test/Analysis/ScalarEvolution/trip-count13.ll
index 98bdcb092b5d0..7b6229f127cd5 100644
--- a/llvm/test/Analysis/ScalarEvolution/trip-count13.ll
+++ b/llvm/test/Analysis/ScalarEvolution/trip-count13.ll
@@ -125,14 +125,15 @@ leave:
   ret void
 }
 
-; %start is in [-1, 127], which bounds the backedge-taken count by 128. That is
-; tighter than the backedge-taken count if the backedge is taken at all (241).
+; %start is in [-1, 127], which bounds the backedge-taken count by 128. The
+; backedge-taken count if the backedge is taken at all is 241, so the backedge
+; is never taken.
 define void @s_3(i8 %n) {
 ; CHECK-LABEL: 's_3'
 ; CHECK-NEXT:  Determining loop execution counts for: @s_3
-; CHECK-NEXT:  Loop %loop: backedge-taken count is (-127 + (-1 * %n) + ((112 + %n) smax (127 + %n)<nsw>))
-; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i8 -15, actual taken count either this or zero.
-; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is (-127 + (-1 * %n) + ((112 + %n) smax (127 + %n)<nsw>)), actual taken count either this or zero.
+; CHECK-NEXT:  Loop %loop: backedge-taken count is i8 0
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i8 0
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is i8 0
 ; CHECK-NEXT:  Loop %loop: Trip multiple is 1
 ;
 entry:



More information about the llvm-commits mailing list