llvm.org GIT mirror llvm / c48c6af
LFTR for multiple exit loops Teach IndVarSimply's LinearFunctionTestReplace transform to handle multiple exit loops. LFTR does two key things 1) it rewrites (all) exit tests in terms of a common IV potentially eliminating one in the process and 2) it moves any offset/indexing/f(i) style logic out of the loop. This turns out to actually be pretty easy to implement. SCEV already has all the information we need to know what the backedge taken count is for each individual exit. (We use that when computing the BE taken count for the loop as a whole.) We basically just need to iterate through the exiting blocks and apply the existing logic with the exit specific BE taken count. (The previously landed NFC makes this super obvious.) I chose to go ahead and apply this to all loop exits instead of only latch exits as originally proposed. After reviewing other passes, the only case I could find where LFTR form was harmful was LoopPredication. I've fixed the latch case, and guards aren't LFTRed anyways. We'll have some more work to do on the way towards widenable_conditions, but that's easily deferred. I do want to note that I added one bit after the review. When running tests, I saw a new failure (no idea why didn't see previously) which pointed out LFTR can rewrite a constant condition back to a loop varying one. This was theoretically possible with a single exit, but the zero case covered it in practice. With multiple exits, we saw this happening in practice for the eliminate-comparison.ll test case because we'd compute a ExitCount for one of the exits which was guaranteed to never actually be reached. Since LFTR ran after simplifyAndExtend, we'd immediately turn around and undo the simplication work we'd just done. The solution seemed obvious, so I didn't bother with another round of review. Differential Revision: https://reviews.llvm.org/D62625 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363883 91177308-0d34-0410-b5e6-96231b3b80d8 Philip Reames 3 months ago
3 changed file(s) with 85 addition(s) and 93 deletion(s). Raw diff Collapse all Expand all
20362036 if (!LatchBlock)
20372037 return nullptr;
20382038
2039 BranchInst *BI = dyn_cast(ExitingBB->getTerminator());
2040 assert(BI && "expected exit branch");
2041
2039 BranchInst *BI = cast(ExitingBB->getTerminator());
20422040 return dyn_cast(BI->getCondition());
20432041 }
20442042
20452043 /// linearFunctionTestReplace policy. Return true unless we can show that the
20462044 /// current exit test is already sufficiently canonical.
20472045 static bool needsLFTR(Loop *L, BasicBlock *ExitingBB) {
2046 // Avoid converting a constant or loop invariant test back to a runtime
2047 // test. This is critical for when SCEV's cached ExitCount is less precise
2048 // than the current IR (such as after we've proven a particular exit is
2049 // actually dead and thus the BE count never reaches our ExitCount.)
2050 BranchInst *BI = cast(ExitingBB->getTerminator());
2051 if (L->isLoopInvariant(BI->getCondition()))
2052 return false;
2053
20482054 // Do LFTR to simplify the exit condition to an ICMP.
20492055 ICmpInst *Cond = getLoopTest(L, ExitingBB);
20502056 if (!Cond)
22462252 // have originally had a concrete definition.
22472253 if (!hasConcreteDef(Phi)) {
22482254 // We explicitly allow unknown phis as long as they are already used by
2249 // the loop test. In this case we assume that performing LFTR could not
2250 // increase the number of undef users.
2251 // TODO: Generalize this to allow *any* loop exit which is known to
2252 // execute on each iteration
2253 if (L->getExitingBlock())
2254 if (ICmpInst *Cond = getLoopTest(L, ExitingBB))
2255 if (Phi != getLoopPhiForCounter(Cond->getOperand(0), L) &&
2256 Phi != getLoopPhiForCounter(Cond->getOperand(1), L))
2257 continue;
2255 // the loop exit test. This is legal since performing LFTR could not
2256 // increase the number of undef users.
2257 if (ICmpInst *Cond = getLoopTest(L, ExitingBB))
2258 if (Phi != getLoopPhiForCounter(Cond->getOperand(0), L) &&
2259 Phi != getLoopPhiForCounter(Cond->getOperand(1), L))
2260 continue;
22582261 }
22592262
22602263 // Avoid introducing undefined behavior due to poison which didn't exist in
27002703 // If we have a trip count expression, rewrite the loop's exit condition
27012704 // using it.
27022705 if (!DisableLFTR) {
2703 // For the moment, we only do LFTR for single exit loops. The code is
2704 // structured as it is in the expectation of generalization to multi-exit
2705 // loops in the near future. See D62625 for context.
27062706 SmallVector ExitingBlocks;
2707 if (auto *ExitingBB = L->getExitingBlock())
2708 ExitingBlocks.push_back(ExitingBB);
2707 L->getExitingBlocks(ExitingBlocks);
27092708 for (BasicBlock *ExitingBB : ExitingBlocks) {
27102709 // Can't rewrite non-branch yet.
27112710 if (!isa(ExitingBB->getTerminator()))
176176 ; CHECK-NEXT: br label [[FORCOND:%.*]]
177177 ; CHECK: forcond:
178178 ; CHECK-NEXT: [[__KEY6_0:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[TMP37:%.*]], [[NOASSERT:%.*]] ]
179 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[__KEY6_0]], 10
180 ; CHECK-NEXT: br i1 [[TMP5]], label [[NOASSERT]], label [[FORCOND38_PREHEADER:%.*]]
179 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[__KEY6_0]], 10
180 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[NOASSERT]], label [[FORCOND38_PREHEADER:%.*]]
181181 ; CHECK: forcond38.preheader:
182182 ; CHECK-NEXT: br label [[FORCOND38:%.*]]
183183 ; CHECK: noassert:
192192 ; CHECK-NEXT: unreachable
193193 ; CHECK: forcond38:
194194 ; CHECK-NEXT: [[__KEY8_0:%.*]] = phi i32 [ [[TMP81:%.*]], [[NOASSERT68:%.*]] ], [ 2, [[FORCOND38_PREHEADER]] ]
195 ; CHECK-NEXT: [[TMP46:%.*]] = icmp ult i32 [[__KEY8_0]], 10
196 ; CHECK-NEXT: br i1 [[TMP46]], label [[NOASSERT68]], label [[UNROLLEDEND:%.*]]
195 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[__KEY8_0]], 10
196 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[NOASSERT68]], label [[UNROLLEDEND:%.*]]
197197 ; CHECK: noassert68:
198198 ; CHECK-NEXT: [[TMP57:%.*]] = sdiv i32 -32768, [[__KEY8_0]]
199199 ; CHECK-NEXT: [[SEXT34:%.*]] = shl i32 [[TMP57]], 16
260260 ; CHECK-NEXT: br label [[FORCOND:%.*]]
261261 ; CHECK: forcond:
262262 ; CHECK-NEXT: [[__KEY6_0:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ [[TMP37:%.*]], [[NOASSERT:%.*]] ]
263 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ult i32 [[__KEY6_0]], 10
264 ; CHECK-NEXT: br i1 [[TMP5]], label [[NOASSERT]], label [[FORCOND38_PREHEADER:%.*]]
263 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[__KEY6_0]], 10
264 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[NOASSERT]], label [[FORCOND38_PREHEADER:%.*]]
265265 ; CHECK: forcond38.preheader:
266266 ; CHECK-NEXT: br label [[FORCOND38:%.*]]
267267 ; CHECK: noassert:
340340 ; CHECK-LABEL: @func_13(
341341 ; CHECK-NEXT: entry:
342342 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], !range !0
343 ; CHECK-NEXT: [[LEN_SUB_1:%.*]] = add i32 [[LEN]], -1
344343 ; CHECK-NEXT: [[LEN_IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
345344 ; CHECK-NEXT: br i1 [[LEN_IS_ZERO]], label [[LEAVE:%.*]], label [[LOOP_PREHEADER:%.*]]
346345 ; CHECK: loop.preheader:
352351 ; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
353352 ; CHECK: be:
354353 ; CHECK-NEXT: call void @side_effect()
355 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV]], [[LEN_SUB_1]]
356 ; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
354 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LEN]]
355 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
357356 ; CHECK: leave.loopexit:
358357 ; CHECK-NEXT: br label [[LEAVE]]
359358 ; CHECK: leave:
385384 ; CHECK-LABEL: @func_14(
386385 ; CHECK-NEXT: entry:
387386 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], !range !0
388 ; CHECK-NEXT: [[LEN_SUB_1:%.*]] = add i32 [[LEN]], -1
389387 ; CHECK-NEXT: [[LEN_IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
390388 ; CHECK-NEXT: [[LEN_IS_INT_MIN:%.*]] = icmp eq i32 [[LEN]], -2147483648
391389 ; CHECK-NEXT: [[NO_ENTRY:%.*]] = or i1 [[LEN_IS_ZERO]], [[LEN_IS_INT_MIN]]
399397 ; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
400398 ; CHECK: be:
401399 ; CHECK-NEXT: call void @side_effect()
402 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IV]], [[LEN_SUB_1]]
403 ; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
400 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LEN]]
401 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
404402 ; CHECK: leave.loopexit:
405403 ; CHECK-NEXT: br label [[LEAVE]]
406404 ; CHECK: leave:
446444 ; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
447445 ; CHECK: be:
448446 ; CHECK-NEXT: call void @side_effect()
449 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV]], [[LEN]]
450 ; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
447 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LEN_ADD_1]]
448 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
451449 ; CHECK: leave.loopexit:
452450 ; CHECK-NEXT: br label [[LEAVE]]
453451 ; CHECK: leave:
485483 ; CHECK-NEXT: [[ENTRY_COND:%.*]] = and i1 [[ENTRY_COND_0]], [[ENTRY_COND_1]]
486484 ; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[LEAVE:%.*]]
487485 ; CHECK: loop.preheader:
486 ; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i32 [[LEN]], 1
488487 ; CHECK-NEXT: br label [[LOOP:%.*]]
489488 ; CHECK: loop:
490489 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_INC:%.*]], [[BE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
493492 ; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
494493 ; CHECK: be:
495494 ; CHECK-NEXT: call void @side_effect()
496 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV]], [[LEN]]
497 ; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
495 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[TMP0]]
496 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
498497 ; CHECK: leave.loopexit:
499498 ; CHECK-NEXT: br label [[LEAVE]]
500499 ; CHECK: leave:
655654 ; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
656655 ; CHECK: be:
657656 ; CHECK-NEXT: call void @side_effect()
658 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV_INC]], [[LENGTH]]
659 ; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
657 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LENGTH]]
658 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
660659 ; CHECK: leave.loopexit:
661660 ; CHECK-NEXT: br label [[LEAVE]]
662661 ; CHECK: leave:
695694 ; CHECK: loop:
696695 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_INC:%.*]], [[BE:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
697696 ; CHECK-NEXT: [[IV_INC]] = add nuw nsw i32 [[IV]], 1
698 ; CHECK-NEXT: [[RANGE_CHECK:%.*]] = icmp ult i32 [[IV]], [[LENGTH]]
699 ; CHECK-NEXT: br i1 [[RANGE_CHECK]], label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
697 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[LENGTH]]
698 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
700699 ; CHECK: be:
701700 ; CHECK-NEXT: call void @side_effect()
702701 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IV_INC]], [[LENGTH]]
743742 ; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
744743 ; CHECK: be:
745744 ; CHECK-NEXT: call void @side_effect()
746 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IV_INC]], [[LIM]]
747 ; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
745 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LIM]]
746 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
748747 ; CHECK: leave.loopexit:
749748 ; CHECK-NEXT: br label [[LEAVE]]
750749 ; CHECK: leave:
777776 ; CHECK-LABEL: @func_22(
778777 ; CHECK-NEXT: entry:
779778 ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !0
780 ; CHECK-NEXT: [[LIM:%.*]] = sub i32 [[LENGTH]], 1
781779 ; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp sgt i32 [[LENGTH]], 1
782780 ; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[LEAVE:%.*]]
783781 ; CHECK: loop.preheader:
788786 ; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
789787 ; CHECK: be:
790788 ; CHECK-NEXT: call void @side_effect()
791 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp sle i32 [[IV_INC]], [[LIM]]
792 ; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
789 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LENGTH]]
790 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
793791 ; CHECK: leave.loopexit:
794792 ; CHECK-NEXT: br label [[LEAVE]]
795793 ; CHECK: leave:
830828 ; CHECK-NEXT: br i1 true, label [[BE]], label [[LEAVE_LOOPEXIT:%.*]]
831829 ; CHECK: be:
832830 ; CHECK-NEXT: call void @side_effect()
833 ; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IV_INC]], [[LENGTH]]
834 ; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
831 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_INC]], [[LENGTH]]
832 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE_LOOPEXIT]]
835833 ; CHECK: leave.loopexit:
836834 ; CHECK-NEXT: br label [[LEAVE]]
837835 ; CHECK: leave:
1414 ; CHECK-NEXT: br label [[LOOP:%.*]]
1515 ; CHECK: loop:
1616 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
17 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
18 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
17 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
18 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
1919 ; CHECK: latch:
2020 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
2121 ; CHECK-NEXT: store i32 [[IV]], i32* @A
22 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
23 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
22 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
23 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
2424 ; CHECK: exit:
2525 ; CHECK-NEXT: ret void
2626 ;
5454 ; CHECK: latch:
5555 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
5656 ; CHECK-NEXT: store i32 [[IV]], i32* @A
57 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
58 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
57 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
58 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT]]
5959 ; CHECK: exit:
6060 ; CHECK-NEXT: ret void
6161 ;
8585 ; CHECK-NEXT: br label [[LOOP:%.*]]
8686 ; CHECK: loop:
8787 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
88 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
89 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
88 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
89 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
9090 ; CHECK: continue:
9191 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
92 ; CHECK-NEXT: [[EARLYCND2:%.*]] = icmp ult i32 [[IV]], [[M:%.*]]
93 ; CHECK-NEXT: br i1 [[EARLYCND2]], label [[LATCH]], label [[EXIT]]
94 ; CHECK: latch:
95 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
96 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
97 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
98 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
92 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
93 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
94 ; CHECK: latch:
95 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
96 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
97 ; CHECK-NEXT: [[EXITCOND2:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
98 ; CHECK-NEXT: br i1 [[EXITCOND2]], label [[LOOP]], label [[EXIT]]
9999 ; CHECK: exit:
100100 ; CHECK-NEXT: ret void
101101 ;
137137 ; CHECK: latch:
138138 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
139139 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
140 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV_NEXT]], 1000
141 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
140 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
141 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT]]
142142 ; CHECK: exit:
143143 ; CHECK-NEXT: ret void
144144 ;
169169 ; CHECK-NEXT: br label [[LOOP:%.*]]
170170 ; CHECK: loop:
171171 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
172 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
173 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
172 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
173 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
174174 ; CHECK: latch:
175175 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
176176 ; CHECK-NEXT: store i32 [[IV]], i32* @A
239239 ; CHECK-NEXT: br label [[LOOP:%.*]]
240240 ; CHECK: loop:
241241 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
242 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
243 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
242 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
243 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[EXIT:%.*]]
244244 ; CHECK: continue:
245245 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
246 ; CHECK-NEXT: [[EARLYCND2:%.*]] = icmp ult i32 [[IV]], [[M:%.*]]
247 ; CHECK-NEXT: br i1 [[EARLYCND2]], label [[LATCH]], label [[EXIT]]
246 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV]], [[M:%.*]]
247 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LATCH]], label [[EXIT]]
248248 ; CHECK: latch:
249249 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
250250 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
282282 ; CHECK-NEXT: br label [[LOOP:%.*]]
283283 ; CHECK: loop:
284284 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
285 ; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[LATCH]] ]
286 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
287 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
288 ; CHECK: latch:
289 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
290 ; CHECK-NEXT: [[IV2_NEXT]] = add nuw nsw i32 [[IV2]], 1
291 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
292 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[IV2_NEXT]], 1000
293 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
285 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
286 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
287 ; CHECK: latch:
288 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
289 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
290 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 999
291 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
294292 ; CHECK: exit:
295293 ; CHECK-NEXT: ret void
296294 ;
321319 ; CHECK-NEXT: br label [[LOOP:%.*]]
322320 ; CHECK: loop:
323321 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
324 ; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ 1000, [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[LATCH]] ]
325 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
326 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
327 ; CHECK: latch:
328 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
329 ; CHECK-NEXT: [[IV2_NEXT]] = sub nuw nsw i32 [[IV2]], 1
330 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
331 ; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[IV2_NEXT]], 0
332 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
322 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
323 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
324 ; CHECK: latch:
325 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
326 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
327 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 1000
328 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
333329 ; CHECK: exit:
334330 ; CHECK-NEXT: ret void
335331 ;
361357 ; CHECK-NEXT: br label [[LOOP:%.*]]
362358 ; CHECK: loop:
363359 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
364 ; CHECK-NEXT: [[EARLYCND:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
365 ; CHECK-NEXT: br i1 [[EARLYCND]], label [[LATCH]], label [[EXIT:%.*]]
366 ; CHECK: latch:
367 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
368 ; CHECK-NEXT: [[FX:%.*]] = shl i32 [[IV]], 4
369 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
370 ; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[FX]], 1024
371 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]]
360 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[IV]], [[N:%.*]]
361 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LATCH]], label [[EXIT:%.*]]
362 ; CHECK: latch:
363 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
364 ; CHECK-NEXT: store volatile i32 [[IV]], i32* @A
365 ; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[IV_NEXT]], 65
366 ; CHECK-NEXT: br i1 [[EXITCOND1]], label [[LOOP]], label [[EXIT]]
372367 ; CHECK: exit:
373368 ; CHECK-NEXT: ret void
374369 ;