1 ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
2 ; RUN: llc -mtriple=riscv32 \
3 ; RUN: -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
4 ; RUN: | FileCheck -check-prefixes=RV32I,ILP32 %s
5 ; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f \
6 ; RUN: -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
7 ; RUN: | FileCheck -check-prefixes=RV32I,ILP32F %s
8 ; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi ilp32d \
9 ; RUN: -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \
10 ; RUN: | FileCheck -check-prefixes=RV32I,ILP32D %s
12 ; This file contains tests that should have identical output for the ilp32,
13 ; ilp32f, and ilp32d ABIs. i.e. where no arguments are passed according to
14 ; the floating point ABI.
16 ; Check that on RV32, i64 is passed in a pair of registers. Unlike
17 ; the convention for varargs, this need not be an aligned pair.
19 define i32 @callee_i64_in_regs(i32 %a, i64 %b) nounwind {
20 ; RV32I-LABEL: name: callee_i64_in_regs
21 ; RV32I: bb.1 (%ir-block.0):
22 ; RV32I-NEXT: liveins: $x10, $x11, $x12
24 ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
25 ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
26 ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
27 ; RV32I-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32)
28 ; RV32I-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64)
29 ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[TRUNC]]
30 ; RV32I-NEXT: $x10 = COPY [[ADD]](s32)
31 ; RV32I-NEXT: PseudoRET implicit $x10
32 %b_trunc = trunc i64 %b to i32
33 %1 = add i32 %a, %b_trunc
37 define i32 @caller_i64_in_regs() nounwind {
38 ; ILP32-LABEL: name: caller_i64_in_regs
39 ; ILP32: bb.1 (%ir-block.0):
40 ; ILP32-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
41 ; ILP32-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
42 ; ILP32-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
43 ; ILP32-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64)
44 ; ILP32-NEXT: $x10 = COPY [[C]](s32)
45 ; ILP32-NEXT: $x11 = COPY [[UV]](s32)
46 ; ILP32-NEXT: $x12 = COPY [[UV1]](s32)
47 ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_i64_in_regs, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit-def $x10
48 ; ILP32-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
49 ; ILP32-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
50 ; ILP32-NEXT: $x10 = COPY [[COPY]](s32)
51 ; ILP32-NEXT: PseudoRET implicit $x10
53 ; ILP32F-LABEL: name: caller_i64_in_regs
54 ; ILP32F: bb.1 (%ir-block.0):
55 ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
56 ; ILP32F-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
57 ; ILP32F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
58 ; ILP32F-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64)
59 ; ILP32F-NEXT: $x10 = COPY [[C]](s32)
60 ; ILP32F-NEXT: $x11 = COPY [[UV]](s32)
61 ; ILP32F-NEXT: $x12 = COPY [[UV1]](s32)
62 ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_i64_in_regs, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit-def $x10
63 ; ILP32F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
64 ; ILP32F-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
65 ; ILP32F-NEXT: $x10 = COPY [[COPY]](s32)
66 ; ILP32F-NEXT: PseudoRET implicit $x10
68 ; ILP32D-LABEL: name: caller_i64_in_regs
69 ; ILP32D: bb.1 (%ir-block.0):
70 ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
71 ; ILP32D-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
72 ; ILP32D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
73 ; ILP32D-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64)
74 ; ILP32D-NEXT: $x10 = COPY [[C]](s32)
75 ; ILP32D-NEXT: $x11 = COPY [[UV]](s32)
76 ; ILP32D-NEXT: $x12 = COPY [[UV1]](s32)
77 ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_i64_in_regs, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit-def $x10
78 ; ILP32D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
79 ; ILP32D-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
80 ; ILP32D-NEXT: $x10 = COPY [[COPY]](s32)
81 ; ILP32D-NEXT: PseudoRET implicit $x10
82 %1 = call i32 @callee_i64_in_regs(i32 1, i64 2)
86 ; Check that the stack is used once the GPRs are exhausted
88 define i32 @callee_many_scalars(i8 %a, i16 %b, i32 %c, i64 %d, i32 %e, i32 %f, i64 %g, i32 %h) nounwind {
89 ; RV32I-LABEL: name: callee_many_scalars
90 ; RV32I: bb.1 (%ir-block.0):
91 ; RV32I-NEXT: liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17
93 ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
94 ; RV32I-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32)
95 ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
96 ; RV32I-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
97 ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
98 ; RV32I-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13
99 ; RV32I-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $x14
100 ; RV32I-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY3]](s32), [[COPY4]](s32)
101 ; RV32I-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $x15
102 ; RV32I-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY $x16
103 ; RV32I-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $x17
104 ; RV32I-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1
105 ; RV32I-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.1, align 16)
106 ; RV32I-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY7]](s32), [[LOAD]](s32)
107 ; RV32I-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0
108 ; RV32I-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX1]](p0) :: (load (s32) from %fixed-stack.0)
109 ; RV32I-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8)
110 ; RV32I-NEXT: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC1]](s16)
111 ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ZEXT]], [[ZEXT1]]
112 ; RV32I-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[COPY2]]
113 ; RV32I-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[MV]](s64), [[MV1]]
114 ; RV32I-NEXT: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP]](s1)
115 ; RV32I-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ZEXT2]], [[ADD1]]
116 ; RV32I-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[ADD2]], [[COPY5]]
117 ; RV32I-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[COPY6]]
118 ; RV32I-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[LOAD1]]
119 ; RV32I-NEXT: $x10 = COPY [[ADD5]](s32)
120 ; RV32I-NEXT: PseudoRET implicit $x10
121 %a_ext = zext i8 %a to i32
122 %b_ext = zext i16 %b to i32
123 %1 = add i32 %a_ext, %b_ext
125 %3 = icmp eq i64 %d, %g
126 %4 = zext i1 %3 to i32
134 define i32 @caller_many_scalars() nounwind {
135 ; ILP32-LABEL: name: caller_many_scalars
136 ; ILP32: bb.1 (%ir-block.0):
137 ; ILP32-NEXT: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
138 ; ILP32-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
139 ; ILP32-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
140 ; ILP32-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
141 ; ILP32-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
142 ; ILP32-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 6
143 ; ILP32-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7
144 ; ILP32-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
145 ; ILP32-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2
146 ; ILP32-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s8)
147 ; ILP32-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[C1]](s16)
148 ; ILP32-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64)
149 ; ILP32-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64)
150 ; ILP32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2
151 ; ILP32-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
152 ; ILP32-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C8]](s32)
153 ; ILP32-NEXT: G_STORE [[UV3]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16)
154 ; ILP32-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
155 ; ILP32-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s32)
156 ; ILP32-NEXT: G_STORE [[C7]](s32), [[PTR_ADD1]](p0) :: (store (s32) into stack + 4)
157 ; ILP32-NEXT: $x10 = COPY [[ANYEXT]](s32)
158 ; ILP32-NEXT: $x11 = COPY [[ANYEXT1]](s32)
159 ; ILP32-NEXT: $x12 = COPY [[C2]](s32)
160 ; ILP32-NEXT: $x13 = COPY [[UV]](s32)
161 ; ILP32-NEXT: $x14 = COPY [[UV1]](s32)
162 ; ILP32-NEXT: $x15 = COPY [[C4]](s32)
163 ; ILP32-NEXT: $x16 = COPY [[C5]](s32)
164 ; ILP32-NEXT: $x17 = COPY [[UV2]](s32)
165 ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_many_scalars, csr_ilp32_lp64, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10
166 ; ILP32-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2
167 ; ILP32-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
168 ; ILP32-NEXT: $x10 = COPY [[COPY1]](s32)
169 ; ILP32-NEXT: PseudoRET implicit $x10
171 ; ILP32F-LABEL: name: caller_many_scalars
172 ; ILP32F: bb.1 (%ir-block.0):
173 ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
174 ; ILP32F-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
175 ; ILP32F-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
176 ; ILP32F-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
177 ; ILP32F-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
178 ; ILP32F-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 6
179 ; ILP32F-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7
180 ; ILP32F-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
181 ; ILP32F-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2
182 ; ILP32F-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s8)
183 ; ILP32F-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[C1]](s16)
184 ; ILP32F-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64)
185 ; ILP32F-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64)
186 ; ILP32F-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2
187 ; ILP32F-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
188 ; ILP32F-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C8]](s32)
189 ; ILP32F-NEXT: G_STORE [[UV3]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16)
190 ; ILP32F-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
191 ; ILP32F-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s32)
192 ; ILP32F-NEXT: G_STORE [[C7]](s32), [[PTR_ADD1]](p0) :: (store (s32) into stack + 4)
193 ; ILP32F-NEXT: $x10 = COPY [[ANYEXT]](s32)
194 ; ILP32F-NEXT: $x11 = COPY [[ANYEXT1]](s32)
195 ; ILP32F-NEXT: $x12 = COPY [[C2]](s32)
196 ; ILP32F-NEXT: $x13 = COPY [[UV]](s32)
197 ; ILP32F-NEXT: $x14 = COPY [[UV1]](s32)
198 ; ILP32F-NEXT: $x15 = COPY [[C4]](s32)
199 ; ILP32F-NEXT: $x16 = COPY [[C5]](s32)
200 ; ILP32F-NEXT: $x17 = COPY [[UV2]](s32)
201 ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_many_scalars, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10
202 ; ILP32F-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2
203 ; ILP32F-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
204 ; ILP32F-NEXT: $x10 = COPY [[COPY1]](s32)
205 ; ILP32F-NEXT: PseudoRET implicit $x10
207 ; ILP32D-LABEL: name: caller_many_scalars
208 ; ILP32D: bb.1 (%ir-block.0):
209 ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 1
210 ; ILP32D-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2
211 ; ILP32D-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
212 ; ILP32D-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
213 ; ILP32D-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
214 ; ILP32D-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 6
215 ; ILP32D-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7
216 ; ILP32D-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
217 ; ILP32D-NEXT: ADJCALLSTACKDOWN 8, 0, implicit-def $x2, implicit $x2
218 ; ILP32D-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s8)
219 ; ILP32D-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[C1]](s16)
220 ; ILP32D-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64)
221 ; ILP32D-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64)
222 ; ILP32D-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2
223 ; ILP32D-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
224 ; ILP32D-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C8]](s32)
225 ; ILP32D-NEXT: G_STORE [[UV3]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16)
226 ; ILP32D-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
227 ; ILP32D-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s32)
228 ; ILP32D-NEXT: G_STORE [[C7]](s32), [[PTR_ADD1]](p0) :: (store (s32) into stack + 4)
229 ; ILP32D-NEXT: $x10 = COPY [[ANYEXT]](s32)
230 ; ILP32D-NEXT: $x11 = COPY [[ANYEXT1]](s32)
231 ; ILP32D-NEXT: $x12 = COPY [[C2]](s32)
232 ; ILP32D-NEXT: $x13 = COPY [[UV]](s32)
233 ; ILP32D-NEXT: $x14 = COPY [[UV1]](s32)
234 ; ILP32D-NEXT: $x15 = COPY [[C4]](s32)
235 ; ILP32D-NEXT: $x16 = COPY [[C5]](s32)
236 ; ILP32D-NEXT: $x17 = COPY [[UV2]](s32)
237 ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_many_scalars, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10
238 ; ILP32D-NEXT: ADJCALLSTACKUP 8, 0, implicit-def $x2, implicit $x2
239 ; ILP32D-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10
240 ; ILP32D-NEXT: $x10 = COPY [[COPY1]](s32)
241 ; ILP32D-NEXT: PseudoRET implicit $x10
242 %1 = call i32 @callee_many_scalars(i8 1, i16 2, i32 3, i64 4, i32 5, i32 6, i64 7, i32 8)
246 ; Check return of 2x xlen scalars
248 define i64 @callee_small_scalar_ret() nounwind {
249 ; RV32I-LABEL: name: callee_small_scalar_ret
250 ; RV32I: bb.1 (%ir-block.0):
251 ; RV32I-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1234567898765
252 ; RV32I-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64)
253 ; RV32I-NEXT: $x10 = COPY [[UV]](s32)
254 ; RV32I-NEXT: $x11 = COPY [[UV1]](s32)
255 ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11
256 ret i64 1234567898765
259 define i32 @caller_small_scalar_ret() nounwind {
260 ; ILP32-LABEL: name: caller_small_scalar_ret
261 ; ILP32: bb.1 (%ir-block.0):
262 ; ILP32-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 987654321234567
263 ; ILP32-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
264 ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_small_scalar_ret, csr_ilp32_lp64, implicit-def $x1, implicit-def $x10, implicit-def $x11
265 ; ILP32-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
266 ; ILP32-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
267 ; ILP32-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
268 ; ILP32-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
269 ; ILP32-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[C]](s64), [[MV]]
270 ; ILP32-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP]](s1)
271 ; ILP32-NEXT: $x10 = COPY [[ZEXT]](s32)
272 ; ILP32-NEXT: PseudoRET implicit $x10
274 ; ILP32F-LABEL: name: caller_small_scalar_ret
275 ; ILP32F: bb.1 (%ir-block.0):
276 ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 987654321234567
277 ; ILP32F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
278 ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_small_scalar_ret, csr_ilp32f_lp64f, implicit-def $x1, implicit-def $x10, implicit-def $x11
279 ; ILP32F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
280 ; ILP32F-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
281 ; ILP32F-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
282 ; ILP32F-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
283 ; ILP32F-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[C]](s64), [[MV]]
284 ; ILP32F-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP]](s1)
285 ; ILP32F-NEXT: $x10 = COPY [[ZEXT]](s32)
286 ; ILP32F-NEXT: PseudoRET implicit $x10
288 ; ILP32D-LABEL: name: caller_small_scalar_ret
289 ; ILP32D: bb.1 (%ir-block.0):
290 ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 987654321234567
291 ; ILP32D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
292 ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_small_scalar_ret, csr_ilp32d_lp64d, implicit-def $x1, implicit-def $x10, implicit-def $x11
293 ; ILP32D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
294 ; ILP32D-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
295 ; ILP32D-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
296 ; ILP32D-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
297 ; ILP32D-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[C]](s64), [[MV]]
298 ; ILP32D-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP]](s1)
299 ; ILP32D-NEXT: $x10 = COPY [[ZEXT]](s32)
300 ; ILP32D-NEXT: PseudoRET implicit $x10
301 %1 = call i64 @callee_small_scalar_ret()
302 %2 = icmp eq i64 987654321234567, %1
303 %3 = zext i1 %2 to i32
307 ; Check return of 2x xlen structs
309 %struct.small = type { i32, ptr }
311 define %struct.small @callee_small_struct_ret() nounwind {
312 ; RV32I-LABEL: name: callee_small_struct_ret
313 ; RV32I: bb.1 (%ir-block.0):
314 ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
315 ; RV32I-NEXT: [[C1:%[0-9]+]]:_(p0) = G_CONSTANT i32 0
316 ; RV32I-NEXT: $x10 = COPY [[C]](s32)
317 ; RV32I-NEXT: $x11 = COPY [[C1]](p0)
318 ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11
319 ret %struct.small { i32 1, ptr null }
322 define i32 @caller_small_struct_ret() nounwind {
323 ; ILP32-LABEL: name: caller_small_struct_ret
324 ; ILP32: bb.1 (%ir-block.0):
325 ; ILP32-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
326 ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_small_struct_ret, csr_ilp32_lp64, implicit-def $x1, implicit-def $x10, implicit-def $x11
327 ; ILP32-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
328 ; ILP32-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
329 ; ILP32-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11
330 ; ILP32-NEXT: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[COPY1]](p0)
331 ; ILP32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[PTRTOINT]]
332 ; ILP32-NEXT: $x10 = COPY [[ADD]](s32)
333 ; ILP32-NEXT: PseudoRET implicit $x10
335 ; ILP32F-LABEL: name: caller_small_struct_ret
336 ; ILP32F: bb.1 (%ir-block.0):
337 ; ILP32F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
338 ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_small_struct_ret, csr_ilp32f_lp64f, implicit-def $x1, implicit-def $x10, implicit-def $x11
339 ; ILP32F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
340 ; ILP32F-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
341 ; ILP32F-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11
342 ; ILP32F-NEXT: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[COPY1]](p0)
343 ; ILP32F-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[PTRTOINT]]
344 ; ILP32F-NEXT: $x10 = COPY [[ADD]](s32)
345 ; ILP32F-NEXT: PseudoRET implicit $x10
347 ; ILP32D-LABEL: name: caller_small_struct_ret
348 ; ILP32D: bb.1 (%ir-block.0):
349 ; ILP32D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
350 ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_small_struct_ret, csr_ilp32d_lp64d, implicit-def $x1, implicit-def $x10, implicit-def $x11
351 ; ILP32D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
352 ; ILP32D-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
353 ; ILP32D-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11
354 ; ILP32D-NEXT: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[COPY1]](p0)
355 ; ILP32D-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[PTRTOINT]]
356 ; ILP32D-NEXT: $x10 = COPY [[ADD]](s32)
357 ; ILP32D-NEXT: PseudoRET implicit $x10
358 %1 = call %struct.small @callee_small_struct_ret()
359 %2 = extractvalue %struct.small %1, 0
360 %3 = extractvalue %struct.small %1, 1
361 %4 = ptrtoint ptr %3 to i32
366 ; Check return of >2x xlen structs
368 %struct.large = type { i32, i32, i32, i32 }
370 define void @callee_large_struct_ret(ptr noalias sret(%struct.large) %agg.result) nounwind {
371 ; RV32I-LABEL: name: callee_large_struct_ret
372 ; RV32I: bb.1 (%ir-block.0):
373 ; RV32I-NEXT: liveins: $x10
375 ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10
376 ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
377 ; RV32I-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
378 ; RV32I-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
379 ; RV32I-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
380 ; RV32I-NEXT: G_STORE [[C]](s32), [[COPY]](p0) :: (store (s32) into %ir.agg.result)
381 ; RV32I-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
382 ; RV32I-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[COPY]], [[C4]](s32)
383 ; RV32I-NEXT: G_STORE [[C1]](s32), [[PTR_ADD]](p0) :: (store (s32) into %ir.b)
384 ; RV32I-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
385 ; RV32I-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[COPY]], [[C5]](s32)
386 ; RV32I-NEXT: G_STORE [[C2]](s32), [[PTR_ADD1]](p0) :: (store (s32) into %ir.c)
387 ; RV32I-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
388 ; RV32I-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[COPY]], [[C6]](s32)
389 ; RV32I-NEXT: G_STORE [[C3]](s32), [[PTR_ADD2]](p0) :: (store (s32) into %ir.d)
390 ; RV32I-NEXT: PseudoRET
391 store i32 1, ptr %agg.result, align 4
392 %b = getelementptr inbounds %struct.large, ptr %agg.result, i32 0, i32 1
393 store i32 2, ptr %b, align 4
394 %c = getelementptr inbounds %struct.large, ptr %agg.result, i32 0, i32 2
395 store i32 3, ptr %c, align 4
396 %d = getelementptr inbounds %struct.large, ptr %agg.result, i32 0, i32 3
397 store i32 4, ptr %d, align 4
401 define i32 @caller_large_struct_ret() nounwind {
402 ; ILP32-LABEL: name: caller_large_struct_ret
403 ; ILP32: bb.1 (%ir-block.0):
404 ; ILP32-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
405 ; ILP32-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
406 ; ILP32-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
407 ; ILP32-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_struct_ret, csr_ilp32_lp64, implicit-def $x1, implicit $x10
408 ; ILP32-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
409 ; ILP32-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (dereferenceable load (s32) from %ir.1)
410 ; ILP32-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
411 ; ILP32-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[FRAME_INDEX]], [[C]](s32)
412 ; ILP32-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0) :: (dereferenceable load (s32) from %ir.3)
413 ; ILP32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[LOAD1]]
414 ; ILP32-NEXT: $x10 = COPY [[ADD]](s32)
415 ; ILP32-NEXT: PseudoRET implicit $x10
417 ; ILP32F-LABEL: name: caller_large_struct_ret
418 ; ILP32F: bb.1 (%ir-block.0):
419 ; ILP32F-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
420 ; ILP32F-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
421 ; ILP32F-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
422 ; ILP32F-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_struct_ret, csr_ilp32f_lp64f, implicit-def $x1, implicit $x10
423 ; ILP32F-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
424 ; ILP32F-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (dereferenceable load (s32) from %ir.1)
425 ; ILP32F-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
426 ; ILP32F-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[FRAME_INDEX]], [[C]](s32)
427 ; ILP32F-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0) :: (dereferenceable load (s32) from %ir.3)
428 ; ILP32F-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[LOAD1]]
429 ; ILP32F-NEXT: $x10 = COPY [[ADD]](s32)
430 ; ILP32F-NEXT: PseudoRET implicit $x10
432 ; ILP32D-LABEL: name: caller_large_struct_ret
433 ; ILP32D: bb.1 (%ir-block.0):
434 ; ILP32D-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
435 ; ILP32D-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def $x2, implicit $x2
436 ; ILP32D-NEXT: $x10 = COPY [[FRAME_INDEX]](p0)
437 ; ILP32D-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_struct_ret, csr_ilp32d_lp64d, implicit-def $x1, implicit $x10
438 ; ILP32D-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $x2, implicit $x2
439 ; ILP32D-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (dereferenceable load (s32) from %ir.1)
440 ; ILP32D-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
441 ; ILP32D-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[FRAME_INDEX]], [[C]](s32)
442 ; ILP32D-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0) :: (dereferenceable load (s32) from %ir.3)
443 ; ILP32D-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[LOAD1]]
444 ; ILP32D-NEXT: $x10 = COPY [[ADD]](s32)
445 ; ILP32D-NEXT: PseudoRET implicit $x10
446 %1 = alloca %struct.large
447 call void @callee_large_struct_ret(ptr sret(%struct.large) %1)
448 %2 = load i32, ptr %1
449 %3 = getelementptr inbounds %struct.large, ptr %1, i32 0, i32 3
450 %4 = load i32, ptr %3