xref: /llvm-project/llvm/test/Transforms/InstCombine/icmp-dom.ll (revision 380fa875ab050293be6c8723d770700100b10b8f)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4define void @idom_sign_bit_check_edge_dominates(i64 %a) {
5; CHECK-LABEL: @idom_sign_bit_check_edge_dominates(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[A:%.*]], 0
8; CHECK-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_RHS:%.*]]
9; CHECK:       land.lhs.true:
10; CHECK-NEXT:    br label [[LOR_END:%.*]]
11; CHECK:       lor.rhs:
12; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i64 [[A]], 0
13; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[LOR_END]], label [[LAND_RHS:%.*]]
14; CHECK:       land.rhs:
15; CHECK-NEXT:    br label [[LOR_END]]
16; CHECK:       lor.end:
17; CHECK-NEXT:    ret void
18;
19entry:
20  %cmp = icmp slt i64 %a, 0
21  br i1 %cmp, label %land.lhs.true, label %lor.rhs
22
23land.lhs.true:
24  br label %lor.end
25
26lor.rhs:
27  %cmp2 = icmp sgt i64 %a, 0
28  br i1 %cmp2, label %land.rhs, label %lor.end
29
30land.rhs:
31  br label %lor.end
32
33lor.end:
34  ret void
35}
36
37define void @idom_sign_bit_check_edge_not_dominates(i64 %a, i1 %c1) {
38; CHECK-LABEL: @idom_sign_bit_check_edge_not_dominates(
39; CHECK-NEXT:  entry:
40; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[A:%.*]], 0
41; CHECK-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_RHS:%.*]]
42; CHECK:       land.lhs.true:
43; CHECK-NEXT:    br i1 [[C1:%.*]], label [[LOR_END:%.*]], label [[LOR_RHS]]
44; CHECK:       lor.rhs:
45; CHECK-NEXT:    [[CMP2:%.*]] = icmp sgt i64 [[A]], 0
46; CHECK-NEXT:    br i1 [[CMP2]], label [[LAND_RHS:%.*]], label [[LOR_END]]
47; CHECK:       land.rhs:
48; CHECK-NEXT:    br label [[LOR_END]]
49; CHECK:       lor.end:
50; CHECK-NEXT:    ret void
51;
52entry:
53  %cmp = icmp slt i64 %a, 0
54  br i1 %cmp, label %land.lhs.true, label %lor.rhs
55
56land.lhs.true:
57  br i1 %c1, label %lor.end, label %lor.rhs
58
59lor.rhs:
60  %cmp2 = icmp sgt i64 %a, 0
61  br i1 %cmp2, label %land.rhs, label %lor.end
62
63land.rhs:
64  br label %lor.end
65
66lor.end:
67  ret void
68}
69
70define void @idom_sign_bit_check_edge_dominates_select(i64 %a, i64 %b) {
71; CHECK-LABEL: @idom_sign_bit_check_edge_dominates_select(
72; CHECK-NEXT:  entry:
73; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[A:%.*]], 5
74; CHECK-NEXT:    br i1 [[CMP]], label [[LAND_LHS_TRUE:%.*]], label [[LOR_RHS:%.*]]
75; CHECK:       land.lhs.true:
76; CHECK-NEXT:    br label [[LOR_END:%.*]]
77; CHECK:       lor.rhs:
78; CHECK-NEXT:    [[CMP3_NOT:%.*]] = icmp eq i64 [[A]], [[B:%.*]]
79; CHECK-NEXT:    br i1 [[CMP3_NOT]], label [[LOR_END]], label [[LAND_RHS:%.*]]
80; CHECK:       land.rhs:
81; CHECK-NEXT:    br label [[LOR_END]]
82; CHECK:       lor.end:
83; CHECK-NEXT:    ret void
84;
85entry:
86  %cmp = icmp slt i64 %a, 5
87  br i1 %cmp, label %land.lhs.true, label %lor.rhs
88
89land.lhs.true:
90  br label %lor.end
91
92lor.rhs:
93  %cmp2 = icmp sgt i64 %a, 5
94  %select = select i1 %cmp2, i64 %a, i64 5
95  %cmp3 = icmp ne i64 %select, %b
96  br i1 %cmp3, label %land.rhs, label %lor.end
97
98land.rhs:
99  br label %lor.end
100
101lor.end:
102  ret void
103}
104
105define void @idom_zbranch(i64 %a) {
106; CHECK-LABEL: @idom_zbranch(
107; CHECK-NEXT:  entry:
108; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[A:%.*]], 0
109; CHECK-NEXT:    br i1 [[CMP]], label [[LOR_END:%.*]], label [[LOR_RHS:%.*]]
110; CHECK:       lor.rhs:
111; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i64 [[A]], 0
112; CHECK-NEXT:    br i1 [[CMP2]], label [[LAND_RHS:%.*]], label [[LOR_END]]
113; CHECK:       land.rhs:
114; CHECK-NEXT:    br label [[LOR_END]]
115; CHECK:       lor.end:
116; CHECK-NEXT:    ret void
117;
118entry:
119  %cmp = icmp sgt i64 %a, 0
120  br i1 %cmp, label %lor.end, label %lor.rhs
121
122lor.rhs:
123  %cmp2 = icmp slt i64 %a, 0
124  br i1 %cmp2, label %land.rhs, label %lor.end
125
126land.rhs:
127  br label %lor.end
128
129lor.end:
130  ret void
131}
132
133define void @idom_not_zbranch(i32 %a, i32 %b) {
134; CHECK-LABEL: @idom_not_zbranch(
135; CHECK-NEXT:  entry:
136; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 0
137; CHECK-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[IF_END:%.*]]
138; CHECK:       if.end:
139; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i32 [[A]], [[B:%.*]]
140; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[RETURN]], label [[IF_THEN3:%.*]]
141; CHECK:       if.then3:
142; CHECK-NEXT:    br label [[RETURN]]
143; CHECK:       return:
144; CHECK-NEXT:    ret void
145;
146entry:
147  %cmp = icmp sgt i32 %a, 0
148  br i1 %cmp, label %return, label %if.end
149
150if.end:
151  %cmp1 = icmp slt i32 %a, 0
152  %a. = select i1 %cmp1, i32 %a, i32 0
153  %cmp2 = icmp ne i32 %a., %b
154  br i1 %cmp2, label %if.then3, label %return
155
156if.then3:
157  br label %return
158
159return:
160  ret void
161}
162
163define void @trueblock_cmp_eq(i32 %a, i32 %b) {
164; CHECK-LABEL: @trueblock_cmp_eq(
165; CHECK-NEXT:  entry:
166; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A:%.*]], 0
167; CHECK-NEXT:    br i1 [[CMP]], label [[IF_END:%.*]], label [[RETURN:%.*]]
168; CHECK:       if.end:
169; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[A]], 1
170; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN3:%.*]], label [[RETURN]]
171; CHECK:       if.then3:
172; CHECK-NEXT:    br label [[RETURN]]
173; CHECK:       return:
174; CHECK-NEXT:    ret void
175;
176entry:
177  %cmp = icmp sgt i32 %a, 0
178  br i1 %cmp, label %if.end, label %return
179
180if.end:
181  %cmp1 = icmp slt i32 %a, 2
182  br i1 %cmp1, label %if.then3, label %return
183
184if.then3:
185  br label %return
186
187return:
188  ret void
189}
190
191define i1 @trueblock_cmp_is_false(i32 %x, i32 %y) {
192; CHECK-LABEL: @trueblock_cmp_is_false(
193; CHECK-NEXT:  entry:
194; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
195; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
196; CHECK:       t:
197; CHECK-NEXT:    ret i1 false
198; CHECK:       f:
199; CHECK-NEXT:    ret i1 false
200;
201entry:
202  %cmp = icmp sgt i32 %x, %y
203  br i1 %cmp, label %t, label %f
204t:
205  %cmp2 = icmp slt i32 %x, %y
206  ret i1 %cmp2
207f:
208  ret i1 %cmp
209}
210
211define i1 @trueblock_cmp_is_false_commute(i32 %x, i32 %y) {
212; CHECK-LABEL: @trueblock_cmp_is_false_commute(
213; CHECK-NEXT:  entry:
214; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
215; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
216; CHECK:       t:
217; CHECK-NEXT:    ret i1 false
218; CHECK:       f:
219; CHECK-NEXT:    ret i1 false
220;
221entry:
222  %cmp = icmp eq i32 %x, %y
223  br i1 %cmp, label %t, label %f
224t:
225  %cmp2 = icmp sgt i32 %y, %x
226  ret i1 %cmp2
227f:
228  ret i1 %cmp
229}
230
231define i1 @trueblock_cmp_is_true(i32 %x, i32 %y) {
232; CHECK-LABEL: @trueblock_cmp_is_true(
233; CHECK-NEXT:  entry:
234; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
235; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
236; CHECK:       t:
237; CHECK-NEXT:    ret i1 true
238; CHECK:       f:
239; CHECK-NEXT:    ret i1 false
240;
241entry:
242  %cmp = icmp ult i32 %x, %y
243  br i1 %cmp, label %t, label %f
244t:
245  %cmp2 = icmp ne i32 %x, %y
246  ret i1 %cmp2
247f:
248  ret i1 %cmp
249}
250
251define i1 @trueblock_cmp_is_true_commute(i32 %x, i32 %y) {
252; CHECK-LABEL: @trueblock_cmp_is_true_commute(
253; CHECK-NEXT:  entry:
254; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
255; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
256; CHECK:       t:
257; CHECK-NEXT:    ret i1 true
258; CHECK:       f:
259; CHECK-NEXT:    ret i1 false
260;
261entry:
262  %cmp = icmp ugt i32 %x, %y
263  br i1 %cmp, label %t, label %f
264t:
265  %cmp2 = icmp ne i32 %y, %x
266  ret i1 %cmp2
267f:
268  ret i1 %cmp
269}
270
271define i1 @falseblock_cmp_is_false(i32 %x, i32 %y) {
272; CHECK-LABEL: @falseblock_cmp_is_false(
273; CHECK-NEXT:  entry:
274; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
275; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[F:%.*]], label [[T:%.*]]
276; CHECK:       t:
277; CHECK-NEXT:    ret i1 true
278; CHECK:       f:
279; CHECK-NEXT:    ret i1 false
280;
281entry:
282  %cmp = icmp sle i32 %x, %y
283  br i1 %cmp, label %t, label %f
284t:
285  ret i1 %cmp
286f:
287  %cmp2 = icmp slt i32 %x, %y
288  ret i1 %cmp2
289}
290
291define i1 @falseblock_cmp_is_false_commute(i32 %x, i32 %y) {
292; CHECK-LABEL: @falseblock_cmp_is_false_commute(
293; CHECK-NEXT:  entry:
294; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
295; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
296; CHECK:       t:
297; CHECK-NEXT:    ret i1 true
298; CHECK:       f:
299; CHECK-NEXT:    ret i1 false
300;
301entry:
302  %cmp = icmp eq i32 %x, %y
303  br i1 %cmp, label %t, label %f
304t:
305  ret i1 %cmp
306f:
307  %cmp2 = icmp eq i32 %y, %x
308  ret i1 %cmp2
309}
310
311define i1 @falseblock_cmp_is_true(i32 %x, i32 %y) {
312; CHECK-LABEL: @falseblock_cmp_is_true(
313; CHECK-NEXT:  entry:
314; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
315; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
316; CHECK:       t:
317; CHECK-NEXT:    ret i1 true
318; CHECK:       f:
319; CHECK-NEXT:    ret i1 true
320;
321entry:
322  %cmp = icmp ult i32 %x, %y
323  br i1 %cmp, label %t, label %f
324t:
325  ret i1 %cmp
326f:
327  %cmp2 = icmp uge i32 %x, %y
328  ret i1 %cmp2
329}
330
331define i1 @falseblock_cmp_is_true_commute(i32 %x, i32 %y) {
332; CHECK-LABEL: @falseblock_cmp_is_true_commute(
333; CHECK-NEXT:  entry:
334; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
335; CHECK-NEXT:    br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]]
336; CHECK:       t:
337; CHECK-NEXT:    ret i1 true
338; CHECK:       f:
339; CHECK-NEXT:    ret i1 true
340;
341entry:
342  %cmp = icmp sgt i32 %x, %y
343  br i1 %cmp, label %t, label %f
344t:
345  ret i1 %cmp
346f:
347  %cmp2 = icmp sge i32 %y, %x
348  ret i1 %cmp2
349}
350
351; This used to infinite loop because of a conflict
352; with min/max canonicalization.
353
354define i32 @PR48900(i32 %i, ptr %p) {
355; CHECK-LABEL: @PR48900(
356; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[I:%.*]], i32 1)
357; CHECK-NEXT:    [[I4:%.*]] = icmp sgt i32 [[UMAX]], 0
358; CHECK-NEXT:    br i1 [[I4]], label [[TRUELABEL:%.*]], label [[FALSELABEL:%.*]]
359; CHECK:       truelabel:
360; CHECK-NEXT:    [[SMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[UMAX]], i32 2)
361; CHECK-NEXT:    ret i32 [[SMIN]]
362; CHECK:       falselabel:
363; CHECK-NEXT:    ret i32 0
364;
365  %maxcmp = icmp ugt i32 %i, 1
366  %umax = select i1 %maxcmp, i32 %i, i32 1
367  %i4 = icmp sgt i32 %umax, 0
368  br i1 %i4, label %truelabel, label %falselabel
369
370truelabel:
371  %mincmp = icmp ult i32 %umax, 2
372  %smin = select i1 %mincmp, i32 %umax, i32 2
373  ret i32 %smin
374
375falselabel:
376  ret i32 0
377}
378
379; This used to infinite loop because of a conflict
380; with min/max canonicalization.
381
382define i8 @PR48900_alt(i8 %i, ptr %p) {
383; CHECK-LABEL: @PR48900_alt(
384; CHECK-NEXT:    [[SMAX:%.*]] = call i8 @llvm.smax.i8(i8 [[I:%.*]], i8 -127)
385; CHECK-NEXT:    [[I4:%.*]] = icmp ugt i8 [[SMAX]], -128
386; CHECK-NEXT:    br i1 [[I4]], label [[TRUELABEL:%.*]], label [[FALSELABEL:%.*]]
387; CHECK:       truelabel:
388; CHECK-NEXT:    [[UMIN:%.*]] = call i8 @llvm.smin.i8(i8 [[SMAX]], i8 -126)
389; CHECK-NEXT:    ret i8 [[UMIN]]
390; CHECK:       falselabel:
391; CHECK-NEXT:    ret i8 0
392;
393  %maxcmp = icmp sgt i8 %i, -127
394  %smax = select i1 %maxcmp, i8 %i, i8 -127
395  %i4 = icmp ugt i8 %smax, 128
396  br i1 %i4, label %truelabel, label %falselabel
397
398truelabel:
399  %mincmp = icmp slt i8 %smax, -126
400  %umin = select i1 %mincmp, i8 %smax, i8 -126
401  ret i8 %umin
402
403falselabel:
404  ret i8 0
405}
406
407define i1 @and_mask1_eq(i32 %conv) {
408; CHECK-LABEL: @and_mask1_eq(
409; CHECK-NEXT:  entry:
410; CHECK-NEXT:    [[AND:%.*]] = and i32 [[CONV:%.*]], 1
411; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
412; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
413; CHECK:       then:
414; CHECK-NEXT:    ret i1 false
415; CHECK:       else:
416; CHECK-NEXT:    ret i1 false
417;
418entry:
419  %and = and i32 %conv, 1
420  %cmp = icmp eq i32 %and, 0
421  br i1 %cmp, label %then, label %else
422
423then:
424  ret i1 0
425
426else:
427  %and1 = and i32 %conv, 3
428  %cmp1 = icmp eq i32 %and1, 0
429  ret i1 %cmp1
430}
431
432define i1 @and_mask1_ne(i32 %conv) {
433; CHECK-LABEL: @and_mask1_ne(
434; CHECK-NEXT:  entry:
435; CHECK-NEXT:    [[AND:%.*]] = and i32 [[CONV:%.*]], 1
436; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
437; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
438; CHECK:       then:
439; CHECK-NEXT:    ret i1 false
440; CHECK:       else:
441; CHECK-NEXT:    ret i1 true
442;
443entry:
444  %and = and i32 %conv, 1
445  %cmp = icmp eq i32 %and, 0
446  br i1 %cmp, label %then, label %else
447
448then:
449  ret i1 0
450
451else:
452  %and1 = and i32 %conv, 3
453  %cmp1 = icmp ne i32 %and1, 0
454  ret i1 %cmp1
455}
456
457define i1 @and_mask2(i32 %conv) {
458; CHECK-LABEL: @and_mask2(
459; CHECK-NEXT:  entry:
460; CHECK-NEXT:    [[AND:%.*]] = and i32 [[CONV:%.*]], 4
461; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
462; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
463; CHECK:       then:
464; CHECK-NEXT:    ret i1 false
465; CHECK:       else:
466; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[CONV]], 3
467; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[AND1]], 0
468; CHECK-NEXT:    ret i1 [[CMP1]]
469;
470entry:
471  %and = and i32 %conv, 4
472  %cmp = icmp eq i32 %and, 0
473  br i1 %cmp, label %then, label %else
474
475then:
476  ret i1 0
477
478else:
479  %and1 = and i32 %conv, 3
480  %cmp1 = icmp eq i32 %and1, 0
481  ret i1 %cmp1
482}
483
484; TODO: %cmp1 can be folded into false.
485
486define i1 @and_mask3(i32 %conv) {
487; CHECK-LABEL: @and_mask3(
488; CHECK-NEXT:  entry:
489; CHECK-NEXT:    [[AND:%.*]] = and i32 [[CONV:%.*]], 3
490; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
491; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
492; CHECK:       then:
493; CHECK-NEXT:    ret i1 false
494; CHECK:       else:
495; CHECK-NEXT:    [[AND1:%.*]] = and i32 [[CONV]], 7
496; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[AND1]], 0
497; CHECK-NEXT:    ret i1 [[CMP1]]
498;
499entry:
500  %and = and i32 %conv, 3
501  %cmp = icmp eq i32 %and, 0
502  br i1 %cmp, label %then, label %else
503
504then:
505  ret i1 0
506
507else:
508  %and1 = and i32 %conv, 7
509  %cmp1 = icmp eq i32 %and1, 0
510  ret i1 %cmp1
511}
512
513define i1 @and_mask4(i32 %conv) {
514; CHECK-LABEL: @and_mask4(
515; CHECK-NEXT:  entry:
516; CHECK-NEXT:    [[AND:%.*]] = and i32 [[CONV:%.*]], 4
517; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[AND]], 0
518; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
519; CHECK:       then:
520; CHECK-NEXT:    ret i1 false
521; CHECK:       else:
522; CHECK-NEXT:    ret i1 false
523;
524entry:
525  %and = and i32 %conv, 4
526  %cmp = icmp eq i32 %and, 0
527  br i1 %cmp, label %then, label %else
528
529then:
530  ret i1 0
531
532else:
533  %and1 = and i32 %conv, 7
534  %cmp1 = icmp eq i32 %and1, 0
535  ret i1 %cmp1
536}
537