xref: /llvm-project/llvm/test/Transforms/InstCombine/fptrunc.ll (revision 99dc3967595c472b6edbe789a1346b0350294567)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4define float @fadd_fpext_op0(float %x, double %y) {
5; CHECK-LABEL: @fadd_fpext_op0(
6; CHECK-NEXT:    [[EXT:%.*]] = fpext float [[X:%.*]] to double
7; CHECK-NEXT:    [[BO:%.*]] = fadd reassoc double [[Y:%.*]], [[EXT]]
8; CHECK-NEXT:    [[R:%.*]] = fptrunc double [[BO]] to float
9; CHECK-NEXT:    ret float [[R]]
10;
11  %ext = fpext float %x to double
12  %bo = fadd reassoc double %ext, %y
13  %r = fptrunc double %bo to float
14  ret float %r
15}
16
17define half @fsub_fpext_op1(half %x, double %y) {
18; CHECK-LABEL: @fsub_fpext_op1(
19; CHECK-NEXT:    [[EXT:%.*]] = fpext half [[X:%.*]] to double
20; CHECK-NEXT:    [[BO:%.*]] = fsub reassoc double [[Y:%.*]], [[EXT]]
21; CHECK-NEXT:    [[R:%.*]] = fptrunc double [[BO]] to half
22; CHECK-NEXT:    ret half [[R]]
23;
24  %ext = fpext half %x to double
25  %bo = fsub reassoc double %y, %ext
26  %r = fptrunc double %bo to half
27  ret half %r
28}
29
30define <2 x float> @fdiv_constant_op0(<2 x double> %x) {
31; CHECK-LABEL: @fdiv_constant_op0(
32; CHECK-NEXT:    [[BO:%.*]] = fdiv reassoc <2 x double> <double 4.210000e+01, double -1.000000e-01>, [[X:%.*]]
33; CHECK-NEXT:    [[R:%.*]] = fptrunc <2 x double> [[BO]] to <2 x float>
34; CHECK-NEXT:    ret <2 x float> [[R]]
35;
36  %bo = fdiv reassoc <2 x double> <double 42.1, double -0.1>, %x
37  %r = fptrunc <2 x double> %bo to <2 x float>
38  ret <2 x float> %r
39}
40
41define <2 x half> @fmul_constant_op1(<2 x float> %x) {
42; CHECK-LABEL: @fmul_constant_op1(
43; CHECK-NEXT:    [[BO:%.*]] = fmul reassoc <2 x float> [[X:%.*]], <float 0x47EFFFFFE0000000, float 5.000000e-01>
44; CHECK-NEXT:    [[R:%.*]] = fptrunc <2 x float> [[BO]] to <2 x half>
45; CHECK-NEXT:    ret <2 x half> [[R]]
46;
47  %bo = fmul reassoc <2 x float> %x, <float 0x47efffffe0000000, float 0.5>
48  %r = fptrunc <2 x float> %bo to <2 x half>
49  ret <2 x half> %r
50}
51
52define float @fptrunc_select_true_val(float %x, double %y, i1 %cond) {
53; CHECK-LABEL: @fptrunc_select_true_val(
54; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc double [[Y:%.*]] to float
55; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select i1 [[COND:%.*]], float [[TMP1]], float [[X:%.*]]
56; CHECK-NEXT:    ret float [[NARROW_SEL]]
57;
58  %e = fpext float %x to double
59  %sel = select fast i1 %cond, double %y, double %e
60  %r = fptrunc double %sel to float
61  ret float %r
62}
63
64define float @fptrunc_fast_select_true_val(float %x, double %y, i1 %cond) {
65; CHECK-LABEL: @fptrunc_fast_select_true_val(
66; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc fast double [[Y:%.*]] to float
67; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select i1 [[COND:%.*]], float [[TMP1]], float [[X:%.*]]
68; CHECK-NEXT:    ret float [[NARROW_SEL]]
69;
70  %e = fpext float %x to double
71  %sel = select fast i1 %cond, double %y, double %e
72  %r = fptrunc fast double %sel to float
73  ret float %r
74}
75
76define <2 x float> @fptrunc_select_false_val(<2 x float> %x, <2 x double> %y, <2 x i1> %cond) {
77; CHECK-LABEL: @fptrunc_select_false_val(
78; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc <2 x double> [[Y:%.*]] to <2 x float>
79; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[TMP1]]
80; CHECK-NEXT:    ret <2 x float> [[NARROW_SEL]]
81;
82  %e = fpext <2 x float> %x to <2 x double>
83  %sel = select nnan <2 x i1> %cond, <2 x double> %e, <2 x double> %y
84  %r = fptrunc <2 x double> %sel to <2 x float>
85  ret <2 x float> %r
86}
87
88define <2 x float> @fptrunc_nnan_select_false_val(<2 x float> %x, <2 x double> %y, <2 x i1> %cond) {
89; CHECK-LABEL: @fptrunc_nnan_select_false_val(
90; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc nnan <2 x double> [[Y:%.*]] to <2 x float>
91; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]], <2 x float> [[TMP1]]
92; CHECK-NEXT:    ret <2 x float> [[NARROW_SEL]]
93;
94  %e = fpext <2 x float> %x to <2 x double>
95  %sel = select nnan <2 x i1> %cond, <2 x double> %e, <2 x double> %y
96  %r = fptrunc nnan <2 x double> %sel to <2 x float>
97  ret <2 x float> %r
98}
99
100declare void @use(float)
101
102define half @fptrunc_select_true_val_extra_use(half %x, float %y, i1 %cond) {
103; CHECK-LABEL: @fptrunc_select_true_val_extra_use(
104; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to float
105; CHECK-NEXT:    call void @use(float [[E]])
106; CHECK-NEXT:    [[TMP1:%.*]] = fptrunc float [[Y:%.*]] to half
107; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select i1 [[COND:%.*]], half [[TMP1]], half [[X]]
108; CHECK-NEXT:    ret half [[NARROW_SEL]]
109;
110  %e = fpext half %x to float
111  call void @use(float %e)
112  %sel = select ninf i1 %cond, float %y, float %e
113  %r = fptrunc float %sel to half
114  ret half %r
115}
116
117define half @fptrunc_max(half %arg) {
118; CHECK-LABEL: @fptrunc_max(
119; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt half [[ARG:%.*]], 0xH0000
120; CHECK-NEXT:    [[NARROW_SEL:%.*]] = select i1 [[CMP]], half 0xH0000, half [[ARG]]
121; CHECK-NEXT:    ret half [[NARROW_SEL]]
122;
123  %ext = fpext half %arg to double
124  %cmp = fcmp olt double %ext, 0.000000e+00
125  %max = select i1 %cmp, double 0.000000e+00, double %ext
126  %trunc = fptrunc double %max to half
127  ret half %trunc
128}
129
130; Negative test - this would require an extra instruction.
131
132define half @fptrunc_select_true_val_extra_use_2(half %x, float %y, i1 %cond) {
133; CHECK-LABEL: @fptrunc_select_true_val_extra_use_2(
134; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to float
135; CHECK-NEXT:    [[SEL:%.*]] = select ninf i1 [[COND:%.*]], float [[Y:%.*]], float [[E]]
136; CHECK-NEXT:    call void @use(float [[SEL]])
137; CHECK-NEXT:    [[R:%.*]] = fptrunc float [[SEL]] to half
138; CHECK-NEXT:    ret half [[R]]
139;
140  %e = fpext half %x to float
141  %sel = select ninf i1 %cond, float %y, float %e
142  call void @use(float %sel)
143  %r = fptrunc float %sel to half
144  ret half %r
145}
146
147; Negative test - the extend must be from the same source type as the result of the trunc.
148
149define float @fptrunc_select_true_val_type_mismatch(half %x, double %y, i1 %cond) {
150; CHECK-LABEL: @fptrunc_select_true_val_type_mismatch(
151; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to double
152; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], double [[Y:%.*]], double [[E]]
153; CHECK-NEXT:    [[R:%.*]] = fptrunc double [[SEL]] to float
154; CHECK-NEXT:    ret float [[R]]
155;
156  %e = fpext half %x to double
157  %sel = select i1 %cond, double %y, double %e
158  %r = fptrunc double %sel to float
159  ret float %r
160}
161
162; Negative test - but given enough FMF, should this be folded?
163
164define float @fptrunc_select_true_val_type_mismatch_fast(half %x, double %y, i1 %cond) {
165; CHECK-LABEL: @fptrunc_select_true_val_type_mismatch_fast(
166; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to double
167; CHECK-NEXT:    [[SEL:%.*]] = select fast i1 [[COND:%.*]], double [[Y:%.*]], double [[E]]
168; CHECK-NEXT:    [[R:%.*]] = fptrunc double [[SEL]] to float
169; CHECK-NEXT:    ret float [[R]]
170;
171  %e = fpext half %x to double
172  %sel = select fast i1 %cond, double %y, double %e
173  %r = fptrunc double %sel to float
174  ret float %r
175}
176
177; Convert from integer is exact, so convert directly to float.
178
179define <2 x float> @ItoFtoF_s54_f64_f32(<2 x i54> %i) {
180; CHECK-LABEL: @ItoFtoF_s54_f64_f32(
181; CHECK-NEXT:    [[R:%.*]] = sitofp <2 x i54> [[I:%.*]] to <2 x float>
182; CHECK-NEXT:    ret <2 x float> [[R]]
183;
184  %x = sitofp <2 x i54> %i to <2 x double>
185  %r = fptrunc <2 x double> %x to <2 x float>
186  ret <2 x float> %r
187}
188
189; Convert from integer is exact, so convert directly to half.
190; Extra use is ok.
191
192define half @ItoFtoF_u24_f32_f16(i24 %i) {
193; CHECK-LABEL: @ItoFtoF_u24_f32_f16(
194; CHECK-NEXT:    [[X:%.*]] = uitofp i24 [[I:%.*]] to float
195; CHECK-NEXT:    call void @use(float [[X]])
196; CHECK-NEXT:    [[R:%.*]] = uitofp i24 [[I]] to half
197; CHECK-NEXT:    ret half [[R]]
198;
199  %x = uitofp i24 %i to float
200  call void @use(float %x)
201  %r = fptrunc float %x to half
202  ret half %r
203}
204
205; Negative test - intermediate rounding in float type.
206
207define float @ItoFtoF_s55_f64_f32(i55 %i) {
208; CHECK-LABEL: @ItoFtoF_s55_f64_f32(
209; CHECK-NEXT:    [[X:%.*]] = sitofp i55 [[I:%.*]] to double
210; CHECK-NEXT:    [[R:%.*]] = fptrunc double [[X]] to float
211; CHECK-NEXT:    ret float [[R]]
212;
213  %x = sitofp i55 %i to double
214  %r = fptrunc double %x to float
215  ret float %r
216}
217
218; Negative test - intermediate rounding in float type.
219
220define half @ItoFtoF_u25_f32_f16(i25 %i) {
221; CHECK-LABEL: @ItoFtoF_u25_f32_f16(
222; CHECK-NEXT:    [[X:%.*]] = uitofp i25 [[I:%.*]] to float
223; CHECK-NEXT:    [[R:%.*]] = fptrunc float [[X]] to half
224; CHECK-NEXT:    ret half [[R]]
225;
226  %x = uitofp i25 %i to float
227  %r = fptrunc float %x to half
228  ret half %r
229}
230
231; Negative test - bitcast bfloat to half is not optimized
232
233define half @fptrunc_to_bfloat_bitcast_to_half(float %src) {
234; CHECK-LABEL: @fptrunc_to_bfloat_bitcast_to_half(
235; CHECK-NEXT:    [[TRUNC:%.*]] = fptrunc float [[SRC:%.*]] to bfloat
236; CHECK-NEXT:    [[CAST:%.*]] = bitcast bfloat [[TRUNC]] to half
237; CHECK-NEXT:    ret half [[CAST]]
238;
239  %trunc = fptrunc float %src to bfloat
240  %cast = bitcast bfloat %trunc to half
241  ret half %cast
242}
243