xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll (revision 52361d0368b79841be12156bf03cf8c1851e5df7)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt -p constraint-elimination -S %s | FileCheck %s
3
4declare void @llvm.assume(i1)
5
6define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known(ptr %s) {
7; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known(
8; CHECK-SAME: ptr [[S:%.*]]) {
9; CHECK-NEXT:  [[ENTRY:.*]]:
10; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
11; CHECK:       [[LOOP_HEADER]]:
12; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
13; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
14; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
15; CHECK:       [[LOOP_LATCH]]:
16; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
17; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
18; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
19; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
20; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
21; CHECK:       [[EXIT]]:
22; CHECK-NEXT:    ret i1 true
23;
24entry:
25  br label %loop.header
26
27loop.header:
28  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
29  %exitcond.not = icmp eq i32 %iv, 1234
30  br i1 %exitcond.not, label %exit, label %loop.latch
31
32loop.latch:
33  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
34  %0 = load i8, ptr %arrayidx, align 1
35  %latch.c = icmp ult i8 %0, 10
36  %iv.next = add nuw nsw i32 %iv, 1
37  br i1 %latch.c, label %loop.header, label %exit
38
39exit:
40  %t = icmp ult i32 %iv, 1235
41  ret i1 %t
42}
43
44define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_start_value(ptr %s) {
45; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_start_value(
46; CHECK-SAME: ptr [[S:%.*]]) {
47; CHECK-NEXT:  [[ENTRY:.*]]:
48; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
49; CHECK:       [[LOOP_HEADER]]:
50; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1235, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
51; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
52; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
53; CHECK:       [[LOOP_LATCH]]:
54; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
55; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
56; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
57; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
58; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
59; CHECK:       [[EXIT]]:
60; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[IV]], 1235
61; CHECK-NEXT:    ret i1 [[T]]
62;
63entry:
64  br label %loop.header
65
66loop.header:
67  %iv = phi i32 [ 1235, %entry ], [ %iv.next, %loop.latch ]
68  %exitcond.not = icmp eq i32 %iv, 1234
69  br i1 %exitcond.not, label %exit, label %loop.latch
70
71loop.latch:
72  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
73  %0 = load i8, ptr %arrayidx, align 1
74  %latch.c = icmp ult i8 %0, 10
75  %iv.next = add i32 %iv, 1
76  br i1 %latch.c, label %loop.header, label %exit
77
78exit:
79  %t = icmp ult i32 %iv, 1235
80  ret i1 %t
81}
82
83define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known_due_to_precond_on_start_value(ptr %s, i32 %start) {
84; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_known_due_to_precond_on_start_value(
85; CHECK-SAME: ptr [[S:%.*]], i32 [[START:%.*]]) {
86; CHECK-NEXT:  [[ENTRY:.*]]:
87; CHECK-NEXT:    [[PRE_C:%.*]] = icmp ule i32 [[START]], 1234
88; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE_C]])
89; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
90; CHECK:       [[LOOP_HEADER]]:
91; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
92; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
93; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
94; CHECK:       [[LOOP_LATCH]]:
95; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
96; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
97; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
98; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
99; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
100; CHECK:       [[EXIT]]:
101; CHECK-NEXT:    ret i1 true
102;
103entry:
104  %pre.c = icmp ule i32 %start, 1234
105  call void @llvm.assume(i1 %pre.c)
106  br label %loop.header
107
108loop.header:
109  %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop.latch ]
110  %exitcond.not = icmp eq i32 %iv, 1234
111  br i1 %exitcond.not, label %exit, label %loop.latch
112
113loop.latch:
114  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
115  %0 = load i8, ptr %arrayidx, align 1
116  %latch.c = icmp ult i8 %0, 10
117  %iv.next = add i32 %iv, 1
118  br i1 %latch.c, label %loop.header, label %exit
119
120exit:
121  %t = icmp ult i32 %iv, 1235
122  ret i1 %t
123}
124
125define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_precond_on_start_value(ptr %s, i32 %start) {
126; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_precond_on_start_value(
127; CHECK-SAME: ptr [[S:%.*]], i32 [[START:%.*]]) {
128; CHECK-NEXT:  [[ENTRY:.*]]:
129; CHECK-NEXT:    [[PRE_C:%.*]] = icmp ule i32 [[START]], 1236
130; CHECK-NEXT:    call void @llvm.assume(i1 [[PRE_C]])
131; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
132; CHECK:       [[LOOP_HEADER]]:
133; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
134; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
135; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
136; CHECK:       [[LOOP_LATCH]]:
137; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
138; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
139; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
140; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
141; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
142; CHECK:       [[EXIT]]:
143; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[IV]], 1236
144; CHECK-NEXT:    ret i1 [[T]]
145;
146entry:
147  %pre.c = icmp ule i32 %start, 1236
148  call void @llvm.assume(i1 %pre.c)
149  br label %loop.header
150
151loop.header:
152  %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop.latch ]
153  %exitcond.not = icmp eq i32 %iv, 1234
154  br i1 %exitcond.not, label %exit, label %loop.latch
155
156loop.latch:
157  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
158  %0 = load i8, ptr %arrayidx, align 1
159  %latch.c = icmp ult i8 %0, 10
160  %iv.next = add i32 %iv, 1
161  br i1 %latch.c, label %loop.header, label %exit
162
163exit:
164  %t = icmp ult i32 %iv, 1236
165  ret i1 %t
166}
167
168define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_missing_precond(ptr %s, i32 %start) {
169; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known_due_to_missing_precond(
170; CHECK-SAME: ptr [[S:%.*]], i32 [[START:%.*]]) {
171; CHECK-NEXT:  [[ENTRY:.*]]:
172; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
173; CHECK:       [[LOOP_HEADER]]:
174; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START]], %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
175; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
176; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
177; CHECK:       [[LOOP_LATCH]]:
178; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
179; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
180; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
181; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
182; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
183; CHECK:       [[EXIT]]:
184; CHECK-NEXT:    [[T:%.*]] = icmp ult i32 [[IV]], 1236
185; CHECK-NEXT:    ret i1 [[T]]
186;
187entry:
188  br label %loop.header
189
190loop.header:
191  %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop.latch ]
192  %exitcond.not = icmp eq i32 %iv, 1234
193  br i1 %exitcond.not, label %exit, label %loop.latch
194
195loop.latch:
196  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
197  %0 = load i8, ptr %arrayidx, align 1
198  %latch.c = icmp ult i8 %0, 10
199  %iv.next = add i32 %iv, 1
200  br i1 %latch.c, label %loop.header, label %exit
201
202exit:
203  %t = icmp ult i32 %iv, 1236
204  ret i1 %t
205}
206
207define i1 @multi_exiting_loop_eq_same_exit_with_out_loop_preds_const_compare_not_known(ptr %s, i1 %pre.c, i32 %x) {
208; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_exit_with_out_loop_preds_const_compare_not_known(
209; CHECK-SAME: ptr [[S:%.*]], i1 [[PRE_C:%.*]], i32 [[X:%.*]]) {
210; CHECK-NEXT:  [[ENTRY:.*]]:
211; CHECK-NEXT:    br i1 [[PRE_C]], label %[[LOOP_HEADER:.*]], label %[[EXIT:.*]]
212; CHECK:       [[LOOP_HEADER]]:
213; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
214; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
215; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT]], label %[[LOOP_LATCH]]
216; CHECK:       [[LOOP_LATCH]]:
217; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
218; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
219; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
220; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
221; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
222; CHECK:       [[EXIT]]:
223; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[X]], %[[ENTRY]] ], [ [[IV]], %[[LOOP_HEADER]] ], [ [[IV]], %[[LOOP_LATCH]] ]
224; CHECK-NEXT:    [[U:%.*]] = icmp ult i32 [[P]], 1235
225; CHECK-NEXT:    ret i1 [[U]]
226;
227entry:
228  br i1 %pre.c, label %loop.header, label %exit
229
230loop.header:
231  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
232  %exitcond.not = icmp eq i32 %iv, 1234
233  br i1 %exitcond.not, label %exit, label %loop.latch
234
235loop.latch:
236  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
237  %0 = load i8, ptr %arrayidx, align 1
238  %latch.c = icmp ult i8 %0, 10
239  %iv.next = add nuw nsw i32 %iv, 1
240  br i1 %latch.c, label %loop.header, label %exit
241
242exit:
243  %p = phi i32 [ %x, %entry ], [ %iv, %loop.header ], [ %iv, %loop.latch ]
244  %u = icmp ult i32 %p, 1235
245  ret i1 %u
246}
247
248define i1 @multi_exiting_loop_eq_same_unique_exit_successors_swapped(ptr %s) {
249; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_successors_swapped(
250; CHECK-SAME: ptr [[S:%.*]]) {
251; CHECK-NEXT:  [[ENTRY:.*]]:
252; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
253; CHECK:       [[LOOP_HEADER]]:
254; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
255; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
256; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]
257; CHECK:       [[LOOP_LATCH]]:
258; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
259; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
260; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
261; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
262; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
263; CHECK:       [[EXIT]]:
264; CHECK-NEXT:    [[U:%.*]] = icmp ult i32 [[IV]], 1235
265; CHECK-NEXT:    ret i1 [[U]]
266;
267entry:
268  br label %loop.header
269
270loop.header:
271  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
272  %exitcond.not = icmp eq i32 %iv, 1234
273  br i1 %exitcond.not, label %loop.latch, label %exit
274
275loop.latch:
276  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
277  %0 = load i8, ptr %arrayidx, align 1
278  %latch.c = icmp ult i8 %0, 10
279  %iv.next = add nuw nsw i32 %iv, 1
280  br i1 %latch.c, label %loop.header, label %exit
281
282exit:
283  %u = icmp ult i32 %iv, 1235
284  ret i1 %u
285}
286
287define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known(ptr %s) {
288; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_const_compare_not_known(
289; CHECK-SAME: ptr [[S:%.*]]) {
290; CHECK-NEXT:  [[ENTRY:.*]]:
291; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
292; CHECK:       [[LOOP_HEADER]]:
293; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
294; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
295; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
296; CHECK:       [[LOOP_LATCH]]:
297; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
298; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
299; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
300; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
301; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
302; CHECK:       [[EXIT]]:
303; CHECK-NEXT:    [[U:%.*]] = icmp ult i32 [[IV]], 1234
304; CHECK-NEXT:    ret i1 [[U]]
305;
306entry:
307  br label %loop.header
308
309loop.header:
310  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
311  %exitcond.not = icmp eq i32 %iv, 1234
312  br i1 %exitcond.not, label %exit, label %loop.latch
313
314loop.latch:
315  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
316  %0 = load i8, ptr %arrayidx, align 1
317  %latch.c = icmp ult i8 %0, 10
318  %iv.next = add nuw nsw i32 %iv, 1
319  br i1 %latch.c, label %loop.header, label %exit
320
321exit:
322  %u = icmp ult i32 %iv, 1234
323  ret i1 %u
324}
325
326define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_known(ptr %s, i32 %N) {
327; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_known(
328; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) {
329; CHECK-NEXT:  [[ENTRY:.*]]:
330; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
331; CHECK:       [[LOOP_HEADER]]:
332; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
333; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]]
334; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
335; CHECK:       [[LOOP_LATCH]]:
336; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
337; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
338; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
339; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
340; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
341; CHECK:       [[EXIT]]:
342; CHECK-NEXT:    ret i1 true
343;
344entry:
345  br label %loop.header
346
347loop.header:
348  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
349  %exitcond.not = icmp eq i32 %iv, %N
350  br i1 %exitcond.not, label %exit, label %loop.latch
351
352loop.latch:
353  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
354  %0 = load i8, ptr %arrayidx, align 1
355  %latch.c = icmp ult i8 %0, 10
356  %iv.next = add nuw nsw i32 %iv, 1
357  br i1 %latch.c, label %loop.header, label %exit
358
359exit:
360  %t = icmp ule i32 %iv, %N
361  ret i1 %t
362}
363
364define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_not_known_due_to_start(ptr %s, i32 %N) {
365; CHECK-LABEL: define i1 @multi_exiting_loop_eq_same_unique_exit_var_compare_not_known_due_to_start(
366; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) {
367; CHECK-NEXT:  [[ENTRY:.*]]:
368; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
369; CHECK:       [[LOOP_HEADER]]:
370; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
371; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]]
372; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
373; CHECK:       [[LOOP_LATCH]]:
374; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
375; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
376; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
377; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
378; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
379; CHECK:       [[EXIT]]:
380; CHECK-NEXT:    [[C:%.*]] = icmp ule i32 [[IV]], [[N]]
381; CHECK-NEXT:    ret i1 [[C]]
382;
383entry:
384  br label %loop.header
385
386loop.header:
387  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
388  %exitcond.not = icmp eq i32 %iv, %N
389  br i1 %exitcond.not, label %exit, label %loop.latch
390
391loop.latch:
392  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
393  %0 = load i8, ptr %arrayidx, align 1
394  %latch.c = icmp ult i8 %0, 10
395  %iv.next = add nuw nsw i32 %iv, 1
396  br i1 %latch.c, label %loop.header, label %exit
397
398exit:
399  %c = icmp ule i32 %iv, %N
400  ret i1 %c
401}
402
403define i1 @multi_exiting_loop_ne_same_unique_exit_const_compare_known(ptr %s) {
404; CHECK-LABEL: define i1 @multi_exiting_loop_ne_same_unique_exit_const_compare_known(
405; CHECK-SAME: ptr [[S:%.*]]) {
406; CHECK-NEXT:  [[ENTRY:.*]]:
407; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
408; CHECK:       [[LOOP_HEADER]]:
409; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
410; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], 1234
411; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT:.*]]
412; CHECK:       [[LOOP_LATCH]]:
413; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
414; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
415; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
416; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
417; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
418; CHECK:       [[EXIT]]:
419; CHECK-NEXT:    ret i1 true
420;
421entry:
422  br label %loop.header
423
424loop.header:
425  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
426  %exitcond.not = icmp ne i32 %iv, 1234
427  br i1 %exitcond.not, label %loop.latch, label %exit
428
429loop.latch:
430  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
431  %0 = load i8, ptr %arrayidx, align 1
432  %latch.c = icmp ult i8 %0, 10
433  %iv.next = add nuw nsw i32 %iv, 1
434  br i1 %latch.c, label %loop.header, label %exit
435
436exit:
437  %t = icmp ult i32 %iv, 1235
438  ret i1 %t
439}
440
441define i1 @multi_exiting_loop_ne_same_unique_exit_successors_swapped(ptr %s) {
442; CHECK-LABEL: define i1 @multi_exiting_loop_ne_same_unique_exit_successors_swapped(
443; CHECK-SAME: ptr [[S:%.*]]) {
444; CHECK-NEXT:  [[ENTRY:.*]]:
445; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
446; CHECK:       [[LOOP_HEADER]]:
447; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
448; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], 1234
449; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
450; CHECK:       [[LOOP_LATCH]]:
451; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
452; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
453; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
454; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
455; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT]]
456; CHECK:       [[EXIT]]:
457; CHECK-NEXT:    [[U:%.*]] = icmp ult i32 [[IV]], 1235
458; CHECK-NEXT:    ret i1 [[U]]
459;
460entry:
461  br label %loop.header
462
463loop.header:
464  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
465  %exitcond.not = icmp ne i32 %iv, 1234
466  br i1 %exitcond.not, label %exit, label %loop.latch
467
468loop.latch:
469  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
470  %0 = load i8, ptr %arrayidx, align 1
471  %latch.c = icmp ult i8 %0, 10
472  %iv.next = add nuw nsw i32 %iv, 1
473  br i1 %latch.c, label %loop.header, label %exit
474
475exit:
476  %u = icmp ult i32 %iv, 1235
477  ret i1 %u
478}
479
480define i1 @multi_exiting_loop_eq_different_exits_const_compare_known(ptr %s) {
481; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_const_compare_known(
482; CHECK-SAME: ptr [[S:%.*]]) {
483; CHECK-NEXT:  [[ENTRY:.*]]:
484; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
485; CHECK:       [[LOOP_HEADER]]:
486; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
487; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
488; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[LOOP_LATCH]]
489; CHECK:       [[LOOP_LATCH]]:
490; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
491; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
492; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
493; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
494; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]]
495; CHECK:       [[EXIT_1]]:
496; CHECK-NEXT:    ret i1 true
497; CHECK:       [[EXIT_2]]:
498; CHECK-NEXT:    ret i1 true
499;
500entry:
501  br label %loop.header
502
503loop.header:
504  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
505  %exitcond.not = icmp eq i32 %iv, 1234
506  br i1 %exitcond.not, label %exit.1, label %loop.latch
507
508loop.latch:
509  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
510  %0 = load i8, ptr %arrayidx, align 1
511  %latch.c = icmp ult i8 %0, 10
512  %iv.next = add nuw nsw i32 %iv, 1
513  br i1 %latch.c, label %loop.header, label %exit.2
514
515exit.1:
516  %t.1 = icmp ult i32 %iv, 1235
517  ret i1 %t.1
518
519exit.2:
520  %t.2 = icmp ult i32 %iv, 1235
521  ret i1 %t.2
522}
523
524define i1 @multi_exiting_loop_eq_different_exits_2_const_compare_known(ptr %s, i1 %c.1, i1 %c.2) {
525; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_2_const_compare_known(
526; CHECK-SAME: ptr [[S:%.*]], i1 [[C_1:%.*]], i1 [[C_2:%.*]]) {
527; CHECK-NEXT:  [[ENTRY:.*]]:
528; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
529; CHECK:       [[LOOP_HEADER]]:
530; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
531; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], 1234
532; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[ELSE_1:.*]]
533; CHECK:       [[ELSE_1]]:
534; CHECK-NEXT:    br i1 [[C_1]], label %[[EXIT_1]], label %[[ELSE_2:.*]]
535; CHECK:       [[ELSE_2]]:
536; CHECK-NEXT:    br i1 [[C_2]], label %[[EXIT_2:.*]], label %[[LOOP_LATCH]]
537; CHECK:       [[LOOP_LATCH]]:
538; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
539; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
540; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
541; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
542; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2]]
543; CHECK:       [[EXIT_1]]:
544; CHECK-NEXT:    ret i1 true
545; CHECK:       [[EXIT_2]]:
546; CHECK-NEXT:    ret i1 true
547;
548entry:
549  br label %loop.header
550
551loop.header:
552  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
553  %exitcond.not = icmp eq i32 %iv, 1234
554  br i1 %exitcond.not, label %exit.1, label %else.1
555
556else.1:
557  br i1 %c.1, label %exit.1, label %else.2
558
559else.2:
560  br i1 %c.2, label %exit.2, label %loop.latch
561
562loop.latch:
563  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
564  %0 = load i8, ptr %arrayidx, align 1
565  %latch.c = icmp ult i8 %0, 10
566  %iv.next = add nuw nsw i32 %iv, 1
567  br i1 %latch.c, label %loop.header, label %exit.2
568
569exit.1:
570  %t.1 = icmp ult i32 %iv, 1235
571  ret i1 %t.1
572
573exit.2:
574  %t.2 = icmp ult i32 %iv, 1235
575  ret i1 %t.2
576}
577
578
579define i1 @multi_exiting_loop_eq_different_exits_compare_not_known(ptr %s, i32 %N) {
580; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_compare_not_known(
581; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) {
582; CHECK-NEXT:  [[ENTRY:.*]]:
583; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
584; CHECK:       [[LOOP_HEADER]]:
585; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
586; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]]
587; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[LOOP_LATCH]]
588; CHECK:       [[LOOP_LATCH]]:
589; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
590; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
591; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
592; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
593; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]]
594; CHECK:       [[EXIT_1]]:
595; CHECK-NEXT:    ret i1 false
596; CHECK:       [[EXIT_2]]:
597; CHECK-NEXT:    ret i1 true
598;
599entry:
600  br label %loop.header
601
602loop.header:
603  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
604  %exitcond.not = icmp eq i32 %iv, %N
605  br i1 %exitcond.not, label %exit.1, label %loop.latch
606
607loop.latch:
608  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
609  %0 = load i8, ptr %arrayidx, align 1
610  %latch.c = icmp ult i8 %0, 10
611  %iv.next = add nuw nsw i32 %iv, 1
612  br i1 %latch.c, label %loop.header, label %exit.2
613
614exit.1:
615  %t.1 = icmp ult i32 %iv, %N
616  ret i1 %t.1
617
618exit.2:
619  %t.2 = icmp ult i32 %iv, %N
620  ret i1 %t.2
621}
622
623define i1 @multi_exiting_loop_eq_different_exits_2_compare_not_known(ptr %s, i32 %N, i1 %c.1, i1 %c.2) {
624; CHECK-LABEL: define i1 @multi_exiting_loop_eq_different_exits_2_compare_not_known(
625; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]], i1 [[C_1:%.*]], i1 [[C_2:%.*]]) {
626; CHECK-NEXT:  [[ENTRY:.*]]:
627; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
628; CHECK:       [[LOOP_HEADER]]:
629; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
630; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[IV]], [[N]]
631; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[EXIT_1:.*]], label %[[ELSE_1:.*]]
632; CHECK:       [[ELSE_1]]:
633; CHECK-NEXT:    br i1 [[C_1]], label %[[EXIT_1]], label %[[ELSE_2:.*]]
634; CHECK:       [[ELSE_2]]:
635; CHECK-NEXT:    br i1 [[C_2]], label %[[EXIT_2:.*]], label %[[LOOP_LATCH]]
636; CHECK:       [[LOOP_LATCH]]:
637; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
638; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
639; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
640; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
641; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2]]
642; CHECK:       [[EXIT_1]]:
643; CHECK-NEXT:    [[T_1:%.*]] = icmp ult i32 [[IV]], [[N]]
644; CHECK-NEXT:    ret i1 [[T_1]]
645; CHECK:       [[EXIT_2]]:
646; CHECK-NEXT:    ret i1 true
647;
648entry:
649  br label %loop.header
650
651loop.header:
652  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
653  %exitcond.not = icmp eq i32 %iv, %N
654  br i1 %exitcond.not, label %exit.1, label %else.1
655
656else.1:
657  br i1 %c.1, label %exit.1, label %else.2
658
659else.2:
660  br i1 %c.2, label %exit.2, label %loop.latch
661
662loop.latch:
663  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
664  %0 = load i8, ptr %arrayidx, align 1
665  %latch.c = icmp ult i8 %0, 10
666  %iv.next = add nuw nsw i32 %iv, 1
667  br i1 %latch.c, label %loop.header, label %exit.2
668
669exit.1:
670  %t.1 = icmp ult i32 %iv, %N
671  ret i1 %t.1
672
673exit.2:
674  %t.2 = icmp ult i32 %iv, %N
675  ret i1 %t.2
676}
677
678define i1 @multi_exiting_loop_ne_different_exits_const_compare_known(ptr %s) {
679; CHECK-LABEL: define i1 @multi_exiting_loop_ne_different_exits_const_compare_known(
680; CHECK-SAME: ptr [[S:%.*]]) {
681; CHECK-NEXT:  [[ENTRY:.*]]:
682; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
683; CHECK:       [[LOOP_HEADER]]:
684; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
685; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], 1234
686; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT_1:.*]]
687; CHECK:       [[LOOP_LATCH]]:
688; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
689; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
690; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
691; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
692; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]]
693; CHECK:       [[EXIT_1]]:
694; CHECK-NEXT:    ret i1 true
695; CHECK:       [[EXIT_2]]:
696; CHECK-NEXT:    ret i1 true
697;
698entry:
699  br label %loop.header
700
701loop.header:
702  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
703  %exitcond.not = icmp ne i32 %iv, 1234
704  br i1 %exitcond.not, label %loop.latch, label %exit.1
705
706loop.latch:
707  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
708  %0 = load i8, ptr %arrayidx, align 1
709  %latch.c = icmp ult i8 %0, 10
710  %iv.next = add nuw nsw i32 %iv, 1
711  br i1 %latch.c, label %loop.header, label %exit.2
712
713exit.1:
714  %t.1 = icmp ult i32 %iv, 1235
715  ret i1 %t.1
716
717exit.2:
718  %t.2 = icmp ult i32 %iv, 1235
719  ret i1 %t.2
720}
721
722define i1 @multi_exiting_loop_ne_different_exits_compare_not_known(ptr %s, i32 %N) {
723; CHECK-LABEL: define i1 @multi_exiting_loop_ne_different_exits_compare_not_known(
724; CHECK-SAME: ptr [[S:%.*]], i32 [[N:%.*]]) {
725; CHECK-NEXT:  [[ENTRY:.*]]:
726; CHECK-NEXT:    br label %[[LOOP_HEADER:.*]]
727; CHECK:       [[LOOP_HEADER]]:
728; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ]
729; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp ne i32 [[IV]], [[N]]
730; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label %[[LOOP_LATCH]], label %[[EXIT_1:.*]]
731; CHECK:       [[LOOP_LATCH]]:
732; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[IV]]
733; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
734; CHECK-NEXT:    [[LATCH_C:%.*]] = icmp ult i8 [[TMP0]], 10
735; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
736; CHECK-NEXT:    br i1 [[LATCH_C]], label %[[LOOP_HEADER]], label %[[EXIT_2:.*]]
737; CHECK:       [[EXIT_1]]:
738; CHECK-NEXT:    ret i1 false
739; CHECK:       [[EXIT_2]]:
740; CHECK-NEXT:    [[T_2:%.*]] = icmp ult i32 [[IV]], [[N]]
741; CHECK-NEXT:    ret i1 [[T_2]]
742;
743entry:
744  br label %loop.header
745
746loop.header:
747  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
748  %exitcond.not = icmp ne i32 %iv, %N
749  br i1 %exitcond.not, label %loop.latch, label %exit.1
750
751loop.latch:
752  %arrayidx = getelementptr inbounds i8, ptr %s, i32 %iv
753  %0 = load i8, ptr %arrayidx, align 1
754  %latch.c = icmp ult i8 %0, 10
755  %iv.next = add nuw nsw i32 %iv, 1
756  br i1 %latch.c, label %loop.header, label %exit.2
757
758exit.1:
759  %t.1 = icmp ult i32 %iv, %N
760  ret i1 %t.1
761
762exit.2:
763  %t.2 = icmp ult i32 %iv, %N
764  ret i1 %t.2
765}
766
767define i1 @test_non_dedicated_exit(i16 %n) {
768; CHECK-LABEL: define i1 @test_non_dedicated_exit(
769; CHECK-SAME: i16 [[N:%.*]]) {
770; CHECK-NEXT:  [[ENTRY:.*:]]
771; CHECK-NEXT:    [[COND:%.*]] = icmp slt i16 [[N]], 1
772; CHECK-NEXT:    br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]]
773; CHECK:       [[LOOP_PREHEADER]]:
774; CHECK-NEXT:    [[SUB:%.*]] = add nsw i16 [[N]], -1
775; CHECK-NEXT:    [[EXT:%.*]] = zext nneg i16 [[SUB]] to i32
776; CHECK-NEXT:    br label %[[LOOP:.*]]
777; CHECK:       [[LOOP]]:
778; CHECK-NEXT:    [[INDVAR:%.*]] = phi i32 [ [[INDVAR_INC:%.*]], %[[LOOP_LATCH:.*]] ], [ 0, %[[LOOP_PREHEADER]] ]
779; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INDVAR]], [[EXT]]
780; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[EXIT]], label %[[LOOP_LATCH]]
781; CHECK:       [[LOOP_LATCH]]:
782; CHECK-NEXT:    [[INDVAR_INC]] = add nuw nsw i32 [[INDVAR]], 1
783; CHECK-NEXT:    br label %[[LOOP]]
784; CHECK:       [[EXIT]]:
785; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i16 [[N]], 0
786; CHECK-NEXT:    ret i1 [[CMP]]
787;
788entry:
789  %cond = icmp slt i16 %n, 1
790  br i1 %cond, label %exit, label %loop.preheader
791
792loop.preheader:
793  %sub = add nsw i16 %n, -1
794  %ext = zext nneg i16 %sub to i32
795  br label %loop
796
797loop:
798  %indvar = phi i32 [ %indvar.inc, %loop.latch ], [ 0, %loop.preheader ]
799  %exitcond = icmp eq i32 %indvar, %ext
800  br i1 %exitcond, label %exit, label %loop.latch
801
802loop.latch:
803  %indvar.inc = add nuw nsw i32 %indvar, 1
804  br label %loop
805
806exit:
807  %cmp = icmp sgt i16 %n, 0
808  ret i1 %cmp
809}
810