xref: /llvm-project/llvm/test/Transforms/InstSimplify/select-implied.ll (revision 15d5c59280c9943b23a372ca5fdd8a88ce930514)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
3
4; A == B implies A >u B is false.
5
6define 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
15;
16  %cmp1 = icmp eq i32 %a, %b
17  br i1 %cmp1, label %taken, label %end
18
19taken:
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
24
25end:
26  ret void
27}
28
29; If A == B is false then A != B is true.
30
31define 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
40;
41  %cmp1 = icmp eq i32 %a, %b
42  br i1 %cmp1, label %end, label %taken
43
44taken:
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
49
50end:
51  ret void
52}
53
54; A >u 10 implies A >u 10 is true.
55
56define 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
65;
66  %cmp1 = icmp ugt i32 %a, 10
67  br i1 %cmp1, label %taken, label %end
68
69taken:
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
74
75end:
76  ret void
77}
78
79define 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
87;
88  %cmp = icmp eq ptr addrspace(1) %ptr, null
89  br i1 %cmp, label %taken, label %end
90
91taken:
92  %cmp2 = icmp ne ptr addrspace(1) %ptr, null
93  %res = select i1 %cmp2, i8 2, i8 1
94  ret i8 %res
95
96end:
97  ret i8 0
98}
99
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?
103
104define 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
121;
122entry:
123  %0 = call i32 @bar(i32 %len);
124  %cmp = icmp ult i32 %len, 4
125  br i1 %cmp, label %bb, label %b1
126bb:
127  %cond = select i1 %cmp, i32 %len, i32 8
128  %cmp11 = icmp eq i32 %cond, 8
129  br i1 %cmp11, label %b0, label %b1
130
131b0:
132  call void @foo(i32 %len)
133  br label %b1
134
135b1:
136  %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ]
137  br label %ret
138
139ret:
140  call void @foo(i32 %1)
141  ret void
142}
143
144; A >u 10 implies A >u 9 is true.
145
146define 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
155;
156  %cmp1 = icmp ugt i32 %a, 10
157  br i1 %cmp1, label %taken, label %end
158
159taken:
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
164
165end:
166  ret void
167}
168
169declare void @foo(i32)
170declare i32 @bar(i32)
171
172define 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
183;
184entry:
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
189
190tpath:
191  %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false
192  %c = select i1 %cmp3, i32 0, i32 313
193  ret i32 %c
194
195end:
196  ret i32 0
197}
198
199; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true.
200
201define 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
212;
213entry:
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
218
219fpath:
220  %cmp3 = icmp ne i32 %a, 0  ;; <-- implied true
221  %c = select i1 %cmp3, i32 37, i32 0
222  ret i32 %c
223
224end:
225  ret i32 0
226}
227
228; LHS ==> RHS by definition (true -> true)
229
230define 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
239;
240  %cmp1 = icmp eq i32 %a, %b
241  br i1 %cmp1, label %taken, label %end
242
243taken:
244  %c = select i1 %cmp1, i32 10, i32 0
245  call void @foo(i32 %c)
246  br label %end
247
248end:
249  ret void
250}
251
252; LHS ==> RHS by definition (false -> false)
253
254define 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
263;
264  %cmp1 = icmp eq i32 %a, %b
265  br i1 %cmp1, label %end, label %taken
266
267taken:
268  %c = select i1 %cmp1, i32 0, i32 11
269  call void @foo(i32 %c)
270  br label %end
271
272end:
273  ret void
274}
275
276define 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
285;
286  %cmp1 = icmp eq i32 %a, %b
287  br i1 %cmp1, label %end, label %taken
288
289taken:
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
295
296end:
297  ret void
298}
299
300define 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
309;
310  %cmp1 = icmp eq i32 %a, %b
311  br i1 %cmp1, label %end, label %taken
312
313taken:
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
319
320end:
321  ret void
322}
323
324define 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
333;
334  %cmp1 = icmp ne i32 %a, %b
335  br i1 %cmp1, label %taken, label %end
336
337taken:
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
343
344end:
345  ret void
346}
347
348define 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
357;
358  %cmp1 = icmp eq i32 %a, %b
359  br i1 %cmp1, label %end, label %taken
360
361taken:
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
367
368end:
369  ret void
370}
371
372define 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
381;
382  %cmp1 = icmp eq i32 %a, %b
383  br i1 %cmp1, label %end, label %taken
384
385taken:
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
391
392end:
393  ret void
394}
395
396define 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
406;
407  %cmp1 = icmp eq i32 %a, %b
408  br i1 %cmp1, label %end, label %taken
409
410taken:
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
416
417end:
418  ret void
419}
420
421define 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
430;
431  %cmp1 = icmp eq i32 %a, %b
432  br i1 %cmp1, label %end, label %taken
433
434taken:
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
440
441end:
442  ret void
443}
444
445define 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
454;
455  %cmp1 = icmp eq i32 %a, %b
456  br i1 %cmp1, label %end, label %taken
457
458taken:
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
464
465end:
466  ret void
467}
468
469define 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
478;
479  %cmp1 = icmp ne i32 %a, %b
480  br i1 %cmp1, label %taken, label %end
481
482taken:
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
488
489end:
490  ret void
491}
492
493define 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
502;
503  %cmp1 = icmp eq i32 %a, %b
504  br i1 %cmp1, label %end, label %taken
505
506taken:
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
512
513end:
514  ret void
515}
516
517define 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
526;
527  %cmp1 = icmp eq i32 %a, %b
528  br i1 %cmp1, label %end, label %taken
529
530taken:
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
536
537end:
538  ret void
539}
540
541define 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
551;
552  %cmp1 = icmp eq i32 %a, %b
553  br i1 %cmp1, label %end, label %taken
554
555taken:
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
561
562end:
563  ret void
564}
565