[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / LICM / min_max.ll
blobc2bf0a7f20cc125e4f3d200b434e819a848fe317
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S %s -passes='loop-mssa(licm)'  -verify-memoryssa  | FileCheck %s
4 ; turn to %iv <u umin(inv_1, inv_2) and hoist it out of loop.
5 define i32 @test_ult(i32 %start, i32 %inv_1, i32 %inv_2) {
6 ; CHECK-LABEL: @test_ult(
7 ; CHECK-NEXT:  entry:
8 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
9 ; CHECK-NEXT:    br label [[LOOP:%.*]]
10 ; CHECK:       loop:
11 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
12 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]
13 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
14 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
15 ; CHECK:       exit:
16 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
17 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
19 entry:
20   br label %loop
22 loop:
23   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
24   %cmp_1 = icmp ult i32 %iv, %inv_1
25   %cmp_2 = icmp ult i32 %iv, %inv_2
26   %loop_cond = and i1 %cmp_1, %cmp_2
27   %iv.next = add i32 %iv, 1
28   br i1 %loop_cond, label %loop, label %exit
30 exit:
31   ret i32 %iv
34 ; Do not optimize: pointer types.
35 define ptr @test_ult_ptr_neg(ptr %start, ptr %inv_1, ptr %inv_2) {
36 ; CHECK-LABEL: @test_ult_ptr_neg(
37 ; CHECK-NEXT:  entry:
38 ; CHECK-NEXT:    br label [[LOOP:%.*]]
39 ; CHECK:       loop:
40 ; CHECK-NEXT:    [[IV:%.*]] = phi ptr [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
41 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult ptr [[IV]], [[INV_1:%.*]]
42 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ult ptr [[IV]], [[INV_2:%.*]]
43 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
44 ; CHECK-NEXT:    [[IV_NEXT]] = getelementptr i32, ptr [[IV]], i64 4
45 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
46 ; CHECK:       exit:
47 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi ptr [ [[IV]], [[LOOP]] ]
48 ; CHECK-NEXT:    ret ptr [[IV_LCSSA]]
50 entry:
51   br label %loop
53 loop:
54   %iv = phi ptr [%start, %entry], [%iv.next, %loop]
55   %cmp_1 = icmp ult ptr %iv, %inv_1
56   %cmp_2 = icmp ult ptr %iv, %inv_2
57   %loop_cond = and i1 %cmp_1, %cmp_2
58   %iv.next = getelementptr i32, ptr %iv, i64 4
59   br i1 %loop_cond, label %loop, label %exit
61 exit:
62   ret ptr %iv
65 ; turn to %iv <=u umin(inv_1, inv_2) and hoist it out of loop.
66 define i32 @test_ule(i32 %start, i32 %inv_1, i32 %inv_2) {
67 ; CHECK-LABEL: @test_ule(
68 ; CHECK-NEXT:  entry:
69 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
70 ; CHECK-NEXT:    br label [[LOOP:%.*]]
71 ; CHECK:       loop:
72 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
73 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ule i32 [[IV]], [[INVARIANT_UMIN]]
74 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
75 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
76 ; CHECK:       exit:
77 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
78 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
80 entry:
81   br label %loop
83 loop:
84   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
85   %cmp_1 = icmp ule i32 %iv, %inv_1
86   %cmp_2 = icmp ule i32 %iv, %inv_2
87   %loop_cond = and i1 %cmp_1, %cmp_2
88   %iv.next = add i32 %iv, 1
89   br i1 %loop_cond, label %loop, label %exit
91 exit:
92   ret i32 %iv
95 ; turn to %iv <s smin(inv_1, inv_2) and hoist it out of loop.
96 define i32 @test_slt(i32 %start, i32 %inv_1, i32 %inv_2) {
97 ; CHECK-LABEL: @test_slt(
98 ; CHECK-NEXT:  entry:
99 ; CHECK-NEXT:    [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
100 ; CHECK-NEXT:    br label [[LOOP:%.*]]
101 ; CHECK:       loop:
102 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
103 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_SMIN]]
104 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
105 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
106 ; CHECK:       exit:
107 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
108 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
110 entry:
111   br label %loop
113 loop:
114   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
115   %cmp_1 = icmp slt i32 %iv, %inv_1
116   %cmp_2 = icmp slt i32 %iv, %inv_2
117   %loop_cond = and i1 %cmp_1, %cmp_2
118   %iv.next = add i32 %iv, 1
119   br i1 %loop_cond, label %loop, label %exit
121 exit:
122   ret i32 %iv
125 ; turn to %iv <=s smin(inv_1, inv_2) and hoist it out of loop.
126 define i32 @test_sle(i32 %start, i32 %inv_1, i32 %inv_2) {
127 ; CHECK-LABEL: @test_sle(
128 ; CHECK-NEXT:  entry:
129 ; CHECK-NEXT:    [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
130 ; CHECK-NEXT:    br label [[LOOP:%.*]]
131 ; CHECK:       loop:
132 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
133 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sle i32 [[IV]], [[INVARIANT_SMIN]]
134 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
135 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
136 ; CHECK:       exit:
137 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
138 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
140 entry:
141   br label %loop
143 loop:
144   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
145   %cmp_1 = icmp sle i32 %iv, %inv_1
146   %cmp_2 = icmp sle i32 %iv, %inv_2
147   %loop_cond = and i1 %cmp_1, %cmp_2
148   %iv.next = add i32 %iv, 1
149   br i1 %loop_cond, label %loop, label %exit
151 exit:
152   ret i32 %iv
155 ; turn to %iv >u umax(inv_1, inv_2) and hoist it out of loop.
156 define i32 @test_ugt(i32 %start, i32 %inv_1, i32 %inv_2) {
157 ; CHECK-LABEL: @test_ugt(
158 ; CHECK-NEXT:  entry:
159 ; CHECK-NEXT:    [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
160 ; CHECK-NEXT:    br label [[LOOP:%.*]]
161 ; CHECK:       loop:
162 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
163 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ugt i32 [[IV]], [[INVARIANT_UMAX]]
164 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
165 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
166 ; CHECK:       exit:
167 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
168 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
170 entry:
171   br label %loop
173 loop:
174   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
175   %cmp_1 = icmp ugt i32 %iv, %inv_1
176   %cmp_2 = icmp ugt i32 %iv, %inv_2
177   %loop_cond = and i1 %cmp_1, %cmp_2
178   %iv.next = add i32 %iv, 1
179   br i1 %loop_cond, label %loop, label %exit
181 exit:
182   ret i32 %iv
185 ; turn to %iv >=u umax(inv_1, inv_2) and hoist it out of loop.
186 define i32 @test_uge(i32 %start, i32 %inv_1, i32 %inv_2) {
187 ; CHECK-LABEL: @test_uge(
188 ; CHECK-NEXT:  entry:
189 ; CHECK-NEXT:    [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
190 ; CHECK-NEXT:    br label [[LOOP:%.*]]
191 ; CHECK:       loop:
192 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
193 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp uge i32 [[IV]], [[INVARIANT_UMAX]]
194 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
195 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
196 ; CHECK:       exit:
197 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
198 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
200 entry:
201   br label %loop
203 loop:
204   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
205   %cmp_1 = icmp uge i32 %iv, %inv_1
206   %cmp_2 = icmp uge i32 %iv, %inv_2
207   %loop_cond = and i1 %cmp_1, %cmp_2
208   %iv.next = add i32 %iv, 1
209   br i1 %loop_cond, label %loop, label %exit
211 exit:
212   ret i32 %iv
215 ; turn to %iv >s smax(inv_1, inv_2) and hoist it out of loop.
216 define i32 @test_sgt(i32 %start, i32 %inv_1, i32 %inv_2) {
217 ; CHECK-LABEL: @test_sgt(
218 ; CHECK-NEXT:  entry:
219 ; CHECK-NEXT:    [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
220 ; CHECK-NEXT:    br label [[LOOP:%.*]]
221 ; CHECK:       loop:
222 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
223 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_SMAX]]
224 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
225 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
226 ; CHECK:       exit:
227 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
228 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
230 entry:
231   br label %loop
233 loop:
234   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
235   %cmp_1 = icmp sgt i32 %iv, %inv_1
236   %cmp_2 = icmp sgt i32 %iv, %inv_2
237   %loop_cond = and i1 %cmp_1, %cmp_2
238   %iv.next = add i32 %iv, 1
239   br i1 %loop_cond, label %loop, label %exit
241 exit:
242   ret i32 %iv
245 ; turn to %iv >=s smax(inv_1, inv_2) and hoist it out of loop.
246 define i32 @test_sge(i32 %start, i32 %inv_1, i32 %inv_2) {
247 ; CHECK-LABEL: @test_sge(
248 ; CHECK-NEXT:  entry:
249 ; CHECK-NEXT:    [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
250 ; CHECK-NEXT:    br label [[LOOP:%.*]]
251 ; CHECK:       loop:
252 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
253 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sge i32 [[IV]], [[INVARIANT_SMAX]]
254 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
255 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
256 ; CHECK:       exit:
257 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
258 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
260 entry:
261   br label %loop
263 loop:
264   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
265   %cmp_1 = icmp sge i32 %iv, %inv_1
266   %cmp_2 = icmp sge i32 %iv, %inv_2
267   %loop_cond = and i1 %cmp_1, %cmp_2
268   %iv.next = add i32 %iv, 1
269   br i1 %loop_cond, label %loop, label %exit
271 exit:
272   ret i32 %iv
275 ; Turn OR to AND and handle accordingly.
276 define i32 @test_ult_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
277 ; CHECK-LABEL: @test_ult_inv(
278 ; CHECK-NEXT:  entry:
279 ; CHECK-NEXT:    [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
280 ; CHECK-NEXT:    br label [[LOOP:%.*]]
281 ; CHECK:       loop:
282 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
283 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMAX]]
284 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
285 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
286 ; CHECK:       exit:
287 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
288 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
290 entry:
291   br label %loop
293 loop:
294   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
295   %cmp_1 = icmp ult i32 %iv, %inv_1
296   %cmp_2 = icmp ult i32 %iv, %inv_2
297   %loop_cond = or i1 %cmp_1, %cmp_2
298   %iv.next = add i32 %iv, 1
299   br i1 %loop_cond, label %loop, label %exit
301 exit:
302   ret i32 %iv
305 ; Turn OR to AND and handle accordingly.
306 define i32 @test_ule_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
307 ; CHECK-LABEL: @test_ule_inv(
308 ; CHECK-NEXT:  entry:
309 ; CHECK-NEXT:    [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
310 ; CHECK-NEXT:    br label [[LOOP:%.*]]
311 ; CHECK:       loop:
312 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
313 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ule i32 [[IV]], [[INVARIANT_UMAX]]
314 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
315 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
316 ; CHECK:       exit:
317 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
318 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
320 entry:
321   br label %loop
323 loop:
324   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
325   %cmp_1 = icmp ule i32 %iv, %inv_1
326   %cmp_2 = icmp ule i32 %iv, %inv_2
327   %loop_cond = or i1 %cmp_1, %cmp_2
328   %iv.next = add i32 %iv, 1
329   br i1 %loop_cond, label %loop, label %exit
331 exit:
332   ret i32 %iv
335 ; Turn OR to AND and handle accordingly.
336 define i32 @test_slt_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
337 ; CHECK-LABEL: @test_slt_inv(
338 ; CHECK-NEXT:  entry:
339 ; CHECK-NEXT:    [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
340 ; CHECK-NEXT:    br label [[LOOP:%.*]]
341 ; CHECK:       loop:
342 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
343 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_SMAX]]
344 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
345 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
346 ; CHECK:       exit:
347 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
348 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
350 entry:
351   br label %loop
353 loop:
354   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
355   %cmp_1 = icmp slt i32 %iv, %inv_1
356   %cmp_2 = icmp slt i32 %iv, %inv_2
357   %loop_cond = or i1 %cmp_1, %cmp_2
358   %iv.next = add i32 %iv, 1
359   br i1 %loop_cond, label %loop, label %exit
361 exit:
362   ret i32 %iv
365 ; Turn OR to AND and handle accordingly.
366 define i32 @test_sle_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
367 ; CHECK-LABEL: @test_sle_inv(
368 ; CHECK-NEXT:  entry:
369 ; CHECK-NEXT:    [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
370 ; CHECK-NEXT:    br label [[LOOP:%.*]]
371 ; CHECK:       loop:
372 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
373 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sle i32 [[IV]], [[INVARIANT_SMAX]]
374 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
375 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
376 ; CHECK:       exit:
377 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
378 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
380 entry:
381   br label %loop
383 loop:
384   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
385   %cmp_1 = icmp sle i32 %iv, %inv_1
386   %cmp_2 = icmp sle i32 %iv, %inv_2
387   %loop_cond = or i1 %cmp_1, %cmp_2
388   %iv.next = add i32 %iv, 1
389   br i1 %loop_cond, label %loop, label %exit
391 exit:
392   ret i32 %iv
395 ; Turn OR to AND and handle accordingly.
396 define i32 @test_ugt_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
397 ; CHECK-LABEL: @test_ugt_inv(
398 ; CHECK-NEXT:  entry:
399 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
400 ; CHECK-NEXT:    br label [[LOOP:%.*]]
401 ; CHECK:       loop:
402 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
403 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ugt i32 [[IV]], [[INVARIANT_UMIN]]
404 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
405 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
406 ; CHECK:       exit:
407 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
408 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
410 entry:
411   br label %loop
413 loop:
414   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
415   %cmp_1 = icmp ugt i32 %iv, %inv_1
416   %cmp_2 = icmp ugt i32 %iv, %inv_2
417   %loop_cond = or i1 %cmp_1, %cmp_2
418   %iv.next = add i32 %iv, 1
419   br i1 %loop_cond, label %loop, label %exit
421 exit:
422   ret i32 %iv
425 ; Turn OR to AND and handle accordingly.
426 define i32 @test_uge_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
427 ; CHECK-LABEL: @test_uge_inv(
428 ; CHECK-NEXT:  entry:
429 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
430 ; CHECK-NEXT:    br label [[LOOP:%.*]]
431 ; CHECK:       loop:
432 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
433 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp uge i32 [[IV]], [[INVARIANT_UMIN]]
434 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
435 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
436 ; CHECK:       exit:
437 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
438 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
440 entry:
441   br label %loop
443 loop:
444   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
445   %cmp_1 = icmp uge i32 %iv, %inv_1
446   %cmp_2 = icmp uge i32 %iv, %inv_2
447   %loop_cond = or i1 %cmp_1, %cmp_2
448   %iv.next = add i32 %iv, 1
449   br i1 %loop_cond, label %loop, label %exit
451 exit:
452   ret i32 %iv
455 ; Turn OR to AND and handle accordingly.
456 define i32 @test_sgt_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
457 ; CHECK-LABEL: @test_sgt_inv(
458 ; CHECK-NEXT:  entry:
459 ; CHECK-NEXT:    [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
460 ; CHECK-NEXT:    br label [[LOOP:%.*]]
461 ; CHECK:       loop:
462 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
463 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_SMIN]]
464 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
465 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
466 ; CHECK:       exit:
467 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
468 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
470 entry:
471   br label %loop
473 loop:
474   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
475   %cmp_1 = icmp sgt i32 %iv, %inv_1
476   %cmp_2 = icmp sgt i32 %iv, %inv_2
477   %loop_cond = or i1 %cmp_1, %cmp_2
478   %iv.next = add i32 %iv, 1
479   br i1 %loop_cond, label %loop, label %exit
481 exit:
482   ret i32 %iv
485 ; Turn OR to AND and handle accordingly.
486 define i32 @test_sge_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
487 ; CHECK-LABEL: @test_sge_inv(
488 ; CHECK-NEXT:  entry:
489 ; CHECK-NEXT:    [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
490 ; CHECK-NEXT:    br label [[LOOP:%.*]]
491 ; CHECK:       loop:
492 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
493 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sge i32 [[IV]], [[INVARIANT_SMIN]]
494 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
495 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
496 ; CHECK:       exit:
497 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
498 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
500 entry:
501   br label %loop
503 loop:
504   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
505   %cmp_1 = icmp sge i32 %iv, %inv_1
506   %cmp_2 = icmp sge i32 %iv, %inv_2
507   %loop_cond = or i1 %cmp_1, %cmp_2
508   %iv.next = add i32 %iv, 1
509   br i1 %loop_cond, label %loop, label %exit
511 exit:
512   ret i32 %iv
515 ; turn to %iv <u umin(inv_1, inv_2) and hoist it out of loop.
516 define i32 @test_ult_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {
517 ; CHECK-LABEL: @test_ult_swapped(
518 ; CHECK-NEXT:  entry:
519 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
520 ; CHECK-NEXT:    br label [[LOOP:%.*]]
521 ; CHECK:       loop:
522 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
523 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]
524 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
525 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
526 ; CHECK:       exit:
527 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
528 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
530 entry:
531   br label %loop
533 loop:
534   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
535   %cmp_1 = icmp ugt i32 %inv_1, %iv
536   %cmp_2 = icmp ugt i32 %inv_2, %iv
537   %loop_cond = and i1 %cmp_1, %cmp_2
538   %iv.next = add i32 %iv, 1
539   br i1 %loop_cond, label %loop, label %exit
541 exit:
542   ret i32 %iv
545 ; turn to %iv <=u umin(inv_1, inv_2) and hoist it out of loop.
546 define i32 @test_ule_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {
547 ; CHECK-LABEL: @test_ule_swapped(
548 ; CHECK-NEXT:  entry:
549 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
550 ; CHECK-NEXT:    br label [[LOOP:%.*]]
551 ; CHECK:       loop:
552 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
553 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ule i32 [[IV]], [[INVARIANT_UMIN]]
554 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
555 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
556 ; CHECK:       exit:
557 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
558 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
560 entry:
561   br label %loop
563 loop:
564   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
565   %cmp_1 = icmp uge i32 %inv_1, %iv
566   %cmp_2 = icmp uge i32 %inv_2, %iv
567   %loop_cond = and i1 %cmp_1, %cmp_2
568   %iv.next = add i32 %iv, 1
569   br i1 %loop_cond, label %loop, label %exit
571 exit:
572   ret i32 %iv
575 ; turn to %iv <s smin(inv_1, inv_2) and hoist it out of loop.
576 define i32 @test_slt_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {
577 ; CHECK-LABEL: @test_slt_swapped(
578 ; CHECK-NEXT:  entry:
579 ; CHECK-NEXT:    [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
580 ; CHECK-NEXT:    br label [[LOOP:%.*]]
581 ; CHECK:       loop:
582 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
583 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV]], [[INVARIANT_SMIN]]
584 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
585 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
586 ; CHECK:       exit:
587 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
588 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
590 entry:
591   br label %loop
593 loop:
594   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
595   %cmp_1 = icmp sgt i32 %inv_1, %iv
596   %cmp_2 = icmp sgt i32 %inv_2, %iv
597   %loop_cond = and i1 %cmp_1, %cmp_2
598   %iv.next = add i32 %iv, 1
599   br i1 %loop_cond, label %loop, label %exit
601 exit:
602   ret i32 %iv
605 ; turn to %iv <=s smin(inv_1, inv_2) and hoist it out of loop.
606 define i32 @test_sle_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {
607 ; CHECK-LABEL: @test_sle_swapped(
608 ; CHECK-NEXT:  entry:
609 ; CHECK-NEXT:    [[INVARIANT_SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
610 ; CHECK-NEXT:    br label [[LOOP:%.*]]
611 ; CHECK:       loop:
612 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
613 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sle i32 [[IV]], [[INVARIANT_SMIN]]
614 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
615 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
616 ; CHECK:       exit:
617 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
618 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
620 entry:
621   br label %loop
623 loop:
624   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
625   %cmp_1 = icmp sge i32 %inv_1, %iv
626   %cmp_2 = icmp sge i32 %inv_2, %iv
627   %loop_cond = and i1 %cmp_1, %cmp_2
628   %iv.next = add i32 %iv, 1
629   br i1 %loop_cond, label %loop, label %exit
631 exit:
632   ret i32 %iv
635 ; turn to %iv >u umax(inv_1, inv_2) and hoist it out of loop.
636 define i32 @test_ugt_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {
637 ; CHECK-LABEL: @test_ugt_swapped(
638 ; CHECK-NEXT:  entry:
639 ; CHECK-NEXT:    [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
640 ; CHECK-NEXT:    br label [[LOOP:%.*]]
641 ; CHECK:       loop:
642 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
643 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ugt i32 [[IV]], [[INVARIANT_UMAX]]
644 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
645 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
646 ; CHECK:       exit:
647 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
648 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
650 entry:
651   br label %loop
653 loop:
654   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
655   %cmp_1 = icmp ult i32 %inv_1, %iv
656   %cmp_2 = icmp ult i32 %inv_2, %iv
657   %loop_cond = and i1 %cmp_1, %cmp_2
658   %iv.next = add i32 %iv, 1
659   br i1 %loop_cond, label %loop, label %exit
661 exit:
662   ret i32 %iv
665 ; turn to %iv >=u umax(inv_1, inv_2) and hoist it out of loop.
666 define i32 @test_uge_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {
667 ; CHECK-LABEL: @test_uge_swapped(
668 ; CHECK-NEXT:  entry:
669 ; CHECK-NEXT:    [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
670 ; CHECK-NEXT:    br label [[LOOP:%.*]]
671 ; CHECK:       loop:
672 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
673 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp uge i32 [[IV]], [[INVARIANT_UMAX]]
674 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
675 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
676 ; CHECK:       exit:
677 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
678 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
680 entry:
681   br label %loop
683 loop:
684   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
685   %cmp_1 = icmp ule i32 %inv_1, %iv
686   %cmp_2 = icmp ule i32 %inv_2, %iv
687   %loop_cond = and i1 %cmp_1, %cmp_2
688   %iv.next = add i32 %iv, 1
689   br i1 %loop_cond, label %loop, label %exit
691 exit:
692   ret i32 %iv
695 ; turn to %iv >s smax(inv_1, inv_2) and hoist it out of loop.
696 define i32 @test_sgt_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {
697 ; CHECK-LABEL: @test_sgt_swapped(
698 ; CHECK-NEXT:  entry:
699 ; CHECK-NEXT:    [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
700 ; CHECK-NEXT:    br label [[LOOP:%.*]]
701 ; CHECK:       loop:
702 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
703 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_SMAX]]
704 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
705 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
706 ; CHECK:       exit:
707 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
708 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
710 entry:
711   br label %loop
713 loop:
714   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
715   %cmp_1 = icmp slt i32 %inv_1, %iv
716   %cmp_2 = icmp slt i32 %inv_2, %iv
717   %loop_cond = and i1 %cmp_1, %cmp_2
718   %iv.next = add i32 %iv, 1
719   br i1 %loop_cond, label %loop, label %exit
721 exit:
722   ret i32 %iv
725 ; turn to %iv >=s smax(inv_1, inv_2) and hoist it out of loop.
726 define i32 @test_sge_swapped(i32 %start, i32 %inv_1, i32 %inv_2) {
727 ; CHECK-LABEL: @test_sge_swapped(
728 ; CHECK-NEXT:  entry:
729 ; CHECK-NEXT:    [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
730 ; CHECK-NEXT:    br label [[LOOP:%.*]]
731 ; CHECK:       loop:
732 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
733 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp sge i32 [[IV]], [[INVARIANT_SMAX]]
734 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
735 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
736 ; CHECK:       exit:
737 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
738 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
740 entry:
741   br label %loop
743 loop:
744   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
745   %cmp_1 = icmp sle i32 %inv_1, %iv
746   %cmp_2 = icmp sle i32 %inv_2, %iv
747   %loop_cond = and i1 %cmp_1, %cmp_2
748   %iv.next = add i32 %iv, 1
749   br i1 %loop_cond, label %loop, label %exit
751 exit:
752   ret i32 %iv
755 ; inv_2 needs freeze because hoisted umax would create a new use that didn't exist before.
756 ; Counter-example: %cmp_1 = false, %inv_2 = poison.
757 define i32 @test_logical_and_ult_needs_freeze(i32 %start, i32 %inv_1, i32 %inv_2) {
758 ; CHECK-LABEL: @test_logical_and_ult_needs_freeze(
759 ; CHECK-NEXT:  entry:
760 ; CHECK-NEXT:    [[INV_2_FR:%.*]] = freeze i32 [[INV_2:%.*]]
761 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2_FR]])
762 ; CHECK-NEXT:    br label [[LOOP:%.*]]
763 ; CHECK:       loop:
764 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
765 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]
766 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
767 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
768 ; CHECK:       exit:
769 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
770 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
772 entry:
773   br label %loop
775 loop:
776   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
777   %cmp_1 = icmp ult i32 %iv, %inv_1
778   %cmp_2 = icmp ult i32 %iv, %inv_2
779   %loop_cond = select i1 %cmp_1, i1 %cmp_2, i1 false
780   %iv.next = add i32 %iv, 1
781   br i1 %loop_cond, label %loop, label %exit
783 exit:
784   ret i32 %iv
787 ; turn to %iv <u umin(inv_1, inv_2) and hoist it out of loop.
788 ; https://alive2.llvm.org/ce/z/mhKGtT
789 define i32 @test_logical_and_ult_pos(i32 %start, i32 %inv_1, i32 noundef %inv_2) {
790 ; CHECK-LABEL: @test_logical_and_ult_pos(
791 ; CHECK-NEXT:  entry:
792 ; CHECK-NEXT:    [[INV_2_FR:%.*]] = freeze i32 [[INV_2:%.*]]
793 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2_FR]])
794 ; CHECK-NEXT:    br label [[LOOP:%.*]]
795 ; CHECK:       loop:
796 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
797 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]
798 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
799 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
800 ; CHECK:       exit:
801 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
802 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
804 entry:
805   br label %loop
807 loop:
808   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
809   %cmp_1 = icmp ult i32 %iv, %inv_1
810   %cmp_2 = icmp ult i32 %iv, %inv_2
811   %loop_cond = select i1 %cmp_1, i1 %cmp_2, i1 false
812   %iv.next = add i32 %iv, 1
813   br i1 %loop_cond, label %loop, label %exit
815 exit:
816   ret i32 %iv
819 ; inv_2 needs freeze because hoisted umax would create a new use that didn't exist before.
820 define i32 @test_logical_or_ult_inv_needs_freeze(i32 %start, i32 %inv_1, i32 %inv_2) {
821 ; CHECK-LABEL: @test_logical_or_ult_inv_needs_freeze(
822 ; CHECK-NEXT:  entry:
823 ; CHECK-NEXT:    [[INV_2_FR:%.*]] = freeze i32 [[INV_2:%.*]]
824 ; CHECK-NEXT:    [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2_FR]])
825 ; CHECK-NEXT:    br label [[LOOP:%.*]]
826 ; CHECK:       loop:
827 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
828 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMAX]]
829 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
830 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
831 ; CHECK:       exit:
832 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
833 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
835 entry:
836   br label %loop
838 loop:
839   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
840   %cmp_1 = icmp ult i32 %iv, %inv_1
841   %cmp_2 = icmp ult i32 %iv, %inv_2
842   %loop_cond = select i1 %cmp_1, i1 true, i1 %cmp_2
843   %iv.next = add i32 %iv, 1
844   br i1 %loop_cond, label %loop, label %exit
846 exit:
847   ret i32 %iv
850 ; turn to %iv <u umax(inv_1, inv_2) and hoist it out of loop.
851 ; https://alive2.llvm.org/ce/z/zgyG5N
852 define i32 @test_logical_or_ult_inv_pos(i32 %start, i32 %inv_1, i32 noundef %inv_2) {
853 ; CHECK-LABEL: @test_logical_or_ult_inv_pos(
854 ; CHECK-NEXT:  entry:
855 ; CHECK-NEXT:    [[INV_2_FR:%.*]] = freeze i32 [[INV_2:%.*]]
856 ; CHECK-NEXT:    [[INVARIANT_UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[INV_1:%.*]], i32 [[INV_2_FR]])
857 ; CHECK-NEXT:    br label [[LOOP:%.*]]
858 ; CHECK:       loop:
859 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
860 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMAX]]
861 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
862 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
863 ; CHECK:       exit:
864 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
865 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
867 entry:
868   br label %loop
870 loop:
871   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
872   %cmp_1 = icmp ult i32 %iv, %inv_1
873   %cmp_2 = icmp ult i32 %iv, %inv_2
874   %loop_cond = select i1 %cmp_1, i1 true, i1 %cmp_2
875   %iv.next = add i32 %iv, 1
876   br i1 %loop_cond, label %loop, label %exit
878 exit:
879   ret i32 %iv
882 ; Mismatched predicates, do not optimize.
883 define i32 @test_mismatched_predicates_neg(i32 %start, i32 %inv_1, i32 %inv_2) {
884 ; CHECK-LABEL: @test_mismatched_predicates_neg(
885 ; CHECK-NEXT:  entry:
886 ; CHECK-NEXT:    br label [[LOOP:%.*]]
887 ; CHECK:       loop:
888 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
889 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]
890 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ule i32 [[IV]], [[INV_2:%.*]]
891 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
892 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
893 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
894 ; CHECK:       exit:
895 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
896 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
898 entry:
899   br label %loop
901 loop:
902   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
903   %cmp_1 = icmp ult i32 %iv, %inv_1
904   %cmp_2 = icmp ule i32 %iv, %inv_2
905   %loop_cond = and i1 %cmp_1, %cmp_2
906   %iv.next = add i32 %iv, 1
907   br i1 %loop_cond, label %loop, label %exit
909 exit:
910   ret i32 %iv
913 ; TODO: Turn ule against constant into ult against constant, then do the same as in test_ult.
914 ; https://alive2.llvm.org/ce/z/rucunQ
915 define i32 @test_mismatched_predicates_constant_pos_1(i32 %start, i32 %inv_1, i32 %inv_2) {
916 ; CHECK-LABEL: @test_mismatched_predicates_constant_pos_1(
917 ; CHECK-NEXT:  entry:
918 ; CHECK-NEXT:    br label [[LOOP:%.*]]
919 ; CHECK:       loop:
920 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
921 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]
922 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ule i32 [[IV]], 100
923 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
924 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
925 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
926 ; CHECK:       exit:
927 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
928 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
930 entry:
931   br label %loop
933 loop:
934   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
935   %cmp_1 = icmp ult i32 %iv, %inv_1
936   %cmp_2 = icmp ule i32 %iv, 100
937   %loop_cond = and i1 %cmp_1, %cmp_2
938   %iv.next = add i32 %iv, 1
939   br i1 %loop_cond, label %loop, label %exit
941 exit:
942   ret i32 %iv
945 ; TODO: Turn ult against a constant into ule, then do the same as in test_ule.
946 ; https://alive2.llvm.org/ce/z/-ht-pU
947 define i32 @test_mismatched_predicates_constant_pos_2(i32 %start, i32 %inv_1, i32 %inv_2) {
948 ; CHECK-LABEL: @test_mismatched_predicates_constant_pos_2(
949 ; CHECK-NEXT:  entry:
950 ; CHECK-NEXT:    br label [[LOOP:%.*]]
951 ; CHECK:       loop:
952 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
953 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[IV]], 100
954 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ule i32 [[IV]], [[INV_2:%.*]]
955 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
956 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
957 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
958 ; CHECK:       exit:
959 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
960 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
962 entry:
963   br label %loop
965 loop:
966   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
967   %cmp_1 = icmp ult i32 %iv, 100
968   %cmp_2 = icmp ule i32 %iv, %inv_2
969   %loop_cond = and i1 %cmp_1, %cmp_2
970   %iv.next = add i32 %iv, 1
971   br i1 %loop_cond, label %loop, label %exit
973 exit:
974   ret i32 %iv
977 ; Do not optimize: `ule -1` cannot be turned into `ult 0` because of overflow.
978 ; However, this condition is trivially true anyways, so do not bother about it.
979 define i32 @test_mismatched_predicates_constant_neg(i32 %start, i32 %inv_1, i32 %inv_2) {
980 ; CHECK-LABEL: @test_mismatched_predicates_constant_neg(
981 ; CHECK-NEXT:  entry:
982 ; CHECK-NEXT:    br label [[LOOP:%.*]]
983 ; CHECK:       loop:
984 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
985 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]
986 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ule i32 [[IV]], -1
987 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
988 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
989 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
990 ; CHECK:       exit:
991 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
992 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
994 entry:
995   br label %loop
997 loop:
998   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
999   %cmp_1 = icmp ult i32 %iv, %inv_1
1000   %cmp_2 = icmp ule i32 %iv, -1
1001   %loop_cond = and i1 %cmp_1, %cmp_2
1002   %iv.next = add i32 %iv, 1
1003   br i1 %loop_cond, label %loop, label %exit
1005 exit:
1006   ret i32 %iv
1009 ; Do not optimize: predicate eq.
1010 define i32 @test_eq_neg(i32 %start, i32 %inv_1, i32 %inv_2) {
1011 ; CHECK-LABEL: @test_eq_neg(
1012 ; CHECK-NEXT:  entry:
1013 ; CHECK-NEXT:    br label [[LOOP:%.*]]
1014 ; CHECK:       loop:
1015 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
1016 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp eq i32 [[IV]], [[INV_1:%.*]]
1017 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp eq i32 [[IV]], [[INV_2:%.*]]
1018 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
1019 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
1020 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
1021 ; CHECK:       exit:
1022 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
1023 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
1025 entry:
1026   br label %loop
1028 loop:
1029   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
1030   %cmp_1 = icmp eq i32 %iv, %inv_1
1031   %cmp_2 = icmp eq i32 %iv, %inv_2
1032   %loop_cond = and i1 %cmp_1, %cmp_2
1033   %iv.next = add i32 %iv, 1
1034   br i1 %loop_cond, label %loop, label %exit
1036 exit:
1037   ret i32 %iv
1040 ; Do not optimize: predicate ne.
1041 define i32 @test_ne_neg(i32 %start, i32 %inv_1, i32 %inv_2) {
1042 ; CHECK-LABEL: @test_ne_neg(
1043 ; CHECK-NEXT:  entry:
1044 ; CHECK-NEXT:    br label [[LOOP:%.*]]
1045 ; CHECK:       loop:
1046 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
1047 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ne i32 [[IV]], [[INV_1:%.*]]
1048 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ne i32 [[IV]], [[INV_2:%.*]]
1049 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
1050 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
1051 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
1052 ; CHECK:       exit:
1053 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
1054 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
1056 entry:
1057   br label %loop
1059 loop:
1060   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
1061   %cmp_1 = icmp ne i32 %iv, %inv_1
1062   %cmp_2 = icmp ne i32 %iv, %inv_2
1063   %loop_cond = and i1 %cmp_1, %cmp_2
1064   %iv.next = add i32 %iv, 1
1065   br i1 %loop_cond, label %loop, label %exit
1067 exit:
1068   ret i32 %iv
1071 ; Do not optimize: extra use.
1072 define i32 @test_ult_extra_use_1_neg(i32 %start, i32 %inv_1, i32 %inv_2) {
1073 ; CHECK-LABEL: @test_ult_extra_use_1_neg(
1074 ; CHECK-NEXT:  entry:
1075 ; CHECK-NEXT:    br label [[LOOP:%.*]]
1076 ; CHECK:       loop:
1077 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
1078 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]
1079 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ult i32 [[IV]], [[INV_2:%.*]]
1080 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
1081 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
1082 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
1083 ; CHECK:       exit:
1084 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
1085 ; CHECK-NEXT:    [[CMP_1_LCSSA:%.*]] = phi i1 [ [[CMP_1]], [[LOOP]] ]
1086 ; CHECK-NEXT:    call void @use(i1 [[CMP_1_LCSSA]])
1087 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
1089 entry:
1090   br label %loop
1092 loop:
1093   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
1094   %cmp_1 = icmp ult i32 %iv, %inv_1
1095   %cmp_2 = icmp ult i32 %iv, %inv_2
1096   %loop_cond = and i1 %cmp_1, %cmp_2
1097   %iv.next = add i32 %iv, 1
1098   br i1 %loop_cond, label %loop, label %exit
1100 exit:
1101   call void @use(i1 %cmp_1)
1102   ret i32 %iv
1105 define i32 @test_ult_extra_use_2_neg(i32 %start, i32 %inv_1, i32 %inv_2) {
1106 ; CHECK-LABEL: @test_ult_extra_use_2_neg(
1107 ; CHECK-NEXT:  entry:
1108 ; CHECK-NEXT:    br label [[LOOP:%.*]]
1109 ; CHECK:       loop:
1110 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
1111 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[IV]], [[INV_1:%.*]]
1112 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ult i32 [[IV]], [[INV_2:%.*]]
1113 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
1114 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
1115 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
1116 ; CHECK:       exit:
1117 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
1118 ; CHECK-NEXT:    [[CMP_2_LCSSA:%.*]] = phi i1 [ [[CMP_2]], [[LOOP]] ]
1119 ; CHECK-NEXT:    call void @use(i1 [[CMP_2_LCSSA]])
1120 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
1122 entry:
1123   br label %loop
1125 loop:
1126   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
1127   %cmp_1 = icmp ult i32 %iv, %inv_1
1128   %cmp_2 = icmp ult i32 %iv, %inv_2
1129   %loop_cond = and i1 %cmp_1, %cmp_2
1130   %iv.next = add i32 %iv, 1
1131   br i1 %loop_cond, label %loop, label %exit
1133 exit:
1134   call void @use(i1 %cmp_2)
1135   ret i32 %iv
1138 ; This can be optimized, despite the fact that loop_cond has other uses.
1139 define i32 @test_ult_extra_use_result_pos(i32 %start, i32 %inv_1, i32 %inv_2) {
1140 ; CHECK-LABEL: @test_ult_extra_use_result_pos(
1141 ; CHECK-NEXT:  entry:
1142 ; CHECK-NEXT:    [[INVARIANT_UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
1143 ; CHECK-NEXT:    br label [[LOOP:%.*]]
1144 ; CHECK:       loop:
1145 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
1146 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[IV]], [[INVARIANT_UMIN]]
1147 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
1148 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
1149 ; CHECK:       exit:
1150 ; CHECK-NEXT:    [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
1151 ; CHECK-NEXT:    [[LOOP_COND_LCSSA:%.*]] = phi i1 [ [[LOOP_COND]], [[LOOP]] ]
1152 ; CHECK-NEXT:    call void @use(i1 [[LOOP_COND_LCSSA]])
1153 ; CHECK-NEXT:    ret i32 [[IV_LCSSA]]
1155 entry:
1156   br label %loop
1158 loop:
1159   %iv = phi i32 [%start, %entry], [%iv.next, %loop]
1160   %cmp_1 = icmp ult i32 %iv, %inv_1
1161   %cmp_2 = icmp ult i32 %iv, %inv_2
1162   %loop_cond = and i1 %cmp_1, %cmp_2
1163   %iv.next = add i32 %iv, 1
1164   br i1 %loop_cond, label %loop, label %exit
1166 exit:
1167   call void @use(i1 %loop_cond)
1168   ret i32 %iv
1171 ; Do not optimize: comparison against different variant values.
1172 define i32 @test_ult_different_variants_neg(i32 %start_1, i32 %start_2, i32 %inv_1, i32 %inv_2) {
1173 ; CHECK-LABEL: @test_ult_different_variants_neg(
1174 ; CHECK-NEXT:  entry:
1175 ; CHECK-NEXT:    br label [[LOOP:%.*]]
1176 ; CHECK:       loop:
1177 ; CHECK-NEXT:    [[IV_1:%.*]] = phi i32 [ [[START_1:%.*]], [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[LOOP]] ]
1178 ; CHECK-NEXT:    [[IV_2:%.*]] = phi i32 [ [[START_2:%.*]], [[ENTRY]] ], [ [[IV_2_NEXT:%.*]], [[LOOP]] ]
1179 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[IV_1]], [[INV_1:%.*]]
1180 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ult i32 [[IV_2]], [[INV_2:%.*]]
1181 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
1182 ; CHECK-NEXT:    [[IV_1_NEXT]] = add i32 [[IV_1]], 1
1183 ; CHECK-NEXT:    [[IV_2_NEXT]] = add i32 [[IV_2]], 1
1184 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
1185 ; CHECK:       exit:
1186 ; CHECK-NEXT:    [[IV_1_LCSSA:%.*]] = phi i32 [ [[IV_1]], [[LOOP]] ]
1187 ; CHECK-NEXT:    ret i32 [[IV_1_LCSSA]]
1189 entry:
1190   br label %loop
1192 loop:
1193   %iv_1 = phi i32 [%start_1, %entry], [%iv_1.next, %loop]
1194   %iv_2 = phi i32 [%start_2, %entry], [%iv_2.next, %loop]
1195   %cmp_1 = icmp ult i32 %iv_1, %inv_1
1196   %cmp_2 = icmp ult i32 %iv_2, %inv_2
1197   %loop_cond = and i1 %cmp_1, %cmp_2
1198   %iv_1.next = add i32 %iv_1, 1
1199   %iv_2.next = add i32 %iv_2, 1
1200   br i1 %loop_cond, label %loop, label %exit
1202 exit:
1203   ret i32 %iv_1
1206 ; Do not optimize: one of comparisons is against loop-variant.
1207 define i32 @test_ult_compare_against_variant_neg(i32 %start_1, i32 %start_2, i32 %inv_1, i32 %inv_2) {
1208 ; CHECK-LABEL: @test_ult_compare_against_variant_neg(
1209 ; CHECK-NEXT:  entry:
1210 ; CHECK-NEXT:    br label [[LOOP:%.*]]
1211 ; CHECK:       loop:
1212 ; CHECK-NEXT:    [[IV_1:%.*]] = phi i32 [ [[START_1:%.*]], [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[LOOP]] ]
1213 ; CHECK-NEXT:    [[IV_2:%.*]] = phi i32 [ [[START_2:%.*]], [[ENTRY]] ], [ [[IV_2_NEXT:%.*]], [[LOOP]] ]
1214 ; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[IV_1]], [[INV_1:%.*]]
1215 ; CHECK-NEXT:    [[CMP_2:%.*]] = icmp ult i32 [[IV_1]], [[IV_2]]
1216 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = and i1 [[CMP_1]], [[CMP_2]]
1217 ; CHECK-NEXT:    [[IV_1_NEXT]] = add i32 [[IV_1]], 1
1218 ; CHECK-NEXT:    [[IV_2_NEXT]] = add i32 [[IV_2]], 1
1219 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
1220 ; CHECK:       exit:
1221 ; CHECK-NEXT:    [[IV_1_LCSSA:%.*]] = phi i32 [ [[IV_1]], [[LOOP]] ]
1222 ; CHECK-NEXT:    ret i32 [[IV_1_LCSSA]]
1224 entry:
1225   br label %loop
1227 loop:
1228   %iv_1 = phi i32 [%start_1, %entry], [%iv_1.next, %loop]
1229   %iv_2 = phi i32 [%start_2, %entry], [%iv_2.next, %loop]
1230   %cmp_1 = icmp ult i32 %iv_1, %inv_1
1231   %cmp_2 = icmp ult i32 %iv_1, %iv_2
1232   %loop_cond = and i1 %cmp_1, %cmp_2
1233   %iv_1.next = add i32 %iv_1, 1
1234   %iv_2.next = add i32 %iv_2, 1
1235   br i1 %loop_cond, label %loop, label %exit
1237 exit:
1238   ret i32 %iv_1
1241 declare void @use(i1)