[llvm] [SCEV] Add function to compute minium of countable exits. (PR #93498)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon May 27 20:18:15 PDT 2024


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

This patch introduces getBackedgeTakenCountForCountableExits and a predicated version to compute the minimum of the countable exits.

The intended use for this is loop access analysis for loops with uncountable exits. When analyzing dependences and computing runtime checks, we need the smallest upper bound on the number of iterations. In terms of memory safety, it shouldn't matter if any uncomputable exits leave the loop, as long as we prove that there are no dependences given the minimum of the countable exits. The same should apply also for generating runtime checks.

>From c354c6bb33a27c2388cf0b6f6a795ee841f58eca Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Wed, 8 May 2024 20:46:33 +0100
Subject: [PATCH] [SCEV] Add function to compute minium of countable exits.

This patch introduces getBackedgeTakenCountForCountableExits and a
predicated version to compute the minimum of the countable exits.

The intended use for this is loop access analysis for loops with
uncountable exits. When analyzing dependences and computing runtime
checks, we need the smallest upper bound on the number of iterations. In
terms of memory safety, it shouldn't matter if any uncomputable exits
leave the loop, as long as we prove that there are no dependences given
the minimum of the countable exits. The same should apply also for
generating runtime checks.
---
 llvm/include/llvm/Analysis/ScalarEvolution.h  | 18 ++++++-
 llvm/lib/Analysis/ScalarEvolution.cpp         | 50 ++++++++++++++++---
 .../ScalarEvolution/becount-invalidation.ll   |  1 +
 .../ScalarEvolution/exit-count-non-strict.ll  |  2 +
 .../ScalarEvolution/exponential-behavior.ll   |  1 +
 .../ScalarEvolution/flags-from-poison.ll      |  2 +
 .../ScalarEvolution/incorrect-exit-count.ll   |  3 ++
 .../ScalarEvolution/max-trip-count.ll         |  4 ++
 .../Analysis/ScalarEvolution/ne-overflow.ll   |  1 +
 .../no-wrap-symbolic-becount.ll               |  1 +
 .../Analysis/ScalarEvolution/outer_phi.ll     |  2 +
 llvm/test/Analysis/ScalarEvolution/pr48225.ll |  2 +
 .../test/Analysis/ScalarEvolution/ptrtoint.ll |  2 +
 .../symbolic_max_exit_count.ll                |  3 ++
 .../Analysis/ScalarEvolution/trip-count6.ll   |  1 +
 15 files changed, 85 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 5828cc156cc78..4d75b9f61607a 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -912,6 +912,16 @@ class ScalarEvolution {
     return getBackedgeTakenCount(L, SymbolicMaximum);
   }
 
+  /// When successful, return the minimum of the exit counts for all countable exits, ignoring uncountable exits. This is an upper bound on the  number of iterations of the loop.
+  const SCEV *getBackedgeTakenCountForCountableExits(const Loop *L);
+
+  /// Similar to getBackedgeTakenCountForCountableExits, except it will add a set of
+  /// SCEV predicates to Predicates that are required to be true in order for
+  /// the answer to be correct. Predicates can be checked with run-time
+  /// checks and can be used to perform loop versioning.
+  const SCEV *getPredicatedBackedgeTakenCountForCountableExits(
+      const Loop *L, SmallVector<const SCEVPredicate *, 4> &Predicates);
+
   /// Return true if the backedge taken count is either the value returned by
   /// getConstantMaxBackedgeTakenCount or zero.
   bool isBackedgeTakenCountMaxOrZero(const Loop *L);
@@ -1531,8 +1541,9 @@ class ScalarEvolution {
     /// If we allowed SCEV predicates to be generated when populating this
     /// vector, this information can contain them and therefore a
     /// SCEVPredicate argument should be added to getExact.
-    const SCEV *getExact(const Loop *L, ScalarEvolution *SE,
-                         SmallVector<const SCEVPredicate *, 4> *Predicates = nullptr) const;
+    const SCEV *
+    getExact(const Loop *L, ScalarEvolution *SE, bool SkipUncountable = false,
+             SmallVector<const SCEVPredicate *, 4> *Predicates = nullptr) const;
 
     /// Return the number of times this loop exit may fall through to the back
     /// edge, or SCEVCouldNotCompute. The loop is guaranteed not to exit via
@@ -2316,6 +2327,9 @@ class PredicatedScalarEvolution {
   /// Get the (predicated) backedge count for the analyzed loop.
   const SCEV *getBackedgeTakenCount();
 
+  // Get the (predicated) minimum of the exit counts for all countable exits, ignoring uncountable exits.
+  const SCEV *getBackedgeTakenCountForCountableExits();
+
   /// Adds a new predicate.
   void addPredicate(const SCEVPredicate &Pred);
 
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 8d971e6a78e42..16b20392afce4 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -8279,7 +8279,17 @@ const SCEV *ScalarEvolution::getExitCount(const Loop *L,
 const SCEV *
 ScalarEvolution::getPredicatedBackedgeTakenCount(const Loop *L,
                                                  SmallVector<const SCEVPredicate *, 4> &Preds) {
-  return getPredicatedBackedgeTakenInfo(L).getExact(L, this, &Preds);
+  return getPredicatedBackedgeTakenInfo(L).getExact(L, this, false, &Preds);
+}
+
+const SCEV *
+ScalarEvolution::getBackedgeTakenCountForCountableExits(const Loop *L) {
+  return getBackedgeTakenInfo(L).getExact(L, this, true);
+}
+
+const SCEV *ScalarEvolution::getPredicatedBackedgeTakenCountForCountableExits(
+    const Loop *L, SmallVector<const SCEVPredicate *, 4> &Preds) {
+  return getPredicatedBackedgeTakenInfo(L).getExact(L, this, true, &Preds);
 }
 
 const SCEV *ScalarEvolution::getBackedgeTakenCount(const Loop *L,
@@ -8561,11 +8571,11 @@ void ScalarEvolution::forgetBlockAndLoopDispositions(Value *V) {
 /// is never skipped. This is a valid assumption as long as the loop exits via
 /// that test. For precise results, it is the caller's responsibility to specify
 /// the relevant loop exiting block using getExact(ExitingBlock, SE).
-const SCEV *
-ScalarEvolution::BackedgeTakenInfo::getExact(const Loop *L, ScalarEvolution *SE,
-                                             SmallVector<const SCEVPredicate *, 4> *Preds) const {
+const SCEV *ScalarEvolution::BackedgeTakenInfo::getExact(
+    const Loop *L, ScalarEvolution *SE, bool SkipUncountable,
+    SmallVector<const SCEVPredicate *, 4> *Preds) const {
   // If any exits were not computable, the loop is not computable.
-  if (!isComplete() || ExitNotTaken.empty())
+  if ((!SkipUncountable && !isComplete()) || ExitNotTaken.empty())
     return SE->getCouldNotCompute();
 
   const BasicBlock *Latch = L->getLoopLatch();
@@ -8573,11 +8583,22 @@ ScalarEvolution::BackedgeTakenInfo::getExact(const Loop *L, ScalarEvolution *SE,
   if (!Latch)
     return SE->getCouldNotCompute();
 
+  if (SkipUncountable) {
+    SmallVector<BasicBlock *, 8> ExitingBlocks;
+    L->getExitingBlocks(ExitingBlocks);
+    if (any_of(ExitingBlocks, [SE, Latch](BasicBlock *Exiting) {
+          return !SE->DT.dominates(Exiting, Latch);
+        }))
+      return SE->getCouldNotCompute();
+  }
+
   // All exiting blocks we have gathered dominate loop's latch, so exact trip
   // count is simply a minimum out of all these calculated exit counts.
   SmallVector<const SCEV *, 2> Ops;
   for (const auto &ENT : ExitNotTaken) {
     const SCEV *BECount = ENT.ExactNotTaken;
+    if (SkipUncountable && BECount == SE->getCouldNotCompute())
+      return SE->getCouldNotCompute();
     assert(BECount != SE->getCouldNotCompute() && "Bad exit SCEV!");
     assert(SE->DT.dominates(ENT.ExitingBlock, Latch) &&
            "We should only have known counts for exiting blocks that dominate "
@@ -13522,8 +13543,15 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE,
   if (!isa<SCEVCouldNotCompute>(BTC)) {
     OS << "backedge-taken count is ";
     PrintSCEVWithTypeHint(OS, BTC);
-  } else
+  } else {
     OS << "Unpredictable backedge-taken count.";
+    SmallVector<const SCEVPredicate *, 4> Predicates;
+    auto *BTC = SE->getBackedgeTakenCountForCountableExits(L);
+    if (!isa<SCEVCouldNotCompute>(BTC)) {
+      OS << "\nbackedge-taken count for computable exits is ";
+      PrintSCEVWithTypeHint(OS, BTC);
+    }
+  }
   OS << "\n";
 
   if (ExitingBlocks.size() > 1)
@@ -14802,6 +14830,16 @@ const SCEV *PredicatedScalarEvolution::getBackedgeTakenCount() {
   return BackedgeCount;
 }
 
+const SCEV *
+PredicatedScalarEvolution::getBackedgeTakenCountForCountableExits() {
+  SmallVector<const SCEVPredicate *, 4> Preds;
+  auto *BackedgeCount =
+      SE.getPredicatedBackedgeTakenCountForCountableExits(&L, Preds);
+  for (const auto *P : Preds)
+    addPredicate(*P);
+  return BackedgeCount;
+}
+
 void PredicatedScalarEvolution::addPredicate(const SCEVPredicate &Pred) {
   if (Preds->implies(&Pred))
     return;
diff --git a/llvm/test/Analysis/ScalarEvolution/becount-invalidation.ll b/llvm/test/Analysis/ScalarEvolution/becount-invalidation.ll
index 0e37cf5efe3e4..4fd3cea9d0083 100644
--- a/llvm/test/Analysis/ScalarEvolution/becount-invalidation.ll
+++ b/llvm/test/Analysis/ScalarEvolution/becount-invalidation.ll
@@ -28,6 +28,7 @@ define void @test(ptr %arg) {
 ; CHECK-NEXT:    --> %ptr2.next U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop.header: Variant, %loop2.header: Invariant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test
 ; CHECK-NEXT:  Loop %loop2.header: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i1 false
 ; CHECK-NEXT:    exit count for loop2.header: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for loop2.latch: i1 false
 ; CHECK-NEXT:  Loop %loop2.header: constant max backedge-taken count is i1 false
diff --git a/llvm/test/Analysis/ScalarEvolution/exit-count-non-strict.ll b/llvm/test/Analysis/ScalarEvolution/exit-count-non-strict.ll
index e9faf98eee449..1a2b57a918266 100644
--- a/llvm/test/Analysis/ScalarEvolution/exit-count-non-strict.ll
+++ b/llvm/test/Analysis/ScalarEvolution/exit-count-non-strict.ll
@@ -92,6 +92,7 @@ define void @ule_from_zero_no_nuw(i32 %M, i32 %N) {
 ; CHECK-LABEL: 'ule_from_zero_no_nuw'
 ; CHECK-NEXT:  Determining loop execution counts for: @ule_from_zero_no_nuw
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is %N
 ; CHECK-NEXT:    exit count for loop: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for latch: %N
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 -1
@@ -210,6 +211,7 @@ define void @sle_from_int_min_no_nsw(i32 %M, i32 %N) {
 ; CHECK-LABEL: 'sle_from_int_min_no_nsw'
 ; CHECK-NEXT:  Determining loop execution counts for: @sle_from_int_min_no_nsw
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is (-2147483648 + %N)
 ; CHECK-NEXT:    exit count for loop: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for latch: (-2147483648 + %N)
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 -1
diff --git a/llvm/test/Analysis/ScalarEvolution/exponential-behavior.ll b/llvm/test/Analysis/ScalarEvolution/exponential-behavior.ll
index 397e1d5efcc73..5d044a205de1a 100644
--- a/llvm/test/Analysis/ScalarEvolution/exponential-behavior.ll
+++ b/llvm/test/Analysis/ScalarEvolution/exponential-behavior.ll
@@ -6,6 +6,7 @@ define void @f(i32 %n, ptr %ptr) {
 ; CHECK-LABEL: 'f'
 ; CHECK-NEXT:  Determining loop execution counts for: @f
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 0
 ; CHECK-NEXT:    exit count for loop: i32 0
 ; CHECK-NEXT:    exit count for be: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 0
diff --git a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
index a8531a8f57799..039004bd9e7c1 100644
--- a/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
+++ b/llvm/test/Analysis/ScalarEvolution/flags-from-poison.ll
@@ -529,6 +529,7 @@ define void @test-add-not-header3(ptr %input, i32 %offset, i32 %numIterations,
 ; CHECK-NEXT:    --> %cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test-add-not-header3
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is (-1 + %numIterations)
 ; CHECK-NEXT:    exit count for loop: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for loop2: (-1 + %numIterations)
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 -1
@@ -1546,6 +1547,7 @@ define void @test-sext-sub(ptr %input, i32 %sub, i32 %numIterations) {
 ; CHECK-NEXT:    --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test-sext-sub
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is (-1 + %numIterations)
 ; CHECK-NEXT:    exit count for loop: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for cont: (-1 + %numIterations)
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 -1
diff --git a/llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll b/llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll
index b456f11bade6b..fecf49353c347 100644
--- a/llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll
+++ b/llvm/test/Analysis/ScalarEvolution/incorrect-exit-count.ll
@@ -58,6 +58,7 @@ define dso_local i32 @f() {
 ; CHECK-NEXT:    --> {2,+,-1}<nsw><%outer.loop> U: [0,3) S: [0,3) Exits: <<Unknown>> LoopDispositions: { %outer.loop: Computable, %for.cond6: Invariant, %inner.loop: Invariant }
 ; CHECK-NEXT:  Determining loop execution counts for: @f
 ; CHECK-NEXT:  Loop %for.cond6: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 0
 ; CHECK-NEXT:    exit count for for.cond6: i32 0
 ; CHECK-NEXT:    exit count for for.end: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %for.cond6: constant max backedge-taken count is i32 0
@@ -65,6 +66,7 @@ define dso_local i32 @f() {
 ; CHECK-NEXT:    symbolic max exit count for for.cond6: i32 0
 ; CHECK-NEXT:    symbolic max exit count for for.end: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %inner.loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 0
 ; CHECK-NEXT:    exit count for inner.loop: i32 0
 ; CHECK-NEXT:    exit count for for.end.3: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %inner.loop: constant max backedge-taken count is i32 0
@@ -72,6 +74,7 @@ define dso_local i32 @f() {
 ; CHECK-NEXT:    symbolic max exit count for inner.loop: i32 0
 ; CHECK-NEXT:    symbolic max exit count for for.end.3: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %outer.loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 2
 ; CHECK-NEXT:    exit count for for.cond6: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for inner.loop: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for for.inc13.3: i32 2
diff --git a/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll b/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll
index 501aa963f9294..90328c4ca8221 100644
--- a/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll
+++ b/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll
@@ -53,6 +53,7 @@ define i32 @main() nounwind {
 ; CHECK-LABEL: 'main'
 ; CHECK-NEXT:  Determining loop execution counts for: @main
 ; CHECK-NEXT:  Loop %for.cond: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 5
 ; CHECK-NEXT:    exit count for for.cond: i32 5
 ; CHECK-NEXT:    exit count for for.body: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %for.cond: constant max backedge-taken count is i32 5
@@ -125,6 +126,7 @@ define i32 @pr19799() {
 ; CHECK-LABEL: 'pr19799'
 ; CHECK-NEXT:  Determining loop execution counts for: @pr19799
 ; CHECK-NEXT:  Loop %for.body.i: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 1
 ; CHECK-NEXT:    exit count for for.body.i: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for for.cond.i: i32 1
 ; CHECK-NEXT:  Loop %for.body.i: constant max backedge-taken count is i32 1
@@ -158,6 +160,7 @@ define i32 @pr18886() {
 ; CHECK-LABEL: 'pr18886'
 ; CHECK-NEXT:  Determining loop execution counts for: @pr18886
 ; CHECK-NEXT:  Loop %for.body: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i64 3
 ; CHECK-NEXT:    exit count for for.body: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for for.cond: i64 3
 ; CHECK-NEXT:  Loop %for.body: constant max backedge-taken count is i64 3
@@ -571,6 +574,7 @@ define void @max_overflow_me(i8 %n) mustprogress {
 ; CHECK-LABEL: 'max_overflow_me'
 ; CHECK-NEXT:  Determining loop execution counts for: @max_overflow_me
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i8 1
 ; CHECK-NEXT:    exit count for loop: i8 1
 ; CHECK-NEXT:    exit count for latch: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i8 1
diff --git a/llvm/test/Analysis/ScalarEvolution/ne-overflow.ll b/llvm/test/Analysis/ScalarEvolution/ne-overflow.ll
index 82b4d0e4fb483..c77b8d0fd5f5a 100644
--- a/llvm/test/Analysis/ScalarEvolution/ne-overflow.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ne-overflow.ll
@@ -207,6 +207,7 @@ define void @test_other_exit(i32 %N) mustprogress {
 ; CHECK-LABEL: 'test_other_exit'
 ; CHECK-NEXT:  Determining loop execution counts for: @test_other_exit
 ; CHECK-NEXT:  Loop %for.body: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 9
 ; CHECK-NEXT:    exit count for for.body: i32 9
 ; CHECK-NEXT:    exit count for for.latch: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %for.body: constant max backedge-taken count is i32 9
diff --git a/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll b/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
index e13a8976bf5ac..808ce50f0e5b4 100644
--- a/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
+++ b/llvm/test/Analysis/ScalarEvolution/no-wrap-symbolic-becount.ll
@@ -24,6 +24,7 @@ define i32 @test_01(i32 %start, ptr %p, ptr %q) {
 ; CHECK-NEXT:    --> {(-1 + (zext i32 %start to i64))<nsw>,+,-1}<nsw><%loop> U: [-4294967296,4294967295) S: [-1,4294967295) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_01
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is (zext i32 %start to i64)
 ; CHECK-NEXT:    exit count for loop: (zext i32 %start to i64)
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i64 4294967295
diff --git a/llvm/test/Analysis/ScalarEvolution/outer_phi.ll b/llvm/test/Analysis/ScalarEvolution/outer_phi.ll
index e4a9753b24054..a14d2e88f689f 100644
--- a/llvm/test/Analysis/ScalarEvolution/outer_phi.ll
+++ b/llvm/test/Analysis/ScalarEvolution/outer_phi.ll
@@ -18,6 +18,7 @@ define i32 @test_01(i32 %a, i32 %b) {
 ; CHECK-NEXT:    --> %outer.loop.cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %outer: Variant, %inner: Invariant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_01
 ; CHECK-NEXT:  Loop %inner: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is %b
 ; CHECK-NEXT:    exit count for inner: %b
 ; CHECK-NEXT:    exit count for inner.backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %inner: constant max backedge-taken count is i32 2147483647
@@ -80,6 +81,7 @@ define i32 @test_02(i32 %a, i32 %b) {
 ; CHECK-NEXT:    --> %outer.loop.cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %outer: Variant, %inner: Invariant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_02
 ; CHECK-NEXT:  Loop %inner: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is ((-1 * %outer.iv) + (%b smax %outer.iv))
 ; CHECK-NEXT:    exit count for inner: ((-1 * %outer.iv) + (%b smax %outer.iv))
 ; CHECK-NEXT:    exit count for inner.backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %inner: constant max backedge-taken count is i32 -1
diff --git a/llvm/test/Analysis/ScalarEvolution/pr48225.ll b/llvm/test/Analysis/ScalarEvolution/pr48225.ll
index 157e98f99aa9f..7c2849f5c989f 100644
--- a/llvm/test/Analysis/ScalarEvolution/pr48225.ll
+++ b/llvm/test/Analysis/ScalarEvolution/pr48225.ll
@@ -22,6 +22,7 @@ define void @test_and(i1 %boolcond) {
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,4) S: [1,4) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_and
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 2
 ; CHECK-NEXT:    exit count for loop: i32 2
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 2
@@ -71,6 +72,7 @@ define void @test_or(i1 %boolcond) {
 ; CHECK-NEXT:    --> {1,+,1}<nuw><nsw><%loop> U: [1,4) S: [1,4) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_or
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i32 2
 ; CHECK-NEXT:    exit count for loop: i32 2
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 2
diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
index e784d25385980..9509dc2d2f5c8 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint.ll
@@ -550,6 +550,7 @@ define void @ptrtoint_of_integer(ptr %arg, i64 %arg1, i1 %arg2) local_unnamed_ad
 ; X64-NEXT:    --> {2,+,1}<nw><%bb8> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb8: Computable }
 ; X64-NEXT:  Determining loop execution counts for: @ptrtoint_of_integer
 ; X64-NEXT:  Loop %bb8: <multiple exits> Unpredictable backedge-taken count.
+; X64-NEXT:  backedge-taken count for computable exits is (-2 + (-1 * %arg1) + (ptrtoint ptr %arg to i64))
 ; X64-NEXT:    exit count for bb8: ***COULDNOTCOMPUTE***
 ; X64-NEXT:    exit count for bb10: (-2 + (-1 * %arg1) + (ptrtoint ptr %arg to i64))
 ; X64-NEXT:  Loop %bb8: constant max backedge-taken count is i64 -1
@@ -569,6 +570,7 @@ define void @ptrtoint_of_integer(ptr %arg, i64 %arg1, i1 %arg2) local_unnamed_ad
 ; X32-NEXT:    --> {2,+,1}<nw><%bb8> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %bb8: Computable }
 ; X32-NEXT:  Determining loop execution counts for: @ptrtoint_of_integer
 ; X32-NEXT:  Loop %bb8: <multiple exits> Unpredictable backedge-taken count.
+; X32-NEXT:  backedge-taken count for computable exits is (-2 + (zext i32 (ptrtoint ptr %arg to i32) to i64) + (-1 * %arg1))
 ; X32-NEXT:    exit count for bb8: ***COULDNOTCOMPUTE***
 ; X32-NEXT:    exit count for bb10: (-2 + (zext i32 (ptrtoint ptr %arg to i32) to i64) + (-1 * %arg1))
 ; X32-NEXT:  Loop %bb8: constant max backedge-taken count is i64 -1
diff --git a/llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll b/llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll
index ab43182d2e822..d6bce17aa0f3c 100644
--- a/llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll
+++ b/llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll
@@ -16,6 +16,7 @@ define i32 @test_simple_case(i32 %start, i32 %len) {
 ; CHECK-NEXT:    --> %loop_cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_simple_case
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is %start
 ; CHECK-NEXT:    exit count for loop: %start
 ; CHECK-NEXT:    exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
@@ -233,6 +234,7 @@ define i32 @test_mixup_constant_symbolic(i32 %end, i32 %len) {
 ; CHECK-NEXT:    --> %loop_cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_mixup_constant_symbolic
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is (1000 umin %end)
 ; CHECK-NEXT:    exit count for loop: %end
 ; CHECK-NEXT:    exit count for range_check_block: i32 1000
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
@@ -282,6 +284,7 @@ define i32 @test_mixup_constant_symbolic_merged(i32 %end, i32 %len) {
 ; CHECK-NEXT:    --> %loop_cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_mixup_constant_symbolic_merged
 ; CHECK-NEXT:  Loop %loop: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is (1000 umin %end)
 ; CHECK-NEXT:    exit count for loop: (1000 umin %end)
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is i32 1000
diff --git a/llvm/test/Analysis/ScalarEvolution/trip-count6.ll b/llvm/test/Analysis/ScalarEvolution/trip-count6.ll
index ed256323aedb1..43567b4cab121 100644
--- a/llvm/test/Analysis/ScalarEvolution/trip-count6.ll
+++ b/llvm/test/Analysis/ScalarEvolution/trip-count6.ll
@@ -7,6 +7,7 @@ define i8 @f() {
 ; CHECK-LABEL: 'f'
 ; CHECK-NEXT:  Determining loop execution counts for: @f
 ; CHECK-NEXT:  Loop %bb: <multiple exits> Unpredictable backedge-taken count.
+; CHECK-NEXT:  backedge-taken count for computable exits is i8 1
 ; CHECK-NEXT:    exit count for bb: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for bb2: i8 1
 ; CHECK-NEXT:  Loop %bb: constant max backedge-taken count is i8 1



More information about the llvm-commits mailing list