[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-transforms
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