summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Transforms/Scalar/IndVarSimplify.cpp33
-rw-r--r--llvm/test/Transforms/IndVarSimplify/eliminate-comparison.ll52
-rw-r--r--llvm/test/Transforms/IndVarSimplify/lftr-multi-exit.ll69
3 files changed, 73 insertions, 81 deletions
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 969ad50e96d..b8f3d1b9c1b 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -2037,15 +2037,21 @@ static ICmpInst *getLoopTest(Loop *L, BasicBlock *ExitingBB) {
if (!LatchBlock)
return nullptr;
- BranchInst *BI = dyn_cast<BranchInst>(ExitingBB->getTerminator());
- assert(BI && "expected exit branch");
-
+ BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
return dyn_cast<ICmpInst>(BI->getCondition());
}
/// linearFunctionTestReplace policy. Return true unless we can show that the
/// current exit test is already sufficiently canonical.
static bool needsLFTR(Loop *L, BasicBlock *ExitingBB) {
+ // Avoid converting a constant or loop invariant test back to a runtime
+ // test. This is critical for when SCEV's cached ExitCount is less precise
+ // than the current IR (such as after we've proven a particular exit is
+ // actually dead and thus the BE count never reaches our ExitCount.)
+ BranchInst *BI = cast<BranchInst>(ExitingBB->getTerminator());
+ if (L->isLoopInvariant(BI->getCondition()))
+ return false;
+
// Do LFTR to simplify the exit condition to an ICMP.
ICmpInst *Cond = getLoopTest(L, ExitingBB);
if (!Cond)
@@ -2247,15 +2253,12 @@ static PHINode *FindLoopCounter(Loop *L, BasicBlock *ExitingBB,
// have originally had a concrete definition.
if (!hasConcreteDef(Phi)) {
// We explicitly allow unknown phis as long as they are already used by
- // the loop test. In this case we assume that performing LFTR could not
- // increase the number of undef users.
- // TODO: Generalize this to allow *any* loop exit which is known to
- // execute on each iteration
- if (L->getExitingBlock())
- if (ICmpInst *Cond = getLoopTest(L, ExitingBB))
- if (Phi != getLoopPhiForCounter(Cond->getOperand(0), L) &&
- Phi != getLoopPhiForCounter(Cond->getOperand(1), L))
- continue;
+ // the loop exit test. This is legal since performing LFTR could not
+ // increase the number of undef users.
+ if (ICmpInst *Cond = getLoopTest(L, ExitingBB))
+ if (Phi != getLoopPhiForCounter(Cond->getOperand(0), L) &&
+ Phi != getLoopPhiForCounter(Cond->getOperand(1), L))
+ continue;
}
// Avoid introducing undefined behavior due to poison which didn't exist in
@@ -2701,12 +2704,8 @@ bool IndVarSimplify::run(Loop *L) {
// If we have a trip count expression, rewrite the loop's exit condition
// using it.
if (!DisableLFTR) {
- // For the moment, we only do LFTR for single exit loops. The code is
- // structured as it is in the expectation of generalization to multi-exit
- // loops in the near future. See D62625 for context.
SmallVector<BasicBlock*, 16> ExitingBlocks;
- if (auto *ExitingBB = L->getExitingBlock())
- ExitingBlocks.push_back(ExitingBB);
+ L->getExitingBlocks(ExitingBlocks);
for (BasicBlock *ExitingBB : ExitingBlocks) {
// Can't rewrite non-branch yet.
if (!isa<BranchInst>(ExitingBB->getTerminator()))
diff --git a/llvm/test/Transforms/IndVarSimplify/eliminate-comparison.ll b/llvm/test/Transforms/IndVarSimplify/eliminate-comparison.ll
index 0c1a262417c..cd639f8d731 100644
--- a/llvm/test/Transforms/IndVarSimplify/eliminate-comparison.ll
+++ b/llvm/test/Transforms/IndVarSimplify/eliminate-comparison.ll
@@ -177,8 +177,8 @@ define i32 @func_11() nounwind uwtable {
; CHECK-NEXT: br label [[FORCOND:%.*]]
; CHECK: forcond:
; CHECK-NEXT: [[__KEY6_0:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[TMP37:%.*]], [[NOASSERT:%.*]] ]
-; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[__KEY6_0]], 10
-; CHECK-NEXT: br i1 [[TMP5]], label [[NOASSERT]], label [[FORCOND38_PREHEADER:%.*]]
+; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[__KEY6_0]], 10
+; CHECK-NEXT: br i1 [[EXITCOND1]], label [[NOASSERT]], label [[FORCOND38_PREHEADER:%.*]]
; CHECK: forcond38.preheader:
; CHECK-NEXT: br label [[FORCOND38:%.*]]
; CHECK: noassert:
@@ -193,8 +193,8 @@ define i32 @func_11() nounwind uwtable {
; CHECK-NEXT: unreachable
; CHECK: forcond38:
; CHECK-NEXT: [[__KEY8_0:%.*]] = phi i32 [ [[TMP81:%.*]], [[NOASSERT68:%.*]] ], [ 2, [[FORCOND38_PREHEADER]] ]
-; CHECK-NEXT: [[TMP46:%.*]] = icmp ult i32 [[__KEY8_0]], 10
-; CHECK-NEXT: br i1 [[TMP46]], label [[NOASSERT68]], label [[UNROLLEDEND:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[__KEY8_0]], 10
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[NOASSERT68]], label [[UNROLLEDEND:%.*]]
; CHECK: noassert68:
; CHECK-NEXT: [[TMP57:%.*]] = sdiv i32 -32768, [[__KEY8_0]]
; CHECK-NEXT: [[SEXT34:%.*]] = shl i32 [[TMP57]], 16
@@ -261,8 +261,8 @@ define i32 @func_12() nounwind uwtable {
; CHECK-NEXT: br label [[FORCOND:%.*]]
; CHECK: forcond:
; CHECK-NEXT: [[__KEY6_0:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[TMP37:%.*]], [[NOASSERT:%.*]] ]
-; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[__KEY6_0]], 10
-; CHECK-NEXT: br i1 [[TMP5]], label [[NOASSERT]], label [[FORCOND38_PREHEADER:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[__KEY6_0]], 10
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[NOASSERT]], label [[FORCOND38_PREHEADER:%.*]]
; CHECK: forcond38.preheader:
; CHECK-NEXT: br label [[FORCOND38:%.*]]
; CHECK: noassert:
@@ -341,7 +341,6 @@ define void @func_13(i32* %len.ptr) {
; CHECK-LABEL: @func_13(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], !range !0
-; CHECK-NEXT: [[LEN_SUB_1:%.*]] = add i32 [[LEN]], -1
; CHECK-NEXT: [[LEN_IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
; CHECK-NEXT: br i1 [[LEN_IS_ZERO]], label [[LEAVE:%.*]], label [[LOOP_PREHEADER:%.*]]
; CHECK: loop.preheader:
@@ -353,8 +352,8 @@ define void @func_13(i32* %len.ptr) {
; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
-; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV]], [[LEN_SUB_1]]
-; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LEN]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
; CHECK: leave.loopexit:
; CHECK-NEXT: br label [[LEAVE]]
; CHECK: leave:
@@ -386,7 +385,6 @@ define void @func_14(i32* %len.ptr) {
; CHECK-LABEL: @func_14(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], !range !0
-; CHECK-NEXT: [[LEN_SUB_1:%.*]] = add i32 [[LEN]], -1
; CHECK-NEXT: [[LEN_IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
; CHECK-NEXT: [[LEN_IS_INT_MIN:%.*]] = icmp eq i32 [[LEN]], -2147483648
; CHECK-NEXT: [[NO_ENTRY:%.*]] = or i1 [[LEN_IS_ZERO]], [[LEN_IS_INT_MIN]]
@@ -400,8 +398,8 @@ define void @func_14(i32* %len.ptr) {
; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
-; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IV]], [[LEN_SUB_1]]
-; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LEN]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
; CHECK: leave.loopexit:
; CHECK-NEXT: br label [[LEAVE]]
; CHECK: leave:
@@ -447,8 +445,8 @@ define void @func_15(i32* %len.ptr) {
; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
-; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV]], [[LEN]]
-; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LEN_ADD_1]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
; CHECK: leave.loopexit:
; CHECK-NEXT: br label [[LEAVE]]
; CHECK: leave:
@@ -486,6 +484,7 @@ define void @func_16(i32* %len.ptr) {
; CHECK-NEXT: [[ENTRY_COND:%.*]] = and i1 [[ENTRY_COND_0]], [[ENTRY_COND_1]]
; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[LEAVE:%.*]]
; CHECK: loop.preheader:
+; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[LEN]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_INC:%.*]], [[BE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
@@ -494,8 +493,8 @@ define void @func_16(i32* %len.ptr) {
; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
-; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV]], [[LEN]]
-; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[TMP0]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
; CHECK: leave.loopexit:
; CHECK-NEXT: br label [[LEAVE]]
; CHECK: leave:
@@ -656,8 +655,8 @@ define void @func_19(i32* %length.ptr) {
; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
-; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV_INC]], [[LENGTH]]
-; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LENGTH]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
; CHECK: leave.loopexit:
; CHECK-NEXT: br label [[LEAVE]]
; CHECK: leave:
@@ -696,8 +695,8 @@ define void @func_20(i32* %length.ptr) {
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_INC:%.*]], [[BE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
; CHECK-NEXT: [[IV_INC]] = add nuw nsw i32 [[IV]], 1
-; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp ult i32 [[IV]], [[LENGTH]]
-; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[LENGTH]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IV_INC]], [[LENGTH]]
@@ -744,8 +743,8 @@ define void @func_21(i32* %length.ptr) {
; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
-; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IV_INC]], [[LIM]]
-; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LIM]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
; CHECK: leave.loopexit:
; CHECK-NEXT: br label [[LEAVE]]
; CHECK: leave:
@@ -778,7 +777,6 @@ define void @func_22(i32* %length.ptr) {
; CHECK-LABEL: @func_22(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !0
-; CHECK-NEXT: [[LIM:%.*]] = sub i32 [[LENGTH]], 1
; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp sgt i32 [[LENGTH]], 1
; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[LEAVE:%.*]]
; CHECK: loop.preheader:
@@ -789,8 +787,8 @@ define void @func_22(i32* %length.ptr) {
; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
-; CHECK-NEXT: [[BE_COND:%.*]] = icmp sle i32 [[IV_INC]], [[LIM]]
-; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LENGTH]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
; CHECK: leave.loopexit:
; CHECK-NEXT: br label [[LEAVE]]
; CHECK: leave:
@@ -831,8 +829,8 @@ define void @func_23(i32* %length.ptr) {
; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
; CHECK: be:
; CHECK-NEXT: call void @side_effect()
-; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV_INC]], [[LENGTH]]
-; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LENGTH]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
; CHECK: leave.loopexit:
; CHECK-NEXT: br label [[LEAVE]]
; CHECK: leave:
diff --git a/llvm/test/Transforms/IndVarSimplify/lftr-multi-exit.ll b/llvm/test/Transforms/IndVarSimplify/lftr-multi-exit.ll
index a45f26b88a9..b8555ede966 100644
--- a/llvm/test/Transforms/IndVarSimplify/lftr-multi-exit.ll
+++ b/llvm/test/Transforms/IndVarSimplify/lftr-multi-exit.ll
@@ -15,13 +15,13 @@ define void @analyzeable_early_exit(i32 %n) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
-; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
; CHECK: latch:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: store i32 [[IV]], i32* @A
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
-; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
+; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -55,8 +55,8 @@ define void @unanalyzeable_early_exit() {
; CHECK: latch:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: store i32 [[IV]], i32* @A
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
-; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -86,17 +86,17 @@ define void @multiple_early_exits(i32 %n, i32 %m) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
-; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
; CHECK: continue:
; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
-; CHECK-NEXT: [[EARLYCND2:%.*]] = icmp ult i32 [[IV]], [[M:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND2]], label [[LATCH]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
; CHECK: latch:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
-; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
+; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -138,8 +138,8 @@ define void @compound_early_exit(i32 %n, i32 %m) {
; CHECK: latch:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
-; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -170,8 +170,8 @@ define void @unanalyzeable_latch(i32 %n) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
-; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
; CHECK: latch:
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT: store i32 [[IV]], i32* @A
@@ -240,12 +240,12 @@ define void @no_latch_exit(i32 %n, i32 %m) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
-; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
; CHECK: continue:
; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
-; CHECK-NEXT: [[EARLYCND2:%.*]] = icmp ult i32 [[IV]], [[M:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND2]], label [[LATCH]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
; CHECK: latch:
; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
@@ -283,15 +283,13 @@ define void @combine_ivs(i32 %n) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
-; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[LATCH]] ]
-; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
; CHECK: latch:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
-; CHECK-NEXT: [[IV2_NEXT]] = add nuw nsw i32 [[IV2]], 1
; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV2_NEXT]], 1000
-; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 999
+; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -322,15 +320,13 @@ define void @combine_ivs2(i32 %n) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
-; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 1000, [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[LATCH]] ]
-; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
; CHECK: latch:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
-; CHECK-NEXT: [[IV2_NEXT]] = sub nuw nsw i32 [[IV2]], 1
; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
-; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[IV2_NEXT]], 0
-; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
+; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
@@ -362,14 +358,13 @@ define void @simplify_exit_test(i32 %n) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
-; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
-; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
; CHECK: latch:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
-; CHECK-NEXT: [[FX:%.*]] = shl i32 [[IV]], 4
; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
-; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[FX]], 1024
-; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
+; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 65
+; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
OpenPOWER on IntegriCloud