[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / CodeGen / RISCV / calling-conv-ilp32-ilp32f-ilp32d-common.ll
blob10b0d54627da8bc72e20dc78911f9177c5fbc15f
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, 0(sp)
86 ; RV32I-FPELIM-NEXT:    xor a4, a4, t0
87 ; RV32I-FPELIM-NEXT:    xor a3, a3, a7
88 ; RV32I-FPELIM-NEXT:    or a3, a3, a4
89 ; RV32I-FPELIM-NEXT:    lui a4, 16
90 ; RV32I-FPELIM-NEXT:    addi a4, a4, -1
91 ; RV32I-FPELIM-NEXT:    and a1, a1, a4
92 ; RV32I-FPELIM-NEXT:    andi a0, a0, 255
93 ; RV32I-FPELIM-NEXT:    add a0, a0, a1
94 ; RV32I-FPELIM-NEXT:    add a0, a0, a2
95 ; RV32I-FPELIM-NEXT:    seqz a1, a3
96 ; RV32I-FPELIM-NEXT:    add a0, a1, a0
97 ; RV32I-FPELIM-NEXT:    add a0, a0, a5
98 ; RV32I-FPELIM-NEXT:    add a0, a0, a6
99 ; RV32I-FPELIM-NEXT:    lw a1, 4(sp)
100 ; RV32I-FPELIM-NEXT:    add a0, a0, a1
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, 0(s0)
110 ; RV32I-WITHFP-NEXT:    xor a4, a4, t0
111 ; RV32I-WITHFP-NEXT:    xor a3, a3, a7
112 ; RV32I-WITHFP-NEXT:    or a3, a3, a4
113 ; RV32I-WITHFP-NEXT:    lui a4, 16
114 ; RV32I-WITHFP-NEXT:    addi a4, a4, -1
115 ; RV32I-WITHFP-NEXT:    and a1, a1, a4
116 ; RV32I-WITHFP-NEXT:    andi a0, a0, 255
117 ; RV32I-WITHFP-NEXT:    add a0, a0, a1
118 ; RV32I-WITHFP-NEXT:    add a0, a0, a2
119 ; RV32I-WITHFP-NEXT:    seqz a1, a3
120 ; RV32I-WITHFP-NEXT:    add a0, a1, a0
121 ; RV32I-WITHFP-NEXT:    add a0, a0, a5
122 ; RV32I-WITHFP-NEXT:    add a0, a0, a6
123 ; RV32I-WITHFP-NEXT:    lw a1, 4(s0)
124 ; RV32I-WITHFP-NEXT:    add a0, a0, a1
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:    sw zero, 0(sp)
150 ; RV32I-FPELIM-NEXT:    addi a0, zero, 1
151 ; RV32I-FPELIM-NEXT:    addi a1, zero, 2
152 ; RV32I-FPELIM-NEXT:    addi a2, zero, 3
153 ; RV32I-FPELIM-NEXT:    addi a3, zero, 4
154 ; RV32I-FPELIM-NEXT:    mv a4, zero
155 ; RV32I-FPELIM-NEXT:    addi a5, zero, 5
156 ; RV32I-FPELIM-NEXT:    addi a6, zero, 6
157 ; RV32I-FPELIM-NEXT:    addi a7, zero, 7
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:    sw zero, 0(sp)
172 ; RV32I-WITHFP-NEXT:    addi a0, zero, 1
173 ; RV32I-WITHFP-NEXT:    addi a1, zero, 2
174 ; RV32I-WITHFP-NEXT:    addi a2, zero, 3
175 ; RV32I-WITHFP-NEXT:    addi a3, zero, 4
176 ; RV32I-WITHFP-NEXT:    mv a4, zero
177 ; RV32I-WITHFP-NEXT:    addi a5, zero, 5
178 ; RV32I-WITHFP-NEXT:    addi a6, zero, 6
179 ; RV32I-WITHFP-NEXT:    addi a7, zero, 7
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 a2, 12(a1)
196 ; RV32I-FPELIM-NEXT:    lw a3, 12(a0)
197 ; RV32I-FPELIM-NEXT:    xor a2, a3, a2
198 ; RV32I-FPELIM-NEXT:    lw a3, 4(a1)
199 ; RV32I-FPELIM-NEXT:    lw a4, 4(a0)
200 ; RV32I-FPELIM-NEXT:    xor a3, a4, a3
201 ; RV32I-FPELIM-NEXT:    or a2, a3, a2
202 ; RV32I-FPELIM-NEXT:    lw a3, 8(a1)
203 ; RV32I-FPELIM-NEXT:    lw a4, 8(a0)
204 ; RV32I-FPELIM-NEXT:    xor a3, a4, a3
205 ; RV32I-FPELIM-NEXT:    lw a1, 0(a1)
206 ; RV32I-FPELIM-NEXT:    lw a0, 0(a0)
207 ; RV32I-FPELIM-NEXT:    xor a0, a0, a1
208 ; RV32I-FPELIM-NEXT:    or a0, a0, a3
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 a2, 12(a1)
220 ; RV32I-WITHFP-NEXT:    lw a3, 12(a0)
221 ; RV32I-WITHFP-NEXT:    xor a2, a3, a2
222 ; RV32I-WITHFP-NEXT:    lw a3, 4(a1)
223 ; RV32I-WITHFP-NEXT:    lw a4, 4(a0)
224 ; RV32I-WITHFP-NEXT:    xor a3, a4, a3
225 ; RV32I-WITHFP-NEXT:    or a2, a3, a2
226 ; RV32I-WITHFP-NEXT:    lw a3, 8(a1)
227 ; RV32I-WITHFP-NEXT:    lw a4, 8(a0)
228 ; RV32I-WITHFP-NEXT:    xor a3, a4, a3
229 ; RV32I-WITHFP-NEXT:    lw a1, 0(a1)
230 ; RV32I-WITHFP-NEXT:    lw a0, 0(a0)
231 ; RV32I-WITHFP-NEXT:    xor a0, a0, a1
232 ; RV32I-WITHFP-NEXT:    or a0, a0, a3
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 a0, zero, 1
259 ; RV32I-FPELIM-NEXT:    sw a0, 24(sp)
260 ; RV32I-FPELIM-NEXT:    addi a0, sp, 24
261 ; RV32I-FPELIM-NEXT:    mv a1, 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 a0, zero, 1
282 ; RV32I-WITHFP-NEXT:    sw a0, -24(s0)
283 ; RV32I-WITHFP-NEXT:    addi a0, s0, -24
284 ; RV32I-WITHFP-NEXT:    addi a1, s0, -48
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 a1, 12(a0)
303 ; RV32I-FPELIM-NEXT:    lw a2, 12(a7)
304 ; RV32I-FPELIM-NEXT:    xor a1, a2, a1
305 ; RV32I-FPELIM-NEXT:    lw a2, 4(a0)
306 ; RV32I-FPELIM-NEXT:    lw a3, 4(a7)
307 ; RV32I-FPELIM-NEXT:    xor a2, a3, a2
308 ; RV32I-FPELIM-NEXT:    or a1, a2, a1
309 ; RV32I-FPELIM-NEXT:    lw a2, 8(a0)
310 ; RV32I-FPELIM-NEXT:    lw a3, 8(a7)
311 ; RV32I-FPELIM-NEXT:    xor a2, a3, a2
312 ; RV32I-FPELIM-NEXT:    lw a0, 0(a0)
313 ; RV32I-FPELIM-NEXT:    lw a3, 0(a7)
314 ; RV32I-FPELIM-NEXT:    xor a0, a3, a0
315 ; RV32I-FPELIM-NEXT:    or a0, a0, a2
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 a1, 12(a0)
328 ; RV32I-WITHFP-NEXT:    lw a2, 12(a7)
329 ; RV32I-WITHFP-NEXT:    xor a1, a2, a1
330 ; RV32I-WITHFP-NEXT:    lw a2, 4(a0)
331 ; RV32I-WITHFP-NEXT:    lw a3, 4(a7)
332 ; RV32I-WITHFP-NEXT:    xor a2, a3, a2
333 ; RV32I-WITHFP-NEXT:    or a1, a2, a1
334 ; RV32I-WITHFP-NEXT:    lw a2, 8(a0)
335 ; RV32I-WITHFP-NEXT:    lw a3, 8(a7)
336 ; RV32I-WITHFP-NEXT:    xor a2, a3, a2
337 ; RV32I-WITHFP-NEXT:    lw a0, 0(a0)
338 ; RV32I-WITHFP-NEXT:    lw a3, 0(a7)
339 ; RV32I-WITHFP-NEXT:    xor a0, a3, a0
340 ; RV32I-WITHFP-NEXT:    or a0, a0, a2
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 a0, zero, 8
371 ; RV32I-FPELIM-NEXT:    sw a0, 40(sp)
372 ; RV32I-FPELIM-NEXT:    addi a7, sp, 40
373 ; RV32I-FPELIM-NEXT:    addi a0, zero, 1
374 ; RV32I-FPELIM-NEXT:    addi a1, zero, 2
375 ; RV32I-FPELIM-NEXT:    addi a2, zero, 3
376 ; RV32I-FPELIM-NEXT:    addi a3, zero, 4
377 ; RV32I-FPELIM-NEXT:    addi a4, zero, 5
378 ; RV32I-FPELIM-NEXT:    addi a5, zero, 6
379 ; RV32I-FPELIM-NEXT:    addi a6, zero, 7
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 a0, zero, 8
404 ; RV32I-WITHFP-NEXT:    sw a0, -24(s0)
405 ; RV32I-WITHFP-NEXT:    addi a7, s0, -24
406 ; RV32I-WITHFP-NEXT:    addi a0, zero, 1
407 ; RV32I-WITHFP-NEXT:    addi a1, zero, 2
408 ; RV32I-WITHFP-NEXT:    addi a2, zero, 3
409 ; RV32I-WITHFP-NEXT:    addi a3, zero, 4
410 ; RV32I-WITHFP-NEXT:    addi a4, zero, 5
411 ; RV32I-WITHFP-NEXT:    addi a5, zero, 6
412 ; RV32I-WITHFP-NEXT:    addi a6, zero, 7
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, 12(a0)
528 ; RV32I-FPELIM-NEXT:    lw a0, 0(a0)
529 ; RV32I-FPELIM-NEXT:    add a0, a0, a1
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, 12(a0)
539 ; RV32I-WITHFP-NEXT:    lw a0, 0(a0)
540 ; RV32I-WITHFP-NEXT:    add a0, a0, a1
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:    sw a0, 8(sp)
561 ; RV32I-FPELIM-NEXT:    addi a0, zero, 2
562 ; RV32I-FPELIM-NEXT:    sw a0, 28(sp)
563 ; RV32I-FPELIM-NEXT:    sw a0, 12(sp)
564 ; RV32I-FPELIM-NEXT:    addi a0, zero, 3
565 ; RV32I-FPELIM-NEXT:    sw a0, 32(sp)
566 ; RV32I-FPELIM-NEXT:    sw a0, 16(sp)
567 ; RV32I-FPELIM-NEXT:    addi a0, zero, 4
568 ; RV32I-FPELIM-NEXT:    sw a0, 36(sp)
569 ; RV32I-FPELIM-NEXT:    sw a0, 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:    sw a0, -40(s0)
585 ; RV32I-WITHFP-NEXT:    addi a0, zero, 2
586 ; RV32I-WITHFP-NEXT:    sw a0, -20(s0)
587 ; RV32I-WITHFP-NEXT:    sw a0, -36(s0)
588 ; RV32I-WITHFP-NEXT:    addi a0, zero, 3
589 ; RV32I-WITHFP-NEXT:    sw a0, -16(s0)
590 ; RV32I-WITHFP-NEXT:    sw a0, -32(s0)
591 ; RV32I-WITHFP-NEXT:    addi a0, zero, 4
592 ; RV32I-WITHFP-NEXT:    sw a0, -12(s0)
593 ; RV32I-WITHFP-NEXT:    sw a0, -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:    add a0, a0, a7
623 ; RV32I-FPELIM-NEXT:    lw a1, 0(sp)
624 ; RV32I-FPELIM-NEXT:    add a0, a0, a1
625 ; RV32I-FPELIM-NEXT:    lw a1, 8(sp)
626 ; RV32I-FPELIM-NEXT:    add a0, a0, a1
627 ; RV32I-FPELIM-NEXT:    lw a1, 16(sp)
628 ; RV32I-FPELIM-NEXT:    add a0, a0, a1
629 ; RV32I-FPELIM-NEXT:    lw a1, 20(sp)
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:    add a0, a0, a7
641 ; RV32I-WITHFP-NEXT:    lw a1, 0(s0)
642 ; RV32I-WITHFP-NEXT:    add a0, a0, a1
643 ; RV32I-WITHFP-NEXT:    lw a1, 8(s0)
644 ; RV32I-WITHFP-NEXT:    add a0, a0, a1
645 ; RV32I-WITHFP-NEXT:    lw a1, 16(s0)
646 ; RV32I-WITHFP-NEXT:    add a0, a0, a1
647 ; RV32I-WITHFP-NEXT:    lw a1, 20(s0)
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 a0, a0, 1311
694 ; RV32I-FPELIM-NEXT:    sw a0, 32(sp)
695 ; RV32I-FPELIM-NEXT:    lui a0, 688509
696 ; RV32I-FPELIM-NEXT:    addi a5, a0, -2048
697 ; RV32I-FPELIM-NEXT:    addi a2, sp, 32
698 ; RV32I-FPELIM-NEXT:    addi a0, zero, 1
699 ; RV32I-FPELIM-NEXT:    addi a1, zero, 11
700 ; RV32I-FPELIM-NEXT:    addi a3, zero, 12
701 ; RV32I-FPELIM-NEXT:    addi a4, zero, 13
702 ; RV32I-FPELIM-NEXT:    addi a6, zero, 4
703 ; RV32I-FPELIM-NEXT:    addi a7, zero, 14
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 a0, a0, 1311
737 ; RV32I-WITHFP-NEXT:    sw a0, -32(s0)
738 ; RV32I-WITHFP-NEXT:    lui a0, 688509
739 ; RV32I-WITHFP-NEXT:    addi a5, a0, -2048
740 ; RV32I-WITHFP-NEXT:    addi a2, s0, -32
741 ; RV32I-WITHFP-NEXT:    addi a0, zero, 1
742 ; RV32I-WITHFP-NEXT:    addi a1, zero, 11
743 ; RV32I-WITHFP-NEXT:    addi a3, zero, 12
744 ; RV32I-WITHFP-NEXT:    addi a4, zero, 13
745 ; RV32I-WITHFP-NEXT:    addi a6, zero, 4
746 ; RV32I-WITHFP-NEXT:    addi a7, zero, 14
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:    sw s0, 8(sp)
791 ; RV32I-FPELIM-NEXT:    lui a0, 56
792 ; RV32I-FPELIM-NEXT:    addi s0, a0, 580
793 ; RV32I-FPELIM-NEXT:    call callee_small_scalar_ret
794 ; RV32I-FPELIM-NEXT:    xor a1, a1, s0
795 ; RV32I-FPELIM-NEXT:    lui a2, 200614
796 ; RV32I-FPELIM-NEXT:    addi a2, a2, 647
797 ; RV32I-FPELIM-NEXT:    xor a0, a0, a2
798 ; RV32I-FPELIM-NEXT:    or a0, a0, a1
799 ; RV32I-FPELIM-NEXT:    seqz a0, a0
800 ; RV32I-FPELIM-NEXT:    lw s0, 8(sp)
801 ; RV32I-FPELIM-NEXT:    lw ra, 12(sp)
802 ; RV32I-FPELIM-NEXT:    addi sp, sp, 16
803 ; RV32I-FPELIM-NEXT:    ret
805 ; RV32I-WITHFP-LABEL: caller_small_scalar_ret:
806 ; RV32I-WITHFP:       # %bb.0:
807 ; RV32I-WITHFP-NEXT:    addi sp, sp, -16
808 ; RV32I-WITHFP-NEXT:    sw ra, 12(sp)
809 ; RV32I-WITHFP-NEXT:    sw s0, 8(sp)
810 ; RV32I-WITHFP-NEXT:    sw s1, 4(sp)
811 ; RV32I-WITHFP-NEXT:    addi s0, sp, 16
812 ; RV32I-WITHFP-NEXT:    lui a0, 56
813 ; RV32I-WITHFP-NEXT:    addi s1, a0, 580
814 ; RV32I-WITHFP-NEXT:    call callee_small_scalar_ret
815 ; RV32I-WITHFP-NEXT:    xor a1, a1, s1
816 ; RV32I-WITHFP-NEXT:    lui a2, 200614
817 ; RV32I-WITHFP-NEXT:    addi a2, a2, 647
818 ; RV32I-WITHFP-NEXT:    xor a0, a0, a2
819 ; RV32I-WITHFP-NEXT:    or a0, a0, a1
820 ; RV32I-WITHFP-NEXT:    seqz a0, a0
821 ; RV32I-WITHFP-NEXT:    lw s1, 4(sp)
822 ; RV32I-WITHFP-NEXT:    lw s0, 8(sp)
823 ; RV32I-WITHFP-NEXT:    lw ra, 12(sp)
824 ; RV32I-WITHFP-NEXT:    addi sp, sp, 16
825 ; RV32I-WITHFP-NEXT:    ret
826   %1 = call i64 @callee_small_scalar_ret()
827   %2 = icmp eq i64 987654321234567, %1
828   %3 = zext i1 %2 to i32
829   ret i32 %3
832 ; Check return of 2x xlen structs
834 define %struct.small @callee_small_struct_ret() nounwind {
835 ; RV32I-FPELIM-LABEL: callee_small_struct_ret:
836 ; RV32I-FPELIM:       # %bb.0:
837 ; RV32I-FPELIM-NEXT:    addi a0, zero, 1
838 ; RV32I-FPELIM-NEXT:    mv a1, zero
839 ; RV32I-FPELIM-NEXT:    ret
841 ; RV32I-WITHFP-LABEL: callee_small_struct_ret:
842 ; RV32I-WITHFP:       # %bb.0:
843 ; RV32I-WITHFP-NEXT:    addi sp, sp, -16
844 ; RV32I-WITHFP-NEXT:    sw ra, 12(sp)
845 ; RV32I-WITHFP-NEXT:    sw s0, 8(sp)
846 ; RV32I-WITHFP-NEXT:    addi s0, sp, 16
847 ; RV32I-WITHFP-NEXT:    addi a0, zero, 1
848 ; RV32I-WITHFP-NEXT:    mv a1, zero
849 ; RV32I-WITHFP-NEXT:    lw s0, 8(sp)
850 ; RV32I-WITHFP-NEXT:    lw ra, 12(sp)
851 ; RV32I-WITHFP-NEXT:    addi sp, sp, 16
852 ; RV32I-WITHFP-NEXT:    ret
853   ret %struct.small { i32 1, i32* null }
856 define i32 @caller_small_struct_ret() nounwind {
857 ; RV32I-FPELIM-LABEL: caller_small_struct_ret:
858 ; RV32I-FPELIM:       # %bb.0:
859 ; RV32I-FPELIM-NEXT:    addi sp, sp, -16
860 ; RV32I-FPELIM-NEXT:    sw ra, 12(sp)
861 ; RV32I-FPELIM-NEXT:    call callee_small_struct_ret
862 ; RV32I-FPELIM-NEXT:    add a0, a0, a1
863 ; RV32I-FPELIM-NEXT:    lw ra, 12(sp)
864 ; RV32I-FPELIM-NEXT:    addi sp, sp, 16
865 ; RV32I-FPELIM-NEXT:    ret
867 ; RV32I-WITHFP-LABEL: caller_small_struct_ret:
868 ; RV32I-WITHFP:       # %bb.0:
869 ; RV32I-WITHFP-NEXT:    addi sp, sp, -16
870 ; RV32I-WITHFP-NEXT:    sw ra, 12(sp)
871 ; RV32I-WITHFP-NEXT:    sw s0, 8(sp)
872 ; RV32I-WITHFP-NEXT:    addi s0, sp, 16
873 ; RV32I-WITHFP-NEXT:    call callee_small_struct_ret
874 ; RV32I-WITHFP-NEXT:    add a0, a0, a1
875 ; RV32I-WITHFP-NEXT:    lw s0, 8(sp)
876 ; RV32I-WITHFP-NEXT:    lw ra, 12(sp)
877 ; RV32I-WITHFP-NEXT:    addi sp, sp, 16
878 ; RV32I-WITHFP-NEXT:    ret
879   %1 = call %struct.small @callee_small_struct_ret()
880   %2 = extractvalue %struct.small %1, 0
881   %3 = extractvalue %struct.small %1, 1
882   %4 = ptrtoint i32* %3 to i32
883   %5 = add i32 %2, %4
884   ret i32 %5
887 ; Check return of >2x xlen scalars
889 define fp128 @callee_large_scalar_ret() nounwind {
890 ; RV32I-FPELIM-LABEL: callee_large_scalar_ret:
891 ; RV32I-FPELIM:       # %bb.0:
892 ; RV32I-FPELIM-NEXT:    lui a1, 524272
893 ; RV32I-FPELIM-NEXT:    sw a1, 12(a0)
894 ; RV32I-FPELIM-NEXT:    sw zero, 8(a0)
895 ; RV32I-FPELIM-NEXT:    sw zero, 4(a0)
896 ; RV32I-FPELIM-NEXT:    sw zero, 0(a0)
897 ; RV32I-FPELIM-NEXT:    ret
899 ; RV32I-WITHFP-LABEL: callee_large_scalar_ret:
900 ; RV32I-WITHFP:       # %bb.0:
901 ; RV32I-WITHFP-NEXT:    addi sp, sp, -16
902 ; RV32I-WITHFP-NEXT:    sw ra, 12(sp)
903 ; RV32I-WITHFP-NEXT:    sw s0, 8(sp)
904 ; RV32I-WITHFP-NEXT:    addi s0, sp, 16
905 ; RV32I-WITHFP-NEXT:    lui a1, 524272
906 ; RV32I-WITHFP-NEXT:    sw a1, 12(a0)
907 ; RV32I-WITHFP-NEXT:    sw zero, 8(a0)
908 ; RV32I-WITHFP-NEXT:    sw zero, 4(a0)
909 ; RV32I-WITHFP-NEXT:    sw zero, 0(a0)
910 ; RV32I-WITHFP-NEXT:    lw s0, 8(sp)
911 ; RV32I-WITHFP-NEXT:    lw ra, 12(sp)
912 ; RV32I-WITHFP-NEXT:    addi sp, sp, 16
913 ; RV32I-WITHFP-NEXT:    ret
914   ret fp128 0xL00000000000000007FFF000000000000
917 define void @caller_large_scalar_ret() nounwind {
918 ; RV32I-FPELIM-LABEL: caller_large_scalar_ret:
919 ; RV32I-FPELIM:       # %bb.0:
920 ; RV32I-FPELIM-NEXT:    addi sp, sp, -32
921 ; RV32I-FPELIM-NEXT:    sw ra, 28(sp)
922 ; RV32I-FPELIM-NEXT:    mv a0, sp
923 ; RV32I-FPELIM-NEXT:    call callee_large_scalar_ret
924 ; RV32I-FPELIM-NEXT:    lw ra, 28(sp)
925 ; RV32I-FPELIM-NEXT:    addi sp, sp, 32
926 ; RV32I-FPELIM-NEXT:    ret
928 ; RV32I-WITHFP-LABEL: caller_large_scalar_ret:
929 ; RV32I-WITHFP:       # %bb.0:
930 ; RV32I-WITHFP-NEXT:    addi sp, sp, -32
931 ; RV32I-WITHFP-NEXT:    sw ra, 28(sp)
932 ; RV32I-WITHFP-NEXT:    sw s0, 24(sp)
933 ; RV32I-WITHFP-NEXT:    addi s0, sp, 32
934 ; RV32I-WITHFP-NEXT:    addi a0, s0, -32
935 ; RV32I-WITHFP-NEXT:    call callee_large_scalar_ret
936 ; RV32I-WITHFP-NEXT:    lw s0, 24(sp)
937 ; RV32I-WITHFP-NEXT:    lw ra, 28(sp)
938 ; RV32I-WITHFP-NEXT:    addi sp, sp, 32
939 ; RV32I-WITHFP-NEXT:    ret
940   %1 = call fp128 @callee_large_scalar_ret()
941   ret void
944 ; Check return of >2x xlen structs
946 define void @callee_large_struct_ret(%struct.large* noalias sret %agg.result) nounwind {
947 ; RV32I-FPELIM-LABEL: callee_large_struct_ret:
948 ; RV32I-FPELIM:       # %bb.0:
949 ; RV32I-FPELIM-NEXT:    addi a1, zero, 4
950 ; RV32I-FPELIM-NEXT:    sw a1, 12(a0)
951 ; RV32I-FPELIM-NEXT:    addi a1, zero, 3
952 ; RV32I-FPELIM-NEXT:    sw a1, 8(a0)
953 ; RV32I-FPELIM-NEXT:    addi a1, zero, 2
954 ; RV32I-FPELIM-NEXT:    sw a1, 4(a0)
955 ; RV32I-FPELIM-NEXT:    addi a1, zero, 1
956 ; RV32I-FPELIM-NEXT:    sw a1, 0(a0)
957 ; RV32I-FPELIM-NEXT:    ret
959 ; RV32I-WITHFP-LABEL: callee_large_struct_ret:
960 ; RV32I-WITHFP:       # %bb.0:
961 ; RV32I-WITHFP-NEXT:    addi sp, sp, -16
962 ; RV32I-WITHFP-NEXT:    sw ra, 12(sp)
963 ; RV32I-WITHFP-NEXT:    sw s0, 8(sp)
964 ; RV32I-WITHFP-NEXT:    addi s0, sp, 16
965 ; RV32I-WITHFP-NEXT:    addi a1, zero, 4
966 ; RV32I-WITHFP-NEXT:    sw a1, 12(a0)
967 ; RV32I-WITHFP-NEXT:    addi a1, zero, 3
968 ; RV32I-WITHFP-NEXT:    sw a1, 8(a0)
969 ; RV32I-WITHFP-NEXT:    addi a1, zero, 2
970 ; RV32I-WITHFP-NEXT:    sw a1, 4(a0)
971 ; RV32I-WITHFP-NEXT:    addi a1, zero, 1
972 ; RV32I-WITHFP-NEXT:    sw a1, 0(a0)
973 ; RV32I-WITHFP-NEXT:    lw s0, 8(sp)
974 ; RV32I-WITHFP-NEXT:    lw ra, 12(sp)
975 ; RV32I-WITHFP-NEXT:    addi sp, sp, 16
976 ; RV32I-WITHFP-NEXT:    ret
977   %a = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 0
978   store i32 1, i32* %a, align 4
979   %b = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 1
980   store i32 2, i32* %b, align 4
981   %c = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 2
982   store i32 3, i32* %c, align 4
983   %d = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 3
984   store i32 4, i32* %d, align 4
985   ret void
988 define i32 @caller_large_struct_ret() nounwind {
989 ; RV32I-FPELIM-LABEL: caller_large_struct_ret:
990 ; RV32I-FPELIM:       # %bb.0:
991 ; RV32I-FPELIM-NEXT:    addi sp, sp, -32
992 ; RV32I-FPELIM-NEXT:    sw ra, 28(sp)
993 ; RV32I-FPELIM-NEXT:    addi a0, sp, 8
994 ; RV32I-FPELIM-NEXT:    call callee_large_struct_ret
995 ; RV32I-FPELIM-NEXT:    lw a0, 20(sp)
996 ; RV32I-FPELIM-NEXT:    lw a1, 8(sp)
997 ; RV32I-FPELIM-NEXT:    add a0, a1, a0
998 ; RV32I-FPELIM-NEXT:    lw ra, 28(sp)
999 ; RV32I-FPELIM-NEXT:    addi sp, sp, 32
1000 ; RV32I-FPELIM-NEXT:    ret
1002 ; RV32I-WITHFP-LABEL: caller_large_struct_ret:
1003 ; RV32I-WITHFP:       # %bb.0:
1004 ; RV32I-WITHFP-NEXT:    addi sp, sp, -32
1005 ; RV32I-WITHFP-NEXT:    sw ra, 28(sp)
1006 ; RV32I-WITHFP-NEXT:    sw s0, 24(sp)
1007 ; RV32I-WITHFP-NEXT:    addi s0, sp, 32
1008 ; RV32I-WITHFP-NEXT:    addi a0, s0, -24
1009 ; RV32I-WITHFP-NEXT:    call callee_large_struct_ret
1010 ; RV32I-WITHFP-NEXT:    lw a0, -12(s0)
1011 ; RV32I-WITHFP-NEXT:    lw a1, -24(s0)
1012 ; RV32I-WITHFP-NEXT:    add a0, a1, a0
1013 ; RV32I-WITHFP-NEXT:    lw s0, 24(sp)
1014 ; RV32I-WITHFP-NEXT:    lw ra, 28(sp)
1015 ; RV32I-WITHFP-NEXT:    addi sp, sp, 32
1016 ; RV32I-WITHFP-NEXT:    ret
1017   %1 = alloca %struct.large
1018   call void @callee_large_struct_ret(%struct.large* sret %1)
1019   %2 = getelementptr inbounds %struct.large, %struct.large* %1, i32 0, i32 0
1020   %3 = load i32, i32* %2
1021   %4 = getelementptr inbounds %struct.large, %struct.large* %1, i32 0, i32 3
1022   %5 = load i32, i32* %4
1023   %6 = add i32 %3, %5
1024   ret i32 %6