Revert "[InstCombine] Support gep nuw in icmp folds" (#118698)
[llvm-project.git] / llvm / test / Transforms / InstCombine / intrinsic-select.ll
blob4ce2908a63078584fe0264a16304489bc1311577
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=instcombine -S < %s | FileCheck %s
4 declare void @use(i32)
6 declare i32 @llvm.ctlz.i32(i32, i1)
7 declare <3 x i17> @llvm.ctlz.v3i17(<3 x i17>, i1)
9 declare i32 @llvm.cttz.i32(i32, i1)
10 declare <3 x i5> @llvm.cttz.v3i5(<3 x i5>, i1)
12 declare i32 @llvm.ctpop.i32(i32)
13 declare <3 x i7> @llvm.ctpop.v3i7(<3 x i7>)
15 declare i32 @llvm.usub.sat.i32(i32, i32)
17 define i32 @ctlz_sel_const_true_false(i1 %b) {
18 ; CHECK-LABEL: @ctlz_sel_const_true_false(
19 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 29, i32 0
20 ; CHECK-NEXT:    ret i32 [[C]]
22   %s = select i1 %b, i32 5, i32 -7
23   %c = call i32 @llvm.ctlz.i32(i32 %s, i1 true)
24   ret i32 %c
27 define i32 @ctlz_sel_const_true(i1 %b, i32 %x) {
28 ; CHECK-LABEL: @ctlz_sel_const_true(
29 ; CHECK-NEXT:    [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
30 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 29, i32 [[TMP1]]
31 ; CHECK-NEXT:    ret i32 [[C]]
33   %s = select i1 %b, i32 5, i32 %x
34   %c = call i32 @llvm.ctlz.i32(i32 %s, i1 false)
35   ret i32 %c
38 define <3 x i17> @ctlz_sel_const_false(<3 x i1> %b, <3 x i17> %x) {
39 ; CHECK-LABEL: @ctlz_sel_const_false(
40 ; CHECK-NEXT:    [[TMP1:%.*]] = call range(i17 0, 18) <3 x i17> @llvm.ctlz.v3i17(<3 x i17> [[X:%.*]], i1 true)
41 ; CHECK-NEXT:    [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i17> [[TMP1]], <3 x i17> <i17 14, i17 0, i17 poison>
42 ; CHECK-NEXT:    ret <3 x i17> [[C]]
44   %s = select <3 x i1> %b, <3 x i17> %x, <3 x i17> <i17 7, i17 -1, i17 0>
45   %c = call <3 x i17> @llvm.ctlz.v3i17(<3 x i17> %s, i1 true)
46   ret <3 x i17> %c
49 define i32 @ctlz_sel_const_true_false_extra_use(i1 %b) {
50 ; CHECK-LABEL: @ctlz_sel_const_true_false_extra_use(
51 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 -1, i32 7
52 ; CHECK-NEXT:    call void @use(i32 [[S]])
53 ; CHECK-NEXT:    [[C:%.*]] = call range(i32 0, 30) i32 @llvm.ctlz.i32(i32 [[S]], i1 true)
54 ; CHECK-NEXT:    ret i32 [[C]]
56   %s = select i1 %b, i32 -1, i32 7
57   call void @use(i32 %s)
58   %c = call i32 @llvm.ctlz.i32(i32 %s, i1 false)
59   ret i32 %c
62 define i32 @cttz_sel_const_true_false(i1 %b) {
63 ; CHECK-LABEL: @cttz_sel_const_true_false(
64 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 0
65 ; CHECK-NEXT:    ret i32 [[C]]
67   %s = select i1 %b, i32 4, i32 -7
68   %c = call i32 @llvm.cttz.i32(i32 %s, i1 false)
69   ret i32 %c
72 define i32 @cttz_sel_const_true(i1 %b, i32 %x) {
73 ; CHECK-LABEL: @cttz_sel_const_true(
74 ; CHECK-NEXT:    [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
75 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 [[TMP1]]
76 ; CHECK-NEXT:    ret i32 [[C]]
78   %s = select i1 %b, i32 5, i32 %x
79   %c = call i32 @llvm.cttz.i32(i32 %s, i1 true)
80   ret i32 %c
83 define <3 x i5> @cttz_sel_const_false(<3 x i1> %b, <3 x i5> %x) {
84 ; CHECK-LABEL: @cttz_sel_const_false(
85 ; CHECK-NEXT:    [[TMP1:%.*]] = call range(i5 0, 6) <3 x i5> @llvm.cttz.v3i5(<3 x i5> [[X:%.*]], i1 false)
86 ; CHECK-NEXT:    [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> [[TMP1]], <3 x i5> <i5 0, i5 0, i5 5>
87 ; CHECK-NEXT:    ret <3 x i5> [[C]]
89   %s = select <3 x i1> %b, <3 x i5> %x, <3 x i5> <i5 7, i5 -1, i5 0>
90   %c = call <3 x i5> @llvm.cttz.v3i5(<3 x i5> %s, i1 false)
91   ret <3 x i5> %c
94 define i32 @cttz_sel_const_true_false_extra_use(i1 %b) {
95 ; CHECK-LABEL: @cttz_sel_const_true_false_extra_use(
96 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 -8
97 ; CHECK-NEXT:    call void @use(i32 [[S]])
98 ; CHECK-NEXT:    [[C:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[S]], i1 true)
99 ; CHECK-NEXT:    ret i32 [[C]]
101   %s = select i1 %b, i32 5, i32 -8
102   call void @use(i32 %s)
103   %c = call i32 @llvm.cttz.i32(i32 %s, i1 true)
104   ret i32 %c
107 define i32 @ctpop_sel_const_true_false(i1 %b) {
108 ; CHECK-LABEL: @ctpop_sel_const_true_false(
109 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 30
110 ; CHECK-NEXT:    ret i32 [[C]]
112   %s = select i1 %b, i32 5, i32 -7
113   %c = call i32 @llvm.ctpop.i32(i32 %s)
114   ret i32 %c
117 define i32 @ctpop_sel_const_true(i1 %b, i32 %x) {
118 ; CHECK-LABEL: @ctpop_sel_const_true(
119 ; CHECK-NEXT:    [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
120 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 [[TMP1]]
121 ; CHECK-NEXT:    ret i32 [[C]]
123   %s = select i1 %b, i32 5, i32 %x
124   %c = call i32 @llvm.ctpop.i32(i32 %s)
125   ret i32 %c
128 define <3 x i7> @ctpop_sel_const_false(<3 x i1> %b, <3 x i7> %x) {
129 ; CHECK-LABEL: @ctpop_sel_const_false(
130 ; CHECK-NEXT:    [[TMP1:%.*]] = call range(i7 0, 8) <3 x i7> @llvm.ctpop.v3i7(<3 x i7> [[X:%.*]])
131 ; CHECK-NEXT:    [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i7> [[TMP1]], <3 x i7> <i7 3, i7 7, i7 0>
132 ; CHECK-NEXT:    ret <3 x i7> [[C]]
134   %s = select <3 x i1> %b, <3 x i7> %x, <3 x i7> <i7 7, i7 -1, i7 0>
135   %c = call <3 x i7> @llvm.ctpop.v3i7(<3 x i7> %s)
136   ret <3 x i7> %c
139 define i32 @ctpop_sel_const_true_false_extra_use(i1 %b) {
140 ; CHECK-LABEL: @ctpop_sel_const_true_false_extra_use(
141 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 7
142 ; CHECK-NEXT:    call void @use(i32 [[S]])
143 ; CHECK-NEXT:    [[C:%.*]] = call range(i32 2, 4) i32 @llvm.ctpop.i32(i32 [[S]])
144 ; CHECK-NEXT:    ret i32 [[C]]
146   %s = select i1 %b, i32 5, i32 7
147   call void @use(i32 %s)
148   %c = call i32 @llvm.ctpop.i32(i32 %s)
149   ret i32 %c
152 define i32 @usub_sat_rhs_const_select_all_const(i1 %b) {
153 ; CHECK-LABEL: @usub_sat_rhs_const_select_all_const(
154 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 3
155 ; CHECK-NEXT:    ret i32 [[C]]
157   %s = select i1 %b, i32 5, i32 10
158   %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)
159   ret i32 %c
162 define i32 @usub_sat_rhs_var_select_all_const(i1 %b, i32 %x) {
163 ; CHECK-LABEL: @usub_sat_rhs_var_select_all_const(
164 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 5, i32 10
165 ; CHECK-NEXT:    [[C:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[S]], i32 [[X:%.*]])
166 ; CHECK-NEXT:    ret i32 [[C]]
168   %s = select i1 %b, i32 5, i32 10
169   %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 %x)
170   ret i32 %c
173 define i32 @usub_sat_rhs_const_select_one_const(i1 %b, i32 %x) {
174 ; CHECK-LABEL: @usub_sat_rhs_const_select_one_const(
175 ; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[X:%.*]], i32 7)
176 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 0, i32 [[TMP1]]
177 ; CHECK-NEXT:    ret i32 [[C]]
179   %s = select i1 %b, i32 5, i32 %x
180   %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)
181   ret i32 %c
184 define i32 @usub_sat_rhs_const_select_no_const(i1 %b, i32 %x, i32 %y) {
185 ; CHECK-LABEL: @usub_sat_rhs_const_select_no_const(
186 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], i32 [[Y:%.*]], i32 [[X:%.*]]
187 ; CHECK-NEXT:    [[C:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[S]], i32 7)
188 ; CHECK-NEXT:    ret i32 [[C]]
190   %s = select i1 %b, i32 %y, i32 %x
191   %c = call i32 @llvm.usub.sat.i32(i32 %s, i32 7)
192   ret i32 %c
195 define i32 @usub_sat_lhs_const_select_all_const(i1 %b) {
196 ; CHECK-LABEL: @usub_sat_lhs_const_select_all_const(
197 ; CHECK-NEXT:    [[C:%.*]] = select i1 [[B:%.*]], i32 2, i32 0
198 ; CHECK-NEXT:    ret i32 [[C]]
200   %s = select i1 %b, i32 5, i32 10
201   %c = call i32 @llvm.usub.sat.i32(i32 7, i32 %s)
202   ret i32 %c
205 @g1 = constant <2 x i32> zeroinitializer
206 @g2 = external global i8
207 declare <2 x i32> @llvm.masked.load.v2i32.p0(ptr, i32, <2 x i1>, <2 x i32>)
209 define <2 x i32> @non_speculatable(i1 %b) {
210 ; CHECK-LABEL: @non_speculatable(
211 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], ptr @g1, ptr @g2
212 ; 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)
213 ; CHECK-NEXT:    ret <2 x i32> [[C]]
215   %s = select i1 %b, ptr @g1, ptr @g2
216   %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)
217   ret <2 x i32> %c
220 declare i32 @llvm.vector.reduce.add.v2i32(<2 x i32>)
222 define i32 @vec_to_scalar_select_scalar(i1 %b) {
223 ; CHECK-LABEL: @vec_to_scalar_select_scalar(
224 ; CHECK-NEXT:    [[S:%.*]] = select i1 [[B:%.*]], <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
225 ; CHECK-NEXT:    [[C:%.*]] = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> [[S]])
226 ; CHECK-NEXT:    ret i32 [[C]]
228   %s = select i1 %b, <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
229   %c = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %s)
230   ret i32 %c
233 define i32 @vec_to_scalar_select_vector(<2 x i1> %b) {
234 ; CHECK-LABEL: @vec_to_scalar_select_vector(
235 ; CHECK-NEXT:    [[S:%.*]] = select <2 x i1> [[B:%.*]], <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
236 ; CHECK-NEXT:    [[C:%.*]] = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> [[S]])
237 ; CHECK-NEXT:    ret i32 [[C]]
239   %s = select <2 x i1> %b, <2 x i32> <i32 1, i32 2>, <2 x i32> <i32 3, i32 4>
240   %c = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %s)
241   ret i32 %c
244 define i8 @test_drop_noundef(i1 %cond, i8 %val) {
245 ; CHECK-LABEL: @test_drop_noundef(
246 ; CHECK-NEXT:  entry:
247 ; CHECK-NEXT:    [[TMP0:%.*]] = call i8 @llvm.smin.i8(i8 [[VAL:%.*]], i8 0)
248 ; CHECK-NEXT:    [[RET:%.*]] = select i1 [[COND:%.*]], i8 -1, i8 [[TMP0]]
249 ; CHECK-NEXT:    ret i8 [[RET]]
251 entry:
252   %sel = select i1 %cond, i8 -1, i8 %val
253   %ret = call noundef i8 @llvm.smin.i8(i8 %sel, i8 0)
254   ret i8 %ret
257 define i1 @pr85536(i32 %a) {
258 ; CHECK-LABEL: @pr85536(
259 ; CHECK-NEXT:  entry:
260 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], 31
261 ; CHECK-NEXT:    [[SHL1:%.*]] = shl nsw i32 -1, [[A]]
262 ; CHECK-NEXT:    [[ZEXT:%.*]] = zext i32 [[SHL1]] to i64
263 ; CHECK-NEXT:    [[SHL2:%.*]] = shl i64 [[ZEXT]], 48
264 ; CHECK-NEXT:    [[SHR:%.*]] = ashr exact i64 [[SHL2]], 48
265 ; CHECK-NEXT:    [[TMP0:%.*]] = call i64 @llvm.smin.i64(i64 [[SHR]], i64 0)
266 ; CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 65535
267 ; CHECK-NEXT:    [[RET1:%.*]] = icmp eq i64 [[TMP1]], 0
268 ; CHECK-NEXT:    [[RET:%.*]] = select i1 [[CMP1]], i1 [[RET1]], i1 false
269 ; CHECK-NEXT:    ret i1 [[RET]]
271 entry:
272   %cmp1 = icmp ugt i32 %a, 30
273   %shl1 = shl nsw i32 -1, %a
274   %zext = zext i32 %shl1 to i64
275   %shl2 = shl i64 %zext, 48
276   %shr = ashr exact i64 %shl2, 48
277   %sel = select i1 %cmp1, i64 -1, i64 %shr
278   %smin = call noundef i64 @llvm.smin.i64(i64 %sel, i64 0)
279   %masked = and i64 %smin, 65535
280   %ret = icmp eq i64 %masked, 0
281   ret i1 %ret
284 define double @test_fabs_select1(double %a) {
285 ; CHECK-LABEL: @test_fabs_select1(
286 ; CHECK-NEXT:    [[COND:%.*]] = fcmp uno double [[A:%.*]], 0.000000e+00
287 ; CHECK-NEXT:    [[SEL1:%.*]] = select i1 [[COND]], double 0x7FF8000000000000, double [[A]]
288 ; CHECK-NEXT:    ret double [[SEL1]]
290   %cond = fcmp uno double %a, 0.000000e+00
291   %sel1 = select i1 %cond, double 0x7FF8000000000000, double %a
292   %fabs = call double @llvm.fabs.f64(double %sel1)
293   %sel2 = select i1 %cond, double %fabs, double %a
294   ret double %sel2
297 define <2 x double> @test_fabs_select1_vec(<2 x double> %a) {
298 ; CHECK-LABEL: @test_fabs_select1_vec(
299 ; CHECK-NEXT:    [[COND:%.*]] = fcmp uno <2 x double> [[A:%.*]], zeroinitializer
300 ; CHECK-NEXT:    [[SEL2:%.*]] = select <2 x i1> [[COND]], <2 x double> splat (double 0x7FF8000000000000), <2 x double> [[A]]
301 ; CHECK-NEXT:    ret <2 x double> [[SEL2]]
303   %cond = fcmp uno <2 x double> %a, zeroinitializer
304   %sel1 = select <2 x i1> %cond, <2 x double> splat(double 0x7FF8000000000000), <2 x double> %a
305   %fabs = call <2 x double> @llvm.fabs.v2f64(<2 x double> %sel1)
306   %sel2 = select <2 x i1> %cond, <2 x double> %fabs, <2 x double> %a
307   ret <2 x double> %sel2
310 define double @test_fabs_select2(double %a) {
311 ; CHECK-LABEL: @test_fabs_select2(
312 ; CHECK-NEXT:    [[ABS1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])
313 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq double [[ABS1]], 0x7FF0000000000000
314 ; CHECK-NEXT:    [[ABS2:%.*]] = select i1 [[CMP]], double 0.000000e+00, double [[ABS1]]
315 ; CHECK-NEXT:    ret double [[ABS2]]
317   %abs1 = call double @llvm.fabs.f64(double %a)
318   %cmp = fcmp oeq double %abs1, 0x7FF0000000000000
319   %sel = select i1 %cmp, double -0.000000e+00, double %abs1
320   %abs2 = call double @llvm.fabs.f64(double %sel)
321   ret double %abs2
324 ; nsz flag should be dropped.
326 define double @test_fabs_select_fmf1(i1 %cond, double %a) {
327 ; CHECK-LABEL: @test_fabs_select_fmf1(
328 ; CHECK-NEXT:    [[A:%.*]] = call double @llvm.fabs.f64(double [[A1:%.*]])
329 ; CHECK-NEXT:    [[FABS:%.*]] = select nnan ninf i1 [[COND:%.*]], double 0.000000e+00, double [[A]]
330 ; CHECK-NEXT:    ret double [[FABS]]
332   %sel1 = select nnan ninf nsz i1 %cond, double 0.0, double %a
333   %fabs = call double @llvm.fabs.f64(double %sel1)
334   ret double %fabs
337 define double @test_fabs_select_fmf2(i1 %cond, double %a) {
338 ; CHECK-LABEL: @test_fabs_select_fmf2(
339 ; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])
340 ; CHECK-NEXT:    [[SEL1:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], double 0.000000e+00, double [[TMP1]]
341 ; CHECK-NEXT:    ret double [[SEL1]]
343   %sel1 = select i1 %cond, double 0.0, double %a
344   %fabs = call nnan ninf nsz double @llvm.fabs.f64(double %sel1)
345   ret double %fabs