xref: /llvm-project/llvm/test/Transforms/InstCombine/intrinsic-select.ll (revision cf37ae5caeafb372593ca4bb9ce0e91258524ca1)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3
4declare void @use(i32)
5declare void @usef32(float)
6
7declare i32 @llvm.ctlz.i32(i32, i1)
8declare <3 x i17> @llvm.ctlz.v3i17(<3 x i17>, i1)
9
10declare i32 @llvm.cttz.i32(i32, i1)
11declare <3 x i5> @llvm.cttz.v3i5(<3 x i5>, i1)
12
13declare i32 @llvm.ctpop.i32(i32)
14declare <3 x i7> @llvm.ctpop.v3i7(<3 x i7>)
15
16declare i32 @llvm.usub.sat.i32(i32, i32)
17
18define i32 @ctlz_sel_const_true_false(i1 %b) {
19; CHECK-LABEL: @ctlz_sel_const_true_false(
20; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 29, i32 0
21; CHECK-NEXT:    ret i32 [[C]]
22;
23  %s = select i1 %b, i32 5, i32 -7
24  %c = call i32 @llvm.ctlz.i32(i32 %s, i1 true)
25  ret i32 %c
26}
27
28define i32 @ctlz_sel_const_true(i1 %b, i32 %x) {
29; CHECK-LABEL: @ctlz_sel_const_true(
30; CHECK-NEXT:    [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
31; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 29, i32 [[TMP1]]
32; CHECK-NEXT:    ret i32 [[C]]
33;
34  %s = select i1 %b, i32 5, i32 %x
35  %c = call i32 @llvm.ctlz.i32(i32 %s, i1 false)
36  ret i32 %c
37}
38
39define <3 x i17> @ctlz_sel_const_false(<3 x i1> %b, <3 x i17> %x) {
40; CHECK-LABEL: @ctlz_sel_const_false(
41; CHECK-NEXT:    [[TMP1:%.*]] = call range(i17 0, 18) <3 x i17> @llvm.ctlz.v3i17(<3 x i17> [[X:%.*]], i1 true)
42; CHECK-NEXT:    [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i17> [[TMP1]], <3 x i17> <i17 14, i17 0, i17 poison>
43; CHECK-NEXT:    ret <3 x i17> [[C]]
44;
45  %s = select <3 x i1> %b, <3 x i17> %x, <3 x i17> <i17 7, i17 -1, i17 0>
46  %c = call <3 x i17> @llvm.ctlz.v3i17(<3 x i17> %s, i1 true)
47  ret <3 x i17> %c
48}
49
50define i32 @ctlz_sel_const_true_false_extra_use(i1 %b) {
51; CHECK-LABEL: @ctlz_sel_const_true_false_extra_use(
52; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 -1, i32 7
53; CHECK-NEXT:    call void @use(i32 [[S]])
54; CHECK-NEXT:    [[C:%.*]] = call range(i32 0, 30) i32 @llvm.ctlz.i32(i32 [[S]], i1 true)
55; CHECK-NEXT:    ret i32 [[C]]
56;
57  %s = select i1 %b, i32 -1, i32 7
58  call void @use(i32 %s)
59  %c = call i32 @llvm.ctlz.i32(i32 %s, i1 false)
60  ret i32 %c
61}
62
63define i32 @cttz_sel_const_true_false(i1 %b) {
64; CHECK-LABEL: @cttz_sel_const_true_false(
65; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 0
66; CHECK-NEXT:    ret i32 [[C]]
67;
68  %s = select i1 %b, i32 4, i32 -7
69  %c = call i32 @llvm.cttz.i32(i32 %s, i1 false)
70  ret i32 %c
71}
72
73define i32 @cttz_sel_const_true(i1 %b, i32 %x) {
74; CHECK-LABEL: @cttz_sel_const_true(
75; CHECK-NEXT:    [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
76; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 [[TMP1]]
77; CHECK-NEXT:    ret i32 [[C]]
78;
79  %s = select i1 %b, i32 5, i32 %x
80  %c = call i32 @llvm.cttz.i32(i32 %s, i1 true)
81  ret i32 %c
82}
83
84define <3 x i5> @cttz_sel_const_false(<3 x i1> %b, <3 x i5> %x) {
85; CHECK-LABEL: @cttz_sel_const_false(
86; CHECK-NEXT:    [[TMP1:%.*]] = call range(i5 0, 6) <3 x i5> @llvm.cttz.v3i5(<3 x i5> [[X:%.*]], i1 false)
87; CHECK-NEXT:    [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> [[TMP1]], <3 x i5> <i5 0, i5 0, i5 5>
88; CHECK-NEXT:    ret <3 x i5> [[C]]
89;
90  %s = select <3 x i1> %b, <3 x i5> %x, <3 x i5> <i5 7, i5 -1, i5 0>
91  %c = call <3 x i5> @llvm.cttz.v3i5(<3 x i5> %s, i1 false)
92  ret <3 x i5> %c
93}
94
95define i32 @cttz_sel_const_true_false_extra_use(i1 %b) {
96; CHECK-LABEL: @cttz_sel_const_true_false_extra_use(
97; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 -8
98; CHECK-NEXT:    call void @use(i32 [[S]])
99; CHECK-NEXT:    [[C:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[S]], i1 true)
100; CHECK-NEXT:    ret i32 [[C]]
101;
102  %s = select i1 %b, i32 5, i32 -8
103  call void @use(i32 %s)
104  %c = call i32 @llvm.cttz.i32(i32 %s, i1 true)
105  ret i32 %c
106}
107
108define i32 @ctpop_sel_const_true_false(i1 %b) {
109; CHECK-LABEL: @ctpop_sel_const_true_false(
110; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 30
111; CHECK-NEXT:    ret i32 [[C]]
112;
113  %s = select i1 %b, i32 5, i32 -7
114  %c = call i32 @llvm.ctpop.i32(i32 %s)
115  ret i32 %c
116}
117
118define i32 @ctpop_sel_const_true(i1 %b, i32 %x) {
119; CHECK-LABEL: @ctpop_sel_const_true(
120; CHECK-NEXT:    [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
121; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 [[TMP1]]
122; CHECK-NEXT:    ret i32 [[C]]
123;
124  %s = select i1 %b, i32 5, i32 %x
125  %c = call i32 @llvm.ctpop.i32(i32 %s)
126  ret i32 %c
127}
128
129define <3 x i7> @ctpop_sel_const_false(<3 x i1> %b, <3 x i7> %x) {
130; CHECK-LABEL: @ctpop_sel_const_false(
131; CHECK-NEXT:    [[TMP1:%.*]] = call range(i7 0, 8) <3 x i7> @llvm.ctpop.v3i7(<3 x i7> [[X:%.*]])
132; CHECK-NEXT:    [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i7> [[TMP1]], <3 x i7> <i7 3, i7 7, i7 0>
133; CHECK-NEXT:    ret <3 x i7> [[C]]
134;
135  %s = select <3 x i1> %b, <3 x i7> %x, <3 x i7> <i7 7, i7 -1, i7 0>
136  %c = call <3 x i7> @llvm.ctpop.v3i7(<3 x i7> %s)
137  ret <3 x i7> %c
138}
139
140define i32 @ctpop_sel_const_true_false_extra_use(i1 %b) {
141; CHECK-LABEL: @ctpop_sel_const_true_false_extra_use(
142; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 7
143; CHECK-NEXT:    call void @use(i32 [[S]])
144; CHECK-NEXT:    [[C:%.*]] = call range(i32 2, 4) i32 @llvm.ctpop.i32(i32 [[S]])
145; CHECK-NEXT:    ret i32 [[C]]
146;
147  %s = select i1 %b, i32 5, i32 7
148  call void @use(i32 %s)
149  %c = call i32 @llvm.ctpop.i32(i32 %s)
150  ret i32 %c
151}
152
153define i32 @usub_sat_rhs_const_select_all_const(i1 %b) {
154; CHECK-LABEL: @usub_sat_rhs_const_select_all_const(
155; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 3
156; CHECK-NEXT:    ret i32 [[C]]
157;
158  %s = select i1 %b, i32 5, i32 10
159  %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)
160  ret i32 %c
161}
162
163define i32 @usub_sat_rhs_var_select_all_const(i1 %b, i32 %x) {
164; CHECK-LABEL: @usub_sat_rhs_var_select_all_const(
165; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 10
166; CHECK-NEXT:    [[C:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[S]], i32 [[X:%.*]])
167; CHECK-NEXT:    ret i32 [[C]]
168;
169  %s = select i1 %b, i32 5, i32 10
170  %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 %x)
171  ret i32 %c
172}
173
174define i32 @usub_sat_rhs_const_select_one_const(i1 %b, i32 %x) {
175; CHECK-LABEL: @usub_sat_rhs_const_select_one_const(
176; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[X:%.*]], i32 7)
177; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 [[TMP1]]
178; CHECK-NEXT:    ret i32 [[C]]
179;
180  %s = select i1 %b, i32 5, i32 %x
181  %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)
182  ret i32 %c
183}
184
185define i32 @usub_sat_rhs_const_select_no_const(i1 %b, i32 %x, i32 %y) {
186; CHECK-LABEL: @usub_sat_rhs_const_select_no_const(
187; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 [[Y:%.*]], i32 [[X:%.*]]
188; CHECK-NEXT:    [[C:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[S]], i32 7)
189; CHECK-NEXT:    ret i32 [[C]]
190;
191  %s = select i1 %b, i32 %y, i32 %x
192  %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)
193  ret i32 %c
194}
195
196define i32 @usub_sat_lhs_const_select_all_const(i1 %b) {
197; CHECK-LABEL: @usub_sat_lhs_const_select_all_const(
198; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 0
199; CHECK-NEXT:    ret i32 [[C]]
200;
201  %s = select i1 %b, i32 5, i32 10
202  %c = call i32 @llvm.usub.sat.i32(i32 7, i32 %s)
203  ret i32 %c
204}
205
206@g1 = constant <2 x i32> zeroinitializer
207@g2 = external global i8
208declare <2 x i32> @llvm.masked.load.v2i32.p0(ptr, i32, <2 x i1>, <2 x i32>)
209
210define <2 x i32> @non_speculatable(i1 %b) {
211; CHECK-LABEL: @non_speculatable(
212; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], ptr @g1, ptr @g2
213; CHECK-NEXT:    [[C:%.*]] = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr nonnull [[S]], i32 64, <2 x i1> <i1 true, i1 false>, <2 x i32> poison)
214; CHECK-NEXT:    ret <2 x i32> [[C]]
215;
216  %s = select i1 %b, ptr @g1, ptr @g2
217  %c = call <2 x i32> @llvm.masked.load.v2i32.p0(ptr %s, i32 64, <2 x i1> <i1 true, i1 false>, <2 x i32> poison)
218  ret <2 x i32> %c
219}
220
221declare i32 @llvm.vector.reduce.add.v2i32(<2 x i32>)
222
223define i32 @vec_to_scalar_select_scalar(i1 %b) {
224; CHECK-LABEL: @vec_to_scalar_select_scalar(
225; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
226; CHECK-NEXT:    [[C:%.*]] = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> [[S]])
227; CHECK-NEXT:    ret i32 [[C]]
228;
229  %s = select i1 %b, <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
230  %c = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %s)
231  ret i32 %c
232}
233
234define i32 @vec_to_scalar_select_vector(<2 x i1> %b) {
235; CHECK-LABEL: @vec_to_scalar_select_vector(
236; CHECK-NEXT:    [[S:%.*]] = select <2 x i1> [[B:%.*]], <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
237; CHECK-NEXT:    [[C:%.*]] = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> [[S]])
238; CHECK-NEXT:    ret i32 [[C]]
239;
240  %s = select <2 x i1> %b, <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
241  %c = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %s)
242  ret i32 %c
243}
244
245define i8 @test_drop_noundef(i1 %cond, i8 %val) {
246; CHECK-LABEL: @test_drop_noundef(
247; CHECK-NEXT:  entry:
248; CHECK-NEXT:    [[TMP0:%.*]] = call i8 @llvm.smin.i8(i8 [[VAL:%.*]], i8 0)
249; CHECK-NEXT:    [[RET:%.*]] = select i1 [[COND:%.*]], i8 -1, i8 [[TMP0]]
250; CHECK-NEXT:    ret i8 [[RET]]
251;
252entry:
253  %sel = select i1 %cond, i8 -1, i8 %val
254  %ret = call noundef i8 @llvm.smin.i8(i8 %sel, i8 0)
255  ret i8 %ret
256}
257
258define i1 @pr85536(i32 %a) {
259; CHECK-LABEL: @pr85536(
260; CHECK-NEXT:  entry:
261; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], 31
262; CHECK-NEXT:    [[SHL1:%.*]] = shl nsw i32 -1, [[A]]
263; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[SHL1]] to i64
264; CHECK-NEXT:    [[SHL2:%.*]] = shl i64 [[ZEXT]], 48
265; CHECK-NEXT:    [[SHR:%.*]] = ashr exact i64 [[SHL2]], 48
266; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.smin.i64(i64 [[SHR]], i64 0)
267; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 65535
268; CHECK-NEXT:    [[RET1:%.*]] = icmp eq i64 [[TMP1]], 0
269; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP1]], i1 [[RET1]], i1 false
270; CHECK-NEXT:    ret i1 [[RET]]
271;
272entry:
273  %cmp1 = icmp ugt i32 %a, 30
274  %shl1 = shl nsw i32 -1, %a
275  %zext = zext i32 %shl1 to i64
276  %shl2 = shl i64 %zext, 48
277  %shr = ashr exact i64 %shl2, 48
278  %sel = select i1 %cmp1, i64 -1, i64 %shr
279  %smin = call noundef i64 @llvm.smin.i64(i64 %sel, i64 0)
280  %masked = and i64 %smin, 65535
281  %ret = icmp eq i64 %masked, 0
282  ret i1 %ret
283}
284
285define double @test_fabs_select1(double %a) {
286; CHECK-LABEL: @test_fabs_select1(
287; CHECK-NEXT:    [[COND:%.*]] = fcmp uno double [[A:%.*]], 0.000000e+00
288; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[COND]], double 0x7FF8000000000000, double [[A]]
289; CHECK-NEXT:    ret double [[SEL1]]
290;
291  %cond = fcmp uno double %a, 0.000000e+00
292  %sel1 = select i1 %cond, double 0x7FF8000000000000, double %a
293  %fabs = call double @llvm.fabs.f64(double %sel1)
294  %sel2 = select i1 %cond, double %fabs, double %a
295  ret double %sel2
296}
297
298define <2 x double> @test_fabs_select1_vec(<2 x double> %a) {
299; CHECK-LABEL: @test_fabs_select1_vec(
300; CHECK-NEXT:    [[COND:%.*]] = fcmp uno <2 x double> [[A:%.*]], zeroinitializer
301; CHECK-NEXT:    [[SEL2:%.*]] = select <2 x i1> [[COND]], <2 x double> splat (double 0x7FF8000000000000), <2 x double> [[A]]
302; CHECK-NEXT:    ret <2 x double> [[SEL2]]
303;
304  %cond = fcmp uno <2 x double> %a, zeroinitializer
305  %sel1 = select <2 x i1> %cond, <2 x double> splat(double 0x7FF8000000000000), <2 x double> %a
306  %fabs = call <2 x double> @llvm.fabs.v2f64(<2 x double> %sel1)
307  %sel2 = select <2 x i1> %cond, <2 x double> %fabs, <2 x double> %a
308  ret <2 x double> %sel2
309}
310
311define double @test_fabs_select2(double %a) {
312; CHECK-LABEL: @test_fabs_select2(
313; CHECK-NEXT:    [[ABS1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])
314; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[ABS1]], 0x7FF0000000000000
315; CHECK-NEXT:    [[ABS2:%.*]] = select i1 [[CMP]], double 0.000000e+00, double [[ABS1]]
316; CHECK-NEXT:    ret double [[ABS2]]
317;
318  %abs1 = call double @llvm.fabs.f64(double %a)
319  %cmp = fcmp oeq double %abs1, 0x7FF0000000000000
320  %sel = select i1 %cmp, double -0.000000e+00, double %abs1
321  %abs2 = call double @llvm.fabs.f64(double %sel)
322  ret double %abs2
323}
324
325; nsz flag should be dropped.
326
327define double @test_fabs_select_fmf1(i1 %cond, double %a) {
328; CHECK-LABEL: @test_fabs_select_fmf1(
329; CHECK-NEXT:    [[A:%.*]] = call double @llvm.fabs.f64(double [[A1:%.*]])
330; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[COND:%.*]], double 0.000000e+00, double [[A]]
331; CHECK-NEXT:    ret double [[FABS]]
332;
333  %sel1 = select nnan ninf nsz i1 %cond, double 0.0, double %a
334  %fabs = call double @llvm.fabs.f64(double %sel1)
335  ret double %fabs
336}
337
338define double @test_fabs_select_fmf2(i1 %cond, double %a) {
339; CHECK-LABEL: @test_fabs_select_fmf2(
340; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])
341; CHECK-NEXT:    [[SEL1:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], double 0.000000e+00, double [[TMP1]]
342; CHECK-NEXT:    ret double [[SEL1]]
343;
344  %sel1 = select i1 %cond, double 0.0, double %a
345  %fabs = call nnan ninf nsz double @llvm.fabs.f64(double %sel1)
346  ret double %fabs
347}
348
349define float @test_fabs_select_multiuse(i1 %cond, float %x) {
350; CHECK-LABEL: @test_fabs_select_multiuse(
351; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND:%.*]], float [[X:%.*]], float 0x7FF0000000000000
352; CHECK-NEXT:    call void @usef32(float [[SELECT]])
353; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
354; CHECK-NEXT:    ret float [[FABS]]
355;
356  %select = select i1 %cond, float %x, float 0x7FF0000000000000
357  call void @usef32(float %select)
358  %fabs = call float @llvm.fabs.f32(float %select)
359  ret float %fabs
360}
361
362define float @test_fabs_select_multiuse_both_constant(i1 %cond, float %x) {
363; CHECK-LABEL: @test_fabs_select_multiuse_both_constant(
364; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND:%.*]], float -1.000000e+00, float -2.000000e+00
365; CHECK-NEXT:    call void @usef32(float [[SELECT]])
366; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[COND]], float 1.000000e+00, float 2.000000e+00
367; CHECK-NEXT:    ret float [[FABS]]
368;
369  %select = select i1 %cond, float -1.0, float -2.0
370  call void @usef32(float %select)
371  %fabs = call float @llvm.fabs.f32(float %select)
372  ret float %fabs
373}
374