[gn build] Port 077cc3deeebe
[llvm-project.git] / llvm / test / Transforms / InstSimplify / select-implied.ll
blob97448833a3ce503cd4ad244e81a80d4cc3804cc1
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
4 ; A == B implies A >u B is false.
6 define void @test1(i32 %a, i32 %b) {
7 ; CHECK-LABEL: @test1(
8 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
9 ; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
10 ; CHECK:       taken:
11 ; CHECK-NEXT:    call void @foo(i32 10)
12 ; CHECK-NEXT:    br label [[END]]
13 ; CHECK:       end:
14 ; CHECK-NEXT:    ret void
16   %cmp1 = icmp eq i32 %a, %b
17   br i1 %cmp1, label %taken, label %end
19 taken:
20   %cmp2 = icmp ugt i32 %a, %b
21   %c = select i1 %cmp2, i32 0, i32 10
22   call void @foo(i32 %c)
23   br label %end
25 end:
26   ret void
29 ; If A == B is false then A != B is true.
31 define void @test2(i32 %a, i32 %b) {
32 ; CHECK-LABEL: @test2(
33 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
34 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
35 ; CHECK:       taken:
36 ; CHECK-NEXT:    call void @foo(i32 20)
37 ; CHECK-NEXT:    br label [[END]]
38 ; CHECK:       end:
39 ; CHECK-NEXT:    ret void
41   %cmp1 = icmp eq i32 %a, %b
42   br i1 %cmp1, label %end, label %taken
44 taken:
45   %cmp2 = icmp ne i32 %a, %b
46   %c = select i1 %cmp2, i32 20, i32 0
47   call void @foo(i32 %c)
48   br label %end
50 end:
51   ret void
54 ; A >u 10 implies A >u 10 is true.
56 define void @test3(i32 %a) {
57 ; CHECK-LABEL: @test3(
58 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
59 ; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
60 ; CHECK:       taken:
61 ; CHECK-NEXT:    call void @foo(i32 30)
62 ; CHECK-NEXT:    br label [[END]]
63 ; CHECK:       end:
64 ; CHECK-NEXT:    ret void
66   %cmp1 = icmp ugt i32 %a, 10
67   br i1 %cmp1, label %taken, label %end
69 taken:
70   %cmp2 = icmp ugt i32 %a, 10
71   %c = select i1 %cmp2, i32 30, i32 0
72   call void @foo(i32 %c)
73   br label %end
75 end:
76   ret void
79 define i8 @PR23333(ptr addrspace(1) %ptr) {
80 ; CHECK-LABEL: @PR23333(
81 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr addrspace(1) [[PTR:%.*]], null
82 ; CHECK-NEXT:    br i1 [[CMP]], label [[TAKEN:%.*]], label [[END:%.*]]
83 ; CHECK:       taken:
84 ; CHECK-NEXT:    ret i8 1
85 ; CHECK:       end:
86 ; CHECK-NEXT:    ret i8 0
88   %cmp = icmp eq ptr addrspace(1) %ptr, null
89   br i1 %cmp, label %taken, label %end
91 taken:
92   %cmp2 = icmp ne ptr addrspace(1) %ptr, null
93   %res = select i1 %cmp2, i8 2, i8 1
94   ret i8 %res
96 end:
97   ret i8 0
100 ; We know the condition of the select is true based on a dominating condition.
101 ; Therefore, we can replace %cond with %len.
102 ; TODO: len == 8 is known false in bb. This is handled by other passes, but should it be handled here?
104 define void @test4(i32 %len) {
105 ; CHECK-LABEL: @test4(
106 ; CHECK-NEXT:  entry:
107 ; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @bar(i32 [[LEN:%.*]])
108 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[LEN]], 4
109 ; CHECK-NEXT:    br i1 [[CMP]], label [[BB:%.*]], label [[B1:%.*]]
110 ; CHECK:       bb:
111 ; CHECK-NEXT:    br i1 false, label [[B0:%.*]], label [[B1]]
112 ; CHECK:       b0:
113 ; CHECK-NEXT:    call void @foo(i32 [[LEN]])
114 ; CHECK-NEXT:    br label [[B1]]
115 ; CHECK:       b1:
116 ; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[LEN]], [[BB]] ], [ undef, [[B0]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
117 ; CHECK-NEXT:    br label [[RET:%.*]]
118 ; CHECK:       ret:
119 ; CHECK-NEXT:    call void @foo(i32 [[TMP1]])
120 ; CHECK-NEXT:    ret void
122 entry:
123   %0 = call i32 @bar(i32 %len);
124   %cmp = icmp ult i32 %len, 4
125   br i1 %cmp, label %bb, label %b1
127   %cond = select i1 %cmp, i32 %len, i32 8
128   %cmp11 = icmp eq i32 %cond, 8
129   br i1 %cmp11, label %b0, label %b1
132   call void @foo(i32 %len)
133   br label %b1
136   %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ]
137   br label %ret
139 ret:
140   call void @foo(i32 %1)
141   ret void
144 ; A >u 10 implies A >u 9 is true.
146 define void @test5(i32 %a) {
147 ; CHECK-LABEL: @test5(
148 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
149 ; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
150 ; CHECK:       taken:
151 ; CHECK-NEXT:    call void @foo(i32 30)
152 ; CHECK-NEXT:    br label [[END]]
153 ; CHECK:       end:
154 ; CHECK-NEXT:    ret void
156   %cmp1 = icmp ugt i32 %a, 10
157   br i1 %cmp1, label %taken, label %end
159 taken:
160   %cmp2 = icmp ugt i32 %a, 9
161   %c = select i1 %cmp2, i32 30, i32 0
162   call void @foo(i32 %c)
163   br label %end
165 end:
166   ret void
169 declare void @foo(i32)
170 declare i32 @bar(i32)
172 define i32 @test_and(i32 %a, i32 %b) {
173 ; CHECK-LABEL: @test_and(
174 ; CHECK-NEXT:  entry:
175 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0
176 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0
177 ; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
178 ; CHECK-NEXT:    br i1 [[AND]], label [[TPATH:%.*]], label [[END:%.*]]
179 ; CHECK:       tpath:
180 ; CHECK-NEXT:    ret i32 313
181 ; CHECK:       end:
182 ; CHECK-NEXT:    ret i32 0
184 entry:
185   %cmp1 = icmp ne i32 %a, 0
186   %cmp2 = icmp ne i32 %b, 0
187   %and = and i1 %cmp1, %cmp2
188   br i1 %and, label %tpath, label %end
190 tpath:
191   %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false
192   %c = select i1 %cmp3, i32 0, i32 313
193   ret i32 %c
195 end:
196   ret i32 0
199 ; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true.
201 define i32 @test_or1(i32 %a, i32 %b) {
202 ; CHECK-LABEL: @test_or1(
203 ; CHECK-NEXT:  entry:
204 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
205 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
206 ; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
207 ; CHECK-NEXT:    br i1 [[OR]], label [[END:%.*]], label [[FPATH:%.*]]
208 ; CHECK:       fpath:
209 ; CHECK-NEXT:    ret i32 37
210 ; CHECK:       end:
211 ; CHECK-NEXT:    ret i32 0
213 entry:
214   %cmp1 = icmp eq i32 %a, 0
215   %cmp2 = icmp eq i32 %b, 0
216   %or = or i1 %cmp1, %cmp2
217   br i1 %or, label %end, label %fpath
219 fpath:
220   %cmp3 = icmp ne i32 %a, 0  ;; <-- implied true
221   %c = select i1 %cmp3, i32 37, i32 0
222   ret i32 %c
224 end:
225   ret i32 0
228 ; LHS ==> RHS by definition (true -> true)
230 define void @test6(i32 %a, i32 %b) {
231 ; CHECK-LABEL: @test6(
232 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
233 ; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
234 ; CHECK:       taken:
235 ; CHECK-NEXT:    call void @foo(i32 10)
236 ; CHECK-NEXT:    br label [[END]]
237 ; CHECK:       end:
238 ; CHECK-NEXT:    ret void
240   %cmp1 = icmp eq i32 %a, %b
241   br i1 %cmp1, label %taken, label %end
243 taken:
244   %c = select i1 %cmp1, i32 10, i32 0
245   call void @foo(i32 %c)
246   br label %end
248 end:
249   ret void
252 ; LHS ==> RHS by definition (false -> false)
254 define void @test7(i32 %a, i32 %b) {
255 ; CHECK-LABEL: @test7(
256 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
257 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
258 ; CHECK:       taken:
259 ; CHECK-NEXT:    call void @foo(i32 11)
260 ; CHECK-NEXT:    br label [[END]]
261 ; CHECK:       end:
262 ; CHECK-NEXT:    ret void
264   %cmp1 = icmp eq i32 %a, %b
265   br i1 %cmp1, label %end, label %taken
267 taken:
268   %c = select i1 %cmp1, i32 0, i32 11
269   call void @foo(i32 %c)
270   br label %end
272 end:
273   ret void
276 define void @implies_or(i32 %a, i32 %b, i1 %x) {
277 ; CHECK-LABEL: @implies_or(
278 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
279 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
280 ; CHECK:       taken:
281 ; CHECK-NEXT:    call void @foo(i32 20)
282 ; CHECK-NEXT:    br label [[END]]
283 ; CHECK:       end:
284 ; CHECK-NEXT:    ret void
286   %cmp1 = icmp eq i32 %a, %b
287   br i1 %cmp1, label %end, label %taken
289 taken:
290   %cmp2 = icmp ne i32 %a, %b
291   %or = or i1 %cmp2, %x
292   %c = select i1 %or, i32 20, i32 0
293   call void @foo(i32 %c)
294   br label %end
296 end:
297   ret void
300 define void @implies_or_comm(i32 %a, i32 %b, i1 %x) {
301 ; CHECK-LABEL: @implies_or_comm(
302 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
303 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
304 ; CHECK:       taken:
305 ; CHECK-NEXT:    call void @foo(i32 20)
306 ; CHECK-NEXT:    br label [[END]]
307 ; CHECK:       end:
308 ; CHECK-NEXT:    ret void
310   %cmp1 = icmp eq i32 %a, %b
311   br i1 %cmp1, label %end, label %taken
313 taken:
314   %cmp2 = icmp ne i32 %a, %b
315   %or = or i1 %x, %cmp2
316   %c = select i1 %or, i32 20, i32 0
317   call void @foo(i32 %c)
318   br label %end
320 end:
321   ret void
324 define void @implies_or_branch_comm(i32 %a, i32 %b, i1 %x) {
325 ; CHECK-LABEL: @implies_or_branch_comm(
326 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
327 ; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
328 ; CHECK:       taken:
329 ; CHECK-NEXT:    call void @foo(i32 20)
330 ; CHECK-NEXT:    br label [[END]]
331 ; CHECK:       end:
332 ; CHECK-NEXT:    ret void
334   %cmp1 = icmp ne i32 %a, %b
335   br i1 %cmp1, label %taken, label %end
337 taken:
338   %cmp2 = icmp ne i32 %a, %b
339   %or = or i1 %cmp2, %x
340   %c = select i1 %or, i32 20, i32 0
341   call void @foo(i32 %c)
342   br label %end
344 end:
345   ret void
348 define void @implies_logical_or(i32 %a, i32 %b, i1 %x) {
349 ; CHECK-LABEL: @implies_logical_or(
350 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
351 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
352 ; CHECK:       taken:
353 ; CHECK-NEXT:    call void @foo(i32 20)
354 ; CHECK-NEXT:    br label [[END]]
355 ; CHECK:       end:
356 ; CHECK-NEXT:    ret void
358   %cmp1 = icmp eq i32 %a, %b
359   br i1 %cmp1, label %end, label %taken
361 taken:
362   %cmp2 = icmp ne i32 %a, %b
363   %or = select i1 %cmp2, i1 true, i1 %x
364   %c = select i1 %or, i32 20, i32 0
365   call void @foo(i32 %c)
366   br label %end
368 end:
369   ret void
372 define void @implies_logical_or_comm(i32 %a, i32 %b, i1 %x) {
373 ; CHECK-LABEL: @implies_logical_or_comm(
374 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
375 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
376 ; CHECK:       taken:
377 ; CHECK-NEXT:    call void @foo(i32 20)
378 ; CHECK-NEXT:    br label [[END]]
379 ; CHECK:       end:
380 ; CHECK-NEXT:    ret void
382   %cmp1 = icmp eq i32 %a, %b
383   br i1 %cmp1, label %end, label %taken
385 taken:
386   %cmp2 = icmp ne i32 %a, %b
387   %or = select i1 %x, i1 true, i1 %cmp2
388   %c = select i1 %or, i32 20, i32 0
389   call void @foo(i32 %c)
390   br label %end
392 end:
393   ret void
396 define void @doesnt_imply_and(i32 %a, i32 %b, i1 %x) {
397 ; CHECK-LABEL: @doesnt_imply_and(
398 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
399 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
400 ; CHECK:       taken:
401 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[X:%.*]], i32 20, i32 0
402 ; CHECK-NEXT:    call void @foo(i32 [[C]])
403 ; CHECK-NEXT:    br label [[END]]
404 ; CHECK:       end:
405 ; CHECK-NEXT:    ret void
407   %cmp1 = icmp eq i32 %a, %b
408   br i1 %cmp1, label %end, label %taken
410 taken:
411   %cmp2 = icmp ne i32 %a, %b
412   %or = and i1 %cmp2, %x
413   %c = select i1 %or, i32 20, i32 0
414   call void @foo(i32 %c)
415   br label %end
417 end:
418   ret void
421 define void @implies_not_and(i32 %a, i32 %b, i1 %x) {
422 ; CHECK-LABEL: @implies_not_and(
423 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
424 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
425 ; CHECK:       taken:
426 ; CHECK-NEXT:    call void @foo(i32 0)
427 ; CHECK-NEXT:    br label [[END]]
428 ; CHECK:       end:
429 ; CHECK-NEXT:    ret void
431   %cmp1 = icmp eq i32 %a, %b
432   br i1 %cmp1, label %end, label %taken
434 taken:
435   %cmp2 = icmp eq i32 %a, %b
436   %and = and i1 %cmp2, %x
437   %c = select i1 %and, i32 20, i32 0
438   call void @foo(i32 %c)
439   br label %end
441 end:
442   ret void
445 define void @implies_not_and_comm(i32 %a, i32 %b, i1 %x) {
446 ; CHECK-LABEL: @implies_not_and_comm(
447 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
448 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
449 ; CHECK:       taken:
450 ; CHECK-NEXT:    call void @foo(i32 0)
451 ; CHECK-NEXT:    br label [[END]]
452 ; CHECK:       end:
453 ; CHECK-NEXT:    ret void
455   %cmp1 = icmp eq i32 %a, %b
456   br i1 %cmp1, label %end, label %taken
458 taken:
459   %cmp2 = icmp eq i32 %a, %b
460   %and = and i1 %x, %cmp2
461   %c = select i1 %and, i32 20, i32 0
462   call void @foo(i32 %c)
463   br label %end
465 end:
466   ret void
469 define void @implies_not_and_branch_comm(i32 %a, i32 %b, i1 %x) {
470 ; CHECK-LABEL: @implies_not_and_branch_comm(
471 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
472 ; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
473 ; CHECK:       taken:
474 ; CHECK-NEXT:    call void @foo(i32 0)
475 ; CHECK-NEXT:    br label [[END]]
476 ; CHECK:       end:
477 ; CHECK-NEXT:    ret void
479   %cmp1 = icmp ne i32 %a, %b
480   br i1 %cmp1, label %taken, label %end
482 taken:
483   %cmp2 = icmp eq i32 %a, %b
484   %and = and i1 %cmp2, %x
485   %c = select i1 %and, i32 20, i32 0
486   call void @foo(i32 %c)
487   br label %end
489 end:
490   ret void
493 define void @implies_not_logical_and(i32 %a, i32 %b, i1 %x) {
494 ; CHECK-LABEL: @implies_not_logical_and(
495 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
496 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
497 ; CHECK:       taken:
498 ; CHECK-NEXT:    call void @foo(i32 0)
499 ; CHECK-NEXT:    br label [[END]]
500 ; CHECK:       end:
501 ; CHECK-NEXT:    ret void
503   %cmp1 = icmp eq i32 %a, %b
504   br i1 %cmp1, label %end, label %taken
506 taken:
507   %cmp2 = icmp eq i32 %a, %b
508   %and = select i1 %cmp2, i1 %x, i1 false
509   %c = select i1 %and, i32 20, i32 0
510   call void @foo(i32 %c)
511   br label %end
513 end:
514   ret void
517 define void @implies_not_logical_and_comm(i32 %a, i32 %b, i1 %x) {
518 ; CHECK-LABEL: @implies_not_logical_and_comm(
519 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
520 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
521 ; CHECK:       taken:
522 ; CHECK-NEXT:    call void @foo(i32 0)
523 ; CHECK-NEXT:    br label [[END]]
524 ; CHECK:       end:
525 ; CHECK-NEXT:    ret void
527   %cmp1 = icmp eq i32 %a, %b
528   br i1 %cmp1, label %end, label %taken
530 taken:
531   %cmp2 = icmp eq i32 %a, %b
532   %and = select i1 %x, i1 %cmp2, i1 false
533   %c = select i1 %and, i32 20, i32 0
534   call void @foo(i32 %c)
535   br label %end
537 end:
538   ret void
541 define void @doesnt_imply_or(i32 %a, i32 %b, i1 %x) {
542 ; CHECK-LABEL: @doesnt_imply_or(
543 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
544 ; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
545 ; CHECK:       taken:
546 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[X:%.*]], i32 20, i32 0
547 ; CHECK-NEXT:    call void @foo(i32 [[C]])
548 ; CHECK-NEXT:    br label [[END]]
549 ; CHECK:       end:
550 ; CHECK-NEXT:    ret void
552   %cmp1 = icmp eq i32 %a, %b
553   br i1 %cmp1, label %end, label %taken
555 taken:
556   %cmp2 = icmp eq i32 %a, %b
557   %and = or i1 %cmp2, %x
558   %c = select i1 %and, i32 20, i32 0
559   call void @foo(i32 %c)
560   br label %end
562 end:
563   ret void