Use Align for TFL::TransientStackAlignment
[llvm-core.git] / test / CodeGen / RISCV / calling-conv-ilp32-ilp32f-ilp32d-common.ll
blobe86a8c7406f7c579b7d506453b2f1acdd66b20a2
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
46   ret i32 %1
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)
77   ret i32 %1
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
132   %2 = add i32 %1, %c
133   %3 = icmp eq i64 %d, %g
134   %4 = zext i1 %3 to i32
135   %5 = add i32 %4, %2
136   %6 = add i32 %5, %e
137   %7 = add i32 %6, %f
138   %8 = add i32 %7, %h
139   ret i32 %8
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)
186   ret i32 %1
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
242   ret i32 %2
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)
291   ret i32 %1
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
350   ret i32 %2
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)
421   ret i32 %1
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
458   ret i32 %3
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
488   ret i32 %4
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])
517   ret i32 %1
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
549   %5 = add i32 %3, %4
550   ret i32 %5
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
603   store i32 1, i32* %a
604   %b = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 1
605   store i32 2, i32* %b
606   %c = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 2
607   store i32 3, i32* %c
608   %d = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 3
609   store i32 4, i32* %d
610   %2 = call i32 @callee_large_struct(%struct.large* byval align 4 %ls)
611   ret i32 %2
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
655   %3 = add i32 %2, %g
656   %4 = add i32 %3, %h
657   %5 = trunc i64 %i to i32
658   %6 = add i32 %4, %5
659   %7 = add i32 %6, %j
660   %8 = extractvalue [2 x i32] %k, 0
661   %9 = add i32 %7, %8
662   ret i32 %9
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])
756   ret void
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
825   ret i32 %3
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
879   %5 = add i32 %2, %4
880   ret i32 %5
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()
937   ret void
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
981   ret void
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
1019   %6 = add i32 %3, %5
1020   ret i32 %6