[llvm] [SCEV] Handle backedge-count logic for std::reverse like loops (PR #92560)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 29 14:24:47 PDT 2024
https://github.com/mrdaybird updated https://github.com/llvm/llvm-project/pull/92560
>From 250adcbc8456d31a8601528b43f586b618a90aa2 Mon Sep 17 00:00:00 2001
From: Vaibhav Pathak <pathakvaibhav at protonmail.com>
Date: Fri, 17 May 2024 19:29:36 +0530
Subject: [PATCH 1/8] Update howManyLessThans
---
llvm/lib/Analysis/ScalarEvolution.cpp | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 515b9d0744f6e..9bf5bf80b4570 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12941,12 +12941,16 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
return RHS;
}
- // When the RHS is not invariant, we do not know the end bound of the loop and
- // cannot calculate the ExactBECount needed by ExitLimit. However, we can
- // calculate the MaxBECount, given the start, stride and max value for the end
- // bound of the loop (RHS), and the fact that IV does not overflow (which is
- // checked above).
if (!isLoopInvariant(RHS, L)) {
+ // If RHS is an add recurrence, try again with lhs=lhs-rhs and rhs=0
+ if(auto RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS)){
+ return howManyLessThans(getMinusSCEV(IV, RHSAddRec),
+ getZero(IV->getType()), L, true, ControlsOnlyExit, AllowPredicates);
+ }
+ // If we cannot calculate ExactBECount, we can calculate the MaxBECount,
+ // given the start, stride and max value for the end bound of the
+ // loop (RHS), and the fact that IV does not overflow (which is
+ // checked above).
const SCEV *MaxBECount = computeMaxBECountForLT(
Start, Stride, RHS, getTypeSizeInBits(LHS->getType()), IsSigned);
return ExitLimit(getCouldNotCompute() /* ExactNotTaken */, MaxBECount,
>From b0b81efc0b337528b2a9b08d2ac92be54ba3a8de Mon Sep 17 00:00:00 2001
From: Vaibhav Pathak <pathakvaibhav at protonmail.com>
Date: Sun, 19 May 2024 21:29:03 +0530
Subject: [PATCH 2/8] Update howManyLessThans
---
llvm/lib/Analysis/ScalarEvolution.cpp | 80 +++++++++++++++++++++------
1 file changed, 64 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 9bf5bf80b4570..5fe7219b59f93 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12941,27 +12941,77 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
return RHS;
}
+ const SCEV *End = nullptr, *BECount = nullptr,
+ *BECountIfBackedgeTaken = nullptr;
if (!isLoopInvariant(RHS, L)) {
- // If RHS is an add recurrence, try again with lhs=lhs-rhs and rhs=0
- if(auto RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS)){
- return howManyLessThans(getMinusSCEV(IV, RHSAddRec),
- getZero(IV->getType()), L, true, ControlsOnlyExit, AllowPredicates);
- }
- // If we cannot calculate ExactBECount, we can calculate the MaxBECount,
- // given the start, stride and max value for the end bound of the
- // loop (RHS), and the fact that IV does not overflow (which is
- // checked above).
- const SCEV *MaxBECount = computeMaxBECountForLT(
- Start, Stride, RHS, getTypeSizeInBits(LHS->getType()), IsSigned);
- return ExitLimit(getCouldNotCompute() /* ExactNotTaken */, MaxBECount,
- MaxBECount, false /*MaxOrZero*/, Predicates);
+ if (auto RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS)){
+ /*
+ The structure of loop we are trying to calculate backedge-count of:
+ left = left_start
+ right = right_start
+ while(left < right){
+ // ... do something here ...
+ left += s1; // stride of left is s1>0
+ right -= s2; // stride of right is -s2 (s2 > 0)
+ }
+ // left and right are converging at the middle
+ // (maybe not exactly at center)
+
+ */
+ const SCEV *RHSStart = RHSAddRec->getStart();
+ const SCEV *RHSStride = RHSAddRec->getStepRecurrence(*this);
+ // if Stride-RHSStride>0 and does not overflow, we can write
+ // backedge count as:
+ // RHSStart >= Start ? (RHSStart - Start)/(Stride - RHSStride) ? 0
+
+ // check if Stride-RHSStride will not overflow
+ if (willNotOverflow(llvm::Instruction::Sub, true, Stride, RHSStride)) {
+ const SCEV *Denominator = getMinusSCEV(Stride, RHSStride);
+ if (isKnownPositive(Denominator)) {
+ End = IsSigned ? getSMaxExpr(RHSStart, Start) :
+ getUMaxExpr(RHSStart, Start); // max(RHSStart, Start)
+
+ const SCEV *Delta = getMinusSCEV(End, Start); // End >= Start
+
+ BECount = getUDivCeilSCEV(Delta, Denominator);
+ BECountIfBackedgeTaken = getUDivCeilSCEV(
+ getMinusSCEV(RHSStart, Start), Denominator);
+
+ const SCEV *ConstantMaxBECount;
+ bool MaxOrZero = false;
+ if (isa<SCEVConstant>(BECount)) {
+ ConstantMaxBECount = BECount;
+ } else if (isa<SCEVConstant>(BECountIfBackedgeTaken)) {
+ ConstantMaxBECount = BECountIfBackedgeTaken;
+ MaxOrZero = true;
+ } else {
+ ConstantMaxBECount = computeMaxBECountForLT(
+ Start, Stride, RHS, getTypeSizeInBits(LHS->getType()),
+ IsSigned);
+ }
+
+ const SCEV *SymbolicMaxBECount = BECount;
+ return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount,
+ MaxOrZero, Predicates);
+ }
+ }
+ }
+ if (BECount == nullptr) {
+ // If we cannot calculate ExactBECount, we can calculate the MaxBECount,
+ // given the start, stride and max value for the end bound of the
+ // loop (RHS), and the fact that IV does not overflow (which is
+ // checked above).
+ const SCEV *MaxBECount = computeMaxBECountForLT(
+ Start, Stride, RHS, getTypeSizeInBits(LHS->getType()), IsSigned);
+ return ExitLimit(getCouldNotCompute() /* ExactNotTaken */, MaxBECount,
+ MaxBECount, false /*MaxOrZero*/, Predicates);
+ }
}
// We use the expression (max(End,Start)-Start)/Stride to describe the
// backedge count, as if the backedge is taken at least once max(End,Start)
// is End and so the result is as above, and if not max(End,Start) is Start
// so we get a backedge count of zero.
- const SCEV *BECount = nullptr;
auto *OrigStartMinusStride = getMinusSCEV(OrigStart, Stride);
assert(isAvailableAtLoopEntry(OrigStartMinusStride, L) && "Must be!");
assert(isAvailableAtLoopEntry(OrigStart, L) && "Must be!");
@@ -12993,7 +13043,6 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
BECount = getUDivExpr(Numerator, Stride);
}
- const SCEV *BECountIfBackedgeTaken = nullptr;
if (!BECount) {
auto canProveRHSGreaterThanEqualStart = [&]() {
auto CondGE = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
@@ -13021,7 +13070,6 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
// If we know that RHS >= Start in the context of loop, then we know that
// max(RHS, Start) = RHS at this point.
- const SCEV *End;
if (canProveRHSGreaterThanEqualStart()) {
End = RHS;
} else {
>From a702df91a2e2b748e89f1be72c94bf5f1175a00f Mon Sep 17 00:00:00 2001
From: Vaibhav Pathak <pathakvaibhav at protonmail.com>
Date: Sun, 19 May 2024 22:18:08 +0530
Subject: [PATCH 3/8] Add negative rhs stride condition
---
llvm/lib/Analysis/ScalarEvolution.cpp | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 5fe7219b59f93..c273abf088206 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12964,8 +12964,11 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
// backedge count as:
// RHSStart >= Start ? (RHSStart - Start)/(Stride - RHSStride) ? 0
- // check if Stride-RHSStride will not overflow
- if (willNotOverflow(llvm::Instruction::Sub, true, Stride, RHSStride)) {
+ // check if RHSStride<0 and Stride-RHSStride will not overflow
+ // FIXME: Can RHSStride be positive?
+ if (isKnownNegative(RHSStride) &&
+ willNotOverflow(llvm::Instruction::Sub, true, Stride, RHSStride)) {
+
const SCEV *Denominator = getMinusSCEV(Stride, RHSStride);
if (isKnownPositive(Denominator)) {
End = IsSigned ? getSMaxExpr(RHSStart, Start) :
>From 71cd21dd2ea284b037f9add5aae9244aa151b741 Mon Sep 17 00:00:00 2001
From: Vaibhav Pathak <pathakvaibhav at protonmail.com>
Date: Tue, 21 May 2024 02:24:56 +0530
Subject: [PATCH 4/8] Fix formatting
---
llvm/lib/Analysis/ScalarEvolution.cpp | 363 +++++++++++++-------------
1 file changed, 176 insertions(+), 187 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index c273abf088206..2447dfa8d2004 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12941,10 +12941,10 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
return RHS;
}
- const SCEV *End = nullptr, *BECount = nullptr,
- *BECountIfBackedgeTaken = nullptr;
+ const SCEV *End = nullptr, *BECount = nullptr,
+ *BECountIfBackedgeTaken = nullptr;
if (!isLoopInvariant(RHS, L)) {
- if (auto RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS)){
+ if (auto RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS)) {
/*
The structure of loop we are trying to calculate backedge-count of:
left = left_start
@@ -12962,213 +12962,202 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
const SCEV *RHSStride = RHSAddRec->getStepRecurrence(*this);
// if Stride-RHSStride>0 and does not overflow, we can write
// backedge count as:
- // RHSStart >= Start ? (RHSStart - Start)/(Stride - RHSStride) ? 0
+ // RHSStart >= Start ? (RHSStart - Start)/(Stride - RHSStride) ? 0
- // check if RHSStride<0 and Stride-RHSStride will not overflow
+ // check if RHSStride<0 and Stride-RHSStride will not overflow
// FIXME: Can RHSStride be positive?
- if (isKnownNegative(RHSStride) &&
- willNotOverflow(llvm::Instruction::Sub, true, Stride, RHSStride)) {
-
- const SCEV *Denominator = getMinusSCEV(Stride, RHSStride);
+ if (isKnownNegative(RHSStride) &&
+ willNotOverflow(llvm::Instruction::Sub, true, Stride, RHSStride)) {
+
+ const SCEV *Denominator = getMinusSCEV(Stride, RHSStride);
if (isKnownPositive(Denominator)) {
- End = IsSigned ? getSMaxExpr(RHSStart, Start) :
- getUMaxExpr(RHSStart, Start); // max(RHSStart, Start)
+ End = IsSigned ? getSMaxExpr(RHSStart, Start)
+ : getUMaxExpr(RHSStart, Start); // max(RHSStart, Start)
const SCEV *Delta = getMinusSCEV(End, Start); // End >= Start
-
- BECount = getUDivCeilSCEV(Delta, Denominator);
- BECountIfBackedgeTaken = getUDivCeilSCEV(
- getMinusSCEV(RHSStart, Start), Denominator);
-
- const SCEV *ConstantMaxBECount;
- bool MaxOrZero = false;
- if (isa<SCEVConstant>(BECount)) {
- ConstantMaxBECount = BECount;
- } else if (isa<SCEVConstant>(BECountIfBackedgeTaken)) {
- ConstantMaxBECount = BECountIfBackedgeTaken;
- MaxOrZero = true;
- } else {
- ConstantMaxBECount = computeMaxBECountForLT(
- Start, Stride, RHS, getTypeSizeInBits(LHS->getType()),
- IsSigned);
- }
- const SCEV *SymbolicMaxBECount = BECount;
- return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount,
- MaxOrZero, Predicates);
+ BECount = getUDivCeilSCEV(Delta, Denominator);
+ BECountIfBackedgeTaken =
+ getUDivCeilSCEV(getMinusSCEV(RHSStart, Start), Denominator);
}
}
- }
+ }
if (BECount == nullptr) {
- // If we cannot calculate ExactBECount, we can calculate the MaxBECount,
- // given the start, stride and max value for the end bound of the
+ // If we cannot calculate ExactBECount, we can calculate the MaxBECount,
+ // given the start, stride and max value for the end bound of the
// loop (RHS), and the fact that IV does not overflow (which is
// checked above).
const SCEV *MaxBECount = computeMaxBECountForLT(
Start, Stride, RHS, getTypeSizeInBits(LHS->getType()), IsSigned);
return ExitLimit(getCouldNotCompute() /* ExactNotTaken */, MaxBECount,
- MaxBECount, false /*MaxOrZero*/, Predicates);
- }
- }
-
- // We use the expression (max(End,Start)-Start)/Stride to describe the
- // backedge count, as if the backedge is taken at least once max(End,Start)
- // is End and so the result is as above, and if not max(End,Start) is Start
- // so we get a backedge count of zero.
- auto *OrigStartMinusStride = getMinusSCEV(OrigStart, Stride);
- assert(isAvailableAtLoopEntry(OrigStartMinusStride, L) && "Must be!");
- 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) &&
- isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigRHS)) {
- // In this case, we can use a refined formula for computing backedge taken
- // count. The general formula remains:
- // "End-Start /uceiling Stride" where "End = max(RHS,Start)"
- // We want to use the alternate formula:
- // "((End - 1) - (Start - Stride)) /u Stride"
- // Let's do a quick case analysis to show these are equivalent under
- // our precondition that max(RHS,Start) > Start - Stride.
- // * For RHS <= Start, the backedge-taken count must be zero.
- // "((End - 1) - (Start - Stride)) /u Stride" reduces to
- // "((Start - 1) - (Start - Stride)) /u Stride" which simplies to
- // "Stride - 1 /u Stride" which is indeed zero for all non-zero values
- // of Stride. For 0 stride, we've use umin(1,Stride) above, reducing
- // this to the stride of 1 case.
- // * For RHS >= Start, the backedge count must be "RHS-Start /uceil Stride".
- // "((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.
- const SCEV *MinusOne = getMinusOne(Stride->getType());
- const SCEV *Numerator =
- getMinusSCEV(getAddExpr(RHS, MinusOne), getMinusSCEV(Start, Stride));
- BECount = getUDivExpr(Numerator, Stride);
- }
-
- if (!BECount) {
- auto canProveRHSGreaterThanEqualStart = [&]() {
- auto CondGE = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
- const SCEV *GuardedRHS = applyLoopGuards(OrigRHS, L);
- const SCEV *GuardedStart = applyLoopGuards(OrigStart, L);
-
- if (isLoopEntryGuardedByCond(L, CondGE, OrigRHS, OrigStart) ||
- isKnownPredicate(CondGE, GuardedRHS, GuardedStart))
- return true;
+ MaxBECount, false /*MaxOrZero*/, Predicates);
+ }
+ } else {
+ // We use the expression (max(End,Start)-Start)/Stride to describe the
+ // backedge count, as if the backedge is taken at least once
+ // max(End,Start) is End and so the result is as above, and if not
+ // max(End,Start) is Start so we get a backedge count of zero.
+ auto *OrigStartMinusStride = getMinusSCEV(OrigStart, Stride);
+ assert(isAvailableAtLoopEntry(OrigStartMinusStride, L) && "Must be!");
+ 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) &&
+ isLoopEntryGuardedByCond(L, Cond, OrigStartMinusStride, OrigRHS)) {
+ // In this case, we can use a refined formula for computing backedge
+ // taken count. The general formula remains:
+ // "End-Start /uceiling Stride" where "End = max(RHS,Start)"
+ // We want to use the alternate formula:
+ // "((End - 1) - (Start - Stride)) /u Stride"
+ // Let's do a quick case analysis to show these are equivalent under
+ // our precondition that max(RHS,Start) > Start - Stride.
+ // * For RHS <= Start, the backedge-taken count must be zero.
+ // "((End - 1) - (Start - Stride)) /u Stride" reduces to
+ // "((Start - 1) - (Start - Stride)) /u Stride" which simplies to
+ // "Stride - 1 /u Stride" which is indeed zero for all non-zero values
+ // of Stride. For 0 stride, we've use umin(1,Stride) above,
+ // reducing this to the stride of 1 case.
+ // * For RHS >= Start, the backedge count must be "RHS-Start /uceil
+ // Stride".
+ // "((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.
+ const SCEV *MinusOne = getMinusOne(Stride->getType());
+ const SCEV *Numerator =
+ getMinusSCEV(getAddExpr(RHS, MinusOne), getMinusSCEV(Start, Stride));
+ BECount = getUDivExpr(Numerator, Stride);
+ }
+
+ if (!BECount) {
+ auto canProveRHSGreaterThanEqualStart = [&]() {
+ auto CondGE = IsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE;
+ const SCEV *GuardedRHS = applyLoopGuards(OrigRHS, L);
+ const SCEV *GuardedStart = applyLoopGuards(OrigStart, L);
+
+ if (isLoopEntryGuardedByCond(L, CondGE, OrigRHS, OrigStart) ||
+ isKnownPredicate(CondGE, GuardedRHS, GuardedStart))
+ return true;
- // (RHS > Start - 1) implies RHS >= Start.
- // * "RHS >= Start" is trivially equivalent to "RHS > Start - 1" if
- // "Start - 1" doesn't overflow.
- // * For signed comparison, if Start - 1 does overflow, it's equal
- // to INT_MAX, and "RHS >s INT_MAX" is trivially false.
- // * For unsigned comparison, if Start - 1 does overflow, it's equal
- // to UINT_MAX, and "RHS >u UINT_MAX" is trivially false.
- //
- // FIXME: Should isLoopEntryGuardedByCond do this for us?
- auto CondGT = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
- auto *StartMinusOne = getAddExpr(OrigStart,
- getMinusOne(OrigStart->getType()));
- return isLoopEntryGuardedByCond(L, CondGT, OrigRHS, StartMinusOne);
- };
+ // (RHS > Start - 1) implies RHS >= Start.
+ // * "RHS >= Start" is trivially equivalent to "RHS > Start - 1" if
+ // "Start - 1" doesn't overflow.
+ // * For signed comparison, if Start - 1 does overflow, it's equal
+ // to INT_MAX, and "RHS >s INT_MAX" is trivially false.
+ // * For unsigned comparison, if Start - 1 does overflow, it's equal
+ // to UINT_MAX, and "RHS >u UINT_MAX" is trivially false.
+ //
+ // FIXME: Should isLoopEntryGuardedByCond do this for us?
+ auto CondGT = IsSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
+ auto *StartMinusOne =
+ getAddExpr(OrigStart, getMinusOne(OrigStart->getType()));
+ return isLoopEntryGuardedByCond(L, CondGT, OrigRHS, StartMinusOne);
+ };
- // If we know that RHS >= Start in the context of loop, then we know that
- // max(RHS, Start) = RHS at this point.
- if (canProveRHSGreaterThanEqualStart()) {
- End = RHS;
- } else {
- // If RHS < Start, the backedge will be taken zero times. So in
- // general, we can write the backedge-taken count as:
+ // If we know that RHS >= Start in the context of loop, then we know
+ // that max(RHS, Start) = RHS at this point.
+ if (canProveRHSGreaterThanEqualStart()) {
+ End = RHS;
+ } else {
+ // If RHS < Start, the backedge will be taken zero times. So in
+ // general, we can write the backedge-taken count as:
+ //
+ // RHS >= Start ? ceil(RHS - Start) / Stride : 0
+ //
+ // We convert it to the following to make it more convenient for SCEV:
+ //
+ // ceil(max(RHS, Start) - Start) / Stride
+ End = IsSigned ? getSMaxExpr(RHS, Start) : getUMaxExpr(RHS, Start);
+
+ // See what would happen if we assume the backedge is taken. This is
+ // used to compute MaxBECount.
+ BECountIfBackedgeTaken =
+ getUDivCeilSCEV(getMinusSCEV(RHS, Start), Stride);
+ }
+
+ // At this point, we know:
//
- // RHS >= Start ? ceil(RHS - Start) / Stride : 0
+ // 1. If IsSigned, Start <=s End; otherwise, Start <=u End
+ // 2. The index variable doesn't overflow.
//
- // We convert it to the following to make it more convenient for SCEV:
+ // Therefore, we know N exists such that
+ // (Start + Stride * N) >= End, and computing "(Start + Stride * N)"
+ // doesn't overflow.
//
- // ceil(max(RHS, Start) - Start) / Stride
- End = IsSigned ? getSMaxExpr(RHS, Start) : getUMaxExpr(RHS, Start);
-
- // See what would happen if we assume the backedge is taken. This is
- // used to compute MaxBECount.
- BECountIfBackedgeTaken = getUDivCeilSCEV(getMinusSCEV(RHS, Start), Stride);
- }
-
- // At this point, we know:
- //
- // 1. If IsSigned, Start <=s End; otherwise, Start <=u End
- // 2. The index variable doesn't overflow.
- //
- // Therefore, we know N exists such that
- // (Start + Stride * N) >= End, and computing "(Start + Stride * N)"
- // doesn't overflow.
- //
- // Using this information, try to prove whether the addition in
- // "(Start - End) + (Stride - 1)" has unsigned overflow.
- const SCEV *One = getOne(Stride->getType());
- bool MayAddOverflow = [&] {
- if (auto *StrideC = dyn_cast<SCEVConstant>(Stride)) {
- if (StrideC->getAPInt().isPowerOf2()) {
- // Suppose Stride is a power of two, and Start/End are unsigned
- // integers. Let UMAX be the largest representable unsigned
- // integer.
- //
- // By the preconditions of this function, we know
- // "(Start + Stride * N) >= End", and this doesn't overflow.
- // As a formula:
- //
- // End <= (Start + Stride * N) <= UMAX
- //
- // Subtracting Start from all the terms:
- //
- // End - Start <= Stride * N <= UMAX - Start
- //
- // Since Start is unsigned, UMAX - Start <= UMAX. Therefore:
- //
- // End - Start <= Stride * N <= UMAX
- //
- // Stride * N is a multiple of Stride. Therefore,
- //
- // End - Start <= Stride * N <= UMAX - (UMAX mod Stride)
- //
- // Since Stride is a power of two, UMAX + 1 is divisible by Stride.
- // Therefore, UMAX mod Stride == Stride - 1. So we can write:
- //
- // End - Start <= Stride * N <= UMAX - Stride - 1
- //
- // Dropping the middle term:
- //
- // End - Start <= UMAX - Stride - 1
- //
- // Adding Stride - 1 to both sides:
- //
- // (End - Start) + (Stride - 1) <= UMAX
- //
- // In other words, the addition doesn't have unsigned overflow.
+ // Using this information, try to prove whether the addition in
+ // "(Start - End) + (Stride - 1)" has unsigned overflow.
+ const SCEV *One = getOne(Stride->getType());
+ bool MayAddOverflow = [&] {
+ if (auto *StrideC = dyn_cast<SCEVConstant>(Stride)) {
+ if (StrideC->getAPInt().isPowerOf2()) {
+ // Suppose Stride is a power of two, and Start/End are unsigned
+ // integers. Let UMAX be the largest representable unsigned
+ // integer.
+ //
+ // By the preconditions of this function, we know
+ // "(Start + Stride * N) >= End", and this doesn't overflow.
+ // As a formula:
+ //
+ // End <= (Start + Stride * N) <= UMAX
+ //
+ // Subtracting Start from all the terms:
+ //
+ // End - Start <= Stride * N <= UMAX - Start
+ //
+ // Since Start is unsigned, UMAX - Start <= UMAX. Therefore:
+ //
+ // End - Start <= Stride * N <= UMAX
+ //
+ // Stride * N is a multiple of Stride. Therefore,
+ //
+ // End - Start <= Stride * N <= UMAX - (UMAX mod Stride)
+ //
+ // Since Stride is a power of two, UMAX + 1 is divisible by
+ // Stride. Therefore, UMAX mod Stride == Stride - 1. So we can
+ // write:
+ //
+ // End - Start <= Stride * N <= UMAX - Stride - 1
+ //
+ // Dropping the middle term:
+ //
+ // End - Start <= UMAX - Stride - 1
+ //
+ // Adding Stride - 1 to both sides:
+ //
+ // (End - Start) + (Stride - 1) <= UMAX
+ //
+ // In other words, the addition doesn't have unsigned overflow.
+ //
+ // A similar proof works if we treat Start/End as signed values.
+ // Just rewrite steps before "End - Start <= Stride * N <= UMAX"
+ // to use signed max instead of unsigned max. Note that we're
+ // trying to prove a lack of unsigned overflow in either case.
+ return false;
+ }
+ }
+ if (Start == Stride || Start == getMinusSCEV(Stride, One)) {
+ // If Start is equal to Stride, (End - Start) + (Stride - 1) == End
+ // - 1. If !IsSigned, 0 <u Stride == Start <=u End; so 0 <u End - 1
+ // <u End. If IsSigned, 0 <s Stride == Start <=s End; so 0 <s End -
+ // 1 <s End.
//
- // A similar proof works if we treat Start/End as signed values.
- // Just rewrite steps before "End - Start <= Stride * N <= UMAX" to
- // use signed max instead of unsigned max. Note that we're trying
- // to prove a lack of unsigned overflow in either case.
+ // If Start is equal to Stride - 1, (End - Start) + Stride - 1 ==
+ // End.
return false;
}
+ return true;
+ }();
+
+ const SCEV *Delta = getMinusSCEV(End, Start);
+ if (!MayAddOverflow) {
+ // floor((D + (S - 1)) / S)
+ // We prefer this formulation if it's legal because it's fewer
+ // operations.
+ BECount =
+ getUDivExpr(getAddExpr(Delta, getMinusSCEV(Stride, One)), Stride);
+ } else {
+ BECount = getUDivCeilSCEV(Delta, Stride);
}
- if (Start == Stride || Start == getMinusSCEV(Stride, One)) {
- // If Start is equal to Stride, (End - Start) + (Stride - 1) == End - 1.
- // If !IsSigned, 0 <u Stride == Start <=u End; so 0 <u End - 1 <u End.
- // If IsSigned, 0 <s Stride == Start <=s End; so 0 <s End - 1 <s End.
- //
- // If Start is equal to Stride - 1, (End - Start) + Stride - 1 == End.
- return false;
- }
- return true;
- }();
-
- const SCEV *Delta = getMinusSCEV(End, Start);
- if (!MayAddOverflow) {
- // floor((D + (S - 1)) / S)
- // We prefer this formulation if it's legal because it's fewer operations.
- BECount =
- getUDivExpr(getAddExpr(Delta, getMinusSCEV(Stride, One)), Stride);
- } else {
- BECount = getUDivCeilSCEV(Delta, Stride);
}
}
>From 8a6ef3b77e02a130ba27b59d43952e0458a0ea9d Mon Sep 17 00:00:00 2001
From: Vaibhav Pathak <pathakvaibhav at protonmail.com>
Date: Tue, 21 May 2024 16:22:48 +0530
Subject: [PATCH 5/8] Add tests
---
llvm/lib/Analysis/ScalarEvolution.cpp | 4 +-
llvm/test/Analysis/ScalarEvolution/pr92560.ll | 69 +++++++++++++++++++
2 files changed, 71 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/Analysis/ScalarEvolution/pr92560.ll
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 4add399344bc3..165efbf12c7fa 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12944,7 +12944,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
const SCEV *End = nullptr, *BECount = nullptr,
*BECountIfBackedgeTaken = nullptr;
if (!isLoopInvariant(RHS, L)) {
- if (auto RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS)) {
+ if (const auto *RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS)) {
/*
The structure of loop we are trying to calculate backedge-count of:
left = left_start
@@ -12967,7 +12967,7 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
// check if RHSStride<0 and Stride-RHSStride will not overflow
// FIXME: Can RHSStride be positive?
if (isKnownNegative(RHSStride) &&
- willNotOverflow(llvm::Instruction::Sub, true, Stride, RHSStride)) {
+ willNotOverflow(Instruction::Sub, /*Signed=*/true, Stride, RHSStride)) {
const SCEV *Denominator = getMinusSCEV(Stride, RHSStride);
if (isKnownPositive(Denominator)) {
diff --git a/llvm/test/Analysis/ScalarEvolution/pr92560.ll b/llvm/test/Analysis/ScalarEvolution/pr92560.ll
new file mode 100644
index 0000000000000..bfd92c4fe83ee
--- /dev/null
+++ b/llvm/test/Analysis/ScalarEvolution/pr92560.ll
@@ -0,0 +1,69 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -disable-output "-passes=print<scalar-evolution>" < %s 2>&1 | FileCheck %s
+
+define dso_local void @simple(i32 noundef %n) local_unnamed_addr {
+; CHECK-LABEL: 'simple'
+; CHECK-NEXT: Classifying expressions for: @simple
+; CHECK-NEXT: %right.06 = phi i32 [ %dec, %while.body ], [ %n, %entry ]
+; CHECK-NEXT: --> {%n,+,-4}<nsw><%while.body> U: full-set S: full-set Exits: ((-4 * (((-4 + (-1 * (1 umin (-4 + (4 smax (-4 + %n)))<nsw>))<nuw><nsw> + (4 smax (-4 + %n))) /u 8) + (1 umin (-4 + (4 smax (-4 + %n)))<nsw>)))<nsw> + %n) LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %left.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
+; CHECK-NEXT: --> {0,+,4}<nuw><nsw><%while.body> U: [0,2147483641) S: [0,2147483641) Exits: (4 * (((-4 + (-1 * (1 umin (-4 + (4 smax (-4 + %n)))<nsw>))<nuw><nsw> + (4 smax (-4 + %n))) /u 8) + (1 umin (-4 + (4 smax (-4 + %n)))<nsw>)))<nuw> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %inc = add nuw nsw i32 %left.05, 4
+; CHECK-NEXT: --> {4,+,4}<nuw><nsw><%while.body> U: [4,2147483645) S: [4,2147483645) Exits: (4 + (4 * (((-4 + (-1 * (1 umin (-4 + (4 smax (-4 + %n)))<nsw>))<nuw><nsw> + (4 smax (-4 + %n))) /u 8) + (1 umin (-4 + (4 smax (-4 + %n)))<nsw>)))<nuw>)<nuw> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %dec = add nsw i32 %right.06, -4
+; CHECK-NEXT: --> {(-4 + %n),+,-4}<nsw><%while.body> U: full-set S: full-set Exits: (-4 + (-4 * (((-4 + (-1 * (1 umin (-4 + (4 smax (-4 + %n)))<nsw>))<nuw><nsw> + (4 smax (-4 + %n))) /u 8) + (1 umin (-4 + (4 smax (-4 + %n)))<nsw>)))<nsw> + %n) LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: Determining loop execution counts for: @simple
+; CHECK-NEXT: Loop %while.body: backedge-taken count is (((-4 + (-1 * (1 umin (-4 + (4 smax (-4 + %n)))<nsw>))<nuw><nsw> + (4 smax (-4 + %n))) /u 8) + (1 umin (-4 + (4 smax (-4 + %n)))<nsw>))
+; CHECK-NEXT: Loop %while.body: constant max backedge-taken count is i32 536870910
+; CHECK-NEXT: Loop %while.body: symbolic max backedge-taken count is (((-4 + (-1 * (1 umin (-4 + (4 smax (-4 + %n)))<nsw>))<nuw><nsw> + (4 smax (-4 + %n))) /u 8) + (1 umin (-4 + (4 smax (-4 + %n)))<nsw>))
+; CHECK-NEXT: Loop %while.body: Trip multiple is 1
+;
+entry:
+ %cmp4 = icmp sgt i32 %n, 0
+ br i1 %cmp4, label %while.body, label %while.end
+
+while.body:
+ %right.06 = phi i32 [ %dec, %while.body ], [ %n, %entry ]
+ %left.05 = phi i32 [ %inc, %while.body ], [ 0, %entry ]
+ %inc = add nuw nsw i32 %left.05, 4
+ %dec = add nsw i32 %right.06, -4
+ %cmp = icmp slt i32 %inc, %dec
+ br i1 %cmp, label %while.body, label %while.end
+
+while.end:
+ ret void
+}
+
+define dso_local void @overflow(i32 noundef %n) local_unnamed_addr {
+; CHECK-LABEL: 'overflow'
+; CHECK-NEXT: Classifying expressions for: @overflow
+; CHECK-NEXT: %right.06 = phi i32 [ %dec, %while.body ], [ %n, %entry ]
+; CHECK-NEXT: --> {%n,+,-1}<nsw><%while.body> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %left.05 = phi i32 [ %inc, %while.body ], [ 2147483647, %entry ]
+; CHECK-NEXT: --> {2147483647,+,2147483647}<nuw><nsw><%while.body> U: [2147483647,-2147483648) S: [2147483647,-2147483648) Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %inc = add nuw nsw i32 %left.05, 2147483647
+; CHECK-NEXT: --> {-2,+,2147483647}<nuw><nsw><%while.body> U: [-2,-1) S: [-2,0) Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %dec = add nsw i32 %right.06, -1
+; CHECK-NEXT: --> {(-1 + %n),+,-1}<nsw><%while.body> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: Determining loop execution counts for: @overflow
+; CHECK-NEXT: Loop %while.body: Unpredictable backedge-taken count.
+; CHECK-NEXT: Loop %while.body: constant max backedge-taken count is i32 1
+; CHECK-NEXT: Loop %while.body: symbolic max backedge-taken count is i32 1
+;
+entry:
+ %cmp4 = icmp sgt i32 %n, 0
+ br i1 %cmp4, label %while.body, label %while.end
+
+while.body:
+ %right.06 = phi i32 [ %dec, %while.body ], [ %n, %entry ]
+ %left.05 = phi i32 [ %inc, %while.body ], [ 2147483647, %entry ]
+ %inc = add nuw nsw i32 %left.05, 2147483647
+ %dec = add nsw i32 %right.06, -1
+ %cmp = icmp slt i32 %inc, %dec
+ br i1 %cmp, label %while.body, label %while.end
+
+while.end:
+ ret void
+}
+
+
>From c3cfa5b7657659209a01f7e47f769048aedf773e Mon Sep 17 00:00:00 2001
From: Vaibhav Pathak <pathakvaibhav at protonmail.com>
Date: Thu, 23 May 2024 10:59:57 +0530
Subject: [PATCH 6/8] Add condition for RHS to be in the same loop, fix
formatting
---
llvm/lib/Analysis/ScalarEvolution.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 165efbf12c7fa..163c47cfde069 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12944,7 +12944,8 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
const SCEV *End = nullptr, *BECount = nullptr,
*BECountIfBackedgeTaken = nullptr;
if (!isLoopInvariant(RHS, L)) {
- if (const auto *RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS)) {
+ const auto *RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS);
+ if (RHSAddRec != nullptr && RHSAddRec->getLoop() == L) {
/*
The structure of loop we are trying to calculate backedge-count of:
left = left_start
@@ -12967,7 +12968,8 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
// check if RHSStride<0 and Stride-RHSStride will not overflow
// FIXME: Can RHSStride be positive?
if (isKnownNegative(RHSStride) &&
- willNotOverflow(Instruction::Sub, /*Signed=*/true, Stride, RHSStride)) {
+ willNotOverflow(Instruction::Sub, /*Signed=*/true, Stride,
+ RHSStride)) {
const SCEV *Denominator = getMinusSCEV(Stride, RHSStride);
if (isKnownPositive(Denominator)) {
>From 65304a9cdf67bc8fc3da578609191b70be33ce77 Mon Sep 17 00:00:00 2001
From: Vaibhav Pathak <pathakvaibhav at protonmail.com>
Date: Wed, 29 May 2024 12:45:18 +0530
Subject: [PATCH 7/8] Update comment formatting
---
llvm/lib/Analysis/ScalarEvolution.cpp | 39 ++++++++++++++-------------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 163c47cfde069..c0a48e42e4f47 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12946,26 +12946,28 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
if (!isLoopInvariant(RHS, L)) {
const auto *RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS);
if (RHSAddRec != nullptr && RHSAddRec->getLoop() == L) {
- /*
- The structure of loop we are trying to calculate backedge-count of:
- left = left_start
- right = right_start
- while(left < right){
- // ... do something here ...
- left += s1; // stride of left is s1>0
- right -= s2; // stride of right is -s2 (s2 > 0)
- }
- // left and right are converging at the middle
- // (maybe not exactly at center)
+ // The structure of loop we are trying to calculate backedge count of:
+ //
+ // left = left_start
+ // right = right_start
+ //
+ // while(left < right){
+ // ... do something here ...
+ // left += s1; // stride of left is s1>0
+ // right -= s2; // stride of right is -s2 (s2 > 0)
+ // }
+ //
+ // Here, left and right are converging somewhere in the middle.
- */
const SCEV *RHSStart = RHSAddRec->getStart();
const SCEV *RHSStride = RHSAddRec->getStepRecurrence(*this);
- // if Stride-RHSStride>0 and does not overflow, we can write
- // backedge count as:
- // RHSStart >= Start ? (RHSStart - Start)/(Stride - RHSStride) ? 0
- // check if RHSStride<0 and Stride-RHSStride will not overflow
+ // If Stride - RHSStride is positive and does not overflow, we can write
+ // backedge count as ->
+ // ceil((End - Start) /u (Stride - RHSStride))
+ // Where, End = max(RHSStart, Start)
+
+ // Check if RHSStride < 0 and Stride - RHSStride will not overflow.
// FIXME: Can RHSStride be positive?
if (isKnownNegative(RHSStride) &&
willNotOverflow(Instruction::Sub, /*Signed=*/true, Stride,
@@ -12974,9 +12976,10 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
const SCEV *Denominator = getMinusSCEV(Stride, RHSStride);
if (isKnownPositive(Denominator)) {
End = IsSigned ? getSMaxExpr(RHSStart, Start)
- : getUMaxExpr(RHSStart, Start); // max(RHSStart, Start)
+ : getUMaxExpr(RHSStart, Start);
- const SCEV *Delta = getMinusSCEV(End, Start); // End >= Start
+ // We can do this because End >= Start, as End = max(RHSStart, Start)
+ const SCEV *Delta = getMinusSCEV(End, Start);
BECount = getUDivCeilSCEV(Delta, Denominator);
BECountIfBackedgeTaken =
>From f5652e7be67d3c0bc5b46f727d560bd2d0a1e124 Mon Sep 17 00:00:00 2001
From: Vaibhav Pathak <pathakvaibhav at protonmail.com>
Date: Thu, 30 May 2024 02:54:23 +0530
Subject: [PATCH 8/8] Check for RHSAddRec nowrap flags and add test
---
llvm/lib/Analysis/ScalarEvolution.cpp | 3 +-
llvm/test/Analysis/ScalarEvolution/pr92560.ll | 44 +++++++++++++++++--
2 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index c0a48e42e4f47..adbb66f796d4c 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12945,7 +12945,8 @@ ScalarEvolution::howManyLessThans(const SCEV *LHS, const SCEV *RHS,
*BECountIfBackedgeTaken = nullptr;
if (!isLoopInvariant(RHS, L)) {
const auto *RHSAddRec = dyn_cast<SCEVAddRecExpr>(RHS);
- if (RHSAddRec != nullptr && RHSAddRec->getLoop() == L) {
+ bool RHSNoWrap = RHSAddRec->getNoWrapFlags();
+ if (RHSAddRec != nullptr && RHSAddRec->getLoop() == L && RHSNoWrap) {
// The structure of loop we are trying to calculate backedge count of:
//
// left = left_start
diff --git a/llvm/test/Analysis/ScalarEvolution/pr92560.ll b/llvm/test/Analysis/ScalarEvolution/pr92560.ll
index bfd92c4fe83ee..3ce3a8f3e4eb8 100644
--- a/llvm/test/Analysis/ScalarEvolution/pr92560.ll
+++ b/llvm/test/Analysis/ScalarEvolution/pr92560.ll
@@ -34,9 +34,10 @@ while.end:
ret void
}
-define dso_local void @overflow(i32 noundef %n) local_unnamed_addr {
-; CHECK-LABEL: 'overflow'
-; CHECK-NEXT: Classifying expressions for: @overflow
+; Cannot find backedge-count because subtraction of strides is wrapping.
+define dso_local void @stride_overflow(i32 noundef %n) local_unnamed_addr {
+; CHECK-LABEL: 'stride_overflow'
+; CHECK-NEXT: Classifying expressions for: @stride_overflow
; CHECK-NEXT: %right.06 = phi i32 [ %dec, %while.body ], [ %n, %entry ]
; CHECK-NEXT: --> {%n,+,-1}<nsw><%while.body> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
; CHECK-NEXT: %left.05 = phi i32 [ %inc, %while.body ], [ 2147483647, %entry ]
@@ -45,7 +46,7 @@ define dso_local void @overflow(i32 noundef %n) local_unnamed_addr {
; CHECK-NEXT: --> {-2,+,2147483647}<nuw><nsw><%while.body> U: [-2,-1) S: [-2,0) Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
; CHECK-NEXT: %dec = add nsw i32 %right.06, -1
; CHECK-NEXT: --> {(-1 + %n),+,-1}<nsw><%while.body> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
-; CHECK-NEXT: Determining loop execution counts for: @overflow
+; CHECK-NEXT: Determining loop execution counts for: @stride_overflow
; CHECK-NEXT: Loop %while.body: Unpredictable backedge-taken count.
; CHECK-NEXT: Loop %while.body: constant max backedge-taken count is i32 1
; CHECK-NEXT: Loop %while.body: symbolic max backedge-taken count is i32 1
@@ -66,4 +67,39 @@ while.end:
ret void
}
+; Cannot find backedge-count because %conv110 is wrapping
+define dso_local void @rhs_wrapping() local_unnamed_addr {
+; CHECK-LABEL: 'rhs_wrapping'
+; CHECK-NEXT: Classifying expressions for: @rhs_wrapping
+; CHECK-NEXT: %a = alloca i8, align 1
+; CHECK-NEXT: --> %a U: full-set S: full-set
+; CHECK-NEXT: %conv110 = phi i32 [ 0, %entry ], [ %sext8, %while.body ]
+; CHECK-NEXT: --> {0,+,-1090519040}<%while.body> U: [0,-16777215) S: [-2147483648,2130706433) Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %conv9 = phi i32 [ -2147483648, %entry ], [ %sext, %while.body ]
+; CHECK-NEXT: --> {-2147483648,+,16777216}<nsw><%while.body> U: [0,-16777215) S: [-2147483648,2113929217) Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %sext = add nsw i32 %conv9, 16777216
+; CHECK-NEXT: --> {-2130706432,+,16777216}<nsw><%while.body> U: [0,-16777215) S: [-2130706432,2130706433) Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: %sext8 = add i32 %conv110, -1090519040
+; CHECK-NEXT: --> {-1090519040,+,-1090519040}<%while.body> U: [0,-16777215) S: [-2147483648,2130706433) Exits: <<Unknown>> LoopDispositions: { %while.body: Computable }
+; CHECK-NEXT: Determining loop execution counts for: @rhs_wrapping
+; CHECK-NEXT: Loop %while.body: Unpredictable backedge-taken count.
+; CHECK-NEXT: Loop %while.body: constant max backedge-taken count is i32 254
+; CHECK-NEXT: Loop %while.body: symbolic max backedge-taken count is i32 254
+;
+entry:
+ %a = alloca i8, align 1
+ br label %while.body
+
+while.body:
+ %conv110 = phi i32 [ 0, %entry ], [ %sext8, %while.body ]
+ %conv9 = phi i32 [ -2147483648, %entry ], [ %sext, %while.body ]
+ %sext = add nsw i32 %conv9, 16777216
+ %sext8 = add i32 %conv110, -1090519040
+ %cmp = icmp slt i32 %sext, %sext8
+ br i1 %cmp, label %while.body, label %while.end
+
+while.end:
+ ret void
+}
+
More information about the llvm-commits
mailing list