[llvm] [SCEV] Extend cache-lookup for AR (NFC) (PR #218927)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 00:13:56 PDT 2026


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/218927

>From c40eeb502859c1881ba3373c3896e765918ab8f6 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Thu, 17 Sep 2026 17:24:36 +0100
Subject: [PATCH 1/2] [SCEV] Add test from Florian, thanks!

---
 ...drec-computed-during-addrec-calculation.ll | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/llvm/test/Analysis/ScalarEvolution/addrec-computed-during-addrec-calculation.ll b/llvm/test/Analysis/ScalarEvolution/addrec-computed-during-addrec-calculation.ll
index 81d7fbe2d0c9e..f30b51162a4e1 100644
--- a/llvm/test/Analysis/ScalarEvolution/addrec-computed-during-addrec-calculation.ll
+++ b/llvm/test/Analysis/ScalarEvolution/addrec-computed-during-addrec-calculation.ll
@@ -64,3 +64,41 @@ loop.latch:
   %iv.next = trunc i64 %iv3 to i32
   br label %loop.header
 }
+
+define void @cached_result(i32 %n) {
+; CHECK-LABEL: 'cached_result'
+; CHECK-NEXT:  Classifying expressions for: @cached_result
+; CHECK-NEXT:    %b = phi i32 [ 2, %entry ], [ %b.n, %loop ]
+; CHECK-NEXT:    --> {2,+,4}<%loop> U: [0,-1) S: [-2147483648,2147483647) Exits: (2 + (4 * ((-2 + (3 umax %n)) /u 2)))<nuw><nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %a = phi i32 [ 1, %entry ], [ %a.n, %loop ]
+; CHECK-NEXT:    --> {1,+,2}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: (1 + (2 * ((-2 + (3 umax %n)) /u 2))<nuw>)<nuw><nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %b.n = add i32 %b, 4
+; CHECK-NEXT:    --> {6,+,4}<%loop> U: [0,-1) S: [-2147483648,2147483647) Exits: (6 + (4 * ((-2 + (3 umax %n)) /u 2))) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %a.n = add nsw i32 %a, 2
+; CHECK-NEXT:    --> {3,+,2}<nuw><nsw><%loop> U: [3,-2147483648) S: [3,-2147483648) Exits: (3 + (2 * ((-2 + (3 umax %n)) /u 2))<nuw>)<nuw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %c = add nsw i32 %a, %a
+; CHECK-NEXT:    --> {2,+,4}<nuw><%loop> U: [2,-1) S: [-2147483648,2147483647) Exits: (2 + (4 * ((-2 + (3 umax %n)) /u 2)))<nuw><nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:    %d = add i32 %b, 0
+; CHECK-NEXT:    --> {2,+,4}<nuw><%loop> U: [2,-1) S: [-2147483648,2147483647) Exits: (2 + (4 * ((-2 + (3 umax %n)) /u 2)))<nuw><nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @cached_result
+; CHECK-NEXT:  Loop %loop: backedge-taken count is ((-2 + (3 umax %n)) /u 2)
+; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 2147483646
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is ((-2 + (3 umax %n)) /u 2)
+; CHECK-NEXT:  Loop %loop: Trip multiple is 1
+;
+entry:
+  br label %loop
+
+loop:
+  %b = phi i32 [ 2, %entry ], [ %b.n, %loop ]
+  %a = phi i32 [ 1, %entry ], [ %a.n, %loop ]
+  %b.n = add i32 %b, 4
+  %a.n = add nsw i32 %a, 2
+  %c = add nsw i32 %a, %a
+  %d = add i32 %b, 0
+  %cmp = icmp ult i32 %a.n, %n
+  br i1 %cmp, label %loop, label %exit
+
+exit:
+  ret void
+}

>From fb9ca517b0c24c63edcb5e29ac7d0012bc1f77e7 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Wed, 26 Aug 2026 13:34:02 +0100
Subject: [PATCH 2/2] [SCEV] Extend cache-lookup for AR (NFC)

It allows us to improve some code, but it cannot be used in getAR
without making functional changes.
---
 llvm/include/llvm/Analysis/ScalarEvolution.h |  8 +++++---
 llvm/lib/Analysis/ScalarEvolution.cpp        | 18 ++++++++----------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index f2275513a7db8..8e0af061d82ca 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -2569,9 +2569,11 @@ class ScalarEvolution {
   /// an add rec on said loop.
   void getUsedLoops(const SCEV *S, SmallPtrSetImpl<const Loop *> &LoopsUsed);
 
-  /// Look for a SCEV expression with type `SCEVType` and operands `Ops` in
-  /// `UniqueSCEVs`.  Return if found, else nullptr.
-  SCEV *findExistingSCEVInCache(SCEVTypes SCEVType, ArrayRef<SCEVUse> Ops);
+  /// Look for a SCEV expression with type \p SCEVType and operands \p Ops in
+  /// UniqueSCEVs. If \p SCEVType is scAddRecExpr, the loop \p L must be passed.
+  /// Return if found, else nullptr.
+  SCEV *findExistingSCEVInCache(SCEVTypes SCEVType, ArrayRef<SCEVUse> Ops,
+                                const Loop *L = nullptr);
 
   /// Get reachable blocks in this function, making limited use of SCEV
   /// reasoning about conditions.
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 0e111b78048f3..530b1400ae69e 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -1444,15 +1444,8 @@ bool ScalarEvolution::proveNoWrapByVaryingStart(const SCEV *Start,
 
   for (unsigned Delta : {-2, -1, 1, 2}) {
     const SCEV *PreStart = getConstant(StartAI - Delta);
-
-    FoldingSetNodeID ID;
-    ID.AddInteger(scAddRecExpr);
-    ID.AddPointer(PreStart);
-    ID.AddPointer(Step);
-    ID.AddPointer(L);
-    FoldingSetInsertToken Token;
-    const auto *PreAR =
-        static_cast<SCEVAddRecExpr *>(UniqueSCEVs.lookup(ID, Token));
+    const auto *PreAR = static_cast<SCEVAddRecExpr *>(
+        findExistingSCEVInCache(scAddRecExpr, {PreStart, Step}, L));
 
     // Give up if we don't already have the add recurrence we need because
     // actually constructing an add recurrence is relatively expensive.
@@ -3867,11 +3860,16 @@ const SCEV *ScalarEvolution::getGEPExpr(SCEVUse BaseExpr,
 }
 
 SCEV *ScalarEvolution::findExistingSCEVInCache(SCEVTypes SCEVType,
-                                               ArrayRef<SCEVUse> Ops) {
+                                               ArrayRef<SCEVUse> Ops,
+                                               const Loop *L) {
+  assert((SCEVType != scAddRecExpr || L) &&
+         "L must be passed to find existing AddRecs");
   FoldingSetNodeID ID;
   ID.AddInteger(SCEVType);
   for (SCEVUse Op : Ops)
     ID.AddPointer(Op.getOpaqueValue());
+  if (L)
+    ID.AddPointer(L);
   FoldingSetInsertToken Token;
   return UniqueSCEVs.lookup(ID, Token);
 }



More information about the llvm-commits mailing list