[llvm] [SCEV] Use AddRec monotonicity in isKnownViaNonRecursiveReasoning. (PR #218280)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 23 12:18:50 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: Florian Hahn (fhahn)

<details>
<summary>Changes</summary>

Monotonic AddRecs are never less than their start value; use that in
when reasoning about predicates involving an AddRec and its start value.

Improves results in a few cases on llvm-opt-benchmark-nightly:
https://github.com/dtcxzyw/llvm-opt-benchmark-nightly/pull/996

---

Patch is 26.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/218280.diff


3 Files Affected:

- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+28) 
- (added) llvm/test/Analysis/ScalarEvolution/addrec-vs-start-monotonic.ll (+318) 
- (added) llvm/test/Transforms/IndVarSimplify/addrec-vs-start-monotonic.ll (+151) 


``````````diff
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 2be8495c164fc..d005df1369507 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12913,6 +12913,33 @@ static bool IsKnownPredicateViaAddRecStart(ScalarEvolution &SE,
   return SE.isKnownPredicate(Pred, LStart, RStart);
 }
 
+/// Is LHS `Pred` RHS true because one of them is an AddRec that is known not to
+/// go below its own start value, which is the other side?
+static bool IsKnownPredicateViaAddRecMonotonicity(ScalarEvolution &SE,
+                                                  CmpPredicate Pred,
+                                                  const SCEV *LHS,
+                                                  const SCEV *RHS) {
+  // Normalize to (AddRec Pred Start).
+  if (!isa<SCEVAddRecExpr>(LHS) && isa<SCEVAddRecExpr>(RHS)) {
+    Pred = ICmpInst::getSwappedCmpPredicate(Pred);
+    std::swap(LHS, RHS);
+  }
+
+  // The recurrence is equal to Start in the first iteration, so only the
+  // non-strict predicate holds.
+  if (Pred != ICmpInst::ICMP_UGE && Pred != ICmpInst::ICMP_SGE)
+    return false;
+
+  const auto *AR = dyn_cast<SCEVAddRecExpr>(LHS);
+  if (!AR || AR->getStart() != RHS)
+    return false;
+
+  // A recurrence that neither wraps nor steps backwards never goes below the
+  // value it started at.
+  return SE.getMonotonicPredicateType(AR, Pred) ==
+         ScalarEvolution::MonotonicallyIncreasing;
+}
+
 /// Is LHS `Pred` RHS true on the virtue of LHS or RHS being a Min or Max
 /// expression?
 static bool IsKnownPredicateViaMinOrMax(ScalarEvolution &SE, CmpPredicate Pred,
@@ -13173,6 +13200,7 @@ bool ScalarEvolution::isKnownViaNonRecursiveReasoning(CmpPredicate Pred,
          isKnownPredicateViaConstantRanges(Pred, LHS, RHS) ||
          IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||
          IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS) ||
+         IsKnownPredicateViaAddRecMonotonicity(*this, Pred, LHS, RHS) ||
          isKnownPredicateViaNoOverflow(Pred, LHS, RHS);
 }
 
diff --git a/llvm/test/Analysis/ScalarEvolution/addrec-vs-start-monotonic.ll b/llvm/test/Analysis/ScalarEvolution/addrec-vs-start-monotonic.ll
new file mode 100644
index 0000000000000..6d8df85620ce4
--- /dev/null
+++ b/llvm/test/Analysis/ScalarEvolution/addrec-vs-start-monotonic.ll
@@ -0,0 +1,318 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -disable-output -passes='print<scalar-evolution>' %s 2>&1 | FileCheck %s
+
+define void @dec_to_start_of_nuw_ptr_addrec(ptr %start, i32 %n) {
+; CHECK-LABEL: 'dec_to_start_of_nuw_ptr_addrec'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nuw_ptr_addrec
+; CHECK-NEXT:    %p = phi ptr [ %start, %entry ], [ %p.next, %up.latch ]
+; CHECK-NEXT:    --> {%start,+,1}<nuw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+; CHECK-NEXT:    --> %v U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %p.next = getelementptr nuw i8, ptr %p, i64 1
+; CHECK-NEXT:    --> {(1 + %start),+,1}<nw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v.next = mul i32 %v, 10
+; CHECK-NEXT:    --> (10 * %v) U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %q = phi ptr [ %p, %up.header ], [ %q.next, %down.latch ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nuw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: %start LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:    %q.next = getelementptr i8, ptr %q, i64 -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,1}<nw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: (-1 + %start) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nuw_ptr_addrec
+; CHECK-NEXT:  Loop %down.header: backedge-taken count is {0,+,1}<nuw><%up.header>
+; CHECK-NEXT:  Loop %down.header: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down.header: symbolic max backedge-taken count is {0,+,1}<nuw><%up.header>
+; CHECK-NEXT:  Loop %down.header: Trip multiple is 1
+; CHECK-NEXT:  Loop %up.header: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  br label %up.header
+
+up.header:
+  %p = phi ptr [ %start, %entry ], [ %p.next, %up.latch ]
+  %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+  %pos = icmp sgt i32 %v, 0
+  br i1 %pos, label %up.latch, label %down.header
+
+up.latch:
+  %p.next = getelementptr nuw i8, ptr %p, i64 1
+  %v.next = mul i32 %v, 10
+  br label %up.header
+
+down.header:
+  %q = phi ptr [ %p, %up.header ], [ %q.next, %down.latch ]
+  %in.range = icmp ugt ptr %q, %start
+  br i1 %in.range, label %down.latch, label %exit
+
+down.latch:
+  %q.next = getelementptr i8, ptr %q, i64 -1
+  br label %down.header
+
+exit:
+  ret void
+}
+
+; Same for an integer recurrence.
+define void @dec_to_start_of_nuw_int_addrec(i64 %start, i32 %n) {
+; CHECK-LABEL: 'dec_to_start_of_nuw_int_addrec'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nuw_int_addrec
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up.latch ]
+; CHECK-NEXT:    --> {%start,+,1}<nuw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+; CHECK-NEXT:    --> %v U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %x.next = add nuw i64 %x, 1
+; CHECK-NEXT:    --> {(1 + %start),+,1}<nw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v.next = mul i32 %v, 10
+; CHECK-NEXT:    --> (10 * %v) U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %y = phi i64 [ %x, %up.header ], [ %y.next, %down.latch ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<nuw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: %start LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:    %y.next = add i64 %y, -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,1}<nw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: (-1 + %start) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nuw_int_addrec
+; CHECK-NEXT:  Loop %down.header: backedge-taken count is {0,+,1}<nuw><%up.header>
+; CHECK-NEXT:  Loop %down.header: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down.header: symbolic max backedge-taken count is {0,+,1}<nuw><%up.header>
+; CHECK-NEXT:  Loop %down.header: Trip multiple is 1
+; CHECK-NEXT:  Loop %up.header: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  br label %up.header
+
+up.header:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up.latch ]
+  %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+  %pos = icmp sgt i32 %v, 0
+  br i1 %pos, label %up.latch, label %down.header
+
+up.latch:
+  %x.next = add nuw i64 %x, 1
+  %v.next = mul i32 %v, 10
+  br label %up.header
+
+down.header:
+  %y = phi i64 [ %x, %up.header ], [ %y.next, %down.latch ]
+  %in.range = icmp ugt i64 %y, %start
+  br i1 %in.range, label %down.latch, label %exit
+
+down.latch:
+  %y.next = add i64 %y, -1
+  br label %down.header
+
+exit:
+  ret void
+}
+
+define void @dec_to_start_of_wrapping_ptr_addrec(ptr %start, i32 %n) {
+; CHECK-LABEL: 'dec_to_start_of_wrapping_ptr_addrec'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_wrapping_ptr_addrec
+; CHECK-NEXT:    %p = phi ptr [ %start, %entry ], [ %p.next, %up.latch ]
+; CHECK-NEXT:    --> {%start,+,1}<%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+; CHECK-NEXT:    --> %v U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %p.next = getelementptr i8, ptr %p, i64 1
+; CHECK-NEXT:    --> {(1 + %start),+,1}<%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v.next = mul i32 %v, 10
+; CHECK-NEXT:    --> (10 * %v) U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %q = phi ptr [ %p, %up.header ], [ %q.next, %down.latch ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,1}<%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: ((-1 * (ptrtoaddr ptr %start to i64)) + ({(ptrtoaddr ptr %start to i64),+,1}<%up.header> umin (ptrtoaddr ptr %start to i64)) + %start) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:    %q.next = getelementptr i8, ptr %q, i64 -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,1}<%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: (-1 + (-1 * (ptrtoaddr ptr %start to i64)) + ({(ptrtoaddr ptr %start to i64),+,1}<%up.header> umin (ptrtoaddr ptr %start to i64)) + %start) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_wrapping_ptr_addrec
+; CHECK-NEXT:  Loop %down.header: backedge-taken count is ((-1 * ({(ptrtoaddr ptr %start to i64),+,1}<%up.header> umin (ptrtoaddr ptr %start to i64))) + {(ptrtoaddr ptr %start to i64),+,1}<%up.header>)
+; CHECK-NEXT:  Loop %down.header: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down.header: symbolic max backedge-taken count is ((-1 * ({(ptrtoaddr ptr %start to i64),+,1}<%up.header> umin (ptrtoaddr ptr %start to i64))) + {(ptrtoaddr ptr %start to i64),+,1}<%up.header>)
+; CHECK-NEXT:  Loop %down.header: Trip multiple is 1
+; CHECK-NEXT:  Loop %up.header: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  br label %up.header
+
+up.header:
+  %p = phi ptr [ %start, %entry ], [ %p.next, %up.latch ]
+  %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+  %pos = icmp sgt i32 %v, 0
+  br i1 %pos, label %up.latch, label %down.header
+
+up.latch:
+  %p.next = getelementptr i8, ptr %p, i64 1
+  %v.next = mul i32 %v, 10
+  br label %up.header
+
+down.header:
+  %q = phi ptr [ %p, %up.header ], [ %q.next, %down.latch ]
+  %in.range = icmp ugt ptr %q, %start
+  br i1 %in.range, label %down.latch, label %exit
+
+down.latch:
+  %q.next = getelementptr i8, ptr %q, i64 -1
+  br label %down.header
+
+exit:
+  ret void
+}
+
+; With nsw and a step that cannot be negative, the recurrence cannot be
+; signed-below %start.
+define void @dec_to_start_of_nsw_addrec(i64 %start, i32 %n, i64 %step.raw) {
+; CHECK-LABEL: 'dec_to_start_of_nsw_addrec'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nsw_addrec
+; CHECK-NEXT:    %step = and i64 %step.raw, 7
+; CHECK-NEXT:    --> (zext i3 (trunc i64 %step.raw to i3) to i64) U: [0,8) S: [0,8)
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up.latch ]
+; CHECK-NEXT:    --> {%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+; CHECK-NEXT:    --> %v U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %x.next = add nsw i64 %x, %step
+; CHECK-NEXT:    --> {((zext i3 (trunc i64 %step.raw to i3) to i64) + %start),+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v.next = mul i32 %v, 10
+; CHECK-NEXT:    --> (10 * %v) U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %y = phi i64 [ %x, %up.header ], [ %y.next, %down.latch ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: %start LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:    %y.next = add i64 %y, -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: (-1 + %start) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nsw_addrec
+; CHECK-NEXT:  Loop %down.header: backedge-taken count is {0,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nuw><%up.header>
+; CHECK-NEXT:  Loop %down.header: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down.header: symbolic max backedge-taken count is {0,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nuw><%up.header>
+; CHECK-NEXT:  Loop %down.header: Trip multiple is 1
+; CHECK-NEXT:  Loop %up.header: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  %step = and i64 %step.raw, 7
+  br label %up.header
+
+up.header:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up.latch ]
+  %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+  %pos = icmp sgt i32 %v, 0
+  br i1 %pos, label %up.latch, label %down.header
+
+up.latch:
+  %x.next = add nsw i64 %x, %step
+  %v.next = mul i32 %v, 10
+  br label %up.header
+
+down.header:
+  %y = phi i64 [ %x, %up.header ], [ %y.next, %down.latch ]
+  %in.range = icmp sgt i64 %y, %start
+  br i1 %in.range, label %down.latch, label %exit
+
+down.latch:
+  %y.next = add i64 %y, -1
+  br label %down.header
+
+exit:
+  ret void
+}
+
+; AddRec is nsw, but step may be negative.
+define void @dec_to_start_of_nsw_addrec_unknown_step(i64 %start, i32 %n, i64 %step) {
+; CHECK-LABEL: 'dec_to_start_of_nsw_addrec_unknown_step'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nsw_addrec_unknown_step
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up.latch ]
+; CHECK-NEXT:    --> {%start,+,%step}<nsw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+; CHECK-NEXT:    --> %v U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %x.next = add nsw i64 %x, %step
+; CHECK-NEXT:    --> {(%start + %step),+,%step}<nw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v.next = mul i32 %v, 10
+; CHECK-NEXT:    --> (10 * %v) U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %y = phi i64 [ %x, %up.header ], [ %y.next, %down.latch ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,%step}<nsw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: ({%start,+,%step}<nsw><%up.header> smin %start) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:    %y.next = add i64 %y, -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,%step}<nw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: (-1 + ({%start,+,%step}<nsw><%up.header> smin %start)) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nsw_addrec_unknown_step
+; CHECK-NEXT:  Loop %down.header: backedge-taken count is ((-1 * ({%start,+,%step}<nsw><%up.header> smin %start)) + {%start,+,%step}<nsw><%up.header>)
+; CHECK-NEXT:  Loop %down.header: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down.header: symbolic max backedge-taken count is ((-1 * ({%start,+,%step}<nsw><%up.header> smin %start)) + {%start,+,%step}<nsw><%up.header>)
+; CHECK-NEXT:  Loop %down.header: Trip multiple is 1
+; CHECK-NEXT:  Loop %up.header: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  br label %up.header
+
+up.header:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up.latch ]
+  %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+  %pos = icmp sgt i32 %v, 0
+  br i1 %pos, label %up.latch, label %down.header
+
+up.latch:
+  %x.next = add nsw i64 %x, %step
+  %v.next = mul i32 %v, 10
+  br label %up.header
+
+down.header:
+  %y = phi i64 [ %x, %up.header ], [ %y.next, %down.latch ]
+  %in.range = icmp sgt i64 %y, %start
+  br i1 %in.range, label %down.latch, label %exit
+
+down.latch:
+  %y.next = add i64 %y, -1
+  br label %down.header
+
+exit:
+  ret void
+}
+
+define void @dec_to_start_of_nsw_addrec_unsigned_clamp(i64 %start, i32 %n, i64 %step.raw) {
+; CHECK-LABEL: 'dec_to_start_of_nsw_addrec_unsigned_clamp'
+; CHECK-NEXT:  Classifying expressions for: @dec_to_start_of_nsw_addrec_unsigned_clamp
+; CHECK-NEXT:    %step = and i64 %step.raw, 7
+; CHECK-NEXT:    --> (zext i3 (trunc i64 %step.raw to i3) to i64) U: [0,8) S: [0,8)
+; CHECK-NEXT:    %x = phi i64 [ %start, %entry ], [ %x.next, %up.latch ]
+; CHECK-NEXT:    --> {%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v = phi i32 [ %n, %entry ], [ %v.next, %up.latch ]
+; CHECK-NEXT:    --> %v U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %x.next = add nsw i64 %x, %step
+; CHECK-NEXT:    --> {((zext i3 (trunc i64 %step.raw to i3) to i64) + %start),+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nw><%up.header> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %up.header: Computable }
+; CHECK-NEXT:    %v.next = mul i32 %v, 10
+; CHECK-NEXT:    --> (10 * %v) U: [0,-1) S: [-2147483648,2147483647) Exits: <<Unknown>> LoopDispositions: { %up.header: Variant }
+; CHECK-NEXT:    %y = phi i64 [ %x, %up.header ], [ %y.next, %down.latch ]
+; CHECK-NEXT:    --> {{\{\{}}%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: ({%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header> umin %start) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:    %y.next = add i64 %y, -1
+; CHECK-NEXT:    --> {{\{\{}}(-1 + %start),+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nw><%up.header>,+,-1}<%down.header> U: full-set S: full-set Exits: (-1 + ({%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header> umin %start)) LoopDispositions: { %down.header: Computable }
+; CHECK-NEXT:  Determining loop execution counts for: @dec_to_start_of_nsw_addrec_unsigned_clamp
+; CHECK-NEXT:  Loop %down.header: backedge-taken count is ((-1 * ({%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header> umin %start)) + {%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header>)
+; CHECK-NEXT:  Loop %down.header: constant max backedge-taken count is i64 -1
+; CHECK-NEXT:  Loop %down.header: symbolic max backedge-taken count is ((-1 * ({%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header> umin %start)) + {%start,+,(zext i3 (trunc i64 %step.raw to i3) to i64)}<nsw><%up.header>)
+; CHECK-NEXT:  Loop %down.header: Trip multiple is 1
+; CHECK-NEXT:  Loop %up.header: Unpredictable backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable constant max backedge-taken count.
+; CHECK-NEXT:  Loop %up.header: Unpredictable symbolic max backedge-taken count.
+;
+entry:
+  %step = and i64 %step.raw, 7
+  br label %up.header
+
+up.header:
+  %x = phi i64 [ %start, %entry ], [ %x.next, %up.latch ]
+  %v = phi i32 [ %n, %entry ], [ %v.next, %up.latc...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/218280


More information about the llvm-commits mailing list