Skip to content

Commit

Permalink
[ScalarEvolution] Refine computeMaxBECountForLT to be accurate in mor…
Browse files Browse the repository at this point in the history
…e cases.

Allow arbitrary strides, and make sure we return the correct result when
the backedge-taken count is zero.

Differential Revision: https://reviews.llvm.org/D106197
  • Loading branch information
efriedma-quic committed Jul 19, 2021
1 parent 381c3b9 commit de3ea51
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 9 deletions.
22 changes: 13 additions & 9 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11529,9 +11529,11 @@ const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start,
const SCEV *End,
unsigned BitWidth,
bool IsSigned) {
// The logic in this function assumes we can represent a positive stride.
// If we can't, the backedge-taken count must be zero.
if (IsSigned && BitWidth == 1)
return getZero(Stride->getType());

assert(!isKnownNonPositive(Stride) &&
"Stride is expected strictly positive!");
// Calculate the maximum backedge count based on the range of values
// permitted by Start, End, and Stride.
const SCEV *MaxBECount;
Expand All @@ -11541,13 +11543,11 @@ const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start,
APInt StrideForMaxBECount =
IsSigned ? getSignedRangeMin(Stride) : getUnsignedRangeMin(Stride);

// We already know that the stride is positive, so we paper over conservatism
// in our range computation by forcing StrideForMaxBECount to be at least one.
// In theory this is unnecessary, but we expect MaxBECount to be a
// SCEVConstant, and (udiv <constant> 0) is not constant folded by SCEV (there
// is nothing to constant fold it to).
APInt One(BitWidth, 1, IsSigned);
StrideForMaxBECount = APIntOps::smax(One, StrideForMaxBECount);
// We assume either the stride is positive, or the backedge-taken count
// is zero. So force StrideForMaxBECount to be at least one.
APInt One(BitWidth, 1);
StrideForMaxBECount = IsSigned ? APIntOps::smax(One, StrideForMaxBECount)
: APIntOps::umax(One, StrideForMaxBECount);

APInt MaxValue = IsSigned ? APInt::getSignedMaxValue(BitWidth)
: APInt::getMaxValue(BitWidth);
Expand All @@ -11560,6 +11560,10 @@ const SCEV *ScalarEvolution::computeMaxBECountForLT(const SCEV *Start,
APInt MaxEnd = IsSigned ? APIntOps::smin(getSignedRangeMax(End), Limit)
: APIntOps::umin(getUnsignedRangeMax(End), Limit);

// MaxBECount = ceil((max(MaxEnd, MinStart) - MinStart) / Stride)
MaxEnd = IsSigned ? APIntOps::smax(MaxEnd, MinStart)
: APIntOps::umax(MaxEnd, MinStart);

MaxBECount = getUDivCeilSCEV(getConstant(MaxEnd - MinStart) /* Delta */,
getConstant(StrideForMaxBECount) /* Step */);

Expand Down
35 changes: 35 additions & 0 deletions llvm/test/Analysis/ScalarEvolution/max-trip-count.ll
Original file line number Diff line number Diff line change
Expand Up @@ -455,3 +455,38 @@ loop:
loop.exit:
ret void
}

define void @max_overflow(i8 %n) mustprogress {
; CHECK-LABEL: Determining loop execution counts for: @max_overflow
; CHECK: Loop %loop: backedge-taken count is (-126 + (126 smax %n))<nsw>
; CHECK: Loop %loop: max backedge-taken count is 0
entry:
br label %loop

loop:
%i = phi i8 [ 63, %entry ], [ %i.next, %loop ]
%i.next = add nsw i8 %i, 63
%t = icmp slt i8 %i.next, %n
br i1 %t, label %loop, label %exit

exit:
ret void
}

; Max backedge-taken count is zero.
define void @bool_stride(i1 %s, i1 %n) mustprogress {
; CHECK-LABEL: Determining loop execution counts for: @bool_stride
; CHECK: Loop %loop: Unpredictable backedge-taken count.
; CHECK: Loop %loop: Unpredictable max backedge-taken count.
entry:
br label %loop

loop:
%i = phi i1 [ -1, %entry ], [ %i.next, %loop ]
%i.next = add nsw i1 %i, %s
%t = icmp slt i1 %i.next, %n
br i1 %t, label %loop, label %exit

exit:
ret void
}

0 comments on commit de3ea51

Please sign in to comment.