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(i8 addrspace(1)* %ptr) {
80; CHECK-LABEL: @PR23333(
81; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 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 i8 addrspace(1)* %ptr, null
89  br i1 %cmp, label %taken, label %end
90
91taken:
92  %cmp2 = icmp ne i8 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:    [[CMP2:%.*]] = icmp ne i32 [[A]], [[B]]
283; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP2]], [[X:%.*]]
284; CHECK-NEXT:    [[C:%.*]] = select i1 [[OR]], i32 20, i32 0
285; CHECK-NEXT:    call void @foo(i32 [[C]])
286; CHECK-NEXT:    br label [[END]]
287; CHECK:       end:
288; CHECK-NEXT:    ret void
289;
290  %cmp1 = icmp eq i32 %a, %b
291  br i1 %cmp1, label %end, label %taken
292
293taken:
294  %cmp2 = icmp ne i32 %a, %b
295  %or = or i1 %cmp2, %x
296  %c = select i1 %or, i32 20, i32 0
297  call void @foo(i32 %c)
298  br label %end
299
300end:
301  ret void
302}
303
304define void @implies_or_comm(i32 %a, i32 %b, i1 %x) {
305; CHECK-LABEL: @implies_or_comm(
306; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
307; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
308; CHECK:       taken:
309; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[A]], [[B]]
310; CHECK-NEXT:    [[OR:%.*]] = or i1 [[X:%.*]], [[CMP2]]
311; CHECK-NEXT:    [[C:%.*]] = select i1 [[OR]], i32 20, i32 0
312; CHECK-NEXT:    call void @foo(i32 [[C]])
313; CHECK-NEXT:    br label [[END]]
314; CHECK:       end:
315; CHECK-NEXT:    ret void
316;
317  %cmp1 = icmp eq i32 %a, %b
318  br i1 %cmp1, label %end, label %taken
319
320taken:
321  %cmp2 = icmp ne i32 %a, %b
322  %or = or i1 %x, %cmp2
323  %c = select i1 %or, i32 20, i32 0
324  call void @foo(i32 %c)
325  br label %end
326
327end:
328  ret void
329}
330
331define void @implies_or_branch_comm(i32 %a, i32 %b, i1 %x) {
332; CHECK-LABEL: @implies_or_branch_comm(
333; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
334; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
335; CHECK:       taken:
336; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[A]], [[B]]
337; CHECK-NEXT:    [[OR:%.*]] = or i1 [[CMP2]], [[X:%.*]]
338; CHECK-NEXT:    [[C:%.*]] = select i1 [[OR]], i32 20, i32 0
339; CHECK-NEXT:    call void @foo(i32 [[C]])
340; CHECK-NEXT:    br label [[END]]
341; CHECK:       end:
342; CHECK-NEXT:    ret void
343;
344  %cmp1 = icmp ne i32 %a, %b
345  br i1 %cmp1, label %taken, label %end
346
347taken:
348  %cmp2 = icmp ne i32 %a, %b
349  %or = or i1 %cmp2, %x
350  %c = select i1 %or, i32 20, i32 0
351  call void @foo(i32 %c)
352  br label %end
353
354end:
355  ret void
356}
357
358define void @implies_logical_or(i32 %a, i32 %b, i1 %x) {
359; CHECK-LABEL: @implies_logical_or(
360; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
361; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
362; CHECK:       taken:
363; CHECK-NEXT:    call void @foo(i32 20)
364; CHECK-NEXT:    br label [[END]]
365; CHECK:       end:
366; CHECK-NEXT:    ret void
367;
368  %cmp1 = icmp eq i32 %a, %b
369  br i1 %cmp1, label %end, label %taken
370
371taken:
372  %cmp2 = icmp ne i32 %a, %b
373  %or = select i1 %cmp2, i1 true, i1 %x
374  %c = select i1 %or, i32 20, i32 0
375  call void @foo(i32 %c)
376  br label %end
377
378end:
379  ret void
380}
381
382define void @implies_logical_or_comm(i32 %a, i32 %b, i1 %x) {
383; CHECK-LABEL: @implies_logical_or_comm(
384; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
385; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
386; CHECK:       taken:
387; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[A]], [[B]]
388; CHECK-NEXT:    [[OR:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[CMP2]]
389; CHECK-NEXT:    [[C:%.*]] = select i1 [[OR]], i32 20, i32 0
390; CHECK-NEXT:    call void @foo(i32 [[C]])
391; CHECK-NEXT:    br label [[END]]
392; CHECK:       end:
393; CHECK-NEXT:    ret void
394;
395  %cmp1 = icmp eq i32 %a, %b
396  br i1 %cmp1, label %end, label %taken
397
398taken:
399  %cmp2 = icmp ne i32 %a, %b
400  %or = select i1 %x, i1 true, i1 %cmp2
401  %c = select i1 %or, i32 20, i32 0
402  call void @foo(i32 %c)
403  br label %end
404
405end:
406  ret void
407}
408
409define void @doesnt_imply_and(i32 %a, i32 %b, i1 %x) {
410; CHECK-LABEL: @doesnt_imply_and(
411; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
412; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
413; CHECK:       taken:
414; CHECK-NEXT:    [[CMP2:%.*]] = icmp ne i32 [[A]], [[B]]
415; CHECK-NEXT:    [[OR:%.*]] = and i1 [[CMP2]], [[X:%.*]]
416; CHECK-NEXT:    [[C:%.*]] = select i1 [[OR]], i32 20, i32 0
417; CHECK-NEXT:    call void @foo(i32 [[C]])
418; CHECK-NEXT:    br label [[END]]
419; CHECK:       end:
420; CHECK-NEXT:    ret void
421;
422  %cmp1 = icmp eq i32 %a, %b
423  br i1 %cmp1, label %end, label %taken
424
425taken:
426  %cmp2 = icmp ne i32 %a, %b
427  %or = and i1 %cmp2, %x
428  %c = select i1 %or, i32 20, i32 0
429  call void @foo(i32 %c)
430  br label %end
431
432end:
433  ret void
434}
435
436define void @implies_not_and(i32 %a, i32 %b, i1 %x) {
437; CHECK-LABEL: @implies_not_and(
438; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
439; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
440; CHECK:       taken:
441; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], [[B]]
442; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP2]], [[X:%.*]]
443; CHECK-NEXT:    [[C:%.*]] = select i1 [[AND]], i32 20, i32 0
444; CHECK-NEXT:    call void @foo(i32 [[C]])
445; CHECK-NEXT:    br label [[END]]
446; CHECK:       end:
447; CHECK-NEXT:    ret void
448;
449  %cmp1 = icmp eq i32 %a, %b
450  br i1 %cmp1, label %end, label %taken
451
452taken:
453  %cmp2 = icmp eq i32 %a, %b
454  %and = and i1 %cmp2, %x
455  %c = select i1 %and, i32 20, i32 0
456  call void @foo(i32 %c)
457  br label %end
458
459end:
460  ret void
461}
462
463define void @implies_not_and_comm(i32 %a, i32 %b, i1 %x) {
464; CHECK-LABEL: @implies_not_and_comm(
465; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
466; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
467; CHECK:       taken:
468; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], [[B]]
469; CHECK-NEXT:    [[AND:%.*]] = and i1 [[X:%.*]], [[CMP2]]
470; CHECK-NEXT:    [[C:%.*]] = select i1 [[AND]], i32 20, i32 0
471; CHECK-NEXT:    call void @foo(i32 [[C]])
472; CHECK-NEXT:    br label [[END]]
473; CHECK:       end:
474; CHECK-NEXT:    ret void
475;
476  %cmp1 = icmp eq i32 %a, %b
477  br i1 %cmp1, label %end, label %taken
478
479taken:
480  %cmp2 = icmp eq i32 %a, %b
481  %and = and i1 %x, %cmp2
482  %c = select i1 %and, i32 20, i32 0
483  call void @foo(i32 %c)
484  br label %end
485
486end:
487  ret void
488}
489
490define void @implies_not_and_branch_comm(i32 %a, i32 %b, i1 %x) {
491; CHECK-LABEL: @implies_not_and_branch_comm(
492; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
493; CHECK-NEXT:    br i1 [[CMP1]], label [[TAKEN:%.*]], label [[END:%.*]]
494; CHECK:       taken:
495; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], [[B]]
496; CHECK-NEXT:    [[AND:%.*]] = and i1 [[CMP2]], [[X:%.*]]
497; CHECK-NEXT:    [[C:%.*]] = select i1 [[AND]], i32 20, i32 0
498; CHECK-NEXT:    call void @foo(i32 [[C]])
499; CHECK-NEXT:    br label [[END]]
500; CHECK:       end:
501; CHECK-NEXT:    ret void
502;
503  %cmp1 = icmp ne i32 %a, %b
504  br i1 %cmp1, label %taken, label %end
505
506taken:
507  %cmp2 = icmp eq i32 %a, %b
508  %and = and i1 %cmp2, %x
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(i32 %a, i32 %b, i1 %x) {
518; CHECK-LABEL: @implies_not_logical_and(
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 %cmp2, i1 %x, 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 @implies_not_logical_and_comm(i32 %a, i32 %b, i1 %x) {
542; CHECK-LABEL: @implies_not_logical_and_comm(
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:    [[CMP2:%.*]] = icmp eq i32 [[A]], [[B]]
547; CHECK-NEXT:    [[AND:%.*]] = select i1 [[X:%.*]], i1 [[CMP2]], i1 false
548; CHECK-NEXT:    [[C:%.*]] = select i1 [[AND]], i32 20, i32 0
549; CHECK-NEXT:    call void @foo(i32 [[C]])
550; CHECK-NEXT:    br label [[END]]
551; CHECK:       end:
552; CHECK-NEXT:    ret void
553;
554  %cmp1 = icmp eq i32 %a, %b
555  br i1 %cmp1, label %end, label %taken
556
557taken:
558  %cmp2 = icmp eq i32 %a, %b
559  %and = select i1 %x, i1 %cmp2, i1 false
560  %c = select i1 %and, i32 20, i32 0
561  call void @foo(i32 %c)
562  br label %end
563
564end:
565  ret void
566}
567
568define void @doesnt_imply_or(i32 %a, i32 %b, i1 %x) {
569; CHECK-LABEL: @doesnt_imply_or(
570; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
571; CHECK-NEXT:    br i1 [[CMP1]], label [[END:%.*]], label [[TAKEN:%.*]]
572; CHECK:       taken:
573; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[A]], [[B]]
574; CHECK-NEXT:    [[AND:%.*]] = or i1 [[CMP2]], [[X:%.*]]
575; CHECK-NEXT:    [[C:%.*]] = select i1 [[AND]], i32 20, i32 0
576; CHECK-NEXT:    call void @foo(i32 [[C]])
577; CHECK-NEXT:    br label [[END]]
578; CHECK:       end:
579; CHECK-NEXT:    ret void
580;
581  %cmp1 = icmp eq i32 %a, %b
582  br i1 %cmp1, label %end, label %taken
583
584taken:
585  %cmp2 = icmp eq i32 %a, %b
586  %and = or i1 %cmp2, %x
587  %c = select i1 %and, i32 20, i32 0
588  call void @foo(i32 %c)
589  br label %end
590
591end:
592  ret void
593}
594