xref: /llvm-project/llvm/test/Transforms/InstCombine/fpcast.ll (revision 99dc3967595c472b6edbe789a1346b0350294567)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Test some floating point casting cases
3; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4
5define i8 @test1() {
6; CHECK-LABEL: @test1(
7; CHECK-NEXT:    ret i8 -1
8;
9  %x = fptoui float 2.550000e+02 to i8
10  ret i8 %x
11}
12
13define i8 @test2() {
14; CHECK-LABEL: @test2(
15; CHECK-NEXT:    ret i8 -1
16;
17  %x = fptosi float -1.000000e+00 to i8
18  ret i8 %x
19}
20
21define half @test3(float %a) {
22; CHECK-LABEL: @test3(
23; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half
24; CHECK-NEXT:    [[C:%.*]] = call half @llvm.fabs.f16(half [[TMP1]])
25; CHECK-NEXT:    ret half [[C]]
26;
27  %b = call float @llvm.fabs.f32(float %a)
28  %c = fptrunc float %b to half
29  ret half %c
30}
31
32define half @test3_fast(float %a) {
33; CHECK-LABEL: @test3_fast(
34; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half
35; CHECK-NEXT:    [[C:%.*]] = call half @llvm.fabs.f16(half [[TMP1]])
36; CHECK-NEXT:    ret half [[C]]
37;
38  %b = call float @llvm.fabs.f32(float %a)
39  %c = fptrunc fast float %b to half
40  ret half %c
41}
42
43define half @fneg_fptrunc(float %a) {
44; CHECK-LABEL: @fneg_fptrunc(
45; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half
46; CHECK-NEXT:    [[C:%.*]] = fneg half [[TMP1]]
47; CHECK-NEXT:    ret half [[C]]
48;
49  %b = fsub float -0.0, %a
50  %c = fptrunc float %b to half
51  ret half %c
52}
53
54define half @unary_fneg_fptrunc(float %a) {
55; CHECK-LABEL: @unary_fneg_fptrunc(
56; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half
57; CHECK-NEXT:    [[C:%.*]] = fneg half [[TMP1]]
58; CHECK-NEXT:    ret half [[C]]
59;
60  %b = fneg float %a
61  %c = fptrunc float %b to half
62  ret half %c
63}
64
65define <2 x half> @fneg_fptrunc_vec_poison(<2 x float> %a) {
66; CHECK-LABEL: @fneg_fptrunc_vec_poison(
67; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half>
68; CHECK-NEXT:    [[C:%.*]] = fneg <2 x half> [[TMP1]]
69; CHECK-NEXT:    ret <2 x half> [[C]]
70;
71  %b = fsub <2 x float> <float -0.0, float poison>, %a
72  %c = fptrunc <2 x float> %b to <2 x half>
73  ret <2 x half> %c
74}
75
76define <2 x half> @unary_fneg_fptrunc_vec(<2 x float> %a) {
77; CHECK-LABEL: @unary_fneg_fptrunc_vec(
78; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half>
79; CHECK-NEXT:    [[C:%.*]] = fneg <2 x half> [[TMP1]]
80; CHECK-NEXT:    ret <2 x half> [[C]]
81;
82  %b = fneg <2 x float> %a
83  %c = fptrunc <2 x float> %b to <2 x half>
84  ret <2 x half> %c
85}
86
87define half @test4-fast(float %a) {
88; CHECK-LABEL: @test4-fast(
89; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc fast float [[A:%.*]] to half
90; CHECK-NEXT:    [[C:%.*]] = fneg fast half [[TMP1]]
91; CHECK-NEXT:    ret half [[C]]
92;
93  %b = fsub fast float -0.0, %a
94  %c = fptrunc fast float %b to half
95  ret half %c
96}
97
98define half @test4-mixed-fast-1(float %a) {
99; CHECK-LABEL: @test4-mixed-fast-1(
100; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half
101; CHECK-NEXT:    [[C:%.*]] = fneg half [[TMP1]]
102; CHECK-NEXT:    ret half [[C]]
103;
104  %b = fsub float -0.0, %a
105  %c = fptrunc fast float %b to half
106  ret half %c
107}
108
109define half @test4-mixed-fast-2(float %a) {
110; CHECK-LABEL: @test4-mixed-fast-2(
111; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half
112; CHECK-NEXT:    [[C:%.*]] = fneg half [[TMP1]]
113; CHECK-NEXT:    ret half [[C]]
114;
115  %b = fsub fast float -0.0, %a
116  %c = fptrunc float %b to half
117  ret half %c
118}
119
120define half @test4_unary_fneg-fast(float %a) {
121; CHECK-LABEL: @test4_unary_fneg-fast(
122; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc fast float [[A:%.*]] to half
123; CHECK-NEXT:    [[C:%.*]] = fneg fast half [[TMP1]]
124; CHECK-NEXT:    ret half [[C]]
125;
126  %b = fneg fast float %a
127  %c = fptrunc fast float %b to half
128  ret half %c
129}
130
131define half @test4_unary_fneg-mixed-fast-1(float %a) {
132; CHECK-LABEL: @test4_unary_fneg-mixed-fast-1(
133; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half
134; CHECK-NEXT:    [[C:%.*]] = fneg half [[TMP1]]
135; CHECK-NEXT:    ret half [[C]]
136;
137  %b = fneg float %a
138  %c = fptrunc fast float %b to half
139  ret half %c
140}
141
142define half @test4_unary_fneg-mixed-fast-2(float %a) {
143; CHECK-LABEL: @test4_unary_fneg-mixed-fast-2(
144; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[A:%.*]] to half
145; CHECK-NEXT:    [[C:%.*]] = fneg half [[TMP1]]
146; CHECK-NEXT:    ret half [[C]]
147;
148  %b = fneg fast float %a
149  %c = fptrunc float %b to half
150  ret half %c
151}
152
153define <2 x half> @test4_unary_fneg-vec-fast(<2 x float> %a) {
154; CHECK-LABEL: @test4_unary_fneg-vec-fast(
155; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc fast <2 x float> [[A:%.*]] to <2 x half>
156; CHECK-NEXT:    [[C:%.*]] = fneg fast <2 x half> [[TMP1]]
157; CHECK-NEXT:    ret <2 x half> [[C]]
158;
159  %b = fneg fast <2 x float> %a
160  %c = fptrunc fast <2 x float> %b to <2 x half>
161  ret <2 x half> %c
162}
163
164define <2 x half> @test4_unary_fneg-vec-mixed-fast-1(<2 x float> %a) {
165; CHECK-LABEL: @test4_unary_fneg-vec-mixed-fast-1(
166; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half>
167; CHECK-NEXT:    [[C:%.*]] = fneg <2 x half> [[TMP1]]
168; CHECK-NEXT:    ret <2 x half> [[C]]
169;
170  %b = fneg <2 x float> %a
171  %c = fptrunc fast <2 x float> %b to <2 x half>
172  ret <2 x half> %c
173}
174
175define <2 x half> @test4_unary_fneg-vec-mixed-fast-2(<2 x float> %a) {
176; CHECK-LABEL: @test4_unary_fneg-vec-mixed-fast-2(
177; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x float> [[A:%.*]] to <2 x half>
178; CHECK-NEXT:    [[C:%.*]] = fneg <2 x half> [[TMP1]]
179; CHECK-NEXT:    ret <2 x half> [[C]]
180;
181  %b = fneg fast <2 x float> %a
182  %c = fptrunc <2 x float> %b to <2 x half>
183  ret <2 x half> %c
184}
185
186define half @test5(float %a, float %b, float %c) {
187; CHECK-LABEL: @test5(
188; CHECK-NEXT:    [[D:%.*]] = fcmp ogt float [[A:%.*]], [[B:%.*]]
189; CHECK-NEXT:    [[E:%.*]] = select i1 [[D]], float [[C:%.*]], float 1.000000e+00
190; CHECK-NEXT:    [[F:%.*]] = fptrunc float [[E]] to half
191; CHECK-NEXT:    ret half [[F]]
192;
193  %d = fcmp ogt float %a, %b
194  %e = select i1 %d, float %c, float 1.0
195  %f = fptrunc float %e to half
196  ret half %f
197}
198
199declare float @llvm.fabs.f32(float) nounwind readonly
200
201define <1 x float> @test6(<1 x double> %V) {
202; CHECK-LABEL: @test6(
203; CHECK-NEXT:    [[FREM:%.*]] = frem <1 x double> [[V:%.*]], [[V]]
204; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc <1 x double> [[FREM]] to <1 x float>
205; CHECK-NEXT:    ret <1 x float> [[TRUNC]]
206;
207  %frem = frem <1 x double> %V, %V
208  %trunc = fptrunc <1 x double> %frem to <1 x float>
209  ret <1 x float> %trunc
210}
211
212define float @test7(double %V) {
213; CHECK-LABEL: @test7(
214; CHECK-NEXT:    [[FREM:%.*]] = frem double [[V:%.*]], 1.000000e+00
215; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[FREM]] to float
216; CHECK-NEXT:    ret float [[TRUNC]]
217;
218  %frem = frem double %V, 1.000000e+00
219  %trunc = fptrunc double %frem to float
220  ret float %trunc
221}
222
223define float @test8(float %V) {
224; CHECK-LABEL: @test8(
225; CHECK-NEXT:    [[FEXT:%.*]] = fpext float [[V:%.*]] to double
226; CHECK-NEXT:    [[FREM:%.*]] = frem double [[FEXT]], 1.000000e-01
227; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc double [[FREM]] to float
228; CHECK-NEXT:    ret float [[TRUNC]]
229;
230  %fext = fpext float %V to double
231  %frem = frem double %fext, 1.000000e-01
232  %trunc = fptrunc double %frem to float
233  ret float %trunc
234}
235
236define half @test_fptrunc_fptrunc(double %V) {
237; CHECK-LABEL: @test_fptrunc_fptrunc(
238; CHECK-NEXT:    [[T1:%.*]] = fptrunc double [[V:%.*]] to float
239; CHECK-NEXT:    [[T2:%.*]] = fptrunc float [[T1]] to half
240; CHECK-NEXT:    ret half [[T2]]
241;
242  %t1 = fptrunc double %V to float
243  %t2 = fptrunc float %t1 to half
244  ret half %t2
245}
246
247define half @sint_to_fptrunc(i32 %x) {
248; CHECK-LABEL: @sint_to_fptrunc(
249; CHECK-NEXT:    [[F:%.*]] = sitofp i32 [[X:%.*]] to float
250; CHECK-NEXT:    [[R:%.*]] = fptrunc float [[F]] to half
251; CHECK-NEXT:    ret half [[R]]
252;
253  %f = sitofp i32 %x to float
254  %r = fptrunc float %f to half
255  ret half %r
256}
257
258define half @masked_sint_to_fptrunc1(i32 %x) {
259; CHECK-LABEL: @masked_sint_to_fptrunc1(
260; CHECK-NEXT:    [[M:%.*]] = and i32 [[X:%.*]], 16777215
261; CHECK-NEXT:    [[R:%.*]] = uitofp nneg i32 [[M]] to half
262; CHECK-NEXT:    ret half [[R]]
263;
264  %m = and i32 %x, 16777215
265  %f = sitofp i32 %m to float
266  %r = fptrunc float %f to half
267  ret half %r
268}
269
270define half @masked_sint_to_fptrunc2(i32 %x) {
271; CHECK-LABEL: @masked_sint_to_fptrunc2(
272; CHECK-NEXT:    [[M:%.*]] = lshr i32 [[X:%.*]], 8
273; CHECK-NEXT:    [[R:%.*]] = uitofp nneg i32 [[M]] to half
274; CHECK-NEXT:    ret half [[R]]
275;
276  %m = lshr i32 %x, 8
277  %f = sitofp i32 %m to float
278  %r = fptrunc float %f to half
279  ret half %r
280}
281
282define half @masked_sint_to_fptrunc3(i32 %x) {
283; CHECK-LABEL: @masked_sint_to_fptrunc3(
284; CHECK-NEXT:    [[M:%.*]] = lshr i32 [[X:%.*]], 7
285; CHECK-NEXT:    [[F:%.*]] = uitofp nneg i32 [[M]] to float
286; CHECK-NEXT:    [[R:%.*]] = fptrunc float [[F]] to half
287; CHECK-NEXT:    ret half [[R]]
288;
289  %m = lshr i32 %x, 7
290  %f = sitofp i32 %m to float
291  %r = fptrunc float %f to half
292  ret half %r
293}
294
295define double @sint_to_fpext(i32 %x) {
296; CHECK-LABEL: @sint_to_fpext(
297; CHECK-NEXT:    [[F:%.*]] = sitofp i32 [[X:%.*]] to float
298; CHECK-NEXT:    [[R:%.*]] = fpext float [[F]] to double
299; CHECK-NEXT:    ret double [[R]]
300;
301  %f = sitofp i32 %x to float
302  %r = fpext float %f to double
303  ret double %r
304}
305
306define double @masked_sint_to_fpext1(i32 %x) {
307; CHECK-LABEL: @masked_sint_to_fpext1(
308; CHECK-NEXT:    [[M:%.*]] = and i32 [[X:%.*]], 16777215
309; CHECK-NEXT:    [[R:%.*]] = uitofp nneg i32 [[M]] to double
310; CHECK-NEXT:    ret double [[R]]
311;
312  %m = and i32 %x, 16777215
313  %f = sitofp i32 %m to float
314  %r = fpext float %f to double
315  ret double %r
316}
317
318define double @masked_sint_to_fpext2(i32 %x) {
319; CHECK-LABEL: @masked_sint_to_fpext2(
320; CHECK-NEXT:    [[M:%.*]] = lshr i32 [[X:%.*]], 8
321; CHECK-NEXT:    [[R:%.*]] = uitofp nneg i32 [[M]] to double
322; CHECK-NEXT:    ret double [[R]]
323;
324  %m = lshr i32 %x, 8
325  %f = sitofp i32 %m to float
326  %r = fpext float %f to double
327  ret double %r
328}
329
330define double @masked_sint_to_fpext3(i32 %x) {
331; CHECK-LABEL: @masked_sint_to_fpext3(
332; CHECK-NEXT:    [[M:%.*]] = lshr i32 [[X:%.*]], 7
333; CHECK-NEXT:    [[F:%.*]] = uitofp nneg i32 [[M]] to float
334; CHECK-NEXT:    [[R:%.*]] = fpext float [[F]] to double
335; CHECK-NEXT:    ret double [[R]]
336;
337  %m = lshr i32 %x, 7
338  %f = sitofp i32 %m to float
339  %r = fpext float %f to double
340  ret double %r
341}
342
343define half @uint_to_fptrunc(i32 %x) {
344; CHECK-LABEL: @uint_to_fptrunc(
345; CHECK-NEXT:    [[F:%.*]] = uitofp i32 [[X:%.*]] to float
346; CHECK-NEXT:    [[R:%.*]] = fptrunc float [[F]] to half
347; CHECK-NEXT:    ret half [[R]]
348;
349  %f = uitofp i32 %x to float
350  %r = fptrunc float %f to half
351  ret half %r
352}
353
354define half @masked_uint_to_fptrunc1(i32 %x) {
355; CHECK-LABEL: @masked_uint_to_fptrunc1(
356; CHECK-NEXT:    [[M:%.*]] = and i32 [[X:%.*]], 16777215
357; CHECK-NEXT:    [[R:%.*]] = uitofp nneg i32 [[M]] to half
358; CHECK-NEXT:    ret half [[R]]
359;
360  %m = and i32 %x, 16777215
361  %f = uitofp i32 %m to float
362  %r = fptrunc float %f to half
363  ret half %r
364}
365
366define half @masked_uint_to_fptrunc2(i32 %x) {
367; CHECK-LABEL: @masked_uint_to_fptrunc2(
368; CHECK-NEXT:    [[M:%.*]] = lshr i32 [[X:%.*]], 8
369; CHECK-NEXT:    [[R:%.*]] = uitofp nneg i32 [[M]] to half
370; CHECK-NEXT:    ret half [[R]]
371;
372  %m = lshr i32 %x, 8
373  %f = uitofp i32 %m to float
374  %r = fptrunc float %f to half
375  ret half %r
376}
377
378define half @masked_uint_to_fptrunc3(i32 %x) {
379; CHECK-LABEL: @masked_uint_to_fptrunc3(
380; CHECK-NEXT:    [[M:%.*]] = lshr i32 [[X:%.*]], 7
381; CHECK-NEXT:    [[F:%.*]] = uitofp nneg i32 [[M]] to float
382; CHECK-NEXT:    [[R:%.*]] = fptrunc float [[F]] to half
383; CHECK-NEXT:    ret half [[R]]
384;
385  %m = lshr i32 %x, 7
386  %f = uitofp i32 %m to float
387  %r = fptrunc float %f to half
388  ret half %r
389}
390
391define double @uint_to_fpext(i32 %x) {
392; CHECK-LABEL: @uint_to_fpext(
393; CHECK-NEXT:    [[F:%.*]] = uitofp i32 [[X:%.*]] to float
394; CHECK-NEXT:    [[R:%.*]] = fpext float [[F]] to double
395; CHECK-NEXT:    ret double [[R]]
396;
397  %f = uitofp i32 %x to float
398  %r = fpext float %f to double
399  ret double %r
400}
401
402define double @masked_uint_to_fpext1(i32 %x) {
403; CHECK-LABEL: @masked_uint_to_fpext1(
404; CHECK-NEXT:    [[M:%.*]] = and i32 [[X:%.*]], 16777215
405; CHECK-NEXT:    [[R:%.*]] = uitofp nneg i32 [[M]] to double
406; CHECK-NEXT:    ret double [[R]]
407;
408  %m = and i32 %x, 16777215
409  %f = uitofp i32 %m to float
410  %r = fpext float %f to double
411  ret double %r
412}
413
414define double @masked_uint_to_fpext2(i32 %x) {
415; CHECK-LABEL: @masked_uint_to_fpext2(
416; CHECK-NEXT:    [[M:%.*]] = lshr i32 [[X:%.*]], 8
417; CHECK-NEXT:    [[R:%.*]] = uitofp nneg i32 [[M]] to double
418; CHECK-NEXT:    ret double [[R]]
419;
420  %m = lshr i32 %x, 8
421  %f = uitofp i32 %m to float
422  %r = fpext float %f to double
423  ret double %r
424}
425
426define double @masked_uint_to_fpext3(i32 %x) {
427; CHECK-LABEL: @masked_uint_to_fpext3(
428; CHECK-NEXT:    [[M:%.*]] = lshr i32 [[X:%.*]], 7
429; CHECK-NEXT:    [[F:%.*]] = uitofp nneg i32 [[M]] to float
430; CHECK-NEXT:    [[R:%.*]] = fpext float [[F]] to double
431; CHECK-NEXT:    ret double [[R]]
432;
433  %m = lshr i32 %x, 7
434  %f = uitofp i32 %m to float
435  %r = fpext float %f to double
436  ret double %r
437}
438
439define i32 @fptosi_nonnorm(float nofpclass(norm) %x) {
440; CHECK-LABEL: @fptosi_nonnorm(
441; CHECK-NEXT:    ret i32 0
442;
443  %ret = fptosi float %x to i32
444  ret i32 %ret
445}
446
447define i32 @fptoui_nonnorm(float nofpclass(pnorm) %x) {
448; CHECK-LABEL: @fptoui_nonnorm(
449; CHECK-NEXT:    ret i32 0
450;
451  %ret = fptoui float %x to i32
452  ret i32 %ret
453}
454
455define i32 @fptosi_nonnnorm(float nofpclass(nnorm) %x) {
456; CHECK-LABEL: @fptosi_nonnnorm(
457; CHECK-NEXT:    [[RET:%.*]] = fptosi float [[X:%.*]] to i32
458; CHECK-NEXT:    ret i32 [[RET]]
459;
460  %ret = fptosi float %x to i32
461  ret i32 %ret
462}
463
464define i32 @fptoui_nonnnorm(float nofpclass(nnorm) %x) {
465; CHECK-LABEL: @fptoui_nonnnorm(
466; CHECK-NEXT:    [[RET:%.*]] = fptoui float [[X:%.*]] to i32
467; CHECK-NEXT:    ret i32 [[RET]]
468;
469  %ret = fptoui float %x to i32
470  ret i32 %ret
471}
472
473define i32 @fptosi_nonnorm_copysign(float %x) {
474; CHECK-LABEL: @fptosi_nonnorm_copysign(
475; CHECK-NEXT:    ret i32 0
476;
477  %val = call float @llvm.copysign.f32(float 0.0, float %x)
478  %ret = fptosi float %val to i32
479  ret i32 %ret
480}
481
482define <2 x i32> @fptosi_nonnorm_copysign_vec(<2 x float> %x) {
483; CHECK-LABEL: @fptosi_nonnorm_copysign_vec(
484; CHECK-NEXT:    ret <2 x i32> zeroinitializer
485;
486  %val = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> %x)
487  %ret = fptosi <2 x float> %val to <2 x i32>
488  ret <2 x i32> %ret
489}
490
491define i32 @fptosi_nonnorm_fmul(float %x) {
492; CHECK-LABEL: @fptosi_nonnorm_fmul(
493; CHECK-NEXT:    [[SEL:%.*]] = fmul float [[X:%.*]], 0.000000e+00
494; CHECK-NEXT:    [[RET:%.*]] = fptosi float [[SEL]] to i32
495; CHECK-NEXT:    ret i32 [[RET]]
496;
497  %sel = fmul float %x, 0.000000e+00
498  %ret = fptosi float %sel to i32
499  ret i32 %ret
500}
501
502define i32 @fptosi_select(i1 %cond) {
503; CHECK-LABEL: @fptosi_select(
504; CHECK-NEXT:    [[RET:%.*]] = select i1 [[COND:%.*]], i32 1, i32 -1
505; CHECK-NEXT:    ret i32 [[RET]]
506;
507  %sel = select i1 %cond, float 1.0, float -1.0
508  %ret = fptosi float %sel to i32
509  ret i32 %ret
510}
511
512define i32 @mul_pos_zero_convert(i32 %a) {
513; CHECK-LABEL: @mul_pos_zero_convert(
514; CHECK-NEXT:  entry:
515; CHECK-NEXT:    ret i32 0
516;
517entry:
518  %fp = sitofp i32 %a to float
519  %ret = fmul float %fp, 0.000000e+00
520  %conv = fptosi float %ret to i32
521  ret i32 %conv
522}
523