1; RUN: llc -mtriple armv7-arm-linux-gnueabihf -O2 -mcpu=cortex-a7 < %s | FileCheck %s
2
3%struct.twofloat = type { float, float }
4%struct.twodouble = type { double, double }
5
6; Check support for returning a float in GPR with soft float ABI
7define arm_aapcscc float @zerobits_float_soft() #0 {
8; CHECK-LABEL: zerobits_float_soft
9; CHECK: mov r0, #0
10  %1 = tail call float asm "mov ${0}, #0", "=&r"()
11  ret float %1
12}
13
14; Check support for returning a double in GPR with soft float ABI
15define arm_aapcscc double @zerobits_double_soft() #0 {
16; CHECK-LABEL: zerobits_double_soft
17; CHECK: mov r0, #0
18; CHECK-NEXT: mov r1, #0
19  %1 = tail call double asm "mov ${0:Q}, #0\0Amov ${0:R}, #0", "=&r"()
20  ret double %1
21}
22
23; Check support for returning a float in GPR with matching float input with
24; soft float ABI
25define arm_aapcscc float @flt_gpr_matching_in_op_soft(float %f) #0 {
26; CHECK-LABEL: flt_gpr_matching_in_op_soft
27; CHECK: mov r0, r0
28  %1 = call float asm "mov $0, $1", "=&r,0"(float %f)
29  ret float %1
30}
31
32; Check support for returning a double in GPR with matching double input with
33; soft float ABI
34define arm_aapcscc double @dbl_gpr_matching_in_op_soft(double %d) #0 {
35; CHECK-LABEL: dbl_gpr_matching_in_op_soft
36; CHECK: mov r1, r0
37  %1 = call double asm "mov ${0:R}, ${1:Q}", "=&r,0"(double %d)
38  ret double %1
39}
40
41; Check support for returning a float in specific GPR with matching float input
42; with soft float ABI
43define arm_aapcscc float @flt_gpr_matching_spec_reg_in_op_soft(float %f) #0 {
44; CHECK-LABEL: flt_gpr_matching_spec_reg_in_op_soft
45; CHECK: mov r3, r3
46  %1 = call float asm "mov $0, $1", "=&{r3},0"(float %f)
47  ret float %1
48}
49
50; Check support for returning a double in specific GPR with matching double
51; input with soft float ABI
52define arm_aapcscc double @dbl_gpr_matching_spec_reg_in_op_soft(double %d) #0 {
53; CHECK-LABEL: dbl_gpr_matching_spec_reg_in_op_soft
54; CHECK: mov r3, r2
55  %1 = call double asm "mov ${0:R}, ${1:Q}", "=&{r2},0"(double %d)
56  ret double %1
57}
58
59; Check support for returning several float in GPR
60define arm_aapcscc float @zerobits_float_convoluted_soft() #0 {
61; CHECK-LABEL: zerobits_float_convoluted_soft
62; CHECK: mov r0, #0
63; CHECK-NEXT: mov r1, #0
64  %1 = call { float, float } asm "mov $0, #0; mov $1, #0", "=r,=r"()
65  %asmresult = extractvalue { float, float } %1, 0
66  %asmresult1 = extractvalue { float, float } %1, 1
67  %add = fadd float %asmresult, %asmresult1
68  ret float %add
69}
70
71; Check support for returning several double in GPR
72define double @zerobits_double_convoluted_soft() #0 {
73; CHECK-LABEL: zerobits_double_convoluted_soft
74; CHECK: mov r0, #0
75; CHECK-NEXT: mov r1, #0
76; CHECK-NEXT: mov r2, #0
77; CHECK-NEXT: mov r3, #0
78  %1 = call { double, double } asm "mov ${0:Q}, #0; mov ${0:R}, #0; mov ${1:Q}, #0; mov ${1:R}, #0", "=r,=r"()
79  %asmresult = extractvalue { double, double } %1, 0
80  %asmresult1 = extractvalue { double, double } %1, 1
81  %add = fadd double %asmresult, %asmresult1
82  ret double %add
83}
84
85; Check support for returning several floats in GPRs with matching float inputs
86; with soft float ABI
87define arm_aapcscc float @flt_gprs_matching_in_op_soft(float %f1, float %f2) #0 {
88; CHECK-LABEL: flt_gprs_matching_in_op_soft
89; CHECK: mov r0, r0
90; CHECK-NEXT: mov r1, r1
91  %1 = call { float, float } asm "mov $0, $2; mov $1, $3", "=&r,=&r,0,1"(float %f1, float %f2)
92  %asmresult1 = extractvalue { float, float } %1, 0
93  %asmresult2 = extractvalue { float, float } %1, 1
94  %add = fadd float %asmresult1, %asmresult2
95  ret float %add
96}
97
98; Check support for returning several double in GPRs with matching double input
99; with soft float ABI
100define arm_aapcscc double @dbl_gprs_matching_in_op_soft(double %d1, double %d2) #0 {
101; CHECK-LABEL: dbl_gprs_matching_in_op_soft
102; CHECK: mov r1, r0
103; CHECK-NEXT: mov r3, r2
104  %1 = call { double, double } asm "mov ${0:R}, ${2:Q}; mov ${1:R}, ${3:Q}", "=&r,=&r,0,1"(double %d1, double %d2)
105  %asmresult1 = extractvalue { double, double } %1, 0
106  %asmresult2 = extractvalue { double, double } %1, 1
107  %add = fadd double %asmresult1, %asmresult2
108  ret double %add
109}
110
111; Check support for returning several float in specific GPRs with matching
112; float input with soft float ABI
113define arm_aapcscc float @flt_gprs_matching_spec_reg_in_op_soft(float %f1, float %f2) #0 {
114; CHECK-LABEL: flt_gprs_matching_spec_reg_in_op_soft
115; CHECK: mov r3, r3
116; CHECK-NEXT: mov r4, r4
117  %1 = call { float, float } asm "mov $0, $2; mov $1, $3", "=&{r3},=&{r4},0,1"(float %f1, float %f2)
118  %asmresult1 = extractvalue { float, float } %1, 0
119  %asmresult2 = extractvalue { float, float } %1, 1
120  %add = fadd float %asmresult1, %asmresult2
121  ret float %add
122}
123
124; Check support for returning several double in specific GPRs with matching
125; double input with soft float ABI
126define arm_aapcscc double @dbl_gprs_matching_spec_reg_in_op_soft(double %d1, double %d2) #0 {
127; CHECK-LABEL: dbl_gprs_matching_spec_reg_in_op_soft
128; CHECK: mov r3, r2
129; CHECK-NEXT: mov r5, r4
130  %1 = call { double, double } asm "mov ${0:R}, ${2:Q}; mov ${1:R}, ${3:Q}", "=&{r2},=&{r4},0,1"(double %d1, double %d2)
131  %asmresult1 = extractvalue { double, double } %1, 0
132  %asmresult2 = extractvalue { double, double } %1, 1
133  %add = fadd double %asmresult1, %asmresult2
134  ret double %add
135}
136
137attributes #0 = { nounwind "target-features"="+d16,+vfp2,+vfp3,-fp-only-sp" "use-soft-float"="true" }
138
139
140; Check support for returning a float in GPR with hard float ABI
141define float @zerobits_float_hard() #1 {
142; CHECK-LABEL: zerobits_float_hard
143; CHECK: mov r0, #0
144; CHECK: vmov s0, r0
145  %1 = tail call float asm "mov ${0}, #0", "=&r"()
146  ret float %1
147}
148
149; Check support for returning a double in GPR with hard float ABI
150define double @zerobits_double_hard() #1 {
151; CHECK-LABEL: zerobits_double_hard
152; CHECK: mov r0, #0
153; CHECK-NEXT: mov r1, #0
154; CHECK: vmov d0, r0, r1
155  %1 = tail call double asm "mov ${0:Q}, #0\0Amov ${0:R}, #0", "=&r"()
156  ret double %1
157}
158
159; Check support for returning a float in GPR with matching float input with
160; hard float ABI
161define float @flt_gpr_matching_in_op_hard(float %f) #1 {
162; CHECK-LABEL: flt_gpr_matching_in_op_hard
163; CHECK: vmov r0, s0
164; CHECK: mov r0, r0
165; CHECK: vmov s0, r0
166  %1 = call float asm "mov $0, $1", "=&r,0"(float %f)
167  ret float %1
168}
169
170; Check support for returning a double in GPR with matching double input with
171; hard float ABI
172define double @dbl_gpr_matching_in_op_hard(double %d) #1 {
173; CHECK-LABEL: dbl_gpr_matching_in_op_hard
174; CHECK: vmov r0, r1, d0
175; CHECK: mov r1, r0
176; CHECK: vmov d0, r0, r1
177  %1 = call double asm "mov ${0:R}, ${1:Q}", "=&r,0"(double %d)
178  ret double %1
179}
180
181; Check support for returning a float in specific GPR with matching float
182; input with hard float ABI
183define float @flt_gpr_matching_spec_reg_in_op_hard(float %f) #1 {
184; CHECK-LABEL: flt_gpr_matching_spec_reg_in_op_hard
185; CHECK: vmov r3, s0
186; CHECK: mov r3, r3
187; CHECK: vmov s0, r3
188  %1 = call float asm "mov $0, $1", "=&{r3},0"(float %f)
189  ret float %1
190}
191
192; Check support for returning a double in specific GPR with matching double
193; input with hard float ABI
194define double @dbl_gpr_matching_spec_reg_in_op_hard(double %d) #1 {
195; CHECK-LABEL: dbl_gpr_matching_spec_reg_in_op_hard
196; CHECK: vmov r2, r3, d0
197; CHECK: mov r3, r2
198; CHECK: vmov d0, r2, r3
199  %1 = call double asm "mov ${0:R}, ${1:Q}", "=&{r2},0"(double %d)
200  ret double %1
201}
202
203; Check support for returning several float in GPR
204define %struct.twofloat @zerobits_float_convoluted_hard() #1 {
205; CHECK-LABEL: zerobits_float_convoluted_hard
206; CHECK: mov r0, #0
207; CHECK-NEXT: mov r1, #0
208; CHECK: vmov s0, r0
209; CHECK-NEXT: vmov s1, r1
210  %1 = call { float, float } asm "mov $0, #0; mov $1, #0", "=r,=r"()
211  %asmresult1 = extractvalue { float, float } %1, 0
212  %asmresult2 = extractvalue { float, float } %1, 1
213  %partialres = insertvalue %struct.twofloat undef, float %asmresult1, 0
214  %res = insertvalue %struct.twofloat %partialres, float %asmresult2, 1
215  ret %struct.twofloat %res
216}
217
218; Check support for returning several double in GPR
219define %struct.twodouble @zerobits_double_convoluted_hard() #1 {
220; CHECK-LABEL: zerobits_double_convoluted_hard
221; CHECK: mov r0, #0
222; CHECK-NEXT: mov r1, #0
223; CHECK-NEXT: mov r2, #0
224; CHECK-NEXT: mov r3, #0
225; CHECK: vmov d0, r0, r1
226; CHECK-NEXT: vmov d1, r2, r3
227  %1 = call { double, double } asm "mov ${0:Q}, #0; mov ${0:R}, #0; mov ${1:Q}, #0; mov ${1:R}, #0", "=r,=r"()
228  %asmresult1 = extractvalue { double, double } %1, 0
229  %asmresult2 = extractvalue { double, double } %1, 1
230  %partialres = insertvalue %struct.twodouble undef, double %asmresult1, 0
231  %res = insertvalue %struct.twodouble %partialres, double %asmresult2, 1
232  ret %struct.twodouble %res
233}
234
235; Check support for returning several floats in GPRs with matching float inputs
236; with hard float ABI
237define %struct.twofloat @flt_gprs_matching_in_op_hard(float %f1, float %f2) #1 {
238; CHECK-LABEL: flt_gprs_matching_in_op_hard
239; CHECK: vmov r0, s0
240; CHECK-NEXT: vmov r1, s1
241; CHECK: mov r0, r0
242; CHECK-NEXT: mov r1, r1
243; CHECK: vmov s0, r0
244; CHECK-NEXT: vmov s1, r1
245  %1 = call { float, float } asm "mov $0, $2; mov $1, $3", "=&r,=&r,0,1"(float %f1, float %f2)
246  %asmresult1 = extractvalue { float, float } %1, 0
247  %asmresult2 = extractvalue { float, float } %1, 1
248  %partialres = insertvalue %struct.twofloat undef, float %asmresult1, 0
249  %res = insertvalue %struct.twofloat %partialres, float %asmresult2, 1
250  ret %struct.twofloat %res
251}
252
253; Check support for returning several double in GPRs with matching double input
254; with hard float ABI
255define %struct.twodouble @dbl_gprs_matching_in_op_hard(double %d1, double %d2) #1 {
256; CHECK-LABEL: dbl_gprs_matching_in_op_hard
257; CHECK: vmov r0, r1, d0
258; CHECK-NEXT: vmov r2, r3, d1
259; CHECK: mov r1, r0
260; CHECK-NEXT: mov r3, r2
261; CHECK: vmov d0, r0, r1
262; CHECK-NEXT: vmov d1, r2, r3
263  %1 = call { double, double } asm "mov ${0:R}, ${2:Q}; mov ${1:R}, ${3:Q}", "=&r,=&r,0,1"(double %d1, double %d2)
264  %asmresult1 = extractvalue { double, double } %1, 0
265  %asmresult2 = extractvalue { double, double } %1, 1
266  %partialres = insertvalue %struct.twodouble undef, double %asmresult1, 0
267  %res = insertvalue %struct.twodouble %partialres, double %asmresult2, 1
268  ret %struct.twodouble %res
269}
270
271; Check support for returning several float in specific GPRs with matching
272; float input with hard float ABI
273define %struct.twofloat @flt_gprs_matching_spec_reg_in_op_hard(float %f1, float %f2) #1 {
274; CHECK-LABEL: flt_gprs_matching_spec_reg_in_op_hard
275; CHECK: vmov r3, s0
276; CHECK-NEXT: vmov r4, s1
277; CHECK: mov r3, r3
278; CHECK-NEXT: mov r4, r4
279; CHECK: vmov s0, r3
280; CHECK-NEXT: vmov s1, r4
281  %1 = call { float, float } asm "mov $0, $2; mov $1, $3", "=&{r3},=&{r4},0,1"(float %f1, float %f2)
282  %asmresult1 = extractvalue { float, float } %1, 0
283  %asmresult2 = extractvalue { float, float } %1, 1
284  %partialres = insertvalue %struct.twofloat undef, float %asmresult1, 0
285  %res = insertvalue %struct.twofloat %partialres, float %asmresult2, 1
286  ret %struct.twofloat %res
287}
288
289; Check support for returning several double in specific GPRs with matching
290; double input with hard float ABI
291define %struct.twodouble @dbl_gprs_matching_spec_reg_in_op_hard(double %d1, double %d2) #1 {
292; CHECK-LABEL: dbl_gprs_matching_spec_reg_in_op_hard
293; CHECK: vmov r2, r3, d0
294; CHECK-NEXT: vmov r4, r5, d1
295; CHECK: mov r3, r2
296; CHECK-NEXT: mov r5, r4
297; CHECK: vmov d0, r2, r3
298; CHECK-NEXT: vmov d1, r4, r5
299  %1 = call { double, double } asm "mov ${0:R}, ${2:Q}; mov ${1:R}, ${3:Q}", "=&{r2},=&{r4},0,1"(double %d1, double %d2)
300  %asmresult1 = extractvalue { double, double } %1, 0
301  %asmresult2 = extractvalue { double, double } %1, 1
302  %partialres = insertvalue %struct.twodouble undef, double %asmresult1, 0
303  %res = insertvalue %struct.twodouble %partialres, double %asmresult2, 1
304  ret %struct.twodouble %res
305}
306
307attributes #1 = { nounwind "target-features"="+d16,+vfp2,+vfp3,-fp-only-sp" "use-soft-float"="false" }
308