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:    [[CMP11:%.*]] = icmp eq i32 [[LEN]], 8
112; CHECK-NEXT:    br i1 [[CMP11]], label [[B0:%.*]], label [[B1]]
113; CHECK:       b0:
114; CHECK-NEXT:    call void @foo(i32 [[LEN]])
115; CHECK-NEXT:    br label [[B1]]
116; CHECK:       b1:
117; CHECK-NEXT:    [[TMP1:%.*]] = phi i32 [ [[LEN]], [[BB]] ], [ undef, [[B0]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
118; CHECK-NEXT:    br label [[RET:%.*]]
119; CHECK:       ret:
120; CHECK-NEXT:    call void @foo(i32 [[TMP1]])
121; CHECK-NEXT:    ret void
122;
123entry:
124  %0 = call i32 @bar(i32 %len);
125  %cmp = icmp ult i32 %len, 4
126  br i1 %cmp, label %bb, label %b1
127bb:
128  %cond = select i1 %cmp, i32 %len, i32 8
129  %cmp11 = icmp eq i32 %cond, 8
130  br i1 %cmp11, label %b0, label %b1
131
132b0:
133  call void @foo(i32 %len)
134  br label %b1
135
136b1:
137  %1 = phi i32 [ %cond, %bb ], [ undef, %b0 ], [ %0, %entry ]
138  br label %ret
139
140ret:
141  call void @foo(i32 %1)
142  ret void
143}
144
145; A >u 10 implies A >u 9 is true.
146
147define void @test5(i32 %a) {
148; CHECK-LABEL: @test5(
149; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i32 [[A:%.*]], 10
150; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
151; CHECK:       taken:
152; CHECK-NEXT:    call void @foo(i32 30)
153; CHECK-NEXT:    br label [[END]]
154; CHECK:       end:
155; CHECK-NEXT:    ret void
156;
157  %cmp1 = icmp ugt i32 %a, 10
158  br i1 %cmp1, label %taken, label %end
159
160taken:
161  %cmp2 = icmp ugt i32 %a, 9
162  %c = select i1 %cmp2, i32 30, i32 0
163  call void @foo(i32 %c)
164  br label %end
165
166end:
167  ret void
168}
169
170declare void @foo(i32)
171declare i32 @bar(i32)
172
173define i32 @test_and(i32 %a, i32 %b) {
174; CHECK-LABEL: @test_and(
175; CHECK-NEXT:  entry:
176; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 0
177; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0
178; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]]
179; CHECK-NEXT:    br i1 [[AND]], label [[TPATH:%.*]], label [[END:%.*]]
180; CHECK:       tpath:
181; CHECK-NEXT:    ret i32 313
182; CHECK:       end:
183; CHECK-NEXT:    ret i32 0
184;
185entry:
186  %cmp1 = icmp ne i32 %a, 0
187  %cmp2 = icmp ne i32 %b, 0
188  %and = and i1 %cmp1, %cmp2
189  br i1 %and, label %tpath, label %end
190
191tpath:
192  %cmp3 = icmp eq i32 %a, 0 ;; <-- implied false
193  %c = select i1 %cmp3, i32 0, i32 313
194  ret i32 %c
195
196end:
197  ret i32 0
198}
199
200; cmp1 and cmp2 are false on the 'fpath' path and thus cmp3 is true.
201
202define i32 @test_or1(i32 %a, i32 %b) {
203; CHECK-LABEL: @test_or1(
204; CHECK-NEXT:  entry:
205; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0
206; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0
207; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]]
208; CHECK-NEXT:    br i1 [[OR]], label [[END:%.*]], label [[FPATH:%.*]]
209; CHECK:       fpath:
210; CHECK-NEXT:    ret i32 37
211; CHECK:       end:
212; CHECK-NEXT:    ret i32 0
213;
214entry:
215  %cmp1 = icmp eq i32 %a, 0
216  %cmp2 = icmp eq i32 %b, 0
217  %or = or i1 %cmp1, %cmp2
218  br i1 %or, label %end, label %fpath
219
220fpath:
221  %cmp3 = icmp ne i32 %a, 0  ;; <-- implied true
222  %c = select i1 %cmp3, i32 37, i32 0
223  ret i32 %c
224
225end:
226  ret i32 0
227}
228
229; LHS ==> RHS by definition (true -> true)
230
231define void @test6(i32 %a, i32 %b) {
232; CHECK-LABEL: @test6(
233; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
234; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
235; CHECK:       taken:
236; CHECK-NEXT:    call void @foo(i32 10)
237; CHECK-NEXT:    br label [[END]]
238; CHECK:       end:
239; CHECK-NEXT:    ret void
240;
241  %cmp1 = icmp eq i32 %a, %b
242  br i1 %cmp1, label %taken, label %end
243
244taken:
245  %c = select i1 %cmp1, i32 10, i32 0
246  call void @foo(i32 %c)
247  br label %end
248
249end:
250  ret void
251}
252
253; LHS ==> RHS by definition (false -> false)
254
255define void @test7(i32 %a, i32 %b) {
256; CHECK-LABEL: @test7(
257; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
258; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
259; CHECK:       taken:
260; CHECK-NEXT:    call void @foo(i32 11)
261; CHECK-NEXT:    br label [[END]]
262; CHECK:       end:
263; CHECK-NEXT:    ret void
264;
265  %cmp1 = icmp eq i32 %a, %b
266  br i1 %cmp1, label %end, label %taken
267
268taken:
269  %c = select i1 %cmp1, i32 0, i32 11
270  call void @foo(i32 %c)
271  br label %end
272
273end:
274  ret void
275}
276
277define void @implies_or(i32 %a, i32 %b, i1 %x) {
278; CHECK-LABEL: @implies_or(
279; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
280; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
281; CHECK:       taken:
282; CHECK-NEXT:    call void @foo(i32 20)
283; CHECK-NEXT:    br label [[END]]
284; CHECK:       end:
285; CHECK-NEXT:    ret void
286;
287  %cmp1 = icmp eq i32 %a, %b
288  br i1 %cmp1, label %end, label %taken
289
290taken:
291  %cmp2 = icmp ne i32 %a, %b
292  %or = or i1 %cmp2, %x
293  %c = select i1 %or, i32 20, i32 0
294  call void @foo(i32 %c)
295  br label %end
296
297end:
298  ret void
299}
300
301define void @implies_or_comm(i32 %a, i32 %b, i1 %x) {
302; CHECK-LABEL: @implies_or_comm(
303; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
304; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
305; CHECK:       taken:
306; CHECK-NEXT:    call void @foo(i32 20)
307; CHECK-NEXT:    br label [[END]]
308; CHECK:       end:
309; CHECK-NEXT:    ret void
310;
311  %cmp1 = icmp eq i32 %a, %b
312  br i1 %cmp1, label %end, label %taken
313
314taken:
315  %cmp2 = icmp ne i32 %a, %b
316  %or = or i1 %x, %cmp2
317  %c = select i1 %or, i32 20, i32 0
318  call void @foo(i32 %c)
319  br label %end
320
321end:
322  ret void
323}
324
325define void @implies_or_branch_comm(i32 %a, i32 %b, i1 %x) {
326; CHECK-LABEL: @implies_or_branch_comm(
327; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
328; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
329; CHECK:       taken:
330; CHECK-NEXT:    call void @foo(i32 20)
331; CHECK-NEXT:    br label [[END]]
332; CHECK:       end:
333; CHECK-NEXT:    ret void
334;
335  %cmp1 = icmp ne i32 %a, %b
336  br i1 %cmp1, label %taken, label %end
337
338taken:
339  %cmp2 = icmp ne i32 %a, %b
340  %or = or i1 %cmp2, %x
341  %c = select i1 %or, i32 20, i32 0
342  call void @foo(i32 %c)
343  br label %end
344
345end:
346  ret void
347}
348
349define void @implies_logical_or(i32 %a, i32 %b, i1 %x) {
350; CHECK-LABEL: @implies_logical_or(
351; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
352; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
353; CHECK:       taken:
354; CHECK-NEXT:    call void @foo(i32 20)
355; CHECK-NEXT:    br label [[END]]
356; CHECK:       end:
357; CHECK-NEXT:    ret void
358;
359  %cmp1 = icmp eq i32 %a, %b
360  br i1 %cmp1, label %end, label %taken
361
362taken:
363  %cmp2 = icmp ne i32 %a, %b
364  %or = select i1 %cmp2, i1 true, i1 %x
365  %c = select i1 %or, i32 20, i32 0
366  call void @foo(i32 %c)
367  br label %end
368
369end:
370  ret void
371}
372
373define void @implies_logical_or_comm(i32 %a, i32 %b, i1 %x) {
374; CHECK-LABEL: @implies_logical_or_comm(
375; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
376; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
377; CHECK:       taken:
378; CHECK-NEXT:    call void @foo(i32 20)
379; CHECK-NEXT:    br label [[END]]
380; CHECK:       end:
381; CHECK-NEXT:    ret void
382;
383  %cmp1 = icmp eq i32 %a, %b
384  br i1 %cmp1, label %end, label %taken
385
386taken:
387  %cmp2 = icmp ne i32 %a, %b
388  %or = select i1 %x, i1 true, i1 %cmp2
389  %c = select i1 %or, i32 20, i32 0
390  call void @foo(i32 %c)
391  br label %end
392
393end:
394  ret void
395}
396
397define void @doesnt_imply_and(i32 %a, i32 %b, i1 %x) {
398; CHECK-LABEL: @doesnt_imply_and(
399; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
400; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
401; CHECK:       taken:
402; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[A]], [[B]]
403; CHECK-NEXT:    [[OR:%.*]] = and i1 [[CMP2]], [[X:%.*]]
404; CHECK-NEXT:    [[C:%.*]] = select i1 [[OR]], i32 20, i32 0
405; CHECK-NEXT:    call void @foo(i32 [[C]])
406; CHECK-NEXT:    br label [[END]]
407; CHECK:       end:
408; CHECK-NEXT:    ret void
409;
410  %cmp1 = icmp eq i32 %a, %b
411  br i1 %cmp1, label %end, label %taken
412
413taken:
414  %cmp2 = icmp ne i32 %a, %b
415  %or = and i1 %cmp2, %x
416  %c = select i1 %or, i32 20, i32 0
417  call void @foo(i32 %c)
418  br label %end
419
420end:
421  ret void
422}
423
424define void @implies_not_and(i32 %a, i32 %b, i1 %x) {
425; CHECK-LABEL: @implies_not_and(
426; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
427; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
428; CHECK:       taken:
429; CHECK-NEXT:    call void @foo(i32 0)
430; CHECK-NEXT:    br label [[END]]
431; CHECK:       end:
432; CHECK-NEXT:    ret void
433;
434  %cmp1 = icmp eq i32 %a, %b
435  br i1 %cmp1, label %end, label %taken
436
437taken:
438  %cmp2 = icmp eq i32 %a, %b
439  %and = and i1 %cmp2, %x
440  %c = select i1 %and, i32 20, i32 0
441  call void @foo(i32 %c)
442  br label %end
443
444end:
445  ret void
446}
447
448define void @implies_not_and_comm(i32 %a, i32 %b, i1 %x) {
449; CHECK-LABEL: @implies_not_and_comm(
450; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
451; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
452; CHECK:       taken:
453; CHECK-NEXT:    call void @foo(i32 0)
454; CHECK-NEXT:    br label [[END]]
455; CHECK:       end:
456; CHECK-NEXT:    ret void
457;
458  %cmp1 = icmp eq i32 %a, %b
459  br i1 %cmp1, label %end, label %taken
460
461taken:
462  %cmp2 = icmp eq i32 %a, %b
463  %and = and i1 %x, %cmp2
464  %c = select i1 %and, i32 20, i32 0
465  call void @foo(i32 %c)
466  br label %end
467
468end:
469  ret void
470}
471
472define void @implies_not_and_branch_comm(i32 %a, i32 %b, i1 %x) {
473; CHECK-LABEL: @implies_not_and_branch_comm(
474; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
475; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
476; CHECK:       taken:
477; CHECK-NEXT:    call void @foo(i32 0)
478; CHECK-NEXT:    br label [[END]]
479; CHECK:       end:
480; CHECK-NEXT:    ret void
481;
482  %cmp1 = icmp ne i32 %a, %b
483  br i1 %cmp1, label %taken, label %end
484
485taken:
486  %cmp2 = icmp eq i32 %a, %b
487  %and = and i1 %cmp2, %x
488  %c = select i1 %and, i32 20, i32 0
489  call void @foo(i32 %c)
490  br label %end
491
492end:
493  ret void
494}
495
496define void @implies_not_logical_and(i32 %a, i32 %b, i1 %x) {
497; CHECK-LABEL: @implies_not_logical_and(
498; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
499; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
500; CHECK:       taken:
501; CHECK-NEXT:    call void @foo(i32 0)
502; CHECK-NEXT:    br label [[END]]
503; CHECK:       end:
504; CHECK-NEXT:    ret void
505;
506  %cmp1 = icmp eq i32 %a, %b
507  br i1 %cmp1, label %end, label %taken
508
509taken:
510  %cmp2 = icmp eq i32 %a, %b
511  %and = select i1 %cmp2, i1 %x, i1 false
512  %c = select i1 %and, i32 20, i32 0
513  call void @foo(i32 %c)
514  br label %end
515
516end:
517  ret void
518}
519
520define void @implies_not_logical_and_comm(i32 %a, i32 %b, i1 %x) {
521; CHECK-LABEL: @implies_not_logical_and_comm(
522; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
523; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
524; CHECK:       taken:
525; CHECK-NEXT:    call void @foo(i32 0)
526; CHECK-NEXT:    br label [[END]]
527; CHECK:       end:
528; CHECK-NEXT:    ret void
529;
530  %cmp1 = icmp eq i32 %a, %b
531  br i1 %cmp1, label %end, label %taken
532
533taken:
534  %cmp2 = icmp eq i32 %a, %b
535  %and = select i1 %x, i1 %cmp2, i1 false
536  %c = select i1 %and, i32 20, i32 0
537  call void @foo(i32 %c)
538  br label %end
539
540end:
541  ret void
542}
543
544define void @doesnt_imply_or(i32 %a, i32 %b, i1 %x) {
545; CHECK-LABEL: @doesnt_imply_or(
546; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
547; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
548; CHECK:       taken:
549; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], [[B]]
550; CHECK-NEXT:    [[AND:%.*]] = or i1 [[CMP2]], [[X:%.*]]
551; CHECK-NEXT:    [[C:%.*]] = select i1 [[AND]], i32 20, i32 0
552; CHECK-NEXT:    call void @foo(i32 [[C]])
553; CHECK-NEXT:    br label [[END]]
554; CHECK:       end:
555; CHECK-NEXT:    ret void
556;
557  %cmp1 = icmp eq i32 %a, %b
558  br i1 %cmp1, label %end, label %taken
559
560taken:
561  %cmp2 = icmp eq i32 %a, %b
562  %and = or i1 %cmp2, %x
563  %c = select i1 %and, i32 20, i32 0
564  call void @foo(i32 %c)
565  br label %end
566
567end:
568  ret void
569}
570