[LLVM][IR] Use splat syntax when printing ConstantExpr based splats. (#116856)
[llvm-project.git] / llvm / test / Transforms / ConstraintElimination / induction-condition-in-loop-exit.ll
bloba04b06e1bf0a52009a102010f2b6939dda04b9cc
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
4 declare void @llvm.assume(i1)
6 define 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
24 entry:
25   br label %loop.header
27 loop.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
32 loop.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
39 exit:
40   %t = icmp ult i32 %iv, 1235
41   ret i1 %t
44 define 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]]
63 entry:
64   br label %loop.header
66 loop.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
71 loop.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
78 exit:
79   %t = icmp ult i32 %iv, 1235
80   ret i1 %t
83 define 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
103 entry:
104   %pre.c = icmp ule i32 %start, 1234
105   call void @llvm.assume(i1 %pre.c)
106   br label %loop.header
108 loop.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
113 loop.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
120 exit:
121   %t = icmp ult i32 %iv, 1235
122   ret i1 %t
125 define 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]]
146 entry:
147   %pre.c = icmp ule i32 %start, 1236
148   call void @llvm.assume(i1 %pre.c)
149   br label %loop.header
151 loop.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
156 loop.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
163 exit:
164   %t = icmp ult i32 %iv, 1236
165   ret i1 %t
168 define 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]]
187 entry:
188   br label %loop.header
190 loop.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
195 loop.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
202 exit:
203   %t = icmp ult i32 %iv, 1236
204   ret i1 %t
207 define 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]]
227 entry:
228   br i1 %pre.c, label %loop.header, label %exit
230 loop.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
235 loop.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
242 exit:
243   %p = phi i32 [ %x, %entry ], [ %iv, %loop.header ], [ %iv, %loop.latch ]
244   %u = icmp ult i32 %p, 1235
245   ret i1 %u
248 define 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]]
267 entry:
268   br label %loop.header
270 loop.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
275 loop.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
282 exit:
283   %u = icmp ult i32 %iv, 1235
284   ret i1 %u
287 define 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]]
306 entry:
307   br label %loop.header
309 loop.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
314 loop.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
321 exit:
322   %u = icmp ult i32 %iv, 1234
323   ret i1 %u
326 define 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
344 entry:
345   br label %loop.header
347 loop.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
352 loop.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
359 exit:
360   %t = icmp ule i32 %iv, %N
361   ret i1 %t
364 define 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]]
383 entry:
384   br label %loop.header
386 loop.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
391 loop.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
398 exit:
399   %c = icmp ule i32 %iv, %N
400   ret i1 %c
403 define 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
421 entry:
422   br label %loop.header
424 loop.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
429 loop.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
436 exit:
437   %t = icmp ult i32 %iv, 1235
438   ret i1 %t
441 define 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]]
460 entry:
461   br label %loop.header
463 loop.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
468 loop.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
475 exit:
476   %u = icmp ult i32 %iv, 1235
477   ret i1 %u
480 define 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
500 entry:
501   br label %loop.header
503 loop.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
508 loop.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
515 exit.1:
516   %t.1 = icmp ult i32 %iv, 1235
517   ret i1 %t.1
519 exit.2:
520   %t.2 = icmp ult i32 %iv, 1235
521   ret i1 %t.2
524 define 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
548 entry:
549   br label %loop.header
551 loop.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
556 else.1:
557   br i1 %c.1, label %exit.1, label %else.2
559 else.2:
560   br i1 %c.2, label %exit.2, label %loop.latch
562 loop.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
569 exit.1:
570   %t.1 = icmp ult i32 %iv, 1235
571   ret i1 %t.1
573 exit.2:
574   %t.2 = icmp ult i32 %iv, 1235
575   ret i1 %t.2
579 define 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
599 entry:
600   br label %loop.header
602 loop.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
607 loop.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
614 exit.1:
615   %t.1 = icmp ult i32 %iv, %N
616   ret i1 %t.1
618 exit.2:
619   %t.2 = icmp ult i32 %iv, %N
620   ret i1 %t.2
623 define 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
648 entry:
649   br label %loop.header
651 loop.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
656 else.1:
657   br i1 %c.1, label %exit.1, label %else.2
659 else.2:
660   br i1 %c.2, label %exit.2, label %loop.latch
662 loop.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
669 exit.1:
670   %t.1 = icmp ult i32 %iv, %N
671   ret i1 %t.1
673 exit.2:
674   %t.2 = icmp ult i32 %iv, %N
675   ret i1 %t.2
678 define 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
698 entry:
699   br label %loop.header
701 loop.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
706 loop.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
713 exit.1:
714   %t.1 = icmp ult i32 %iv, 1235
715   ret i1 %t.1
717 exit.2:
718   %t.2 = icmp ult i32 %iv, 1235
719   ret i1 %t.2
722 define 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]]
743 entry:
744   br label %loop.header
746 loop.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
751 loop.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
758 exit.1:
759   %t.1 = icmp ult i32 %iv, %N
760   ret i1 %t.1
762 exit.2:
763   %t.2 = icmp ult i32 %iv, %N
764   ret i1 %t.2
767 define 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]]
788 entry:
789   %cond = icmp slt i16 %n, 1
790   br i1 %cond, label %exit, label %loop.preheader
792 loop.preheader:
793   %sub = add nsw i16 %n, -1
794   %ext = zext nneg i16 %sub to i32
795   br label %loop
797 loop:
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
802 loop.latch:
803   %indvar.inc = add nuw nsw i32 %indvar, 1
804   br label %loop
806 exit:
807   %cmp = icmp sgt i16 %n, 0
808   ret i1 %cmp