Index: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -2037,15 +2037,21 @@ if (!LatchBlock) return nullptr; - BranchInst *BI = dyn_cast(ExitingBB->getTerminator()); - assert(BI && "expected exit branch"); - + BranchInst *BI = cast(ExitingBB->getTerminator()); return dyn_cast(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(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 @@ // 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 @@ // 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 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(ExitingBB->getTerminator())) Index: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll =================================================================== --- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll +++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll @@ -177,8 +177,8 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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: Index: llvm/trunk/test/Transforms/IndVarSimplify/lftr-multi-exit.ll =================================================================== --- llvm/trunk/test/Transforms/IndVarSimplify/lftr-multi-exit.ll +++ llvm/trunk/test/Transforms/IndVarSimplify/lftr-multi-exit.ll @@ -15,13 +15,13 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 ;