[llvm] [SCEV] Consider IVMayOverflow to use cheap BE-count formula. (PR #218694)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 26 06:08:25 PDT 2026
https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/218694
>From a5ca4c18b62b459fe340e94d59b276ff72e9d66c Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 25 Aug 2026 10:25:18 +0100
Subject: [PATCH] [SCEV] Consider IVMayOverflow to use cheap BE-count formula.
If !IVMayOverflow, we proven RHS + stride - 1 does not wrap. This means
adding the `Stride - 1` part of `RHS - (Start - Stride) - 1` does not wrap.
Together with the other condition `Start - Stride < RHS`, this should
guarantee `RHS - (Start - Stride) - 1` does not wrap and the cheap
formula can be used.
This triggers in a number of real-world cases, mostly resulting in
simpler SCEV expansions/checks, and extra unrolling. In a small number
of cases, expansion is slightly worse.
https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/1043
Alive2 Proof: https://alive2.llvm.org/ce/z/u_KUx5
Depends on https://github.com/llvm/llvm-project/pull/218251 (included in
PR)
---
llvm/lib/Analysis/ScalarEvolution.cpp | 8 ++++++--
llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll | 4 ++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 1f2b8baafdaf0..97ac3c483b4e0 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -13569,7 +13569,8 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
assert(isAvailableAtLoopEntry(OrigStart, L) && "Must be!");
assert(isAvailableAtLoopEntry(OrigRHS, L) && "Must be!");
// Can we prove (max(RHS,Start) > Start - Stride?
- if (isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigStart) &&
+ if ((!IVMayOverflow ||
+ isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigStart)) &&
isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigRHS)) {
// In this case, we can use a refined formula for computing backedge
// taken count. The general formula remains:
@@ -13589,7 +13590,10 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
// "((End - 1) - (Start - Stride)) /u Stride" reduces to
// "((RHS - 1) - (Start - Stride)) /u Stride" reassociates to
// "((RHS - (Start - Stride) - 1) /u Stride".
- // Our preconditions trivially imply no overflow in that form.
+ // Our preconditions imply no overflow in that form: If !IVMayOverflow,
+ // we proven RHS + stride - 1 does not wrap. Otherwise, if "Start -
+ // Stride" does not overflow, both operands of the subtraction are in
+ // range and their difference is the exact distance between them.
const SCEV *MinusOne = getMinusOne(Stride->getType());
const SCEV *Numerator =
getMinusSCEV(getAddExpr(RHS, MinusOne), getMinusSCEV(Start, Stride));
diff --git a/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll b/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll
index 86f1757c46002..ca539e5f3c626 100644
--- a/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll
+++ b/llvm/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll
@@ -8,9 +8,9 @@ define i32 @f(i32 %x) nounwind readnone {
;
; CHECK-LABEL: 'f'
; CHECK-NEXT: Determining loop execution counts for: @f
-; CHECK-NEXT: Loop %bb: backedge-taken count is ((-1 + (-1 * %x) + (1000 umax (3 + %x))) /u 3)
+; CHECK-NEXT: Loop %bb: backedge-taken count is ((999 + (-1 * %x)) /u 3)
; CHECK-NEXT: Loop %bb: constant max backedge-taken count is i32 334
-; CHECK-NEXT: Loop %bb: symbolic max backedge-taken count is ((-1 + (-1 * %x) + (1000 umax (3 + %x))) /u 3)
+; CHECK-NEXT: Loop %bb: symbolic max backedge-taken count is ((999 + (-1 * %x)) /u 3)
; CHECK-NEXT: Loop %bb: Trip multiple is 1
;
entry:
More information about the llvm-commits
mailing list