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
6
7define float @fcvt_s_d(double %a) nounwind {
8; RV32IFD-LABEL: fcvt_s_d:
9; RV32IFD:       # %bb.0:
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
17; RV32IFD-NEXT:    ret
18;
19; RV64IFD-LABEL: fcvt_s_d:
20; RV64IFD:       # %bb.0:
21; RV64IFD-NEXT:    fmv.d.x ft0, a0
22; RV64IFD-NEXT:    fcvt.s.d ft0, ft0
23; RV64IFD-NEXT:    fmv.x.w a0, ft0
24; RV64IFD-NEXT:    ret
25  %1 = fptrunc double %a to float
26  ret float %1
27}
28
29define double @fcvt_d_s(float %a) nounwind {
30; RV32IFD-LABEL: fcvt_d_s:
31; RV32IFD:       # %bb.0:
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
39; RV32IFD-NEXT:    ret
40;
41; RV64IFD-LABEL: fcvt_d_s:
42; RV64IFD:       # %bb.0:
43; RV64IFD-NEXT:    fmv.w.x ft0, a0
44; RV64IFD-NEXT:    fcvt.d.s ft0, ft0
45; RV64IFD-NEXT:    fmv.x.d a0, ft0
46; RV64IFD-NEXT:    ret
47  %1 = fpext float %a to double
48  ret double %1
49}
50
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.
53define i32 @fcvt_w_d(double %a) nounwind {
54; RV32IFD-LABEL: fcvt_w_d:
55; RV32IFD:       # %bb.0:
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
62; RV32IFD-NEXT:    ret
63;
64; RV64IFD-LABEL: fcvt_w_d:
65; RV64IFD:       # %bb.0:
66; RV64IFD-NEXT:    fmv.d.x ft0, a0
67; RV64IFD-NEXT:    fcvt.w.d a0, ft0, rtz
68; RV64IFD-NEXT:    ret
69  %1 = fptosi double %a to i32
70  ret i32 %1
71}
72
73define i32 @fcvt_w_d_sat(double %a) nounwind {
74; RV32IFD-LABEL: fcvt_w_d_sat:
75; RV32IFD:       # %bb.0: # %start
76; RV32IFD-NEXT:    addi sp, sp, -16
77; RV32IFD-NEXT:    sw a0, 8(sp)
78; RV32IFD-NEXT:    sw a1, 12(sp)
79; RV32IFD-NEXT:    fld ft0, 8(sp)
80; RV32IFD-NEXT:    feq.d a0, ft0, ft0
81; RV32IFD-NEXT:    bnez a0, .LBB3_2
82; RV32IFD-NEXT:  # %bb.1: # %start
83; RV32IFD-NEXT:    mv a0, zero
84; RV32IFD-NEXT:    addi sp, sp, 16
85; RV32IFD-NEXT:    ret
86; RV32IFD-NEXT:  .LBB3_2:
87; RV32IFD-NEXT:    fcvt.w.d a0, ft0, rtz
88; RV32IFD-NEXT:    addi sp, sp, 16
89; RV32IFD-NEXT:    ret
90;
91; RV64IFD-LABEL: fcvt_w_d_sat:
92; RV64IFD:       # %bb.0: # %start
93; RV64IFD-NEXT:    fmv.d.x ft0, a0
94; RV64IFD-NEXT:    feq.d a0, ft0, ft0
95; RV64IFD-NEXT:    bnez a0, .LBB3_2
96; RV64IFD-NEXT:  # %bb.1: # %start
97; RV64IFD-NEXT:    mv a0, zero
98; RV64IFD-NEXT:    ret
99; RV64IFD-NEXT:  .LBB3_2:
100; RV64IFD-NEXT:    fcvt.w.d a0, ft0, rtz
101; RV64IFD-NEXT:    ret
102start:
103  %0 = tail call i32 @llvm.fptosi.sat.i32.f64(double %a)
104  ret i32 %0
105}
106declare i32 @llvm.fptosi.sat.i32.f64(double)
107
108; For RV64D, fcvt.lu.d is semantically equivalent to fcvt.wu.d in this case
109; because fptosi will produce poison if the result doesn't fit into an i32.
110define i32 @fcvt_wu_d(double %a) nounwind {
111; RV32IFD-LABEL: fcvt_wu_d:
112; RV32IFD:       # %bb.0:
113; RV32IFD-NEXT:    addi sp, sp, -16
114; RV32IFD-NEXT:    sw a0, 8(sp)
115; RV32IFD-NEXT:    sw a1, 12(sp)
116; RV32IFD-NEXT:    fld ft0, 8(sp)
117; RV32IFD-NEXT:    fcvt.wu.d a0, ft0, rtz
118; RV32IFD-NEXT:    addi sp, sp, 16
119; RV32IFD-NEXT:    ret
120;
121; RV64IFD-LABEL: fcvt_wu_d:
122; RV64IFD:       # %bb.0:
123; RV64IFD-NEXT:    fmv.d.x ft0, a0
124; RV64IFD-NEXT:    fcvt.wu.d a0, ft0, rtz
125; RV64IFD-NEXT:    ret
126  %1 = fptoui double %a to i32
127  ret i32 %1
128}
129
130; Test where the fptoui has multiple uses, one of which causes a sext to be
131; inserted on RV64.
132define i32 @fcvt_wu_d_multiple_use(double %x, i32* %y) {
133; RV32IFD-LABEL: fcvt_wu_d_multiple_use:
134; RV32IFD:       # %bb.0:
135; RV32IFD-NEXT:    addi sp, sp, -16
136; RV32IFD-NEXT:    .cfi_def_cfa_offset 16
137; RV32IFD-NEXT:    sw a0, 8(sp)
138; RV32IFD-NEXT:    sw a1, 12(sp)
139; RV32IFD-NEXT:    fld ft0, 8(sp)
140; RV32IFD-NEXT:    fcvt.wu.d a1, ft0, rtz
141; RV32IFD-NEXT:    addi a0, zero, 1
142; RV32IFD-NEXT:    beqz a1, .LBB5_2
143; RV32IFD-NEXT:  # %bb.1:
144; RV32IFD-NEXT:    mv a0, a1
145; RV32IFD-NEXT:  .LBB5_2:
146; RV32IFD-NEXT:    addi sp, sp, 16
147; RV32IFD-NEXT:    ret
148;
149; RV64IFD-LABEL: fcvt_wu_d_multiple_use:
150; RV64IFD:       # %bb.0:
151; RV64IFD-NEXT:    fmv.d.x ft0, a0
152; RV64IFD-NEXT:    fcvt.wu.d a1, ft0, rtz
153; RV64IFD-NEXT:    addi a0, zero, 1
154; RV64IFD-NEXT:    beqz a1, .LBB5_2
155; RV64IFD-NEXT:  # %bb.1:
156; RV64IFD-NEXT:    mv a0, a1
157; RV64IFD-NEXT:  .LBB5_2:
158; RV64IFD-NEXT:    ret
159  %a = fptoui double %x to i32
160  %b = icmp eq i32 %a, 0
161  %c = select i1 %b, i32 1, i32 %a
162  ret i32 %c
163}
164
165define i32 @fcvt_wu_d_sat(double %a) nounwind {
166; RV32IFD-LABEL: fcvt_wu_d_sat:
167; RV32IFD:       # %bb.0: # %start
168; RV32IFD-NEXT:    addi sp, sp, -16
169; RV32IFD-NEXT:    sw a0, 8(sp)
170; RV32IFD-NEXT:    sw a1, 12(sp)
171; RV32IFD-NEXT:    fld ft0, 8(sp)
172; RV32IFD-NEXT:    feq.d a0, ft0, ft0
173; RV32IFD-NEXT:    bnez a0, .LBB6_2
174; RV32IFD-NEXT:  # %bb.1: # %start
175; RV32IFD-NEXT:    mv a0, zero
176; RV32IFD-NEXT:    addi sp, sp, 16
177; RV32IFD-NEXT:    ret
178; RV32IFD-NEXT:  .LBB6_2:
179; RV32IFD-NEXT:    fcvt.wu.d a0, ft0, rtz
180; RV32IFD-NEXT:    addi sp, sp, 16
181; RV32IFD-NEXT:    ret
182;
183; RV64IFD-LABEL: fcvt_wu_d_sat:
184; RV64IFD:       # %bb.0: # %start
185; RV64IFD-NEXT:    fmv.d.x ft0, a0
186; RV64IFD-NEXT:    feq.d a0, ft0, ft0
187; RV64IFD-NEXT:    bnez a0, .LBB6_2
188; RV64IFD-NEXT:  # %bb.1: # %start
189; RV64IFD-NEXT:    mv a0, zero
190; RV64IFD-NEXT:    ret
191; RV64IFD-NEXT:  .LBB6_2:
192; RV64IFD-NEXT:    fcvt.wu.d a0, ft0, rtz
193; RV64IFD-NEXT:    ret
194start:
195  %0 = tail call i32 @llvm.fptoui.sat.i32.f64(double %a)
196  ret i32 %0
197}
198declare i32 @llvm.fptoui.sat.i32.f64(double)
199
200define double @fcvt_d_w(i32 %a) nounwind {
201; RV32IFD-LABEL: fcvt_d_w:
202; RV32IFD:       # %bb.0:
203; RV32IFD-NEXT:    addi sp, sp, -16
204; RV32IFD-NEXT:    fcvt.d.w ft0, a0
205; RV32IFD-NEXT:    fsd ft0, 8(sp)
206; RV32IFD-NEXT:    lw a0, 8(sp)
207; RV32IFD-NEXT:    lw a1, 12(sp)
208; RV32IFD-NEXT:    addi sp, sp, 16
209; RV32IFD-NEXT:    ret
210;
211; RV64IFD-LABEL: fcvt_d_w:
212; RV64IFD:       # %bb.0:
213; RV64IFD-NEXT:    fcvt.d.w ft0, a0
214; RV64IFD-NEXT:    fmv.x.d a0, ft0
215; RV64IFD-NEXT:    ret
216  %1 = sitofp i32 %a to double
217  ret double %1
218}
219
220define double @fcvt_d_w_load(i32* %p) nounwind {
221; RV32IFD-LABEL: fcvt_d_w_load:
222; RV32IFD:       # %bb.0:
223; RV32IFD-NEXT:    addi sp, sp, -16
224; RV32IFD-NEXT:    lw a0, 0(a0)
225; RV32IFD-NEXT:    fcvt.d.w ft0, a0
226; RV32IFD-NEXT:    fsd ft0, 8(sp)
227; RV32IFD-NEXT:    lw a0, 8(sp)
228; RV32IFD-NEXT:    lw a1, 12(sp)
229; RV32IFD-NEXT:    addi sp, sp, 16
230; RV32IFD-NEXT:    ret
231;
232; RV64IFD-LABEL: fcvt_d_w_load:
233; RV64IFD:       # %bb.0:
234; RV64IFD-NEXT:    lw a0, 0(a0)
235; RV64IFD-NEXT:    fcvt.d.w ft0, a0
236; RV64IFD-NEXT:    fmv.x.d a0, ft0
237; RV64IFD-NEXT:    ret
238  %a = load i32, i32* %p
239  %1 = sitofp i32 %a to double
240  ret double %1
241}
242
243define double @fcvt_d_wu(i32 %a) nounwind {
244; RV32IFD-LABEL: fcvt_d_wu:
245; RV32IFD:       # %bb.0:
246; RV32IFD-NEXT:    addi sp, sp, -16
247; RV32IFD-NEXT:    fcvt.d.wu ft0, a0
248; RV32IFD-NEXT:    fsd ft0, 8(sp)
249; RV32IFD-NEXT:    lw a0, 8(sp)
250; RV32IFD-NEXT:    lw a1, 12(sp)
251; RV32IFD-NEXT:    addi sp, sp, 16
252; RV32IFD-NEXT:    ret
253;
254; RV64IFD-LABEL: fcvt_d_wu:
255; RV64IFD:       # %bb.0:
256; RV64IFD-NEXT:    fcvt.d.wu ft0, a0
257; RV64IFD-NEXT:    fmv.x.d a0, ft0
258; RV64IFD-NEXT:    ret
259  %1 = uitofp i32 %a to double
260  ret double %1
261}
262
263define double @fcvt_d_wu_load(i32* %p) nounwind {
264; RV32IFD-LABEL: fcvt_d_wu_load:
265; RV32IFD:       # %bb.0:
266; RV32IFD-NEXT:    addi sp, sp, -16
267; RV32IFD-NEXT:    lw a0, 0(a0)
268; RV32IFD-NEXT:    fcvt.d.wu ft0, a0
269; RV32IFD-NEXT:    fsd ft0, 8(sp)
270; RV32IFD-NEXT:    lw a0, 8(sp)
271; RV32IFD-NEXT:    lw a1, 12(sp)
272; RV32IFD-NEXT:    addi sp, sp, 16
273; RV32IFD-NEXT:    ret
274;
275; RV64IFD-LABEL: fcvt_d_wu_load:
276; RV64IFD:       # %bb.0:
277; RV64IFD-NEXT:    lwu a0, 0(a0)
278; RV64IFD-NEXT:    fcvt.d.wu ft0, a0
279; RV64IFD-NEXT:    fmv.x.d a0, ft0
280; RV64IFD-NEXT:    ret
281  %a = load i32, i32* %p
282  %1 = uitofp i32 %a to double
283  ret double %1
284}
285
286define i64 @fcvt_l_d(double %a) nounwind {
287; RV32IFD-LABEL: fcvt_l_d:
288; RV32IFD:       # %bb.0:
289; RV32IFD-NEXT:    addi sp, sp, -16
290; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
291; RV32IFD-NEXT:    call __fixdfdi@plt
292; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
293; RV32IFD-NEXT:    addi sp, sp, 16
294; RV32IFD-NEXT:    ret
295;
296; RV64IFD-LABEL: fcvt_l_d:
297; RV64IFD:       # %bb.0:
298; RV64IFD-NEXT:    fmv.d.x ft0, a0
299; RV64IFD-NEXT:    fcvt.l.d a0, ft0, rtz
300; RV64IFD-NEXT:    ret
301  %1 = fptosi double %a to i64
302  ret i64 %1
303}
304
305define i64 @fcvt_l_d_sat(double %a) nounwind {
306; RV32IFD-LABEL: fcvt_l_d_sat:
307; RV32IFD:       # %bb.0: # %start
308; RV32IFD-NEXT:    addi sp, sp, -32
309; RV32IFD-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
310; RV32IFD-NEXT:    sw a0, 16(sp)
311; RV32IFD-NEXT:    sw a1, 20(sp)
312; RV32IFD-NEXT:    fld ft0, 16(sp)
313; RV32IFD-NEXT:    fsd ft0, 8(sp) # 8-byte Folded Spill
314; RV32IFD-NEXT:    call __fixdfdi@plt
315; RV32IFD-NEXT:    fld ft1, 8(sp) # 8-byte Folded Reload
316; RV32IFD-NEXT:    lui a2, %hi(.LCPI12_0)
317; RV32IFD-NEXT:    fld ft0, %lo(.LCPI12_0)(a2)
318; RV32IFD-NEXT:    fle.d a3, ft0, ft1
319; RV32IFD-NEXT:    mv a2, a0
320; RV32IFD-NEXT:    bnez a3, .LBB12_2
321; RV32IFD-NEXT:  # %bb.1: # %start
322; RV32IFD-NEXT:    mv a2, zero
323; RV32IFD-NEXT:  .LBB12_2: # %start
324; RV32IFD-NEXT:    lui a0, %hi(.LCPI12_1)
325; RV32IFD-NEXT:    fld ft0, %lo(.LCPI12_1)(a0)
326; RV32IFD-NEXT:    flt.d a4, ft0, ft1
327; RV32IFD-NEXT:    addi a0, zero, -1
328; RV32IFD-NEXT:    beqz a4, .LBB12_9
329; RV32IFD-NEXT:  # %bb.3: # %start
330; RV32IFD-NEXT:    feq.d a2, ft1, ft1
331; RV32IFD-NEXT:    beqz a2, .LBB12_10
332; RV32IFD-NEXT:  .LBB12_4: # %start
333; RV32IFD-NEXT:    lui a5, 524288
334; RV32IFD-NEXT:    beqz a3, .LBB12_11
335; RV32IFD-NEXT:  .LBB12_5: # %start
336; RV32IFD-NEXT:    bnez a4, .LBB12_12
337; RV32IFD-NEXT:  .LBB12_6: # %start
338; RV32IFD-NEXT:    bnez a2, .LBB12_8
339; RV32IFD-NEXT:  .LBB12_7: # %start
340; RV32IFD-NEXT:    mv a1, zero
341; RV32IFD-NEXT:  .LBB12_8: # %start
342; RV32IFD-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
343; RV32IFD-NEXT:    addi sp, sp, 32
344; RV32IFD-NEXT:    ret
345; RV32IFD-NEXT:  .LBB12_9: # %start
346; RV32IFD-NEXT:    mv a0, a2
347; RV32IFD-NEXT:    feq.d a2, ft1, ft1
348; RV32IFD-NEXT:    bnez a2, .LBB12_4
349; RV32IFD-NEXT:  .LBB12_10: # %start
350; RV32IFD-NEXT:    mv a0, zero
351; RV32IFD-NEXT:    lui a5, 524288
352; RV32IFD-NEXT:    bnez a3, .LBB12_5
353; RV32IFD-NEXT:  .LBB12_11: # %start
354; RV32IFD-NEXT:    lui a1, 524288
355; RV32IFD-NEXT:    beqz a4, .LBB12_6
356; RV32IFD-NEXT:  .LBB12_12:
357; RV32IFD-NEXT:    addi a1, a5, -1
358; RV32IFD-NEXT:    beqz a2, .LBB12_7
359; RV32IFD-NEXT:    j .LBB12_8
360;
361; RV64IFD-LABEL: fcvt_l_d_sat:
362; RV64IFD:       # %bb.0: # %start
363; RV64IFD-NEXT:    fmv.d.x ft0, a0
364; RV64IFD-NEXT:    feq.d a0, ft0, ft0
365; RV64IFD-NEXT:    bnez a0, .LBB12_2
366; RV64IFD-NEXT:  # %bb.1: # %start
367; RV64IFD-NEXT:    mv a0, zero
368; RV64IFD-NEXT:    ret
369; RV64IFD-NEXT:  .LBB12_2:
370; RV64IFD-NEXT:    fcvt.l.d a0, ft0, rtz
371; RV64IFD-NEXT:    ret
372start:
373  %0 = tail call i64 @llvm.fptosi.sat.i64.f64(double %a)
374  ret i64 %0
375}
376declare i64 @llvm.fptosi.sat.i64.f64(double)
377
378define i64 @fcvt_lu_d(double %a) nounwind {
379; RV32IFD-LABEL: fcvt_lu_d:
380; RV32IFD:       # %bb.0:
381; RV32IFD-NEXT:    addi sp, sp, -16
382; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
383; RV32IFD-NEXT:    call __fixunsdfdi@plt
384; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
385; RV32IFD-NEXT:    addi sp, sp, 16
386; RV32IFD-NEXT:    ret
387;
388; RV64IFD-LABEL: fcvt_lu_d:
389; RV64IFD:       # %bb.0:
390; RV64IFD-NEXT:    fmv.d.x ft0, a0
391; RV64IFD-NEXT:    fcvt.lu.d a0, ft0, rtz
392; RV64IFD-NEXT:    ret
393  %1 = fptoui double %a to i64
394  ret i64 %1
395}
396
397define i64 @fcvt_lu_d_sat(double %a) nounwind {
398; RV32IFD-LABEL: fcvt_lu_d_sat:
399; RV32IFD:       # %bb.0: # %start
400; RV32IFD-NEXT:    addi sp, sp, -32
401; RV32IFD-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
402; RV32IFD-NEXT:    sw a0, 16(sp)
403; RV32IFD-NEXT:    sw a1, 20(sp)
404; RV32IFD-NEXT:    fld ft0, 16(sp)
405; RV32IFD-NEXT:    fsd ft0, 8(sp) # 8-byte Folded Spill
406; RV32IFD-NEXT:    call __fixunsdfdi@plt
407; RV32IFD-NEXT:    fld ft1, 8(sp) # 8-byte Folded Reload
408; RV32IFD-NEXT:    fcvt.d.w ft0, zero
409; RV32IFD-NEXT:    fle.d a4, ft0, ft1
410; RV32IFD-NEXT:    mv a3, a0
411; RV32IFD-NEXT:    bnez a4, .LBB14_2
412; RV32IFD-NEXT:  # %bb.1: # %start
413; RV32IFD-NEXT:    mv a3, zero
414; RV32IFD-NEXT:  .LBB14_2: # %start
415; RV32IFD-NEXT:    lui a0, %hi(.LCPI14_0)
416; RV32IFD-NEXT:    fld ft0, %lo(.LCPI14_0)(a0)
417; RV32IFD-NEXT:    flt.d a5, ft0, ft1
418; RV32IFD-NEXT:    addi a2, zero, -1
419; RV32IFD-NEXT:    addi a0, zero, -1
420; RV32IFD-NEXT:    beqz a5, .LBB14_7
421; RV32IFD-NEXT:  # %bb.3: # %start
422; RV32IFD-NEXT:    beqz a4, .LBB14_8
423; RV32IFD-NEXT:  .LBB14_4: # %start
424; RV32IFD-NEXT:    bnez a5, .LBB14_6
425; RV32IFD-NEXT:  .LBB14_5: # %start
426; RV32IFD-NEXT:    mv a2, a1
427; RV32IFD-NEXT:  .LBB14_6: # %start
428; RV32IFD-NEXT:    mv a1, a2
429; RV32IFD-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
430; RV32IFD-NEXT:    addi sp, sp, 32
431; RV32IFD-NEXT:    ret
432; RV32IFD-NEXT:  .LBB14_7: # %start
433; RV32IFD-NEXT:    mv a0, a3
434; RV32IFD-NEXT:    bnez a4, .LBB14_4
435; RV32IFD-NEXT:  .LBB14_8: # %start
436; RV32IFD-NEXT:    mv a1, zero
437; RV32IFD-NEXT:    beqz a5, .LBB14_5
438; RV32IFD-NEXT:    j .LBB14_6
439;
440; RV64IFD-LABEL: fcvt_lu_d_sat:
441; RV64IFD:       # %bb.0: # %start
442; RV64IFD-NEXT:    fmv.d.x ft0, a0
443; RV64IFD-NEXT:    feq.d a0, ft0, ft0
444; RV64IFD-NEXT:    bnez a0, .LBB14_2
445; RV64IFD-NEXT:  # %bb.1: # %start
446; RV64IFD-NEXT:    mv a0, zero
447; RV64IFD-NEXT:    ret
448; RV64IFD-NEXT:  .LBB14_2:
449; RV64IFD-NEXT:    fcvt.lu.d a0, ft0, rtz
450; RV64IFD-NEXT:    ret
451start:
452  %0 = tail call i64 @llvm.fptoui.sat.i64.f64(double %a)
453  ret i64 %0
454}
455declare i64 @llvm.fptoui.sat.i64.f64(double)
456
457define i64 @fmv_x_d(double %a, double %b) nounwind {
458; RV32IFD-LABEL: fmv_x_d:
459; RV32IFD:       # %bb.0:
460; RV32IFD-NEXT:    addi sp, sp, -16
461; RV32IFD-NEXT:    sw a2, 0(sp)
462; RV32IFD-NEXT:    sw a3, 4(sp)
463; RV32IFD-NEXT:    fld ft0, 0(sp)
464; RV32IFD-NEXT:    sw a0, 0(sp)
465; RV32IFD-NEXT:    sw a1, 4(sp)
466; RV32IFD-NEXT:    fld ft1, 0(sp)
467; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
468; RV32IFD-NEXT:    fsd ft0, 8(sp)
469; RV32IFD-NEXT:    lw a0, 8(sp)
470; RV32IFD-NEXT:    lw a1, 12(sp)
471; RV32IFD-NEXT:    addi sp, sp, 16
472; RV32IFD-NEXT:    ret
473;
474; RV64IFD-LABEL: fmv_x_d:
475; RV64IFD:       # %bb.0:
476; RV64IFD-NEXT:    fmv.d.x ft0, a1
477; RV64IFD-NEXT:    fmv.d.x ft1, a0
478; RV64IFD-NEXT:    fadd.d ft0, ft1, ft0
479; RV64IFD-NEXT:    fmv.x.d a0, ft0
480; RV64IFD-NEXT:    ret
481  %1 = fadd double %a, %b
482  %2 = bitcast double %1 to i64
483  ret i64 %2
484}
485
486define double @fcvt_d_l(i64 %a) nounwind {
487; RV32IFD-LABEL: fcvt_d_l:
488; RV32IFD:       # %bb.0:
489; RV32IFD-NEXT:    addi sp, sp, -16
490; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
491; RV32IFD-NEXT:    call __floatdidf@plt
492; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
493; RV32IFD-NEXT:    addi sp, sp, 16
494; RV32IFD-NEXT:    ret
495;
496; RV64IFD-LABEL: fcvt_d_l:
497; RV64IFD:       # %bb.0:
498; RV64IFD-NEXT:    fcvt.d.l ft0, a0
499; RV64IFD-NEXT:    fmv.x.d a0, ft0
500; RV64IFD-NEXT:    ret
501  %1 = sitofp i64 %a to double
502  ret double %1
503}
504
505define double @fcvt_d_lu(i64 %a) nounwind {
506; RV32IFD-LABEL: fcvt_d_lu:
507; RV32IFD:       # %bb.0:
508; RV32IFD-NEXT:    addi sp, sp, -16
509; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
510; RV32IFD-NEXT:    call __floatundidf@plt
511; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
512; RV32IFD-NEXT:    addi sp, sp, 16
513; RV32IFD-NEXT:    ret
514;
515; RV64IFD-LABEL: fcvt_d_lu:
516; RV64IFD:       # %bb.0:
517; RV64IFD-NEXT:    fcvt.d.lu ft0, a0
518; RV64IFD-NEXT:    fmv.x.d a0, ft0
519; RV64IFD-NEXT:    ret
520  %1 = uitofp i64 %a to double
521  ret double %1
522}
523
524define double @fmv_d_x(i64 %a, i64 %b) nounwind {
525; Ensure fmv.w.x is generated even for a soft double calling convention
526; RV32IFD-LABEL: fmv_d_x:
527; RV32IFD:       # %bb.0:
528; RV32IFD-NEXT:    addi sp, sp, -32
529; RV32IFD-NEXT:    sw a3, 20(sp)
530; RV32IFD-NEXT:    sw a2, 16(sp)
531; RV32IFD-NEXT:    sw a1, 28(sp)
532; RV32IFD-NEXT:    sw a0, 24(sp)
533; RV32IFD-NEXT:    fld ft0, 16(sp)
534; RV32IFD-NEXT:    fld ft1, 24(sp)
535; RV32IFD-NEXT:    fadd.d ft0, ft1, ft0
536; RV32IFD-NEXT:    fsd ft0, 8(sp)
537; RV32IFD-NEXT:    lw a0, 8(sp)
538; RV32IFD-NEXT:    lw a1, 12(sp)
539; RV32IFD-NEXT:    addi sp, sp, 32
540; RV32IFD-NEXT:    ret
541;
542; RV64IFD-LABEL: fmv_d_x:
543; RV64IFD:       # %bb.0:
544; RV64IFD-NEXT:    fmv.d.x ft0, a0
545; RV64IFD-NEXT:    fmv.d.x ft1, a1
546; RV64IFD-NEXT:    fadd.d ft0, ft0, ft1
547; RV64IFD-NEXT:    fmv.x.d a0, ft0
548; RV64IFD-NEXT:    ret
549  %1 = bitcast i64 %a to double
550  %2 = bitcast i64 %b to double
551  %3 = fadd double %1, %2
552  ret double %3
553}
554
555define double @fcvt_d_w_i8(i8 signext %a) nounwind {
556; RV32IFD-LABEL: fcvt_d_w_i8:
557; RV32IFD:       # %bb.0:
558; RV32IFD-NEXT:    addi sp, sp, -16
559; RV32IFD-NEXT:    fcvt.d.w ft0, a0
560; RV32IFD-NEXT:    fsd ft0, 8(sp)
561; RV32IFD-NEXT:    lw a0, 8(sp)
562; RV32IFD-NEXT:    lw a1, 12(sp)
563; RV32IFD-NEXT:    addi sp, sp, 16
564; RV32IFD-NEXT:    ret
565;
566; RV64IFD-LABEL: fcvt_d_w_i8:
567; RV64IFD:       # %bb.0:
568; RV64IFD-NEXT:    fcvt.d.w ft0, a0
569; RV64IFD-NEXT:    fmv.x.d a0, ft0
570; RV64IFD-NEXT:    ret
571  %1 = sitofp i8 %a to double
572  ret double %1
573}
574
575define double @fcvt_d_wu_i8(i8 zeroext %a) nounwind {
576; RV32IFD-LABEL: fcvt_d_wu_i8:
577; RV32IFD:       # %bb.0:
578; RV32IFD-NEXT:    addi sp, sp, -16
579; RV32IFD-NEXT:    fcvt.d.wu ft0, a0
580; RV32IFD-NEXT:    fsd ft0, 8(sp)
581; RV32IFD-NEXT:    lw a0, 8(sp)
582; RV32IFD-NEXT:    lw a1, 12(sp)
583; RV32IFD-NEXT:    addi sp, sp, 16
584; RV32IFD-NEXT:    ret
585;
586; RV64IFD-LABEL: fcvt_d_wu_i8:
587; RV64IFD:       # %bb.0:
588; RV64IFD-NEXT:    fcvt.d.wu ft0, a0
589; RV64IFD-NEXT:    fmv.x.d a0, ft0
590; RV64IFD-NEXT:    ret
591  %1 = uitofp i8 %a to double
592  ret double %1
593}
594
595define double @fcvt_d_w_i16(i16 signext %a) nounwind {
596; RV32IFD-LABEL: fcvt_d_w_i16:
597; RV32IFD:       # %bb.0:
598; RV32IFD-NEXT:    addi sp, sp, -16
599; RV32IFD-NEXT:    fcvt.d.w ft0, a0
600; RV32IFD-NEXT:    fsd ft0, 8(sp)
601; RV32IFD-NEXT:    lw a0, 8(sp)
602; RV32IFD-NEXT:    lw a1, 12(sp)
603; RV32IFD-NEXT:    addi sp, sp, 16
604; RV32IFD-NEXT:    ret
605;
606; RV64IFD-LABEL: fcvt_d_w_i16:
607; RV64IFD:       # %bb.0:
608; RV64IFD-NEXT:    fcvt.d.w ft0, a0
609; RV64IFD-NEXT:    fmv.x.d a0, ft0
610; RV64IFD-NEXT:    ret
611  %1 = sitofp i16 %a to double
612  ret double %1
613}
614
615define double @fcvt_d_wu_i16(i16 zeroext %a) nounwind {
616; RV32IFD-LABEL: fcvt_d_wu_i16:
617; RV32IFD:       # %bb.0:
618; RV32IFD-NEXT:    addi sp, sp, -16
619; RV32IFD-NEXT:    fcvt.d.wu ft0, a0
620; RV32IFD-NEXT:    fsd ft0, 8(sp)
621; RV32IFD-NEXT:    lw a0, 8(sp)
622; RV32IFD-NEXT:    lw a1, 12(sp)
623; RV32IFD-NEXT:    addi sp, sp, 16
624; RV32IFD-NEXT:    ret
625;
626; RV64IFD-LABEL: fcvt_d_wu_i16:
627; RV64IFD:       # %bb.0:
628; RV64IFD-NEXT:    fcvt.d.wu ft0, a0
629; RV64IFD-NEXT:    fmv.x.d a0, ft0
630; RV64IFD-NEXT:    ret
631  %1 = uitofp i16 %a to double
632  ret double %1
633}
634
635; Make sure we select W version of addi on RV64.
636define signext i32 @fcvt_d_w_demanded_bits(i32 signext %0, double* %1) {
637; RV32IFD-LABEL: fcvt_d_w_demanded_bits:
638; RV32IFD:       # %bb.0:
639; RV32IFD-NEXT:    addi a0, a0, 1
640; RV32IFD-NEXT:    fcvt.d.w ft0, a0
641; RV32IFD-NEXT:    fsd ft0, 0(a1)
642; RV32IFD-NEXT:    ret
643;
644; RV64IFD-LABEL: fcvt_d_w_demanded_bits:
645; RV64IFD:       # %bb.0:
646; RV64IFD-NEXT:    addiw a0, a0, 1
647; RV64IFD-NEXT:    fcvt.d.w ft0, a0
648; RV64IFD-NEXT:    fsd ft0, 0(a1)
649; RV64IFD-NEXT:    ret
650  %3 = add i32 %0, 1
651  %4 = sitofp i32 %3 to double
652  store double %4, double* %1, align 8
653  ret i32 %3
654}
655
656; Make sure we select W version of addi on RV64.
657define signext i32 @fcvt_d_wu_demanded_bits(i32 signext %0, double* %1) {
658; RV32IFD-LABEL: fcvt_d_wu_demanded_bits:
659; RV32IFD:       # %bb.0:
660; RV32IFD-NEXT:    addi a0, a0, 1
661; RV32IFD-NEXT:    fcvt.d.wu ft0, a0
662; RV32IFD-NEXT:    fsd ft0, 0(a1)
663; RV32IFD-NEXT:    ret
664;
665; RV64IFD-LABEL: fcvt_d_wu_demanded_bits:
666; RV64IFD:       # %bb.0:
667; RV64IFD-NEXT:    addiw a0, a0, 1
668; RV64IFD-NEXT:    fcvt.d.wu ft0, a0
669; RV64IFD-NEXT:    fsd ft0, 0(a1)
670; RV64IFD-NEXT:    ret
671  %3 = add i32 %0, 1
672  %4 = uitofp i32 %3 to double
673  store double %4, double* %1, align 8
674  ret i32 %3
675}
676