xref: /llvm-project/llvm/test/Transforms/ConstraintElimination/and-implied-by-operands.ll (revision 0f0c0c36e3e90b4cb04004ed9c930f3863a36422)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
3
4define i1 @test_second_and_condition_implied_by_first(i8 %x) {
5; CHECK-LABEL: @test_second_and_condition_implied_by_first(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
8; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
9; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], true
10; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
11; CHECK:       then:
12; CHECK-NEXT:    ret i1 false
13; CHECK:       else:
14; CHECK-NEXT:    ret i1 true
15;
16entry:
17  %c.1 = icmp ugt i8 %x, 10
18  %t.1 = icmp ugt i8 %x, 5
19  %and = and i1 %c.1, %t.1
20  br i1 %and, label %then, label %else
21
22then:
23  ret i1 0
24
25else:
26  ret i1 1
27}
28
29define i1 @test_first_and_condition_implied_by_second_ops(i8 %x) {
30; CHECK-LABEL: @test_first_and_condition_implied_by_second_ops(
31; CHECK-NEXT:  entry:
32; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
33; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
34; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[C_1]]
35; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
36; CHECK:       then:
37; CHECK-NEXT:    ret i1 false
38; CHECK:       else:
39; CHECK-NEXT:    ret i1 true
40;
41entry:
42  %c.1 = icmp ugt i8 %x, 10
43  %t.1 = icmp ugt i8 %x, 5
44  %and = and i1 %t.1, %c.1
45  br i1 %and, label %then, label %else
46
47then:
48  ret i1 0
49
50else:
51  ret i1 1
52}
53
54define i1 @test_second_and_condition_implied_by_first_select_form(i8 %x) {
55; CHECK-LABEL: @test_second_and_condition_implied_by_first_select_form(
56; CHECK-NEXT:  entry:
57; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
58; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
59; CHECK-NEXT:    [[AND:%.*]] = select i1 [[C_1]], i1 true, i1 false
60; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
61; CHECK:       then:
62; CHECK-NEXT:    ret i1 false
63; CHECK:       else:
64; CHECK-NEXT:    ret i1 true
65;
66entry:
67  %c.1 = icmp ugt i8 %x, 10
68  %t.1 = icmp ugt i8 %x, 5
69  %and = select i1 %c.1, i1 %t.1, i1 false
70  br i1 %and, label %then, label %else
71
72then:
73  ret i1 0
74
75else:
76  ret i1 1
77}
78
79define i1 @test_first_and_condition_implied_by_second_select_form(i8 %x) {
80; CHECK-LABEL: @test_first_and_condition_implied_by_second_select_form(
81; CHECK-NEXT:  entry:
82; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
83; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
84; CHECK-NEXT:    [[AND:%.*]] = select i1 [[T_1]], i1 [[C_1]], i1 false
85; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
86; CHECK:       then:
87; CHECK-NEXT:    ret i1 false
88; CHECK:       else:
89; CHECK-NEXT:    ret i1 true
90;
91entry:
92  %c.1 = icmp ugt i8 %x, 10
93  %t.1 = icmp ugt i8 %x, 5
94  %and = select i1 %t.1, i1 %c.1, i1 false
95  br i1 %and, label %then, label %else
96
97then:
98  ret i1 0
99
100else:
101  ret i1 1
102}
103
104define i1 @test_same_cond_for_and(i8 %x) {
105; CHECK-LABEL: @test_same_cond_for_and(
106; CHECK-NEXT:  entry:
107; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
108; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[C_1]]
109; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
110; CHECK:       then:
111; CHECK-NEXT:    ret i1 false
112; CHECK:       else:
113; CHECK-NEXT:    ret i1 true
114;
115entry:
116  %c.1 = icmp ugt i8 %x, 10
117  %and = and i1 %c.1, %c.1
118  br i1 %and, label %then, label %else
119
120then:
121  ret i1 0
122
123else:
124  ret i1 1
125}
126
127define i1 @test_same_cond_for_and_select_form(i8 %x) {
128; CHECK-LABEL: @test_same_cond_for_and_select_form(
129; CHECK-NEXT:  entry:
130; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
131; CHECK-NEXT:    [[AND:%.*]] = select i1 [[C_1]], i1 [[C_1]], i1 false
132; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
133; CHECK:       then:
134; CHECK-NEXT:    ret i1 false
135; CHECK:       else:
136; CHECK-NEXT:    ret i1 true
137;
138entry:
139  %c.1 = icmp ugt i8 %x, 10
140  %and = select i1 %c.1, i1 %c.1, i1 false
141  br i1 %and, label %then, label %else
142
143then:
144  ret i1 0
145
146else:
147  ret i1 1
148}
149
150define i1 @test_second_and_condition_not_implied_by_first(i8 %x) {
151; CHECK-LABEL: @test_second_and_condition_not_implied_by_first(
152; CHECK-NEXT:  entry:
153; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
154; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt i8 [[X]], 5
155; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[C_1]]
156; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
157; CHECK:       then:
158; CHECK-NEXT:    ret i1 false
159; CHECK:       else:
160; CHECK-NEXT:    ret i1 true
161;
162entry:
163  %c.1 = icmp ugt i8 %x, 10
164  %c.2 = icmp ugt i8 %x, 5
165  %and = and i1 %c.2, %c.1
166  br i1 %and, label %then, label %else
167
168then:
169  ret i1 0
170
171else:
172  ret i1 1
173}
174
175define i1 @test_remove_variables(i1 %c, ptr %A, i64 %B, ptr %C) {
176; CHECK-LABEL: @test_remove_variables(
177; CHECK-NEXT:  entry:
178; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN_1:%.*]], label [[EXIT:%.*]]
179; CHECK:       then.1:
180; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[C:%.*]], align 8
181; CHECK-NEXT:    [[C_1:%.*]] = icmp ult ptr [[TMP0]], [[A:%.*]]
182; CHECK-NEXT:    br i1 [[C_1]], label [[THEN_2:%.*]], label [[ELSE_2:%.*]]
183; CHECK:       then.2:
184; CHECK-NEXT:    [[C_3:%.*]] = icmp sgt i64 [[B:%.*]], 0
185; CHECK-NEXT:    [[AND:%.*]] = and i1 true, [[C_3]]
186; CHECK-NEXT:    ret i1 [[AND]]
187; CHECK:       else.2:
188; CHECK-NEXT:    ret i1 false
189; CHECK:       exit:
190; CHECK-NEXT:    ret i1 true
191;
192entry:
193  br i1 %c, label %then.1, label %exit
194
195then.1:
196  %0 = load ptr, ptr %C, align 8
197  %c.1 = icmp ult ptr %0, %A
198  br i1 %c.1, label %then.2, label %else.2
199
200then.2:
201  %c.2 = icmp ne ptr %A, null
202  %c.3 = icmp sgt i64 %B, 0
203  %and = and i1 %c.2, %c.3
204  ret i1 %and
205
206else.2:
207  ret i1 0
208
209exit:
210  %t = icmp eq ptr null, null
211  ret i1 %t
212}
213
214define i1 @test_and_op_0_simplified(i32 %v) {
215; CHECK-LABEL: @test_and_op_0_simplified(
216; CHECK-NEXT:  entry:
217; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i32 [[V:%.*]], 0
218; CHECK-NEXT:    [[AND:%.*]] = and i1 false, [[C_1]]
219; CHECK-NEXT:    ret i1 [[AND]]
220;
221entry:
222  %c.1 = icmp sgt i32 %v, 0
223  %t.1 = icmp sgt i32 0, 0
224  %and = and i1 %t.1, %c.1
225  ret i1 %and
226}
227
228define i1 @test_and_op_1_simplified(i32 %v) {
229; CHECK-LABEL: @test_and_op_1_simplified(
230; CHECK-NEXT:  entry:
231; CHECK-NEXT:    [[C_1:%.*]] = icmp sgt i32 [[V:%.*]], 0
232; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], false
233; CHECK-NEXT:    ret i1 [[AND]]
234;
235entry:
236  %c.1 = icmp sgt i32 %v, 0
237  %t.1 = icmp sgt i32 0, 0
238  %and = and i1 %c.1, %t.1
239  ret i1 %and
240}
241
242define i1 @and_select_not_used_for_branch(i32 %x, i32 %y,i32 %z) {
243; CHECK-LABEL: @and_select_not_used_for_branch(
244; CHECK-NEXT:  entry:
245; CHECK-NEXT:    [[C_1:%.*]] = icmp ne i32 [[X:%.*]], 0
246; CHECK-NEXT:    [[C_2:%.*]] = icmp ne i32 [[Y:%.*]], 0
247; CHECK-NEXT:    [[C_3:%.*]] = icmp eq i32 [[X]], 16
248; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
249; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[EXIT:%.*]]
250; CHECK:       then:
251; CHECK-NEXT:    [[C_4:%.*]] = icmp eq i32 [[Z:%.*]], 0
252; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[C_4]], i1 true, i1 false
253; CHECK-NEXT:    br label [[EXIT]]
254; CHECK:       exit:
255; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ [[C_1]], [[ENTRY:%.*]] ], [ [[SEL]], [[THEN]] ]
256; CHECK-NEXT:    ret i1 [[RES]]
257;
258entry:
259  %c.1 = icmp ne i32 %x, 0
260  %c.2 = icmp ne i32 %y, 0
261  %c.3 = icmp eq i32 %x, 16
262  %and = and i1 %c.2, %c.3
263  br i1 %and, label %then, label %exit
264
265then:
266  %c.4 = icmp eq i32 %z, 0
267  %sel = select i1 %c.4, i1 %c.1, i1 false
268  br label %exit
269
270exit:
271  %res = phi i1 [ %c.1, %entry ], [ %sel, %then ]
272  ret i1 %res
273}
274
275define i1 @and_select_scope_limited(i32 %x, i32 %y, i32 %z) {
276; CHECK-LABEL: @and_select_scope_limited(
277; CHECK-NEXT:  entry:
278; CHECK-NEXT:    [[C_1:%.*]] = icmp ne i32 [[X:%.*]], 0
279; CHECK-NEXT:    [[C_2:%.*]] = icmp ne i32 [[Y:%.*]], 0
280; CHECK-NEXT:    [[C_3:%.*]] = icmp eq i32 [[X]], 16
281; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
282; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[EXIT:%.*]]
283; CHECK:       then:
284; CHECK-NEXT:    [[C_4:%.*]] = icmp eq i32 [[Z:%.*]], 0
285; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[C_4]], i1 true, i1 false
286; CHECK-NEXT:    br i1 [[SEL]], label [[T_1:%.*]], label [[EXIT]]
287; CHECK:       t.1:
288; CHECK-NEXT:    ret i1 true
289; CHECK:       exit:
290; CHECK-NEXT:    [[RES:%.*]] = phi i1 [ [[C_1]], [[ENTRY:%.*]] ], [ [[SEL]], [[THEN]] ]
291; CHECK-NEXT:    ret i1 [[RES]]
292;
293entry:
294  %c.1 = icmp ne i32 %x, 0
295  %c.2 = icmp ne i32 %y, 0
296  %c.3 = icmp eq i32 %x, 16
297  %and = and i1 %c.2, %c.3
298  br i1 %and, label %then, label %exit
299
300then:
301  %c.4 = icmp eq i32 %z, 0
302  %sel = select i1 %c.4, i1 %c.1, i1 false
303  br i1 %sel, label %t.1, label %exit
304
305t.1:
306  ret i1 %c.1
307
308exit:
309  %res = phi i1 [ %c.1, %entry ], [ %sel, %then ]
310  ret i1 %res
311}
312
313declare void @use(ptr)
314
315define void @test_monotonic_ptr_iv_inc_1_eq_to_uge(ptr %start, i16 %len) {
316; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge(
317; CHECK-NEXT:  entry:
318; CHECK-NEXT:    [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
319; CHECK-NEXT:    br label [[LOOP_PH:%.*]]
320; CHECK:       loop.ph:
321; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
322; CHECK:       loop.header:
323; CHECK-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
324; CHECK-NEXT:    [[LEN_NEG:%.*]] = icmp sgt i16 [[LEN]], 0
325; CHECK-NEXT:    [[C:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
326; CHECK-NEXT:    [[AND_0:%.*]] = and i1 [[LEN_NEG]], [[C]]
327; CHECK-NEXT:    br i1 [[AND_0]], label [[FOR_BODY:%.*]], label [[EXIT:%.*]]
328; CHECK:       for.body:
329; CHECK-NEXT:    [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
330; CHECK-NEXT:    [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
331; CHECK-NEXT:    [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
332; CHECK-NEXT:    br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
333; CHECK:       loop.latch:
334; CHECK-NEXT:    call void @use(ptr [[PTR_IV]])
335; CHECK-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
336; CHECK-NEXT:    br label [[LOOP_HEADER]]
337; CHECK:       exit:
338; CHECK-NEXT:    ret void
339;
340entry:
341  %upper = getelementptr inbounds i32, ptr %start, i16 %len
342  br label %loop.ph
343
344loop.ph:
345  br label %loop.header
346
347loop.header:
348  %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
349  %len.neg = icmp sgt i16 %len, 0
350  %c = icmp ne ptr %ptr.iv, %upper
351  %and.0 = and i1 %len.neg, %c
352  br i1 %and.0, label %for.body, label %exit
353
354for.body:
355  %t.1 = icmp uge ptr %ptr.iv, %start
356  %t.2 = icmp ult ptr %ptr.iv, %upper
357  %and = and i1 %t.1, %t.2
358  br i1 %and, label %loop.latch, label %exit
359
360loop.latch:
361  call void @use(ptr %ptr.iv)
362  %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
363  br label %loop.header
364
365exit:
366  ret void
367}
368
369define i1 @test_and_used_in_false_branch(i8 %x) {
370; CHECK-LABEL: @test_and_used_in_false_branch(
371; CHECK-NEXT:  entry:
372; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
373; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
374; CHECK-NEXT:    [[AND:%.*]] = and i1 [[C_1]], true
375; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
376; CHECK:       then:
377; CHECK-NEXT:    ret i1 true
378; CHECK:       else:
379; CHECK-NEXT:    ret i1 [[T_1]]
380;
381
382entry:
383  %c.1 = icmp ugt i8 %x, 10
384  %t.1 = icmp ugt i8 %x, 5
385  %and = and i1 %c.1, %t.1
386  br i1 %and, label %then, label %else
387
388then:
389  ret i1 %t.1
390
391else:
392  ret i1 %t.1
393}
394
395define i1 @test_or_used_in_false_branch(i8 %x) {
396; CHECK-LABEL: @test_or_used_in_false_branch(
397; CHECK-NEXT:  entry:
398; CHECK-NEXT:    [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
399; CHECK-NEXT:    [[T_1:%.*]] = icmp ule i8 [[X]], 5
400; CHECK-NEXT:    [[AND:%.*]] = or i1 [[C_1]], false
401; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
402; CHECK:       then:
403; CHECK-NEXT:    ret i1 [[T_1]]
404; CHECK:       else:
405; CHECK-NEXT:    ret i1 false
406;
407
408entry:
409  %c.1 = icmp ule i8 %x, 10
410  %t.1 = icmp ule i8 %x, 5
411  %and = or i1 %c.1, %t.1
412  br i1 %and, label %then, label %else
413
414then:
415  ret i1 %t.1
416
417else:
418  ret i1 %t.1
419}
420
421define i1 @test_or_used_in_false_branch2(i8 %x) {
422; CHECK-LABEL: @test_or_used_in_false_branch2(
423; CHECK-NEXT:  entry:
424; CHECK-NEXT:    [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
425; CHECK-NEXT:    [[T_1:%.*]] = icmp ugt i8 [[X]], 5
426; CHECK-NEXT:    [[AND:%.*]] = or i1 false, [[T_1]]
427; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
428; CHECK:       then:
429; CHECK-NEXT:    ret i1 [[T_1]]
430; CHECK:       else:
431; CHECK-NEXT:    ret i1 false
432;
433
434entry:
435  %c.1 = icmp ugt i8 %x, 10
436  %t.1 = icmp ugt i8 %x, 5
437  %and = or i1 %c.1, %t.1
438  br i1 %and, label %then, label %else
439
440then:
441  ret i1 %t.1
442
443else:
444  ret i1 %t.1
445}
446
447define i1 @and_select_first_implies_second_may_be_poison(ptr noundef %A, ptr noundef %B) {
448; CHECK-LABEL: @and_select_first_implies_second_may_be_poison(
449; CHECK-NEXT:  entry:
450; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[A:%.*]], [[B:%.*]]
451; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds ptr, ptr [[B]], i64 -1
452; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt ptr [[GEP]], [[A]]
453; CHECK-NEXT:    [[AND:%.*]] = select i1 [[C_2]], i1 true, i1 false
454; CHECK-NEXT:    ret i1 [[AND]]
455;
456entry:
457  %c.1 = icmp ne ptr %A, %B
458  %gep = getelementptr inbounds ptr, ptr %B, i64 -1
459  %c.2 = icmp ugt ptr %gep, %A
460  %and = select i1 %c.2, i1 %c.1, i1 false
461  ret i1 %and
462}
463
464define i1 @and_select_second_implies_first_may_be_poison(ptr noundef %A, ptr noundef %B) {
465; CHECK-LABEL: @and_select_second_implies_first_may_be_poison(
466; CHECK-NEXT:  entry:
467; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[A:%.*]], [[B:%.*]]
468; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds ptr, ptr [[B]], i64 -1
469; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt ptr [[GEP]], [[A]]
470; CHECK-NEXT:    [[AND:%.*]] = select i1 [[C_1]], i1 [[C_2]], i1 false
471; CHECK-NEXT:    ret i1 [[AND]]
472;
473entry:
474  %c.1 = icmp ne ptr %A, %B
475  %gep = getelementptr inbounds ptr, ptr %B, i64 -1
476  %c.2 = icmp ugt ptr %gep, %A
477  %and = select i1 %c.1, i1 %c.2, i1 false
478  ret i1 %and
479}
480
481define i1 @and_select_second_implies_first_guaranteed_not_poison(ptr noundef %A, ptr noundef %B) {
482; CHECK-LABEL: @and_select_second_implies_first_guaranteed_not_poison(
483; CHECK-NEXT:  entry:
484; CHECK-NEXT:    [[C_1:%.*]] = icmp ne ptr [[A:%.*]], [[B:%.*]]
485; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds ptr, ptr [[B]], i64 -1
486; CHECK-NEXT:    [[C_2:%.*]] = icmp ugt ptr [[GEP]], [[A]]
487; CHECK-NEXT:    call void @no_noundef(i1 [[C_2]])
488; CHECK-NEXT:    [[AND:%.*]] = select i1 [[C_1]], i1 [[C_2]], i1 false
489; CHECK-NEXT:    ret i1 [[AND]]
490;
491entry:
492  %c.1 = icmp ne ptr %A, %B
493  %gep = getelementptr inbounds ptr, ptr %B, i64 -1
494  %c.2 = icmp ugt ptr %gep, %A
495  call void @no_noundef(i1 %c.2)
496  %and = select i1 %c.1, i1 %c.2, i1 false
497  ret i1 %and
498}
499
500define void @and_tree_second_implies_first(i32 noundef %v0, i32 noundef %v1, i32 noundef %v2) {
501; CHECK-LABEL: @and_tree_second_implies_first(
502; CHECK-NEXT:  entry:
503; CHECK-NEXT:    [[CMP0:%.*]] = icmp sge i32 [[V0:%.*]], [[V1:%.*]]
504; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i32 [[V1]], [[V2:%.*]]
505; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[CMP0]], [[CMP1]]
506; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[V0]], [[V2]]
507; CHECK-NEXT:    [[AND2:%.*]] = and i1 false, [[AND1]]
508; CHECK-NEXT:    br i1 [[AND2]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
509; CHECK:       if.then:
510; CHECK-NEXT:    call void @side_effect()
511; CHECK-NEXT:    br label [[RETURN]]
512; CHECK:       return:
513; CHECK-NEXT:    ret void
514;
515entry:
516  %cmp0 = icmp sge i32 %v0, %v1
517  %cmp1 = icmp sge i32 %v1, %v2
518  %and1 = and i1 %cmp0, %cmp1
519  %cmp2 = icmp slt i32 %v0, %v2
520  %and2 = and i1 %cmp2, %and1
521  br i1 %and2, label %if.then, label %return
522
523if.then:
524  call void @side_effect()
525  br label %return
526
527return:
528  ret void
529}
530
531define void @and_tree_second_implies_first_perm1(i32 noundef %v0, i32 noundef %v1, i32 noundef %v2) {
532; CHECK-LABEL: @and_tree_second_implies_first_perm1(
533; CHECK-NEXT:  entry:
534; CHECK-NEXT:    [[CMP0:%.*]] = icmp sge i32 [[V0:%.*]], [[V1:%.*]]
535; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i32 [[V1]], [[V2:%.*]]
536; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[V0]], [[V2]]
537; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[CMP2]], [[CMP1]]
538; CHECK-NEXT:    [[AND2:%.*]] = and i1 false, [[AND1]]
539; CHECK-NEXT:    br i1 [[AND2]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
540; CHECK:       if.then:
541; CHECK-NEXT:    call void @side_effect()
542; CHECK-NEXT:    br label [[RETURN]]
543; CHECK:       return:
544; CHECK-NEXT:    ret void
545;
546entry:
547  %cmp0 = icmp sge i32 %v0, %v1
548  %cmp1 = icmp sge i32 %v1, %v2
549  %cmp2 = icmp slt i32 %v0, %v2
550  %and1 = and i1 %cmp2, %cmp1
551  %and2 = and i1 %cmp0, %and1
552  br i1 %and2, label %if.then, label %return
553
554if.then:
555  call void @side_effect()
556  br label %return
557
558return:
559  ret void
560}
561
562
563define void @and_tree_second_implies_first_perm2(i32 noundef %v0, i32 noundef %v1, i32 noundef %v2) {
564; CHECK-LABEL: @and_tree_second_implies_first_perm2(
565; CHECK-NEXT:  entry:
566; CHECK-NEXT:    [[CMP0:%.*]] = icmp sge i32 [[V0:%.*]], [[V1:%.*]]
567; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i32 [[V1]], [[V2:%.*]]
568; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[V0]], [[V2]]
569; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[CMP0]], [[CMP2]]
570; CHECK-NEXT:    [[AND2:%.*]] = and i1 false, [[AND1]]
571; CHECK-NEXT:    br i1 [[AND2]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
572; CHECK:       if.then:
573; CHECK-NEXT:    call void @side_effect()
574; CHECK-NEXT:    br label [[RETURN]]
575; CHECK:       return:
576; CHECK-NEXT:    ret void
577;
578entry:
579  %cmp0 = icmp sge i32 %v0, %v1
580  %cmp1 = icmp sge i32 %v1, %v2
581  %cmp2 = icmp slt i32 %v0, %v2
582  %and1 = and i1 %cmp0, %cmp2
583  %and2 = and i1 %cmp1, %and1
584  br i1 %and2, label %if.then, label %return
585
586if.then:
587  call void @side_effect()
588  br label %return
589
590return:
591  ret void
592}
593
594define void @logical_and_tree_second_implies_first(i32 %v0, i32 %v1, i32 %v2) {
595; CHECK-LABEL: @logical_and_tree_second_implies_first(
596; CHECK-NEXT:  entry:
597; CHECK-NEXT:    [[CMP0:%.*]] = icmp sge i32 [[V0:%.*]], [[V1:%.*]]
598; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i32 [[V1]], [[V2:%.*]]
599; CHECK-NEXT:    [[AND1:%.*]] = select i1 [[CMP0]], i1 [[CMP1]], i1 false
600; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[V0]], [[V2]]
601; CHECK-NEXT:    [[AND2:%.*]] = select i1 [[CMP2]], i1 [[AND1]], i1 false
602; CHECK-NEXT:    br i1 [[AND2]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
603; CHECK:       if.then:
604; CHECK-NEXT:    call void @side_effect()
605; CHECK-NEXT:    br label [[RETURN]]
606; CHECK:       return:
607; CHECK-NEXT:    ret void
608;
609entry:
610  %cmp0 = icmp sge i32 %v0, %v1
611  %cmp1 = icmp sge i32 %v1, %v2
612  %and1 = select i1 %cmp0, i1 %cmp1, i1 false
613  %cmp2 = icmp slt i32 %v0, %v2
614  %and2 = select i1 %cmp2, i1 %and1, i1 false
615  br i1 %and2, label %if.then, label %return
616
617if.then:
618  call void @side_effect()
619  br label %return
620
621return:
622  ret void
623}
624
625define void @or_tree_second_implies_first(i32 noundef %v0, i32 noundef %v1, i32 noundef %v2) {
626; CHECK-LABEL: @or_tree_second_implies_first(
627; CHECK-NEXT:  entry:
628; CHECK-NEXT:    [[CMP0:%.*]] = icmp sge i32 [[V0:%.*]], [[V1:%.*]]
629; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i32 [[V1]], [[V2:%.*]]
630; CHECK-NEXT:    [[AND1:%.*]] = or i1 [[CMP0]], [[CMP1]]
631; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[V0]], [[V2]]
632; CHECK-NEXT:    [[AND2:%.*]] = or i1 true, [[AND1]]
633; CHECK-NEXT:    br i1 [[AND2]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
634; CHECK:       if.then:
635; CHECK-NEXT:    call void @side_effect()
636; CHECK-NEXT:    br label [[RETURN]]
637; CHECK:       return:
638; CHECK-NEXT:    ret void
639;
640entry:
641  %cmp0 = icmp sge i32 %v0, %v1
642  %cmp1 = icmp sge i32 %v1, %v2
643  %and1 = or i1 %cmp0, %cmp1
644  %cmp2 = icmp slt i32 %v0, %v2
645  %and2 = or i1 %cmp2, %and1
646  br i1 %and2, label %if.then, label %return
647
648if.then:
649  call void @side_effect()
650  br label %return
651
652return:
653  ret void
654}
655
656define void @or_tree_second_implies_first_with_unknown_cond(i64 %x, i1 %cond) {
657; CHECK-LABEL: @or_tree_second_implies_first_with_unknown_cond(
658; CHECK-NEXT:  entry:
659; CHECK-NEXT:    [[CMP1:%.*]] = icmp ugt i64 [[X:%.*]], 1
660; CHECK-NEXT:    [[OR1:%.*]] = select i1 [[CMP1]], i1 [[COND:%.*]], i1 false
661; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i64 [[X]], 2
662; CHECK-NEXT:    [[OR2:%.*]] = select i1 [[OR1]], i1 false, i1 false
663; CHECK-NEXT:    br i1 [[OR2]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
664; CHECK:       if.then:
665; CHECK-NEXT:    call void @side_effect()
666; CHECK-NEXT:    br label [[IF_END]]
667; CHECK:       if.end:
668; CHECK-NEXT:    ret void
669;
670entry:
671  %cmp1 = icmp ugt i64 %x, 1
672  %or1 = select i1 %cmp1, i1 %cond, i1 false
673  %cmp2 = icmp ult i64 %x, 2
674  %or2 = select i1 %or1, i1 %cmp2, i1 false
675  br i1 %or2, label %if.then, label %if.end
676
677if.then:
678  call void @side_effect()
679  br label %if.end
680
681if.end:
682  ret void
683}
684
685define void @negative_and_or_tree_second_implies_first(i32 noundef %v0, i32 noundef %v1, i32 noundef %v2) {
686; CHECK-LABEL: @negative_and_or_tree_second_implies_first(
687; CHECK-NEXT:  entry:
688; CHECK-NEXT:    [[CMP0:%.*]] = icmp sge i32 [[V0:%.*]], [[V1:%.*]]
689; CHECK-NEXT:    [[CMP1:%.*]] = icmp sge i32 [[V1]], [[V2:%.*]]
690; CHECK-NEXT:    [[AND1:%.*]] = or i1 [[CMP0]], [[CMP1]]
691; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[V0]], [[V2]]
692; CHECK-NEXT:    [[AND2:%.*]] = and i1 [[CMP2]], [[AND1]]
693; CHECK-NEXT:    br i1 [[AND2]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
694; CHECK:       if.then:
695; CHECK-NEXT:    call void @side_effect()
696; CHECK-NEXT:    br label [[RETURN]]
697; CHECK:       return:
698; CHECK-NEXT:    ret void
699;
700entry:
701  %cmp0 = icmp sge i32 %v0, %v1
702  %cmp1 = icmp sge i32 %v1, %v2
703  %and1 = or i1 %cmp0, %cmp1
704  %cmp2 = icmp slt i32 %v0, %v2
705  %and2 = and i1 %cmp2, %and1
706  br i1 %and2, label %if.then, label %return
707
708if.then:
709  call void @side_effect()
710  br label %return
711
712return:
713  ret void
714}
715
716declare void @side_effect()
717declare void @no_noundef(i1 noundef)
718