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