xref: /llvm-project/llvm/test/CodeGen/RISCV/double-calling-conv.ll (revision 9122c5235ec85ce0c0ad337e862b006e7b349d84)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi=ilp32 -verify-machineinstrs < %s \
3; RUN:   | FileCheck -check-prefix=RV32IFD %s
4; RUN: llc -mtriple=riscv32 -mattr=+zdinx -target-abi=ilp32 -verify-machineinstrs < %s \
5; RUN:   | FileCheck -check-prefix=RV32IZFINXZDINX %s
6
7; Basic correctness checks for calling convention lowering for RV32D. This can
8; be somewhat error-prone for soft-float RV32D due to the fact that f64 is legal
9; but i64 is not, and there is no instruction to move values directly between
10; the GPRs and 64-bit FPRs.
11
12define double @callee_double_inreg(double %a, double %b) nounwind {
13; RV32IFD-LABEL: callee_double_inreg:
14; RV32IFD:       # %bb.0:
15; RV32IFD-NEXT:    addi sp, sp, -16
16; RV32IFD-NEXT:    sw a2, 8(sp)
17; RV32IFD-NEXT:    sw a3, 12(sp)
18; RV32IFD-NEXT:    fld fa5, 8(sp)
19; RV32IFD-NEXT:    sw a0, 8(sp)
20; RV32IFD-NEXT:    sw a1, 12(sp)
21; RV32IFD-NEXT:    fld fa4, 8(sp)
22; RV32IFD-NEXT:    fadd.d fa5, fa4, fa5
23; RV32IFD-NEXT:    fsd fa5, 8(sp)
24; RV32IFD-NEXT:    lw a0, 8(sp)
25; RV32IFD-NEXT:    lw a1, 12(sp)
26; RV32IFD-NEXT:    addi sp, sp, 16
27; RV32IFD-NEXT:    ret
28;
29; RV32IZFINXZDINX-LABEL: callee_double_inreg:
30; RV32IZFINXZDINX:       # %bb.0:
31; RV32IZFINXZDINX-NEXT:    fadd.d a0, a0, a2
32; RV32IZFINXZDINX-NEXT:    ret
33  %1 = fadd double %a, %b
34  ret double %1
35}
36
37; TODO: code quality for loading and then passing f64 constants is poor.
38
39define double @caller_double_inreg() nounwind {
40; RV32IFD-LABEL: caller_double_inreg:
41; RV32IFD:       # %bb.0:
42; RV32IFD-NEXT:    addi sp, sp, -16
43; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
44; RV32IFD-NEXT:    lui a0, 262236
45; RV32IFD-NEXT:    lui a2, 377487
46; RV32IFD-NEXT:    lui a3, 262364
47; RV32IFD-NEXT:    addi a1, a0, 655
48; RV32IFD-NEXT:    addi a0, a2, 1475
49; RV32IFD-NEXT:    addi a3, a3, 655
50; RV32IFD-NEXT:    mv a2, a0
51; RV32IFD-NEXT:    call callee_double_inreg
52; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
53; RV32IFD-NEXT:    addi sp, sp, 16
54; RV32IFD-NEXT:    ret
55;
56; RV32IZFINXZDINX-LABEL: caller_double_inreg:
57; RV32IZFINXZDINX:       # %bb.0:
58; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
59; RV32IZFINXZDINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
60; RV32IZFINXZDINX-NEXT:    lui a0, 262236
61; RV32IZFINXZDINX-NEXT:    lui a2, 377487
62; RV32IZFINXZDINX-NEXT:    lui a3, 262364
63; RV32IZFINXZDINX-NEXT:    addi a1, a0, 655
64; RV32IZFINXZDINX-NEXT:    addi a0, a2, 1475
65; RV32IZFINXZDINX-NEXT:    addi a3, a3, 655
66; RV32IZFINXZDINX-NEXT:    mv a2, a0
67; RV32IZFINXZDINX-NEXT:    call callee_double_inreg
68; RV32IZFINXZDINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
69; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
70; RV32IZFINXZDINX-NEXT:    ret
71  %1 = call double @callee_double_inreg(double 2.720000e+00, double 3.720000e+00)
72  ret double %1
73}
74
75define double @callee_double_split_reg_stack(i32 %a, i64 %b, i64 %c, double %d, double %e) nounwind {
76; RV32IFD-LABEL: callee_double_split_reg_stack:
77; RV32IFD:       # %bb.0:
78; RV32IFD-NEXT:    addi sp, sp, -16
79; RV32IFD-NEXT:    lw a0, 16(sp)
80; RV32IFD-NEXT:    sw a7, 8(sp)
81; RV32IFD-NEXT:    sw a0, 12(sp)
82; RV32IFD-NEXT:    fld fa5, 8(sp)
83; RV32IFD-NEXT:    sw a5, 8(sp)
84; RV32IFD-NEXT:    sw a6, 12(sp)
85; RV32IFD-NEXT:    fld fa4, 8(sp)
86; RV32IFD-NEXT:    fadd.d fa5, fa4, fa5
87; RV32IFD-NEXT:    fsd fa5, 8(sp)
88; RV32IFD-NEXT:    lw a0, 8(sp)
89; RV32IFD-NEXT:    lw a1, 12(sp)
90; RV32IFD-NEXT:    addi sp, sp, 16
91; RV32IFD-NEXT:    ret
92;
93; RV32IZFINXZDINX-LABEL: callee_double_split_reg_stack:
94; RV32IZFINXZDINX:       # %bb.0:
95; RV32IZFINXZDINX-NEXT:    mv a0, a7
96; RV32IZFINXZDINX-NEXT:    lw a1, 0(sp)
97; RV32IZFINXZDINX-NEXT:    mv a3, a6
98; RV32IZFINXZDINX-NEXT:    mv a2, a5
99; RV32IZFINXZDINX-NEXT:    fadd.d a0, a2, a0
100; RV32IZFINXZDINX-NEXT:    ret
101  %1 = fadd double %d, %e
102  ret double %1
103}
104
105define double @caller_double_split_reg_stack() nounwind {
106; RV32IFD-LABEL: caller_double_split_reg_stack:
107; RV32IFD:       # %bb.0:
108; RV32IFD-NEXT:    addi sp, sp, -16
109; RV32IFD-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
110; RV32IFD-NEXT:    lui a2, 262510
111; RV32IFD-NEXT:    lui a3, 262446
112; RV32IFD-NEXT:    lui a4, 713032
113; RV32IFD-NEXT:    li a0, 1
114; RV32IFD-NEXT:    li a1, 2
115; RV32IFD-NEXT:    addi a2, a2, 327
116; RV32IFD-NEXT:    addi a6, a3, 327
117; RV32IFD-NEXT:    addi a5, a4, -1311
118; RV32IFD-NEXT:    li a3, 3
119; RV32IFD-NEXT:    sw a2, 0(sp)
120; RV32IFD-NEXT:    li a2, 0
121; RV32IFD-NEXT:    li a4, 0
122; RV32IFD-NEXT:    mv a7, a5
123; RV32IFD-NEXT:    call callee_double_split_reg_stack
124; RV32IFD-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
125; RV32IFD-NEXT:    addi sp, sp, 16
126; RV32IFD-NEXT:    ret
127;
128; RV32IZFINXZDINX-LABEL: caller_double_split_reg_stack:
129; RV32IZFINXZDINX:       # %bb.0:
130; RV32IZFINXZDINX-NEXT:    addi sp, sp, -16
131; RV32IZFINXZDINX-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
132; RV32IZFINXZDINX-NEXT:    lui a2, 262510
133; RV32IZFINXZDINX-NEXT:    lui a3, 262446
134; RV32IZFINXZDINX-NEXT:    lui a4, 713032
135; RV32IZFINXZDINX-NEXT:    li a0, 1
136; RV32IZFINXZDINX-NEXT:    li a1, 2
137; RV32IZFINXZDINX-NEXT:    addi a2, a2, 327
138; RV32IZFINXZDINX-NEXT:    addi a6, a3, 327
139; RV32IZFINXZDINX-NEXT:    addi a5, a4, -1311
140; RV32IZFINXZDINX-NEXT:    li a3, 3
141; RV32IZFINXZDINX-NEXT:    sw a2, 0(sp)
142; RV32IZFINXZDINX-NEXT:    li a2, 0
143; RV32IZFINXZDINX-NEXT:    li a4, 0
144; RV32IZFINXZDINX-NEXT:    mv a7, a5
145; RV32IZFINXZDINX-NEXT:    call callee_double_split_reg_stack
146; RV32IZFINXZDINX-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
147; RV32IZFINXZDINX-NEXT:    addi sp, sp, 16
148; RV32IZFINXZDINX-NEXT:    ret
149  %1 = call double @callee_double_split_reg_stack(i32 1, i64 2, i64 3, double 4.72, double 5.72)
150  ret double %1
151}
152
153define double @callee_double_stack(i64 %a, i64 %b, i64 %c, i64 %d, double %e, double %f) nounwind {
154; RV32IFD-LABEL: callee_double_stack:
155; RV32IFD:       # %bb.0:
156; RV32IFD-NEXT:    addi sp, sp, -16
157; RV32IFD-NEXT:    fld fa5, 24(sp)
158; RV32IFD-NEXT:    fld fa4, 16(sp)
159; RV32IFD-NEXT:    fadd.d fa5, fa4, fa5
160; RV32IFD-NEXT:    fsd fa5, 8(sp)
161; RV32IFD-NEXT:    lw a0, 8(sp)
162; RV32IFD-NEXT:    lw a1, 12(sp)
163; RV32IFD-NEXT:    addi sp, sp, 16
164; RV32IFD-NEXT:    ret
165;
166; RV32IZFINXZDINX-LABEL: callee_double_stack:
167; RV32IZFINXZDINX:       # %bb.0:
168; RV32IZFINXZDINX-NEXT:    lw a0, 8(sp)
169; RV32IZFINXZDINX-NEXT:    lw a1, 12(sp)
170; RV32IZFINXZDINX-NEXT:    lw a2, 0(sp)
171; RV32IZFINXZDINX-NEXT:    lw a3, 4(sp)
172; RV32IZFINXZDINX-NEXT:    fadd.d a0, a2, a0
173; RV32IZFINXZDINX-NEXT:    ret
174  %1 = fadd double %e, %f
175  ret double %1
176}
177
178define double @caller_double_stack() nounwind {
179; RV32IFD-LABEL: caller_double_stack:
180; RV32IFD:       # %bb.0:
181; RV32IFD-NEXT:    addi sp, sp, -32
182; RV32IFD-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
183; RV32IFD-NEXT:    lui a1, 262510
184; RV32IFD-NEXT:    lui a3, 713032
185; RV32IFD-NEXT:    lui a5, 262574
186; RV32IFD-NEXT:    li a0, 1
187; RV32IFD-NEXT:    li a2, 2
188; RV32IFD-NEXT:    li a4, 3
189; RV32IFD-NEXT:    li a6, 4
190; RV32IFD-NEXT:    addi a1, a1, 327
191; RV32IFD-NEXT:    addi a3, a3, -1311
192; RV32IFD-NEXT:    addi a5, a5, 327
193; RV32IFD-NEXT:    sw a3, 0(sp)
194; RV32IFD-NEXT:    sw a1, 4(sp)
195; RV32IFD-NEXT:    sw a3, 8(sp)
196; RV32IFD-NEXT:    sw a5, 12(sp)
197; RV32IFD-NEXT:    li a1, 0
198; RV32IFD-NEXT:    li a3, 0
199; RV32IFD-NEXT:    li a5, 0
200; RV32IFD-NEXT:    li a7, 0
201; RV32IFD-NEXT:    call callee_double_stack
202; RV32IFD-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
203; RV32IFD-NEXT:    addi sp, sp, 32
204; RV32IFD-NEXT:    ret
205;
206; RV32IZFINXZDINX-LABEL: caller_double_stack:
207; RV32IZFINXZDINX:       # %bb.0:
208; RV32IZFINXZDINX-NEXT:    addi sp, sp, -32
209; RV32IZFINXZDINX-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
210; RV32IZFINXZDINX-NEXT:    lui a1, 262510
211; RV32IZFINXZDINX-NEXT:    lui a3, 713032
212; RV32IZFINXZDINX-NEXT:    lui a5, 262574
213; RV32IZFINXZDINX-NEXT:    li a0, 1
214; RV32IZFINXZDINX-NEXT:    li a2, 2
215; RV32IZFINXZDINX-NEXT:    li a4, 3
216; RV32IZFINXZDINX-NEXT:    li a6, 4
217; RV32IZFINXZDINX-NEXT:    addi a1, a1, 327
218; RV32IZFINXZDINX-NEXT:    addi a3, a3, -1311
219; RV32IZFINXZDINX-NEXT:    addi a5, a5, 327
220; RV32IZFINXZDINX-NEXT:    sw a3, 0(sp)
221; RV32IZFINXZDINX-NEXT:    sw a1, 4(sp)
222; RV32IZFINXZDINX-NEXT:    sw a3, 8(sp)
223; RV32IZFINXZDINX-NEXT:    sw a5, 12(sp)
224; RV32IZFINXZDINX-NEXT:    li a1, 0
225; RV32IZFINXZDINX-NEXT:    li a3, 0
226; RV32IZFINXZDINX-NEXT:    li a5, 0
227; RV32IZFINXZDINX-NEXT:    li a7, 0
228; RV32IZFINXZDINX-NEXT:    call callee_double_stack
229; RV32IZFINXZDINX-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
230; RV32IZFINXZDINX-NEXT:    addi sp, sp, 32
231; RV32IZFINXZDINX-NEXT:    ret
232  %1 = call double @callee_double_stack(i64 1, i64 2, i64 3, i64 4, double 5.72, double 6.72)
233  ret double %1
234}
235
236define double @func_return_double_undef() nounwind {
237; RV32IFD-LABEL: func_return_double_undef:
238; RV32IFD:       # %bb.0:
239; RV32IFD-NEXT:    ret
240;
241; RV32IZFINXZDINX-LABEL: func_return_double_undef:
242; RV32IZFINXZDINX:       # %bb.0:
243; RV32IZFINXZDINX-NEXT:    ret
244  ret double undef
245}
246