1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3 ; RUN: | FileCheck -check-prefix=RV32I-FPELIM %s
4 ; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f \
5 ; RUN: -verify-machineinstrs < %s \
6 ; RUN: | FileCheck -check-prefix=RV32I-FPELIM %s
7 ; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi ilp32d \
8 ; RUN: -verify-machineinstrs < %s \
9 ; RUN: | FileCheck -check-prefix=RV32I-FPELIM %s
10 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all < %s \
11 ; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s
12 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all \
13 ; RUN: -mattr=+f -target-abi ilp32f < %s \
14 ; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s
15 ; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all \
16 ; RUN: -mattr=+d -target-abi ilp32d < %s \
17 ; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s
19 ; This file contains tests that should have identical output for the ilp32,
20 ; ilp32f, and ilp32d ABIs. i.e. where no arguments are passed according to
21 ; the floating point ABI. As well as calling convention details, we check that
22 ; ra and fp are consistently stored to fp-4 and fp-8.
24 ; Check that on RV32, i64 is passed in a pair of registers. Unlike
25 ; the convention for varargs, this need not be an aligned pair.
27 define i32 @callee_i64_in_regs(i32 %a, i64 %b) nounwind {
28 ; RV32I-FPELIM-LABEL: callee_i64_in_regs:
29 ; RV32I-FPELIM: # %bb.0:
30 ; RV32I-FPELIM-NEXT: add a0, a0, a1
31 ; RV32I-FPELIM-NEXT: ret
33 ; RV32I-WITHFP-LABEL: callee_i64_in_regs:
34 ; RV32I-WITHFP: # %bb.0:
35 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
36 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
37 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
38 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
39 ; RV32I-WITHFP-NEXT: add a0, a0, a1
40 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
41 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
42 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
43 ; RV32I-WITHFP-NEXT: ret
44 %b_trunc = trunc i64 %b to i32
45 %1 = add i32 %a, %b_trunc
49 define i32 @caller_i64_in_regs() nounwind {
50 ; RV32I-FPELIM-LABEL: caller_i64_in_regs:
51 ; RV32I-FPELIM: # %bb.0:
52 ; RV32I-FPELIM-NEXT: addi sp, sp, -16
53 ; RV32I-FPELIM-NEXT: sw ra, 12(sp)
54 ; RV32I-FPELIM-NEXT: addi a0, zero, 1
55 ; RV32I-FPELIM-NEXT: addi a1, zero, 2
56 ; RV32I-FPELIM-NEXT: mv a2, zero
57 ; RV32I-FPELIM-NEXT: call callee_i64_in_regs
58 ; RV32I-FPELIM-NEXT: lw ra, 12(sp)
59 ; RV32I-FPELIM-NEXT: addi sp, sp, 16
60 ; RV32I-FPELIM-NEXT: ret
62 ; RV32I-WITHFP-LABEL: caller_i64_in_regs:
63 ; RV32I-WITHFP: # %bb.0:
64 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
65 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
66 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
67 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
68 ; RV32I-WITHFP-NEXT: addi a0, zero, 1
69 ; RV32I-WITHFP-NEXT: addi a1, zero, 2
70 ; RV32I-WITHFP-NEXT: mv a2, zero
71 ; RV32I-WITHFP-NEXT: call callee_i64_in_regs
72 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
73 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
74 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
75 ; RV32I-WITHFP-NEXT: ret
76 %1 = call i32 @callee_i64_in_regs(i32 1, i64 2)
80 ; Check that the stack is used once the GPRs are exhausted
82 define i32 @callee_many_scalars(i8 %a, i16 %b, i32 %c, i64 %d, i32 %e, i32 %f, i64 %g, i32 %h) nounwind {
83 ; RV32I-FPELIM-LABEL: callee_many_scalars:
84 ; RV32I-FPELIM: # %bb.0:
85 ; RV32I-FPELIM-NEXT: lw t0, 4(sp)
86 ; RV32I-FPELIM-NEXT: lw t1, 0(sp)
87 ; RV32I-FPELIM-NEXT: andi t2, a0, 255
88 ; RV32I-FPELIM-NEXT: lui a0, 16
89 ; RV32I-FPELIM-NEXT: addi a0, a0, -1
90 ; RV32I-FPELIM-NEXT: and a0, a1, a0
91 ; RV32I-FPELIM-NEXT: add a0, t2, a0
92 ; RV32I-FPELIM-NEXT: add a0, a0, a2
93 ; RV32I-FPELIM-NEXT: xor a1, a4, t1
94 ; RV32I-FPELIM-NEXT: xor a2, a3, a7
95 ; RV32I-FPELIM-NEXT: or a1, a2, a1
96 ; RV32I-FPELIM-NEXT: seqz a1, a1
97 ; RV32I-FPELIM-NEXT: add a0, a1, a0
98 ; RV32I-FPELIM-NEXT: add a0, a0, a5
99 ; RV32I-FPELIM-NEXT: add a0, a0, a6
100 ; RV32I-FPELIM-NEXT: add a0, a0, t0
101 ; RV32I-FPELIM-NEXT: ret
103 ; RV32I-WITHFP-LABEL: callee_many_scalars:
104 ; RV32I-WITHFP: # %bb.0:
105 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
106 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
107 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
108 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
109 ; RV32I-WITHFP-NEXT: lw t0, 4(s0)
110 ; RV32I-WITHFP-NEXT: lw t1, 0(s0)
111 ; RV32I-WITHFP-NEXT: andi t2, a0, 255
112 ; RV32I-WITHFP-NEXT: lui a0, 16
113 ; RV32I-WITHFP-NEXT: addi a0, a0, -1
114 ; RV32I-WITHFP-NEXT: and a0, a1, a0
115 ; RV32I-WITHFP-NEXT: add a0, t2, a0
116 ; RV32I-WITHFP-NEXT: add a0, a0, a2
117 ; RV32I-WITHFP-NEXT: xor a1, a4, t1
118 ; RV32I-WITHFP-NEXT: xor a2, a3, a7
119 ; RV32I-WITHFP-NEXT: or a1, a2, a1
120 ; RV32I-WITHFP-NEXT: seqz a1, a1
121 ; RV32I-WITHFP-NEXT: add a0, a1, a0
122 ; RV32I-WITHFP-NEXT: add a0, a0, a5
123 ; RV32I-WITHFP-NEXT: add a0, a0, a6
124 ; RV32I-WITHFP-NEXT: add a0, a0, t0
125 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
126 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
127 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
128 ; RV32I-WITHFP-NEXT: ret
129 %a_ext = zext i8 %a to i32
130 %b_ext = zext i16 %b to i32
131 %1 = add i32 %a_ext, %b_ext
133 %3 = icmp eq i64 %d, %g
134 %4 = zext i1 %3 to i32
142 define i32 @caller_many_scalars() nounwind {
143 ; RV32I-FPELIM-LABEL: caller_many_scalars:
144 ; RV32I-FPELIM: # %bb.0:
145 ; RV32I-FPELIM-NEXT: addi sp, sp, -16
146 ; RV32I-FPELIM-NEXT: sw ra, 12(sp)
147 ; RV32I-FPELIM-NEXT: addi a0, zero, 8
148 ; RV32I-FPELIM-NEXT: sw a0, 4(sp)
149 ; RV32I-FPELIM-NEXT: addi a0, zero, 1
150 ; RV32I-FPELIM-NEXT: addi a1, zero, 2
151 ; RV32I-FPELIM-NEXT: addi a2, zero, 3
152 ; RV32I-FPELIM-NEXT: addi a3, zero, 4
153 ; RV32I-FPELIM-NEXT: addi a5, zero, 5
154 ; RV32I-FPELIM-NEXT: addi a6, zero, 6
155 ; RV32I-FPELIM-NEXT: addi a7, zero, 7
156 ; RV32I-FPELIM-NEXT: sw zero, 0(sp)
157 ; RV32I-FPELIM-NEXT: mv a4, zero
158 ; RV32I-FPELIM-NEXT: call callee_many_scalars
159 ; RV32I-FPELIM-NEXT: lw ra, 12(sp)
160 ; RV32I-FPELIM-NEXT: addi sp, sp, 16
161 ; RV32I-FPELIM-NEXT: ret
163 ; RV32I-WITHFP-LABEL: caller_many_scalars:
164 ; RV32I-WITHFP: # %bb.0:
165 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
166 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
167 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
168 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
169 ; RV32I-WITHFP-NEXT: addi a0, zero, 8
170 ; RV32I-WITHFP-NEXT: sw a0, 4(sp)
171 ; RV32I-WITHFP-NEXT: addi a0, zero, 1
172 ; RV32I-WITHFP-NEXT: addi a1, zero, 2
173 ; RV32I-WITHFP-NEXT: addi a2, zero, 3
174 ; RV32I-WITHFP-NEXT: addi a3, zero, 4
175 ; RV32I-WITHFP-NEXT: addi a5, zero, 5
176 ; RV32I-WITHFP-NEXT: addi a6, zero, 6
177 ; RV32I-WITHFP-NEXT: addi a7, zero, 7
178 ; RV32I-WITHFP-NEXT: sw zero, 0(sp)
179 ; RV32I-WITHFP-NEXT: mv a4, zero
180 ; RV32I-WITHFP-NEXT: call callee_many_scalars
181 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
182 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
183 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
184 ; RV32I-WITHFP-NEXT: ret
185 %1 = call i32 @callee_many_scalars(i8 1, i16 2, i32 3, i64 4, i32 5, i32 6, i64 7, i32 8)
190 ; Check that i128 and fp128 are passed indirectly
192 define i32 @callee_large_scalars(i128 %a, fp128 %b) nounwind {
193 ; RV32I-FPELIM-LABEL: callee_large_scalars:
194 ; RV32I-FPELIM: # %bb.0:
195 ; RV32I-FPELIM-NEXT: lw a6, 0(a1)
196 ; RV32I-FPELIM-NEXT: lw a7, 0(a0)
197 ; RV32I-FPELIM-NEXT: lw a4, 4(a1)
198 ; RV32I-FPELIM-NEXT: lw a5, 12(a1)
199 ; RV32I-FPELIM-NEXT: lw a2, 12(a0)
200 ; RV32I-FPELIM-NEXT: lw a3, 4(a0)
201 ; RV32I-FPELIM-NEXT: lw a1, 8(a1)
202 ; RV32I-FPELIM-NEXT: lw a0, 8(a0)
203 ; RV32I-FPELIM-NEXT: xor a2, a2, a5
204 ; RV32I-FPELIM-NEXT: xor a3, a3, a4
205 ; RV32I-FPELIM-NEXT: or a2, a3, a2
206 ; RV32I-FPELIM-NEXT: xor a0, a0, a1
207 ; RV32I-FPELIM-NEXT: xor a1, a7, a6
208 ; RV32I-FPELIM-NEXT: or a0, a1, a0
209 ; RV32I-FPELIM-NEXT: or a0, a0, a2
210 ; RV32I-FPELIM-NEXT: seqz a0, a0
211 ; RV32I-FPELIM-NEXT: ret
213 ; RV32I-WITHFP-LABEL: callee_large_scalars:
214 ; RV32I-WITHFP: # %bb.0:
215 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
216 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
217 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
218 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
219 ; RV32I-WITHFP-NEXT: lw a6, 0(a1)
220 ; RV32I-WITHFP-NEXT: lw a7, 0(a0)
221 ; RV32I-WITHFP-NEXT: lw a4, 4(a1)
222 ; RV32I-WITHFP-NEXT: lw a5, 12(a1)
223 ; RV32I-WITHFP-NEXT: lw a2, 12(a0)
224 ; RV32I-WITHFP-NEXT: lw a3, 4(a0)
225 ; RV32I-WITHFP-NEXT: lw a1, 8(a1)
226 ; RV32I-WITHFP-NEXT: lw a0, 8(a0)
227 ; RV32I-WITHFP-NEXT: xor a2, a2, a5
228 ; RV32I-WITHFP-NEXT: xor a3, a3, a4
229 ; RV32I-WITHFP-NEXT: or a2, a3, a2
230 ; RV32I-WITHFP-NEXT: xor a0, a0, a1
231 ; RV32I-WITHFP-NEXT: xor a1, a7, a6
232 ; RV32I-WITHFP-NEXT: or a0, a1, a0
233 ; RV32I-WITHFP-NEXT: or a0, a0, a2
234 ; RV32I-WITHFP-NEXT: seqz a0, a0
235 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
236 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
237 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
238 ; RV32I-WITHFP-NEXT: ret
239 %b_bitcast = bitcast fp128 %b to i128
240 %1 = icmp eq i128 %a, %b_bitcast
241 %2 = zext i1 %1 to i32
245 define i32 @caller_large_scalars() nounwind {
246 ; RV32I-FPELIM-LABEL: caller_large_scalars:
247 ; RV32I-FPELIM: # %bb.0:
248 ; RV32I-FPELIM-NEXT: addi sp, sp, -48
249 ; RV32I-FPELIM-NEXT: sw ra, 44(sp)
250 ; RV32I-FPELIM-NEXT: lui a0, 524272
251 ; RV32I-FPELIM-NEXT: sw a0, 12(sp)
252 ; RV32I-FPELIM-NEXT: sw zero, 8(sp)
253 ; RV32I-FPELIM-NEXT: sw zero, 4(sp)
254 ; RV32I-FPELIM-NEXT: sw zero, 0(sp)
255 ; RV32I-FPELIM-NEXT: sw zero, 36(sp)
256 ; RV32I-FPELIM-NEXT: sw zero, 32(sp)
257 ; RV32I-FPELIM-NEXT: sw zero, 28(sp)
258 ; RV32I-FPELIM-NEXT: addi a2, zero, 1
259 ; RV32I-FPELIM-NEXT: addi a0, sp, 24
260 ; RV32I-FPELIM-NEXT: mv a1, sp
261 ; RV32I-FPELIM-NEXT: sw a2, 24(sp)
262 ; RV32I-FPELIM-NEXT: call callee_large_scalars
263 ; RV32I-FPELIM-NEXT: lw ra, 44(sp)
264 ; RV32I-FPELIM-NEXT: addi sp, sp, 48
265 ; RV32I-FPELIM-NEXT: ret
267 ; RV32I-WITHFP-LABEL: caller_large_scalars:
268 ; RV32I-WITHFP: # %bb.0:
269 ; RV32I-WITHFP-NEXT: addi sp, sp, -48
270 ; RV32I-WITHFP-NEXT: sw ra, 44(sp)
271 ; RV32I-WITHFP-NEXT: sw s0, 40(sp)
272 ; RV32I-WITHFP-NEXT: addi s0, sp, 48
273 ; RV32I-WITHFP-NEXT: lui a0, 524272
274 ; RV32I-WITHFP-NEXT: sw a0, -36(s0)
275 ; RV32I-WITHFP-NEXT: sw zero, -40(s0)
276 ; RV32I-WITHFP-NEXT: sw zero, -44(s0)
277 ; RV32I-WITHFP-NEXT: sw zero, -48(s0)
278 ; RV32I-WITHFP-NEXT: sw zero, -12(s0)
279 ; RV32I-WITHFP-NEXT: sw zero, -16(s0)
280 ; RV32I-WITHFP-NEXT: sw zero, -20(s0)
281 ; RV32I-WITHFP-NEXT: addi a2, zero, 1
282 ; RV32I-WITHFP-NEXT: addi a0, s0, -24
283 ; RV32I-WITHFP-NEXT: addi a1, s0, -48
284 ; RV32I-WITHFP-NEXT: sw a2, -24(s0)
285 ; RV32I-WITHFP-NEXT: call callee_large_scalars
286 ; RV32I-WITHFP-NEXT: lw s0, 40(sp)
287 ; RV32I-WITHFP-NEXT: lw ra, 44(sp)
288 ; RV32I-WITHFP-NEXT: addi sp, sp, 48
289 ; RV32I-WITHFP-NEXT: ret
290 %1 = call i32 @callee_large_scalars(i128 1, fp128 0xL00000000000000007FFF000000000000)
294 ; Check that arguments larger than 2*xlen are handled correctly when their
295 ; address is passed on the stack rather than in memory
297 ; Must keep define on a single line due to an update_llc_test_checks.py limitation
298 define i32 @callee_large_scalars_exhausted_regs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i128 %h, i32 %i, fp128 %j) nounwind {
299 ; RV32I-FPELIM-LABEL: callee_large_scalars_exhausted_regs:
300 ; RV32I-FPELIM: # %bb.0:
301 ; RV32I-FPELIM-NEXT: lw a0, 4(sp)
302 ; RV32I-FPELIM-NEXT: lw a6, 0(a0)
303 ; RV32I-FPELIM-NEXT: lw t0, 0(a7)
304 ; RV32I-FPELIM-NEXT: lw a3, 4(a0)
305 ; RV32I-FPELIM-NEXT: lw a4, 12(a0)
306 ; RV32I-FPELIM-NEXT: lw a5, 12(a7)
307 ; RV32I-FPELIM-NEXT: lw a1, 4(a7)
308 ; RV32I-FPELIM-NEXT: lw a0, 8(a0)
309 ; RV32I-FPELIM-NEXT: lw a2, 8(a7)
310 ; RV32I-FPELIM-NEXT: xor a4, a5, a4
311 ; RV32I-FPELIM-NEXT: xor a1, a1, a3
312 ; RV32I-FPELIM-NEXT: or a1, a1, a4
313 ; RV32I-FPELIM-NEXT: xor a0, a2, a0
314 ; RV32I-FPELIM-NEXT: xor a2, t0, a6
315 ; RV32I-FPELIM-NEXT: or a0, a2, a0
316 ; RV32I-FPELIM-NEXT: or a0, a0, a1
317 ; RV32I-FPELIM-NEXT: seqz a0, a0
318 ; RV32I-FPELIM-NEXT: ret
320 ; RV32I-WITHFP-LABEL: callee_large_scalars_exhausted_regs:
321 ; RV32I-WITHFP: # %bb.0:
322 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
323 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
324 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
325 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
326 ; RV32I-WITHFP-NEXT: lw a0, 4(s0)
327 ; RV32I-WITHFP-NEXT: lw a6, 0(a0)
328 ; RV32I-WITHFP-NEXT: lw t0, 0(a7)
329 ; RV32I-WITHFP-NEXT: lw a3, 4(a0)
330 ; RV32I-WITHFP-NEXT: lw a4, 12(a0)
331 ; RV32I-WITHFP-NEXT: lw a5, 12(a7)
332 ; RV32I-WITHFP-NEXT: lw a1, 4(a7)
333 ; RV32I-WITHFP-NEXT: lw a0, 8(a0)
334 ; RV32I-WITHFP-NEXT: lw a2, 8(a7)
335 ; RV32I-WITHFP-NEXT: xor a4, a5, a4
336 ; RV32I-WITHFP-NEXT: xor a1, a1, a3
337 ; RV32I-WITHFP-NEXT: or a1, a1, a4
338 ; RV32I-WITHFP-NEXT: xor a0, a2, a0
339 ; RV32I-WITHFP-NEXT: xor a2, t0, a6
340 ; RV32I-WITHFP-NEXT: or a0, a2, a0
341 ; RV32I-WITHFP-NEXT: or a0, a0, a1
342 ; RV32I-WITHFP-NEXT: seqz a0, a0
343 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
344 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
345 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
346 ; RV32I-WITHFP-NEXT: ret
347 %j_bitcast = bitcast fp128 %j to i128
348 %1 = icmp eq i128 %h, %j_bitcast
349 %2 = zext i1 %1 to i32
353 define i32 @caller_large_scalars_exhausted_regs() nounwind {
354 ; RV32I-FPELIM-LABEL: caller_large_scalars_exhausted_regs:
355 ; RV32I-FPELIM: # %bb.0:
356 ; RV32I-FPELIM-NEXT: addi sp, sp, -64
357 ; RV32I-FPELIM-NEXT: sw ra, 60(sp)
358 ; RV32I-FPELIM-NEXT: addi a0, sp, 16
359 ; RV32I-FPELIM-NEXT: sw a0, 4(sp)
360 ; RV32I-FPELIM-NEXT: addi a0, zero, 9
361 ; RV32I-FPELIM-NEXT: sw a0, 0(sp)
362 ; RV32I-FPELIM-NEXT: lui a0, 524272
363 ; RV32I-FPELIM-NEXT: sw a0, 28(sp)
364 ; RV32I-FPELIM-NEXT: sw zero, 24(sp)
365 ; RV32I-FPELIM-NEXT: sw zero, 20(sp)
366 ; RV32I-FPELIM-NEXT: sw zero, 16(sp)
367 ; RV32I-FPELIM-NEXT: sw zero, 52(sp)
368 ; RV32I-FPELIM-NEXT: sw zero, 48(sp)
369 ; RV32I-FPELIM-NEXT: sw zero, 44(sp)
370 ; RV32I-FPELIM-NEXT: addi t0, zero, 8
371 ; RV32I-FPELIM-NEXT: addi a7, sp, 40
372 ; RV32I-FPELIM-NEXT: addi a0, zero, 1
373 ; RV32I-FPELIM-NEXT: addi a1, zero, 2
374 ; RV32I-FPELIM-NEXT: addi a2, zero, 3
375 ; RV32I-FPELIM-NEXT: addi a3, zero, 4
376 ; RV32I-FPELIM-NEXT: addi a4, zero, 5
377 ; RV32I-FPELIM-NEXT: addi a5, zero, 6
378 ; RV32I-FPELIM-NEXT: addi a6, zero, 7
379 ; RV32I-FPELIM-NEXT: sw t0, 40(sp)
380 ; RV32I-FPELIM-NEXT: call callee_large_scalars_exhausted_regs
381 ; RV32I-FPELIM-NEXT: lw ra, 60(sp)
382 ; RV32I-FPELIM-NEXT: addi sp, sp, 64
383 ; RV32I-FPELIM-NEXT: ret
385 ; RV32I-WITHFP-LABEL: caller_large_scalars_exhausted_regs:
386 ; RV32I-WITHFP: # %bb.0:
387 ; RV32I-WITHFP-NEXT: addi sp, sp, -64
388 ; RV32I-WITHFP-NEXT: sw ra, 60(sp)
389 ; RV32I-WITHFP-NEXT: sw s0, 56(sp)
390 ; RV32I-WITHFP-NEXT: addi s0, sp, 64
391 ; RV32I-WITHFP-NEXT: addi a0, s0, -48
392 ; RV32I-WITHFP-NEXT: sw a0, 4(sp)
393 ; RV32I-WITHFP-NEXT: addi a0, zero, 9
394 ; RV32I-WITHFP-NEXT: sw a0, 0(sp)
395 ; RV32I-WITHFP-NEXT: lui a0, 524272
396 ; RV32I-WITHFP-NEXT: sw a0, -36(s0)
397 ; RV32I-WITHFP-NEXT: sw zero, -40(s0)
398 ; RV32I-WITHFP-NEXT: sw zero, -44(s0)
399 ; RV32I-WITHFP-NEXT: sw zero, -48(s0)
400 ; RV32I-WITHFP-NEXT: sw zero, -12(s0)
401 ; RV32I-WITHFP-NEXT: sw zero, -16(s0)
402 ; RV32I-WITHFP-NEXT: sw zero, -20(s0)
403 ; RV32I-WITHFP-NEXT: addi t0, zero, 8
404 ; RV32I-WITHFP-NEXT: addi a7, s0, -24
405 ; RV32I-WITHFP-NEXT: addi a0, zero, 1
406 ; RV32I-WITHFP-NEXT: addi a1, zero, 2
407 ; RV32I-WITHFP-NEXT: addi a2, zero, 3
408 ; RV32I-WITHFP-NEXT: addi a3, zero, 4
409 ; RV32I-WITHFP-NEXT: addi a4, zero, 5
410 ; RV32I-WITHFP-NEXT: addi a5, zero, 6
411 ; RV32I-WITHFP-NEXT: addi a6, zero, 7
412 ; RV32I-WITHFP-NEXT: sw t0, -24(s0)
413 ; RV32I-WITHFP-NEXT: call callee_large_scalars_exhausted_regs
414 ; RV32I-WITHFP-NEXT: lw s0, 56(sp)
415 ; RV32I-WITHFP-NEXT: lw ra, 60(sp)
416 ; RV32I-WITHFP-NEXT: addi sp, sp, 64
417 ; RV32I-WITHFP-NEXT: ret
418 %1 = call i32 @callee_large_scalars_exhausted_regs(
419 i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i128 8, i32 9,
420 fp128 0xL00000000000000007FFF000000000000)
424 ; Ensure that libcalls generated in the middle-end obey the calling convention
426 define i32 @caller_mixed_scalar_libcalls(i64 %a) nounwind {
427 ; RV32I-FPELIM-LABEL: caller_mixed_scalar_libcalls:
428 ; RV32I-FPELIM: # %bb.0:
429 ; RV32I-FPELIM-NEXT: addi sp, sp, -32
430 ; RV32I-FPELIM-NEXT: sw ra, 28(sp)
431 ; RV32I-FPELIM-NEXT: mv a2, a1
432 ; RV32I-FPELIM-NEXT: mv a1, a0
433 ; RV32I-FPELIM-NEXT: addi a0, sp, 8
434 ; RV32I-FPELIM-NEXT: call __floatditf
435 ; RV32I-FPELIM-NEXT: lw a0, 8(sp)
436 ; RV32I-FPELIM-NEXT: lw ra, 28(sp)
437 ; RV32I-FPELIM-NEXT: addi sp, sp, 32
438 ; RV32I-FPELIM-NEXT: ret
440 ; RV32I-WITHFP-LABEL: caller_mixed_scalar_libcalls:
441 ; RV32I-WITHFP: # %bb.0:
442 ; RV32I-WITHFP-NEXT: addi sp, sp, -32
443 ; RV32I-WITHFP-NEXT: sw ra, 28(sp)
444 ; RV32I-WITHFP-NEXT: sw s0, 24(sp)
445 ; RV32I-WITHFP-NEXT: addi s0, sp, 32
446 ; RV32I-WITHFP-NEXT: mv a2, a1
447 ; RV32I-WITHFP-NEXT: mv a1, a0
448 ; RV32I-WITHFP-NEXT: addi a0, s0, -24
449 ; RV32I-WITHFP-NEXT: call __floatditf
450 ; RV32I-WITHFP-NEXT: lw a0, -24(s0)
451 ; RV32I-WITHFP-NEXT: lw s0, 24(sp)
452 ; RV32I-WITHFP-NEXT: lw ra, 28(sp)
453 ; RV32I-WITHFP-NEXT: addi sp, sp, 32
454 ; RV32I-WITHFP-NEXT: ret
455 %1 = sitofp i64 %a to fp128
456 %2 = bitcast fp128 %1 to i128
457 %3 = trunc i128 %2 to i32
461 ; Check passing of coerced integer arrays
463 %struct.small = type { i32, i32* }
465 define i32 @callee_small_coerced_struct([2 x i32] %a.coerce) nounwind {
466 ; RV32I-FPELIM-LABEL: callee_small_coerced_struct:
467 ; RV32I-FPELIM: # %bb.0:
468 ; RV32I-FPELIM-NEXT: xor a0, a0, a1
469 ; RV32I-FPELIM-NEXT: seqz a0, a0
470 ; RV32I-FPELIM-NEXT: ret
472 ; RV32I-WITHFP-LABEL: callee_small_coerced_struct:
473 ; RV32I-WITHFP: # %bb.0:
474 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
475 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
476 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
477 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
478 ; RV32I-WITHFP-NEXT: xor a0, a0, a1
479 ; RV32I-WITHFP-NEXT: seqz a0, a0
480 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
481 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
482 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
483 ; RV32I-WITHFP-NEXT: ret
484 %1 = extractvalue [2 x i32] %a.coerce, 0
485 %2 = extractvalue [2 x i32] %a.coerce, 1
486 %3 = icmp eq i32 %1, %2
487 %4 = zext i1 %3 to i32
491 define i32 @caller_small_coerced_struct() nounwind {
492 ; RV32I-FPELIM-LABEL: caller_small_coerced_struct:
493 ; RV32I-FPELIM: # %bb.0:
494 ; RV32I-FPELIM-NEXT: addi sp, sp, -16
495 ; RV32I-FPELIM-NEXT: sw ra, 12(sp)
496 ; RV32I-FPELIM-NEXT: addi a0, zero, 1
497 ; RV32I-FPELIM-NEXT: addi a1, zero, 2
498 ; RV32I-FPELIM-NEXT: call callee_small_coerced_struct
499 ; RV32I-FPELIM-NEXT: lw ra, 12(sp)
500 ; RV32I-FPELIM-NEXT: addi sp, sp, 16
501 ; RV32I-FPELIM-NEXT: ret
503 ; RV32I-WITHFP-LABEL: caller_small_coerced_struct:
504 ; RV32I-WITHFP: # %bb.0:
505 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
506 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
507 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
508 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
509 ; RV32I-WITHFP-NEXT: addi a0, zero, 1
510 ; RV32I-WITHFP-NEXT: addi a1, zero, 2
511 ; RV32I-WITHFP-NEXT: call callee_small_coerced_struct
512 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
513 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
514 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
515 ; RV32I-WITHFP-NEXT: ret
516 %1 = call i32 @callee_small_coerced_struct([2 x i32] [i32 1, i32 2])
520 ; Check large struct arguments, which are passed byval
522 %struct.large = type { i32, i32, i32, i32 }
524 define i32 @callee_large_struct(%struct.large* byval align 4 %a) nounwind {
525 ; RV32I-FPELIM-LABEL: callee_large_struct:
526 ; RV32I-FPELIM: # %bb.0:
527 ; RV32I-FPELIM-NEXT: lw a1, 0(a0)
528 ; RV32I-FPELIM-NEXT: lw a0, 12(a0)
529 ; RV32I-FPELIM-NEXT: add a0, a1, a0
530 ; RV32I-FPELIM-NEXT: ret
532 ; RV32I-WITHFP-LABEL: callee_large_struct:
533 ; RV32I-WITHFP: # %bb.0:
534 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
535 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
536 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
537 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
538 ; RV32I-WITHFP-NEXT: lw a1, 0(a0)
539 ; RV32I-WITHFP-NEXT: lw a0, 12(a0)
540 ; RV32I-WITHFP-NEXT: add a0, a1, a0
541 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
542 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
543 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
544 ; RV32I-WITHFP-NEXT: ret
545 %1 = getelementptr inbounds %struct.large, %struct.large* %a, i32 0, i32 0
546 %2 = getelementptr inbounds %struct.large, %struct.large* %a, i32 0, i32 3
547 %3 = load i32, i32* %1
548 %4 = load i32, i32* %2
553 define i32 @caller_large_struct() nounwind {
554 ; RV32I-FPELIM-LABEL: caller_large_struct:
555 ; RV32I-FPELIM: # %bb.0:
556 ; RV32I-FPELIM-NEXT: addi sp, sp, -48
557 ; RV32I-FPELIM-NEXT: sw ra, 44(sp)
558 ; RV32I-FPELIM-NEXT: addi a0, zero, 1
559 ; RV32I-FPELIM-NEXT: sw a0, 24(sp)
560 ; RV32I-FPELIM-NEXT: addi a1, zero, 2
561 ; RV32I-FPELIM-NEXT: sw a1, 28(sp)
562 ; RV32I-FPELIM-NEXT: addi a2, zero, 3
563 ; RV32I-FPELIM-NEXT: sw a2, 32(sp)
564 ; RV32I-FPELIM-NEXT: addi a3, zero, 4
565 ; RV32I-FPELIM-NEXT: sw a3, 36(sp)
566 ; RV32I-FPELIM-NEXT: sw a0, 8(sp)
567 ; RV32I-FPELIM-NEXT: sw a1, 12(sp)
568 ; RV32I-FPELIM-NEXT: sw a2, 16(sp)
569 ; RV32I-FPELIM-NEXT: sw a3, 20(sp)
570 ; RV32I-FPELIM-NEXT: addi a0, sp, 8
571 ; RV32I-FPELIM-NEXT: call callee_large_struct
572 ; RV32I-FPELIM-NEXT: lw ra, 44(sp)
573 ; RV32I-FPELIM-NEXT: addi sp, sp, 48
574 ; RV32I-FPELIM-NEXT: ret
576 ; RV32I-WITHFP-LABEL: caller_large_struct:
577 ; RV32I-WITHFP: # %bb.0:
578 ; RV32I-WITHFP-NEXT: addi sp, sp, -48
579 ; RV32I-WITHFP-NEXT: sw ra, 44(sp)
580 ; RV32I-WITHFP-NEXT: sw s0, 40(sp)
581 ; RV32I-WITHFP-NEXT: addi s0, sp, 48
582 ; RV32I-WITHFP-NEXT: addi a0, zero, 1
583 ; RV32I-WITHFP-NEXT: sw a0, -24(s0)
584 ; RV32I-WITHFP-NEXT: addi a1, zero, 2
585 ; RV32I-WITHFP-NEXT: sw a1, -20(s0)
586 ; RV32I-WITHFP-NEXT: addi a2, zero, 3
587 ; RV32I-WITHFP-NEXT: sw a2, -16(s0)
588 ; RV32I-WITHFP-NEXT: addi a3, zero, 4
589 ; RV32I-WITHFP-NEXT: sw a3, -12(s0)
590 ; RV32I-WITHFP-NEXT: sw a0, -40(s0)
591 ; RV32I-WITHFP-NEXT: sw a1, -36(s0)
592 ; RV32I-WITHFP-NEXT: sw a2, -32(s0)
593 ; RV32I-WITHFP-NEXT: sw a3, -28(s0)
594 ; RV32I-WITHFP-NEXT: addi a0, s0, -40
595 ; RV32I-WITHFP-NEXT: call callee_large_struct
596 ; RV32I-WITHFP-NEXT: lw s0, 40(sp)
597 ; RV32I-WITHFP-NEXT: lw ra, 44(sp)
598 ; RV32I-WITHFP-NEXT: addi sp, sp, 48
599 ; RV32I-WITHFP-NEXT: ret
600 %ls = alloca %struct.large, align 4
601 %1 = bitcast %struct.large* %ls to i8*
602 %a = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 0
604 %b = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 1
606 %c = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 2
608 %d = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 3
610 %2 = call i32 @callee_large_struct(%struct.large* byval align 4 %ls)
614 ; Check 2x*xlen values are aligned appropriately when passed on the stack
615 ; Must keep define on a single line due to an update_llc_test_checks.py limitation
616 define i32 @callee_aligned_stack(i32 %a, i32 %b, fp128 %c, i32 %d, i32 %e, i64 %f, i32 %g, i32 %h, i64 %i, i32 %j, [2 x i32] %k) nounwind {
617 ; The i64 should be 8-byte aligned on the stack, but the two-element array
618 ; should only be 4-byte aligned
619 ; RV32I-FPELIM-LABEL: callee_aligned_stack:
620 ; RV32I-FPELIM: # %bb.0:
621 ; RV32I-FPELIM-NEXT: lw a0, 0(a2)
622 ; RV32I-FPELIM-NEXT: lw a1, 20(sp)
623 ; RV32I-FPELIM-NEXT: lw a2, 0(sp)
624 ; RV32I-FPELIM-NEXT: lw a3, 8(sp)
625 ; RV32I-FPELIM-NEXT: lw a4, 16(sp)
626 ; RV32I-FPELIM-NEXT: add a0, a0, a7
627 ; RV32I-FPELIM-NEXT: add a0, a0, a2
628 ; RV32I-FPELIM-NEXT: add a0, a0, a3
629 ; RV32I-FPELIM-NEXT: add a0, a0, a4
630 ; RV32I-FPELIM-NEXT: add a0, a0, a1
631 ; RV32I-FPELIM-NEXT: ret
633 ; RV32I-WITHFP-LABEL: callee_aligned_stack:
634 ; RV32I-WITHFP: # %bb.0:
635 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
636 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
637 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
638 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
639 ; RV32I-WITHFP-NEXT: lw a0, 0(a2)
640 ; RV32I-WITHFP-NEXT: lw a1, 20(s0)
641 ; RV32I-WITHFP-NEXT: lw a2, 0(s0)
642 ; RV32I-WITHFP-NEXT: lw a3, 8(s0)
643 ; RV32I-WITHFP-NEXT: lw a4, 16(s0)
644 ; RV32I-WITHFP-NEXT: add a0, a0, a7
645 ; RV32I-WITHFP-NEXT: add a0, a0, a2
646 ; RV32I-WITHFP-NEXT: add a0, a0, a3
647 ; RV32I-WITHFP-NEXT: add a0, a0, a4
648 ; RV32I-WITHFP-NEXT: add a0, a0, a1
649 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
650 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
651 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
652 ; RV32I-WITHFP-NEXT: ret
653 %1 = bitcast fp128 %c to i128
654 %2 = trunc i128 %1 to i32
657 %5 = trunc i64 %i to i32
660 %8 = extractvalue [2 x i32] %k, 0
665 define void @caller_aligned_stack() nounwind {
666 ; The i64 should be 8-byte aligned on the stack, but the two-element array
667 ; should only be 4-byte aligned
668 ; RV32I-FPELIM-LABEL: caller_aligned_stack:
669 ; RV32I-FPELIM: # %bb.0:
670 ; RV32I-FPELIM-NEXT: addi sp, sp, -64
671 ; RV32I-FPELIM-NEXT: sw ra, 60(sp)
672 ; RV32I-FPELIM-NEXT: addi a0, zero, 19
673 ; RV32I-FPELIM-NEXT: sw a0, 24(sp)
674 ; RV32I-FPELIM-NEXT: addi a0, zero, 18
675 ; RV32I-FPELIM-NEXT: sw a0, 20(sp)
676 ; RV32I-FPELIM-NEXT: addi a0, zero, 17
677 ; RV32I-FPELIM-NEXT: sw a0, 16(sp)
678 ; RV32I-FPELIM-NEXT: sw zero, 12(sp)
679 ; RV32I-FPELIM-NEXT: addi a0, zero, 16
680 ; RV32I-FPELIM-NEXT: sw a0, 8(sp)
681 ; RV32I-FPELIM-NEXT: addi a0, zero, 15
682 ; RV32I-FPELIM-NEXT: sw a0, 0(sp)
683 ; RV32I-FPELIM-NEXT: lui a0, 262153
684 ; RV32I-FPELIM-NEXT: addi a0, a0, 491
685 ; RV32I-FPELIM-NEXT: sw a0, 44(sp)
686 ; RV32I-FPELIM-NEXT: lui a0, 545260
687 ; RV32I-FPELIM-NEXT: addi a0, a0, -1967
688 ; RV32I-FPELIM-NEXT: sw a0, 40(sp)
689 ; RV32I-FPELIM-NEXT: lui a0, 964690
690 ; RV32I-FPELIM-NEXT: addi a0, a0, -328
691 ; RV32I-FPELIM-NEXT: sw a0, 36(sp)
692 ; RV32I-FPELIM-NEXT: lui a0, 335544
693 ; RV32I-FPELIM-NEXT: addi t0, a0, 1311
694 ; RV32I-FPELIM-NEXT: lui a0, 688509
695 ; RV32I-FPELIM-NEXT: addi a5, a0, -2048
696 ; RV32I-FPELIM-NEXT: addi a2, sp, 32
697 ; RV32I-FPELIM-NEXT: addi a0, zero, 1
698 ; RV32I-FPELIM-NEXT: addi a1, zero, 11
699 ; RV32I-FPELIM-NEXT: addi a3, zero, 12
700 ; RV32I-FPELIM-NEXT: addi a4, zero, 13
701 ; RV32I-FPELIM-NEXT: addi a6, zero, 4
702 ; RV32I-FPELIM-NEXT: addi a7, zero, 14
703 ; RV32I-FPELIM-NEXT: sw t0, 32(sp)
704 ; RV32I-FPELIM-NEXT: call callee_aligned_stack
705 ; RV32I-FPELIM-NEXT: lw ra, 60(sp)
706 ; RV32I-FPELIM-NEXT: addi sp, sp, 64
707 ; RV32I-FPELIM-NEXT: ret
709 ; RV32I-WITHFP-LABEL: caller_aligned_stack:
710 ; RV32I-WITHFP: # %bb.0:
711 ; RV32I-WITHFP-NEXT: addi sp, sp, -64
712 ; RV32I-WITHFP-NEXT: sw ra, 60(sp)
713 ; RV32I-WITHFP-NEXT: sw s0, 56(sp)
714 ; RV32I-WITHFP-NEXT: addi s0, sp, 64
715 ; RV32I-WITHFP-NEXT: addi a0, zero, 19
716 ; RV32I-WITHFP-NEXT: sw a0, 24(sp)
717 ; RV32I-WITHFP-NEXT: addi a0, zero, 18
718 ; RV32I-WITHFP-NEXT: sw a0, 20(sp)
719 ; RV32I-WITHFP-NEXT: addi a0, zero, 17
720 ; RV32I-WITHFP-NEXT: sw a0, 16(sp)
721 ; RV32I-WITHFP-NEXT: sw zero, 12(sp)
722 ; RV32I-WITHFP-NEXT: addi a0, zero, 16
723 ; RV32I-WITHFP-NEXT: sw a0, 8(sp)
724 ; RV32I-WITHFP-NEXT: addi a0, zero, 15
725 ; RV32I-WITHFP-NEXT: sw a0, 0(sp)
726 ; RV32I-WITHFP-NEXT: lui a0, 262153
727 ; RV32I-WITHFP-NEXT: addi a0, a0, 491
728 ; RV32I-WITHFP-NEXT: sw a0, -20(s0)
729 ; RV32I-WITHFP-NEXT: lui a0, 545260
730 ; RV32I-WITHFP-NEXT: addi a0, a0, -1967
731 ; RV32I-WITHFP-NEXT: sw a0, -24(s0)
732 ; RV32I-WITHFP-NEXT: lui a0, 964690
733 ; RV32I-WITHFP-NEXT: addi a0, a0, -328
734 ; RV32I-WITHFP-NEXT: sw a0, -28(s0)
735 ; RV32I-WITHFP-NEXT: lui a0, 335544
736 ; RV32I-WITHFP-NEXT: addi t0, a0, 1311
737 ; RV32I-WITHFP-NEXT: lui a0, 688509
738 ; RV32I-WITHFP-NEXT: addi a5, a0, -2048
739 ; RV32I-WITHFP-NEXT: addi a2, s0, -32
740 ; RV32I-WITHFP-NEXT: addi a0, zero, 1
741 ; RV32I-WITHFP-NEXT: addi a1, zero, 11
742 ; RV32I-WITHFP-NEXT: addi a3, zero, 12
743 ; RV32I-WITHFP-NEXT: addi a4, zero, 13
744 ; RV32I-WITHFP-NEXT: addi a6, zero, 4
745 ; RV32I-WITHFP-NEXT: addi a7, zero, 14
746 ; RV32I-WITHFP-NEXT: sw t0, -32(s0)
747 ; RV32I-WITHFP-NEXT: call callee_aligned_stack
748 ; RV32I-WITHFP-NEXT: lw s0, 56(sp)
749 ; RV32I-WITHFP-NEXT: lw ra, 60(sp)
750 ; RV32I-WITHFP-NEXT: addi sp, sp, 64
751 ; RV32I-WITHFP-NEXT: ret
752 %1 = call i32 @callee_aligned_stack(i32 1, i32 11,
753 fp128 0xLEB851EB851EB851F400091EB851EB851, i32 12, i32 13,
754 i64 20000000000, i32 14, i32 15, i64 16, i32 17,
755 [2 x i32] [i32 18, i32 19])
759 ; Check return of 2x xlen scalars
761 define i64 @callee_small_scalar_ret() nounwind {
762 ; RV32I-FPELIM-LABEL: callee_small_scalar_ret:
763 ; RV32I-FPELIM: # %bb.0:
764 ; RV32I-FPELIM-NEXT: lui a0, 466866
765 ; RV32I-FPELIM-NEXT: addi a0, a0, 1677
766 ; RV32I-FPELIM-NEXT: addi a1, zero, 287
767 ; RV32I-FPELIM-NEXT: ret
769 ; RV32I-WITHFP-LABEL: callee_small_scalar_ret:
770 ; RV32I-WITHFP: # %bb.0:
771 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
772 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
773 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
774 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
775 ; RV32I-WITHFP-NEXT: lui a0, 466866
776 ; RV32I-WITHFP-NEXT: addi a0, a0, 1677
777 ; RV32I-WITHFP-NEXT: addi a1, zero, 287
778 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
779 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
780 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
781 ; RV32I-WITHFP-NEXT: ret
782 ret i64 1234567898765
785 define i32 @caller_small_scalar_ret() nounwind {
786 ; RV32I-FPELIM-LABEL: caller_small_scalar_ret:
787 ; RV32I-FPELIM: # %bb.0:
788 ; RV32I-FPELIM-NEXT: addi sp, sp, -16
789 ; RV32I-FPELIM-NEXT: sw ra, 12(sp)
790 ; RV32I-FPELIM-NEXT: call callee_small_scalar_ret
791 ; RV32I-FPELIM-NEXT: lui a2, 56
792 ; RV32I-FPELIM-NEXT: addi a2, a2, 580
793 ; RV32I-FPELIM-NEXT: xor a1, a1, a2
794 ; RV32I-FPELIM-NEXT: lui a2, 200614
795 ; RV32I-FPELIM-NEXT: addi a2, a2, 647
796 ; RV32I-FPELIM-NEXT: xor a0, a0, a2
797 ; RV32I-FPELIM-NEXT: or a0, a0, a1
798 ; RV32I-FPELIM-NEXT: seqz a0, a0
799 ; RV32I-FPELIM-NEXT: lw ra, 12(sp)
800 ; RV32I-FPELIM-NEXT: addi sp, sp, 16
801 ; RV32I-FPELIM-NEXT: ret
803 ; RV32I-WITHFP-LABEL: caller_small_scalar_ret:
804 ; RV32I-WITHFP: # %bb.0:
805 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
806 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
807 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
808 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
809 ; RV32I-WITHFP-NEXT: call callee_small_scalar_ret
810 ; RV32I-WITHFP-NEXT: lui a2, 56
811 ; RV32I-WITHFP-NEXT: addi a2, a2, 580
812 ; RV32I-WITHFP-NEXT: xor a1, a1, a2
813 ; RV32I-WITHFP-NEXT: lui a2, 200614
814 ; RV32I-WITHFP-NEXT: addi a2, a2, 647
815 ; RV32I-WITHFP-NEXT: xor a0, a0, a2
816 ; RV32I-WITHFP-NEXT: or a0, a0, a1
817 ; RV32I-WITHFP-NEXT: seqz a0, a0
818 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
819 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
820 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
821 ; RV32I-WITHFP-NEXT: ret
822 %1 = call i64 @callee_small_scalar_ret()
823 %2 = icmp eq i64 987654321234567, %1
824 %3 = zext i1 %2 to i32
828 ; Check return of 2x xlen structs
830 define %struct.small @callee_small_struct_ret() nounwind {
831 ; RV32I-FPELIM-LABEL: callee_small_struct_ret:
832 ; RV32I-FPELIM: # %bb.0:
833 ; RV32I-FPELIM-NEXT: addi a0, zero, 1
834 ; RV32I-FPELIM-NEXT: mv a1, zero
835 ; RV32I-FPELIM-NEXT: ret
837 ; RV32I-WITHFP-LABEL: callee_small_struct_ret:
838 ; RV32I-WITHFP: # %bb.0:
839 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
840 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
841 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
842 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
843 ; RV32I-WITHFP-NEXT: addi a0, zero, 1
844 ; RV32I-WITHFP-NEXT: mv a1, zero
845 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
846 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
847 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
848 ; RV32I-WITHFP-NEXT: ret
849 ret %struct.small { i32 1, i32* null }
852 define i32 @caller_small_struct_ret() nounwind {
853 ; RV32I-FPELIM-LABEL: caller_small_struct_ret:
854 ; RV32I-FPELIM: # %bb.0:
855 ; RV32I-FPELIM-NEXT: addi sp, sp, -16
856 ; RV32I-FPELIM-NEXT: sw ra, 12(sp)
857 ; RV32I-FPELIM-NEXT: call callee_small_struct_ret
858 ; RV32I-FPELIM-NEXT: add a0, a0, a1
859 ; RV32I-FPELIM-NEXT: lw ra, 12(sp)
860 ; RV32I-FPELIM-NEXT: addi sp, sp, 16
861 ; RV32I-FPELIM-NEXT: ret
863 ; RV32I-WITHFP-LABEL: caller_small_struct_ret:
864 ; RV32I-WITHFP: # %bb.0:
865 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
866 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
867 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
868 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
869 ; RV32I-WITHFP-NEXT: call callee_small_struct_ret
870 ; RV32I-WITHFP-NEXT: add a0, a0, a1
871 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
872 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
873 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
874 ; RV32I-WITHFP-NEXT: ret
875 %1 = call %struct.small @callee_small_struct_ret()
876 %2 = extractvalue %struct.small %1, 0
877 %3 = extractvalue %struct.small %1, 1
878 %4 = ptrtoint i32* %3 to i32
883 ; Check return of >2x xlen scalars
885 define fp128 @callee_large_scalar_ret() nounwind {
886 ; RV32I-FPELIM-LABEL: callee_large_scalar_ret:
887 ; RV32I-FPELIM: # %bb.0:
888 ; RV32I-FPELIM-NEXT: lui a1, 524272
889 ; RV32I-FPELIM-NEXT: sw a1, 12(a0)
890 ; RV32I-FPELIM-NEXT: sw zero, 8(a0)
891 ; RV32I-FPELIM-NEXT: sw zero, 4(a0)
892 ; RV32I-FPELIM-NEXT: sw zero, 0(a0)
893 ; RV32I-FPELIM-NEXT: ret
895 ; RV32I-WITHFP-LABEL: callee_large_scalar_ret:
896 ; RV32I-WITHFP: # %bb.0:
897 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
898 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
899 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
900 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
901 ; RV32I-WITHFP-NEXT: lui a1, 524272
902 ; RV32I-WITHFP-NEXT: sw a1, 12(a0)
903 ; RV32I-WITHFP-NEXT: sw zero, 8(a0)
904 ; RV32I-WITHFP-NEXT: sw zero, 4(a0)
905 ; RV32I-WITHFP-NEXT: sw zero, 0(a0)
906 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
907 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
908 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
909 ; RV32I-WITHFP-NEXT: ret
910 ret fp128 0xL00000000000000007FFF000000000000
913 define void @caller_large_scalar_ret() nounwind {
914 ; RV32I-FPELIM-LABEL: caller_large_scalar_ret:
915 ; RV32I-FPELIM: # %bb.0:
916 ; RV32I-FPELIM-NEXT: addi sp, sp, -32
917 ; RV32I-FPELIM-NEXT: sw ra, 28(sp)
918 ; RV32I-FPELIM-NEXT: mv a0, sp
919 ; RV32I-FPELIM-NEXT: call callee_large_scalar_ret
920 ; RV32I-FPELIM-NEXT: lw ra, 28(sp)
921 ; RV32I-FPELIM-NEXT: addi sp, sp, 32
922 ; RV32I-FPELIM-NEXT: ret
924 ; RV32I-WITHFP-LABEL: caller_large_scalar_ret:
925 ; RV32I-WITHFP: # %bb.0:
926 ; RV32I-WITHFP-NEXT: addi sp, sp, -32
927 ; RV32I-WITHFP-NEXT: sw ra, 28(sp)
928 ; RV32I-WITHFP-NEXT: sw s0, 24(sp)
929 ; RV32I-WITHFP-NEXT: addi s0, sp, 32
930 ; RV32I-WITHFP-NEXT: addi a0, s0, -32
931 ; RV32I-WITHFP-NEXT: call callee_large_scalar_ret
932 ; RV32I-WITHFP-NEXT: lw s0, 24(sp)
933 ; RV32I-WITHFP-NEXT: lw ra, 28(sp)
934 ; RV32I-WITHFP-NEXT: addi sp, sp, 32
935 ; RV32I-WITHFP-NEXT: ret
936 %1 = call fp128 @callee_large_scalar_ret()
940 ; Check return of >2x xlen structs
942 define void @callee_large_struct_ret(%struct.large* noalias sret %agg.result) nounwind {
943 ; RV32I-FPELIM-LABEL: callee_large_struct_ret:
944 ; RV32I-FPELIM: # %bb.0:
945 ; RV32I-FPELIM-NEXT: addi a1, zero, 1
946 ; RV32I-FPELIM-NEXT: sw a1, 0(a0)
947 ; RV32I-FPELIM-NEXT: addi a1, zero, 2
948 ; RV32I-FPELIM-NEXT: sw a1, 4(a0)
949 ; RV32I-FPELIM-NEXT: addi a1, zero, 3
950 ; RV32I-FPELIM-NEXT: sw a1, 8(a0)
951 ; RV32I-FPELIM-NEXT: addi a1, zero, 4
952 ; RV32I-FPELIM-NEXT: sw a1, 12(a0)
953 ; RV32I-FPELIM-NEXT: ret
955 ; RV32I-WITHFP-LABEL: callee_large_struct_ret:
956 ; RV32I-WITHFP: # %bb.0:
957 ; RV32I-WITHFP-NEXT: addi sp, sp, -16
958 ; RV32I-WITHFP-NEXT: sw ra, 12(sp)
959 ; RV32I-WITHFP-NEXT: sw s0, 8(sp)
960 ; RV32I-WITHFP-NEXT: addi s0, sp, 16
961 ; RV32I-WITHFP-NEXT: addi a1, zero, 1
962 ; RV32I-WITHFP-NEXT: sw a1, 0(a0)
963 ; RV32I-WITHFP-NEXT: addi a1, zero, 2
964 ; RV32I-WITHFP-NEXT: sw a1, 4(a0)
965 ; RV32I-WITHFP-NEXT: addi a1, zero, 3
966 ; RV32I-WITHFP-NEXT: sw a1, 8(a0)
967 ; RV32I-WITHFP-NEXT: addi a1, zero, 4
968 ; RV32I-WITHFP-NEXT: sw a1, 12(a0)
969 ; RV32I-WITHFP-NEXT: lw s0, 8(sp)
970 ; RV32I-WITHFP-NEXT: lw ra, 12(sp)
971 ; RV32I-WITHFP-NEXT: addi sp, sp, 16
972 ; RV32I-WITHFP-NEXT: ret
973 %a = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 0
974 store i32 1, i32* %a, align 4
975 %b = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 1
976 store i32 2, i32* %b, align 4
977 %c = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 2
978 store i32 3, i32* %c, align 4
979 %d = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 3
980 store i32 4, i32* %d, align 4
984 define i32 @caller_large_struct_ret() nounwind {
985 ; RV32I-FPELIM-LABEL: caller_large_struct_ret:
986 ; RV32I-FPELIM: # %bb.0:
987 ; RV32I-FPELIM-NEXT: addi sp, sp, -32
988 ; RV32I-FPELIM-NEXT: sw ra, 28(sp)
989 ; RV32I-FPELIM-NEXT: addi a0, sp, 8
990 ; RV32I-FPELIM-NEXT: call callee_large_struct_ret
991 ; RV32I-FPELIM-NEXT: lw a0, 8(sp)
992 ; RV32I-FPELIM-NEXT: lw a1, 20(sp)
993 ; RV32I-FPELIM-NEXT: add a0, a0, a1
994 ; RV32I-FPELIM-NEXT: lw ra, 28(sp)
995 ; RV32I-FPELIM-NEXT: addi sp, sp, 32
996 ; RV32I-FPELIM-NEXT: ret
998 ; RV32I-WITHFP-LABEL: caller_large_struct_ret:
999 ; RV32I-WITHFP: # %bb.0:
1000 ; RV32I-WITHFP-NEXT: addi sp, sp, -32
1001 ; RV32I-WITHFP-NEXT: sw ra, 28(sp)
1002 ; RV32I-WITHFP-NEXT: sw s0, 24(sp)
1003 ; RV32I-WITHFP-NEXT: addi s0, sp, 32
1004 ; RV32I-WITHFP-NEXT: addi a0, s0, -24
1005 ; RV32I-WITHFP-NEXT: call callee_large_struct_ret
1006 ; RV32I-WITHFP-NEXT: lw a0, -24(s0)
1007 ; RV32I-WITHFP-NEXT: lw a1, -12(s0)
1008 ; RV32I-WITHFP-NEXT: add a0, a0, a1
1009 ; RV32I-WITHFP-NEXT: lw s0, 24(sp)
1010 ; RV32I-WITHFP-NEXT: lw ra, 28(sp)
1011 ; RV32I-WITHFP-NEXT: addi sp, sp, 32
1012 ; RV32I-WITHFP-NEXT: ret
1013 %1 = alloca %struct.large
1014 call void @callee_large_struct_ret(%struct.large* sret %1)
1015 %2 = getelementptr inbounds %struct.large, %struct.large* %1, i32 0, i32 0
1016 %3 = load i32, i32* %2
1017 %4 = getelementptr inbounds %struct.large, %struct.large* %1, i32 0, i32 3
1018 %5 = load i32, i32* %4