diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -11529,9 +11529,11 @@ 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; @@ -11541,13 +11543,11 @@ 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 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); @@ -11560,6 +11560,10 @@ 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 */); diff --git a/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll b/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll --- a/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll +++ b/llvm/test/Analysis/ScalarEvolution/max-trip-count.ll @@ -455,3 +455,38 @@ 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)) +; 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 +}