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]]
22 ; CHECK-NEXT: ret i1 true
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
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
40 %t = icmp ult i32 %iv, 1235
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]]
60 ; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[IV]], 1235
61 ; CHECK-NEXT: ret i1 [[T]]
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
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
79 %t = icmp ult i32 %iv, 1235
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]]
101 ; CHECK-NEXT: ret i1 true
104 %pre.c = icmp ule i32 %start, 1234
105 call void @llvm.assume(i1 %pre.c)
106 br label %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
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
121 %t = icmp ult i32 %iv, 1235
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]]
143 ; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[IV]], 1236
144 ; CHECK-NEXT: ret i1 [[T]]
147 %pre.c = icmp ule i32 %start, 1236
148 call void @llvm.assume(i1 %pre.c)
149 br label %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
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
164 %t = icmp ult i32 %iv, 1236
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]]
184 ; CHECK-NEXT: [[T:%.*]] = icmp ult i32 [[IV]], 1236
185 ; CHECK-NEXT: ret i1 [[T]]
188 br label %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
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
203 %t = icmp ult i32 %iv, 1236
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]]
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]]
228 br i1 %pre.c, label %loop.header, label %exit
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
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
243 %p = phi i32 [ %x, %entry ], [ %iv, %loop.header ], [ %iv, %loop.latch ]
244 %u = icmp ult i32 %p, 1235
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]]
264 ; CHECK-NEXT: [[U:%.*]] = icmp ult i32 [[IV]], 1235
265 ; CHECK-NEXT: ret i1 [[U]]
268 br label %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
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
283 %u = icmp ult i32 %iv, 1235
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]]
303 ; CHECK-NEXT: [[U:%.*]] = icmp ult i32 [[IV]], 1234
304 ; CHECK-NEXT: ret i1 [[U]]
307 br label %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
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
322 %u = icmp ult i32 %iv, 1234
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]]
342 ; CHECK-NEXT: ret i1 true
345 br label %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
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
360 %t = icmp ule i32 %iv, %N
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]]
380 ; CHECK-NEXT: [[C:%.*]] = icmp ule i32 [[IV]], [[N]]
381 ; CHECK-NEXT: ret i1 [[C]]
384 br label %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
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
399 %c = icmp ule i32 %iv, %N
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]]
419 ; CHECK-NEXT: ret i1 true
422 br label %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
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
437 %t = icmp ult i32 %iv, 1235
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]]
457 ; CHECK-NEXT: [[U:%.*]] = icmp ult i32 [[IV]], 1235
458 ; CHECK-NEXT: ret i1 [[U]]
461 br label %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
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
476 %u = icmp ult i32 %iv, 1235
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:.*]]
496 ; CHECK-NEXT: ret i1 true
498 ; CHECK-NEXT: ret i1 true
501 br label %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
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
516 %t.1 = icmp ult i32 %iv, 1235
520 %t.2 = icmp ult i32 %iv, 1235
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:.*]]
534 ; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT_1]], label %[[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]]
544 ; CHECK-NEXT: ret i1 true
546 ; CHECK-NEXT: ret i1 true
549 br label %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
557 br i1 %c.1, label %exit.1, label %else.2
560 br i1 %c.2, label %exit.2, label %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
570 %t.1 = icmp ult i32 %iv, 1235
574 %t.2 = icmp ult i32 %iv, 1235
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:.*]]
595 ; CHECK-NEXT: ret i1 false
597 ; CHECK-NEXT: ret i1 true
600 br label %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
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
615 %t.1 = icmp ult i32 %iv, %N
619 %t.2 = icmp ult i32 %iv, %N
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:.*]]
633 ; CHECK-NEXT: br i1 [[C_1]], label %[[EXIT_1]], label %[[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]]
643 ; CHECK-NEXT: [[T_1:%.*]] = icmp ult i32 [[IV]], [[N]]
644 ; CHECK-NEXT: ret i1 [[T_1]]
646 ; CHECK-NEXT: ret i1 true
649 br label %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
657 br i1 %c.1, label %exit.1, label %else.2
660 br i1 %c.2, label %exit.2, label %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
670 %t.1 = icmp ult i32 %iv, %N
674 %t.2 = icmp ult i32 %iv, %N
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:.*]]
694 ; CHECK-NEXT: ret i1 true
696 ; CHECK-NEXT: ret i1 true
699 br label %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
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
714 %t.1 = icmp ult i32 %iv, 1235
718 %t.2 = icmp ult i32 %iv, 1235
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:.*]]
738 ; CHECK-NEXT: ret i1 false
740 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult i32 [[IV]], [[N]]
741 ; CHECK-NEXT: ret i1 [[T_2]]
744 br label %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
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
759 %t.1 = icmp ult i32 %iv, %N
763 %t.2 = icmp ult i32 %iv, %N
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:.*]]
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]]
785 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[N]], 0
786 ; CHECK-NEXT: ret i1 [[CMP]]
789 %cond = icmp slt i16 %n, 1
790 br i1 %cond, label %exit, label %loop.preheader
793 %sub = add nsw i16 %n, -1
794 %ext = zext nneg i16 %sub to i32
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
803 %indvar.inc = add nuw nsw i32 %indvar, 1
807 %cmp = icmp sgt i16 %n, 0