Fix the the ceiling-division used in computing the MaxBECount so that it doesn't
authorDan Gohman <gohman@apple.com>
Tue, 26 Jan 2010 04:40:18 +0000 (04:40 +0000)
committerDan Gohman <gohman@apple.com>
Tue, 26 Jan 2010 04:40:18 +0000 (04:40 +0000)
have trouble with an intermediate add overflowing. Also, be more conservative
about the case where the induction variable in an SLT loop exit can step past
the RHS of the SLT and overflow in a single step.

Make getSignedRange more aggressive, to recover for some common cases which
the above fixes pessimized.

This addresses rdar://7561161.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94512 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ScalarEvolution.cpp
test/Analysis/ScalarEvolution/nsw-offset.ll
test/Analysis/ScalarEvolution/trip-count9.ll [new file with mode: 0644]

index 2f44913abd4eced65aa00a67d338873a5e63a331..b8755436912d283ce361d817932e8189d6d6b4fc 100644 (file)
@@ -2912,61 +2912,69 @@ ScalarEvolution::getSignedRange(const SCEV *S) {
   if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
     return ConstantRange(C->getValue()->getValue());
 
+  unsigned BitWidth = getTypeSizeInBits(S->getType());
+  ConstantRange ConservativeResult(BitWidth, /*isFullSet=*/true);
+
+  // If the value has known zeros, the maximum signed value will have those
+  // known zeros as well.
+  uint32_t TZ = GetMinTrailingZeros(S);
+  if (TZ != 0)
+    ConservativeResult =
+      ConstantRange(APInt::getSignedMinValue(BitWidth),
+                    APInt::getSignedMaxValue(BitWidth).ashr(TZ).shl(TZ) + 1);
+
   if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
     ConstantRange X = getSignedRange(Add->getOperand(0));
     for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i)
       X = X.add(getSignedRange(Add->getOperand(i)));
-    return X;
+    return ConservativeResult.intersectWith(X);
   }
 
   if (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(S)) {
     ConstantRange X = getSignedRange(Mul->getOperand(0));
     for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i)
       X = X.multiply(getSignedRange(Mul->getOperand(i)));
-    return X;
+    return ConservativeResult.intersectWith(X);
   }
 
   if (const SCEVSMaxExpr *SMax = dyn_cast<SCEVSMaxExpr>(S)) {
     ConstantRange X = getSignedRange(SMax->getOperand(0));
     for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i)
       X = X.smax(getSignedRange(SMax->getOperand(i)));
-    return X;
+    return ConservativeResult.intersectWith(X);
   }
 
   if (const SCEVUMaxExpr *UMax = dyn_cast<SCEVUMaxExpr>(S)) {
     ConstantRange X = getSignedRange(UMax->getOperand(0));
     for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i)
       X = X.umax(getSignedRange(UMax->getOperand(i)));
-    return X;
+    return ConservativeResult.intersectWith(X);
   }
 
   if (const SCEVUDivExpr *UDiv = dyn_cast<SCEVUDivExpr>(S)) {
     ConstantRange X = getSignedRange(UDiv->getLHS());
     ConstantRange Y = getSignedRange(UDiv->getRHS());
-    return X.udiv(Y);
+    return ConservativeResult.intersectWith(X.udiv(Y));
   }
 
   if (const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S)) {
     ConstantRange X = getSignedRange(ZExt->getOperand());
-    return X.zeroExtend(cast<IntegerType>(ZExt->getType())->getBitWidth());
+    return ConservativeResult.intersectWith(X.zeroExtend(BitWidth));
   }
 
   if (const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S)) {
     ConstantRange X = getSignedRange(SExt->getOperand());
-    return X.signExtend(cast<IntegerType>(SExt->getType())->getBitWidth());
+    return ConservativeResult.intersectWith(X.signExtend(BitWidth));
   }
 
   if (const SCEVTruncateExpr *Trunc = dyn_cast<SCEVTruncateExpr>(S)) {
     ConstantRange X = getSignedRange(Trunc->getOperand());
-    return X.truncate(cast<IntegerType>(Trunc->getType())->getBitWidth());
+    return ConservativeResult.intersectWith(X.truncate(BitWidth));
   }
 
-  ConstantRange FullSet(getTypeSizeInBits(S->getType()), true);
-
   if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
     const SCEV *T = getBackedgeTakenCount(AddRec->getLoop());
     const SCEVConstant *Trip = dyn_cast<SCEVConstant>(T);
-    ConstantRange ConservativeResult = FullSet;
 
     // If there's no signed wrap, and all the operands have the same sign or
     // zero, the value won't ever change sign.
@@ -2977,20 +2985,21 @@ ScalarEvolution::getSignedRange(const SCEV *S) {
         if (!isKnownNonNegative(AddRec->getOperand(i))) AllNonNeg = false;
         if (!isKnownNonPositive(AddRec->getOperand(i))) AllNonPos = false;
       }
-      unsigned BitWidth = getTypeSizeInBits(AddRec->getType());
       if (AllNonNeg)
-        ConservativeResult = ConstantRange(APInt(BitWidth, 0),
-                                           APInt::getSignedMinValue(BitWidth));
+        ConservativeResult = ConservativeResult.intersectWith(
+          ConstantRange(APInt(BitWidth, 0),
+                        APInt::getSignedMinValue(BitWidth)));
       else if (AllNonPos)
-        ConservativeResult = ConstantRange(APInt::getSignedMinValue(BitWidth),
-                                           APInt(BitWidth, 1));
+        ConservativeResult = ConservativeResult.intersectWith(
+          ConstantRange(APInt::getSignedMinValue(BitWidth),
+                        APInt(BitWidth, 1)));
     }
 
     // TODO: non-affine addrec
     if (Trip && AddRec->isAffine()) {
       const Type *Ty = AddRec->getType();
       const SCEV *MaxBECount = getMaxBackedgeTakenCount(AddRec->getLoop());
-      if (getTypeSizeInBits(MaxBECount->getType()) <= getTypeSizeInBits(Ty)) {
+      if (getTypeSizeInBits(MaxBECount->getType()) <= BitWidth) {
         MaxBECount = getNoopOrZeroExtend(MaxBECount, Ty);
 
         const SCEV *Start = AddRec->getStart();
@@ -3008,7 +3017,7 @@ ScalarEvolution::getSignedRange(const SCEV *S) {
                                    EndRange.getSignedMax());
         if (Min.isMinSignedValue() && Max.isMaxSignedValue())
           return ConservativeResult;
-        return ConstantRange(Min, Max+1);
+        return ConservativeResult.intersectWith(ConstantRange(Min, Max+1));
       }
     }
 
@@ -3017,18 +3026,17 @@ ScalarEvolution::getSignedRange(const SCEV *S) {
 
   if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
     // For a SCEVUnknown, ask ValueTracking.
-    unsigned BitWidth = getTypeSizeInBits(U->getType());
     if (!U->getValue()->getType()->isInteger() && !TD)
-      return FullSet;
+      return ConservativeResult;
     unsigned NS = ComputeNumSignBits(U->getValue(), TD);
     if (NS == 1)
-      return FullSet;
-    return
+      return ConservativeResult;
+    return ConservativeResult.intersectWith(
       ConstantRange(APInt::getSignedMinValue(BitWidth).ashr(NS - 1),
-                    APInt::getSignedMaxValue(BitWidth).ashr(NS - 1)+1);
+                    APInt::getSignedMaxValue(BitWidth).ashr(NS - 1)+1));
   }
 
-  return FullSet;
+  return ConservativeResult;
 }
 
 /// createSCEV - We know that there is no SCEV for the specified value.
@@ -4947,6 +4955,9 @@ const SCEV *ScalarEvolution::getBECount(const SCEV *Start,
                                         const SCEV *End,
                                         const SCEV *Step,
                                         bool NoWrap) {
+  assert(!isKnownNegative(Step) &&
+         "This code doesn't handle negative strides yet!");
+
   const Type *Ty = Start->getType();
   const SCEV *NegOne = getIntegerSCEV(-1, Ty);
   const SCEV *Diff = getMinusSCEV(End, Start);
@@ -4989,39 +5000,35 @@ ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
                            AddRec->hasNoUnsignedWrap();
 
   if (AddRec->isAffine()) {
-    // FORNOW: We only support unit strides.
     unsigned BitWidth = getTypeSizeInBits(AddRec->getType());
     const SCEV *Step = AddRec->getStepRecurrence(*this);
 
-    // TODO: handle non-constant strides.
-    const SCEVConstant *CStep = dyn_cast<SCEVConstant>(Step);
-    if (!CStep || CStep->isZero())
+    if (Step->isZero())
       return getCouldNotCompute();
-    if (CStep->isOne()) {
+    if (Step->isOne()) {
       // With unit stride, the iteration never steps past the limit value.
-    } else if (CStep->getValue()->getValue().isStrictlyPositive()) {
-      if (NoWrap) {
-        // We know the iteration won't step past the maximum value for its type.
-        ;
-      } else if (const SCEVConstant *CLimit = dyn_cast<SCEVConstant>(RHS)) {
-        // Test whether a positive iteration iteration can step past the limit
-        // value and past the maximum value for its type in a single step.
-        if (isSigned) {
-          APInt Max = APInt::getSignedMaxValue(BitWidth);
-          if ((Max - CStep->getValue()->getValue())
-                .slt(CLimit->getValue()->getValue()))
-            return getCouldNotCompute();
-        } else {
-          APInt Max = APInt::getMaxValue(BitWidth);
-          if ((Max - CStep->getValue()->getValue())
-                .ult(CLimit->getValue()->getValue()))
-            return getCouldNotCompute();
-        }
-      } else
-        // TODO: handle non-constant limit values below.
-        return getCouldNotCompute();
+    } else if (isKnownPositive(Step)) {
+      // Test whether a positive iteration iteration can step past the limit
+      // value and past the maximum value for its type in a single step.
+      // Note that it's not sufficient to check NoWrap here, because even
+      // though the value after a wrap is undefined, it's not undefined
+      // behavior, so if wrap does occur, the loop could either terminate or
+      // loop infinately, but in either case, the loop is guaranteed to
+      // iterate at least until the iteration where the wrapping occurs.
+      const SCEV *One = getIntegerSCEV(1, Step->getType());
+      if (isSigned) {
+        APInt Max = APInt::getSignedMaxValue(BitWidth);
+        if ((Max - getSignedRange(getMinusSCEV(Step, One)).getSignedMax())
+              .slt(getSignedRange(RHS).getSignedMax()))
+          return getCouldNotCompute();
+      } else {
+        APInt Max = APInt::getMaxValue(BitWidth);
+        if ((Max - getUnsignedRange(getMinusSCEV(Step, One)).getUnsignedMax())
+              .ult(getUnsignedRange(RHS).getUnsignedMax()))
+          return getCouldNotCompute();
+      }
     } else
-      // TODO: handle negative strides below.
+      // TODO: Handle negative strides here and below.
       return getCouldNotCompute();
 
     // We know the LHS is of the form {n,+,s} and the RHS is some loop-invariant
@@ -5054,6 +5061,20 @@ ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
       getSignedRange(End).getSignedMax() :
       getUnsignedRange(End).getUnsignedMax());
 
+    // If MaxEnd is within a step of the maximum integer value in its type,
+    // adjust it down to the minimum value which would produce the same effect.
+    // This allows the subsequent ceiling divison of (N+(step-1))/step to
+    // compute the correct value.
+    const SCEV *StepMinusOne = getMinusSCEV(Step,
+                                            getIntegerSCEV(1, Step->getType()));
+    MaxEnd = isSigned ?
+      getSMinExpr(MaxEnd,
+                  getMinusSCEV(getConstant(APInt::getSignedMaxValue(BitWidth)),
+                               StepMinusOne)) :
+      getUMinExpr(MaxEnd,
+                  getMinusSCEV(getConstant(APInt::getMaxValue(BitWidth)),
+                               StepMinusOne));
+
     // Finally, we subtract these two values and divide, rounding up, to get
     // the number of times the backedge is executed.
     const SCEV *BECount = getBECount(Start, End, Step, NoWrap);
index fd0dfe66aee65db3e83d0bf9018bc44c0ab13d4e..ed97de6a504295dfe15c047b5dd2dd78d23e6aa2 100644 (file)
@@ -6,8 +6,9 @@
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
 
-define void @foo(i32 %n, double* nocapture %d, double* nocapture %q) nounwind {
+define void @foo(i32 %no, double* nocapture %d, double* nocapture %q) nounwind {
 entry:
+  %n = and i32 %no, 4294967294
   %0 = icmp sgt i32 %n, 0                         ; <i1> [#uses=1]
   br i1 %0, label %bb.nph, label %return
 
@@ -73,4 +74,4 @@ return:                                           ; preds = %bb1.return_crit_edg
 }
 
 ; CHECK: Loop %bb: backedge-taken count is ((-1 + %n) /u 2)
-; CHECK: Loop %bb: max backedge-taken count is 1073741823
+; CHECK: Loop %bb: max backedge-taken count is 1073741822
diff --git a/test/Analysis/ScalarEvolution/trip-count9.ll b/test/Analysis/ScalarEvolution/trip-count9.ll
new file mode 100644 (file)
index 0000000..9180f2b
--- /dev/null
@@ -0,0 +1,408 @@
+; RUN: opt -analyze -scalar-evolution -S < %s | FileCheck %s
+
+; Every combination of
+;  - starting at 0, 1, or %x
+;  - steping by 1 or 2
+;  - stopping at %n or %n*2
+;  - using nsw, or not
+
+; Some of these represent missed opportunities.
+
+; CHECK: Determining loop execution counts for: @foo
+; CHECK: Loop %loop: backedge-taken count is (-1 + %n)
+; CHECK: Loop %loop: max backedge-taken count is 6
+define void @foo(i4 %n) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 1
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: Unpredictable max backedge-taken count. 
+define void @step2(i4 %n) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 2
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @start1
+; CHECK: Loop %loop: backedge-taken count is (-2 + (2 smax %n))
+; CHECK: Loop %loop: max backedge-taken count is 5
+define void @start1(i4 %n) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 1, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 1
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @start1_step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: Unpredictable max backedge-taken count. 
+define void @start1_step2(i4 %n) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 1, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 2
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @startx
+; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax %n))
+; CHECK: Loop %loop: max backedge-taken count is -1
+define void @startx(i4 %n, i4 %x) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ %x, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 1
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @startx_step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: Unpredictable max backedge-taken count. 
+define void @startx_step2(i4 %n, i4 %x) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ %x, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 2
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @nsw
+; CHECK: Loop %loop: backedge-taken count is (-1 + %n)
+; CHECK: Loop %loop: max backedge-taken count is 6
+define void @nsw(i4 %n) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 1
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; Be careful with this one. If %n is INT4_MAX, %i.next will wrap. The nsw bit
+; says that the result is undefined, but ScalarEvolution must respect that
+; subsequent passes may result the undefined behavior in predictable ways.
+; CHECK: Determining loop execution counts for: @nsw_step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: Unpredictable max backedge-taken count. 
+define void @nsw_step2(i4 %n) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 2
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @nsw_start1
+; CHECK: Loop %loop: backedge-taken count is (-2 + (2 smax %n))
+; CHECK: Loop %loop: max backedge-taken count is 5
+define void @nsw_start1(i4 %n) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 1, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 1
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @nsw_start1_step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: Unpredictable max backedge-taken count. 
+define void @nsw_start1_step2(i4 %n) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 1, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 2
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @nsw_startx
+; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax %n))
+; CHECK: Loop %loop: max backedge-taken count is -1
+define void @nsw_startx(i4 %n, i4 %x) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ %x, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 1
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @nsw_startx_step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: Unpredictable max backedge-taken count. 
+define void @nsw_startx_step2(i4 %n, i4 %x) {
+entry:
+  %s = icmp sgt i4 %n, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ %x, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 2
+  %t = icmp slt i4 %i.next, %n
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even
+; CHECK: Loop %loop: backedge-taken count is (-1 + (2 * %n))
+; CHECK: Loop %loop: max backedge-taken count is 5
+define void @even(i4 %n) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 1
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: max backedge-taken count is 2
+define void @even_step2(i4 %n) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 2
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_start1
+; CHECK: Loop %loop: backedge-taken count is (-2 + (2 smax (2 * %n)))
+; CHECK: Loop %loop: max backedge-taken count is 4
+define void @even_start1(i4 %n) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 1, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 1
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_start1_step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: max backedge-taken count is 2
+define void @even_start1_step2(i4 %n) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 1, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 2
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_startx
+; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax (2 * %n)))
+; CHECK: Loop %loop: max backedge-taken count is -1
+define void @even_startx(i4 %n, i4 %x) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ %x, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 1
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_startx_step2
+; CHECK: Loop %loop: Unpredictable backedge-taken count. 
+; CHECK: Loop %loop: max backedge-taken count is 7
+define void @even_startx_step2(i4 %n, i4 %x) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ %x, %entry ], [ %i.next, %loop ]
+  %i.next = add i4 %i, 2
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_nsw
+; CHECK: Loop %loop: backedge-taken count is (-1 + (2 * %n))
+; CHECK: Loop %loop: max backedge-taken count is 5
+define void @even_nsw(i4 %n) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 1
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_nsw_step2
+; CHECK: Loop %loop: backedge-taken count is ((-1 + (2 * %n)) /u 2)
+; CHECK: Loop %loop: max backedge-taken count is 2
+define void @even_nsw_step2(i4 %n) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 0, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 2
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_nsw_start1
+; CHECK: Loop %loop: backedge-taken count is (-2 + (2 smax (2 * %n)))
+; CHECK: Loop %loop: max backedge-taken count is 4
+define void @even_nsw_start1(i4 %n) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 1, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 1
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_nsw_start1_step2
+; CHECK: Loop %loop: backedge-taken count is ((-2 + (3 smax (2 * %n))) /u 2)
+; CHECK: Loop %loop: max backedge-taken count is 2
+define void @even_nsw_start1_step2(i4 %n) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ 1, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 2
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_nsw_startx
+; CHECK: Loop %loop: backedge-taken count is (-1 + (-1 * %x) + ((1 + %x) smax (2 * %n)))
+; CHECK: Loop %loop: max backedge-taken count is -1
+define void @even_nsw_startx(i4 %n, i4 %x) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ %x, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 1
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}
+
+; CHECK: Determining loop execution counts for: @even_nsw_startx_step2
+; CHECK: Loop %loop: backedge-taken count is ((-1 + (-1 * %x) + ((2 + %x) smax (2 * %n))) /u 2)
+; CHECK: Loop %loop: max backedge-taken count is 7
+define void @even_nsw_startx_step2(i4 %n, i4 %x) {
+entry:
+  %m = shl i4 %n, 1
+  %s = icmp sgt i4 %m, 0
+  br i1 %s, label %loop, label %exit
+loop:
+  %i = phi i4 [ %x, %entry ], [ %i.next, %loop ]
+  %i.next = add nsw i4 %i, 2
+  %t = icmp slt i4 %i.next, %m
+  br i1 %t, label %loop, label %exit
+exit:
+  ret void
+}