1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
3 ; RUN: | FileCheck -check-prefix=RV32IFD %s
4 ; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \
5 ; RUN: | FileCheck -check-prefix=RV64IFD %s
7 define float @fcvt_s_d(double %a) nounwind {
8 ; RV32IFD-LABEL: fcvt_s_d:
10 ; RV32IFD-NEXT: addi sp, sp, -16
11 ; RV32IFD-NEXT: sw a0, 8(sp)
12 ; RV32IFD-NEXT: sw a1, 12(sp)
13 ; RV32IFD-NEXT: fld ft0, 8(sp)
14 ; RV32IFD-NEXT: fcvt.s.d ft0, ft0
15 ; RV32IFD-NEXT: fmv.x.w a0, ft0
16 ; RV32IFD-NEXT: addi sp, sp, 16
19 ; RV64IFD-LABEL: fcvt_s_d:
21 ; RV64IFD-NEXT: fmv.d.x ft0, a0
22 ; RV64IFD-NEXT: fcvt.s.d ft0, ft0
23 ; RV64IFD-NEXT: fmv.x.w a0, ft0
25 %1 = fptrunc double %a to float
29 define double @fcvt_d_s(float %a) nounwind {
30 ; RV32IFD-LABEL: fcvt_d_s:
32 ; RV32IFD-NEXT: addi sp, sp, -16
33 ; RV32IFD-NEXT: fmv.w.x ft0, a0
34 ; RV32IFD-NEXT: fcvt.d.s ft0, ft0
35 ; RV32IFD-NEXT: fsd ft0, 8(sp)
36 ; RV32IFD-NEXT: lw a0, 8(sp)
37 ; RV32IFD-NEXT: lw a1, 12(sp)
38 ; RV32IFD-NEXT: addi sp, sp, 16
41 ; RV64IFD-LABEL: fcvt_d_s:
43 ; RV64IFD-NEXT: fmv.w.x ft0, a0
44 ; RV64IFD-NEXT: fcvt.d.s ft0, ft0
45 ; RV64IFD-NEXT: fmv.x.d a0, ft0
47 %1 = fpext float %a to double
51 ; For RV64D, fcvt.l.d is semantically equivalent to fcvt.w.d in this case
52 ; because fptosi will produce poison if the result doesn't fit into an i32.
53 define i32 @fcvt_w_d(double %a) nounwind {
54 ; RV32IFD-LABEL: fcvt_w_d:
56 ; RV32IFD-NEXT: addi sp, sp, -16
57 ; RV32IFD-NEXT: sw a0, 8(sp)
58 ; RV32IFD-NEXT: sw a1, 12(sp)
59 ; RV32IFD-NEXT: fld ft0, 8(sp)
60 ; RV32IFD-NEXT: fcvt.w.d a0, ft0, rtz
61 ; RV32IFD-NEXT: addi sp, sp, 16
64 ; RV64IFD-LABEL: fcvt_w_d:
66 ; RV64IFD-NEXT: fmv.d.x ft0, a0
67 ; RV64IFD-NEXT: fcvt.l.d a0, ft0, rtz
69 %1 = fptosi double %a to i32
73 ; For RV64D, fcvt.lu.d is semantically equivalent to fcvt.wu.d in this case
74 ; because fptosi will produce poison if the result doesn't fit into an i32.
75 define i32 @fcvt_wu_d(double %a) nounwind {
76 ; RV32IFD-LABEL: fcvt_wu_d:
78 ; RV32IFD-NEXT: addi sp, sp, -16
79 ; RV32IFD-NEXT: sw a0, 8(sp)
80 ; RV32IFD-NEXT: sw a1, 12(sp)
81 ; RV32IFD-NEXT: fld ft0, 8(sp)
82 ; RV32IFD-NEXT: fcvt.wu.d a0, ft0, rtz
83 ; RV32IFD-NEXT: addi sp, sp, 16
86 ; RV64IFD-LABEL: fcvt_wu_d:
88 ; RV64IFD-NEXT: fmv.d.x ft0, a0
89 ; RV64IFD-NEXT: fcvt.lu.d a0, ft0, rtz
91 %1 = fptoui double %a to i32
95 define double @fcvt_d_w(i32 %a) nounwind {
96 ; RV32IFD-LABEL: fcvt_d_w:
98 ; RV32IFD-NEXT: addi sp, sp, -16
99 ; RV32IFD-NEXT: fcvt.d.w ft0, a0
100 ; RV32IFD-NEXT: fsd ft0, 8(sp)
101 ; RV32IFD-NEXT: lw a0, 8(sp)
102 ; RV32IFD-NEXT: lw a1, 12(sp)
103 ; RV32IFD-NEXT: addi sp, sp, 16
106 ; RV64IFD-LABEL: fcvt_d_w:
108 ; RV64IFD-NEXT: fcvt.d.w ft0, a0
109 ; RV64IFD-NEXT: fmv.x.d a0, ft0
111 %1 = sitofp i32 %a to double
115 define double @fcvt_d_wu(i32 %a) nounwind {
116 ; RV32IFD-LABEL: fcvt_d_wu:
118 ; RV32IFD-NEXT: addi sp, sp, -16
119 ; RV32IFD-NEXT: fcvt.d.wu ft0, a0
120 ; RV32IFD-NEXT: fsd ft0, 8(sp)
121 ; RV32IFD-NEXT: lw a0, 8(sp)
122 ; RV32IFD-NEXT: lw a1, 12(sp)
123 ; RV32IFD-NEXT: addi sp, sp, 16
126 ; RV64IFD-LABEL: fcvt_d_wu:
128 ; RV64IFD-NEXT: fcvt.d.wu ft0, a0
129 ; RV64IFD-NEXT: fmv.x.d a0, ft0
131 %1 = uitofp i32 %a to double
135 define i64 @fcvt_l_d(double %a) nounwind {
136 ; RV32IFD-LABEL: fcvt_l_d:
138 ; RV32IFD-NEXT: addi sp, sp, -16
139 ; RV32IFD-NEXT: sw ra, 12(sp)
140 ; RV32IFD-NEXT: call __fixdfdi
141 ; RV32IFD-NEXT: lw ra, 12(sp)
142 ; RV32IFD-NEXT: addi sp, sp, 16
145 ; RV64IFD-LABEL: fcvt_l_d:
147 ; RV64IFD-NEXT: fmv.d.x ft0, a0
148 ; RV64IFD-NEXT: fcvt.l.d a0, ft0, rtz
150 %1 = fptosi double %a to i64
154 define i64 @fcvt_lu_d(double %a) nounwind {
155 ; RV32IFD-LABEL: fcvt_lu_d:
157 ; RV32IFD-NEXT: addi sp, sp, -16
158 ; RV32IFD-NEXT: sw ra, 12(sp)
159 ; RV32IFD-NEXT: call __fixunsdfdi
160 ; RV32IFD-NEXT: lw ra, 12(sp)
161 ; RV32IFD-NEXT: addi sp, sp, 16
164 ; RV64IFD-LABEL: fcvt_lu_d:
166 ; RV64IFD-NEXT: fmv.d.x ft0, a0
167 ; RV64IFD-NEXT: fcvt.lu.d a0, ft0, rtz
169 %1 = fptoui double %a to i64
173 define i64 @fmv_x_d(double %a, double %b) nounwind {
174 ; RV32IFD-LABEL: fmv_x_d:
176 ; RV32IFD-NEXT: addi sp, sp, -16
177 ; RV32IFD-NEXT: sw a2, 0(sp)
178 ; RV32IFD-NEXT: sw a3, 4(sp)
179 ; RV32IFD-NEXT: fld ft0, 0(sp)
180 ; RV32IFD-NEXT: sw a0, 0(sp)
181 ; RV32IFD-NEXT: sw a1, 4(sp)
182 ; RV32IFD-NEXT: fld ft1, 0(sp)
183 ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
184 ; RV32IFD-NEXT: fsd ft0, 8(sp)
185 ; RV32IFD-NEXT: lw a0, 8(sp)
186 ; RV32IFD-NEXT: lw a1, 12(sp)
187 ; RV32IFD-NEXT: addi sp, sp, 16
190 ; RV64IFD-LABEL: fmv_x_d:
192 ; RV64IFD-NEXT: fmv.d.x ft0, a1
193 ; RV64IFD-NEXT: fmv.d.x ft1, a0
194 ; RV64IFD-NEXT: fadd.d ft0, ft1, ft0
195 ; RV64IFD-NEXT: fmv.x.d a0, ft0
197 %1 = fadd double %a, %b
198 %2 = bitcast double %1 to i64
202 define double @fcvt_d_l(i64 %a) nounwind {
203 ; RV32IFD-LABEL: fcvt_d_l:
205 ; RV32IFD-NEXT: addi sp, sp, -16
206 ; RV32IFD-NEXT: sw ra, 12(sp)
207 ; RV32IFD-NEXT: call __floatdidf
208 ; RV32IFD-NEXT: lw ra, 12(sp)
209 ; RV32IFD-NEXT: addi sp, sp, 16
212 ; RV64IFD-LABEL: fcvt_d_l:
214 ; RV64IFD-NEXT: fcvt.d.l ft0, a0
215 ; RV64IFD-NEXT: fmv.x.d a0, ft0
217 %1 = sitofp i64 %a to double
221 define double @fcvt_d_lu(i64 %a) nounwind {
222 ; RV32IFD-LABEL: fcvt_d_lu:
224 ; RV32IFD-NEXT: addi sp, sp, -16
225 ; RV32IFD-NEXT: sw ra, 12(sp)
226 ; RV32IFD-NEXT: call __floatundidf
227 ; RV32IFD-NEXT: lw ra, 12(sp)
228 ; RV32IFD-NEXT: addi sp, sp, 16
231 ; RV64IFD-LABEL: fcvt_d_lu:
233 ; RV64IFD-NEXT: fcvt.d.lu ft0, a0
234 ; RV64IFD-NEXT: fmv.x.d a0, ft0
236 %1 = uitofp i64 %a to double
240 define double @fmv_d_x(i64 %a, i64 %b) nounwind {
241 ; Ensure fmv.w.x is generated even for a soft double calling convention
242 ; RV32IFD-LABEL: fmv_d_x:
244 ; RV32IFD-NEXT: addi sp, sp, -32
245 ; RV32IFD-NEXT: sw a3, 20(sp)
246 ; RV32IFD-NEXT: sw a2, 16(sp)
247 ; RV32IFD-NEXT: sw a1, 28(sp)
248 ; RV32IFD-NEXT: sw a0, 24(sp)
249 ; RV32IFD-NEXT: fld ft0, 16(sp)
250 ; RV32IFD-NEXT: fld ft1, 24(sp)
251 ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0
252 ; RV32IFD-NEXT: fsd ft0, 8(sp)
253 ; RV32IFD-NEXT: lw a0, 8(sp)
254 ; RV32IFD-NEXT: lw a1, 12(sp)
255 ; RV32IFD-NEXT: addi sp, sp, 32
258 ; RV64IFD-LABEL: fmv_d_x:
260 ; RV64IFD-NEXT: fmv.d.x ft0, a1
261 ; RV64IFD-NEXT: fmv.d.x ft1, a0
262 ; RV64IFD-NEXT: fadd.d ft0, ft1, ft0
263 ; RV64IFD-NEXT: fmv.x.d a0, ft0
265 %1 = bitcast i64 %a to double
266 %2 = bitcast i64 %b to double
267 %3 = fadd double %1, %2