Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / test / CodeGen / Mips / cconv / return-struct.ll
blob68f8127ae9f13ef82f4131cd3b9b660394a433f7
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static < %s \
3 ; RUN:   | FileCheck --check-prefixes=O32,O32-BE %s
4 ; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static < %s \
5 ; RUN:   | FileCheck --check-prefixes=O32,O32-LE %s
7 ; RUN-TODO: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi o32 < %s \
8 ; RUN-TODO:   | FileCheck --check-prefixes=O32 %s
9 ; RUN-TODO: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi o32 < %s \
10 ; RUN-TODO:   | FileCheck --check-prefixes=O32 %s
12 ; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n32 < %s \
13 ; RUN:   | FileCheck --check-prefixes=N32,N32-BE %s
14 ; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi n32 < %s \
15 ; RUN:   | FileCheck --check-prefixes=N32,N32-LE %s
17 ; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -target-abi n64 < %s \
18 ; RUN:   | FileCheck --check-prefixes=N64,N64-BE %s
19 ; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -target-abi n64 < %s \
20 ; RUN:   | FileCheck --check-prefixes=N64,N64-LE %s
22 ; Test struct returns for all ABI's and byte orders.
24 @struct_byte = global {i8} zeroinitializer
25 @struct_2byte = global {i8,i8} zeroinitializer
26 @struct_3xi16 = global {[3 x i16]} zeroinitializer
27 @struct_6xi32 = global {[6 x i32]} zeroinitializer
28 @struct_128xi16 = global {[128 x i16]} zeroinitializer
30 declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1)
32 define inreg {i8} @ret_struct_i8() nounwind {
33 ; O32-LABEL: ret_struct_i8:
34 ; O32:       # %bb.0: # %entry
35 ; O32-NEXT:    lui $1, %hi(struct_byte)
36 ; O32-NEXT:    jr $ra
37 ; O32-NEXT:    lbu $2, %lo(struct_byte)($1)
39 ; N32-BE-LABEL: ret_struct_i8:
40 ; N32-BE:       # %bb.0: # %entry
41 ; N32-BE-NEXT:    lui $1, %hi(struct_byte)
42 ; N32-BE-NEXT:    lb $1, %lo(struct_byte)($1)
43 ; N32-BE-NEXT:    jr $ra
44 ; N32-BE-NEXT:    dsll $2, $1, 56
46 ; N32-LE-LABEL: ret_struct_i8:
47 ; N32-LE:       # %bb.0: # %entry
48 ; N32-LE-NEXT:    lui $1, %hi(struct_byte)
49 ; N32-LE-NEXT:    jr $ra
50 ; N32-LE-NEXT:    lb $2, %lo(struct_byte)($1)
52 ; N64-BE-LABEL: ret_struct_i8:
53 ; N64-BE:       # %bb.0: # %entry
54 ; N64-BE-NEXT:    lui $1, %highest(struct_byte)
55 ; N64-BE-NEXT:    daddiu $1, $1, %higher(struct_byte)
56 ; N64-BE-NEXT:    dsll $1, $1, 16
57 ; N64-BE-NEXT:    daddiu $1, $1, %hi(struct_byte)
58 ; N64-BE-NEXT:    dsll $1, $1, 16
59 ; N64-BE-NEXT:    lb $1, %lo(struct_byte)($1)
60 ; N64-BE-NEXT:    jr $ra
61 ; N64-BE-NEXT:    dsll $2, $1, 56
63 ; N64-LE-LABEL: ret_struct_i8:
64 ; N64-LE:       # %bb.0: # %entry
65 ; N64-LE-NEXT:    lui $1, %highest(struct_byte)
66 ; N64-LE-NEXT:    daddiu $1, $1, %higher(struct_byte)
67 ; N64-LE-NEXT:    dsll $1, $1, 16
68 ; N64-LE-NEXT:    daddiu $1, $1, %hi(struct_byte)
69 ; N64-LE-NEXT:    dsll $1, $1, 16
70 ; N64-LE-NEXT:    jr $ra
71 ; N64-LE-NEXT:    lb $2, %lo(struct_byte)($1)
72 entry:
73         %0 = load volatile {i8}, ptr @struct_byte
74         ret {i8} %0
77 ; This test is based on the way clang currently lowers {i8,i8} to {i16}.
78 ; FIXME: It should probably work for without any lowering too but this doesn't
79 ;        work as expected. Each member gets mapped to a register rather than
80 ;        packed into a single register.
81 define inreg {i16} @ret_struct_i16() nounwind {
82 ; O32-LABEL: ret_struct_i16:
83 ; O32:       # %bb.0: # %entry
84 ; O32-NEXT:    addiu $sp, $sp, -8
85 ; O32-NEXT:    lui $1, %hi(struct_2byte)
86 ; O32-NEXT:    lhu $1, %lo(struct_2byte)($1)
87 ; O32-NEXT:    sh $1, 0($sp)
88 ; O32-NEXT:    lhu $2, 0($sp)
89 ; O32-NEXT:    jr $ra
90 ; O32-NEXT:    addiu $sp, $sp, 8
92 ; N32-BE-LABEL: ret_struct_i16:
93 ; N32-BE:       # %bb.0: # %entry
94 ; N32-BE-NEXT:    addiu $sp, $sp, -16
95 ; N32-BE-NEXT:    lui $1, %hi(struct_2byte)
96 ; N32-BE-NEXT:    lhu $1, %lo(struct_2byte)($1)
97 ; N32-BE-NEXT:    sh $1, 8($sp)
98 ; N32-BE-NEXT:    lh $1, 8($sp)
99 ; N32-BE-NEXT:    dsll $2, $1, 48
100 ; N32-BE-NEXT:    jr $ra
101 ; N32-BE-NEXT:    addiu $sp, $sp, 16
103 ; N32-LE-LABEL: ret_struct_i16:
104 ; N32-LE:       # %bb.0: # %entry
105 ; N32-LE-NEXT:    addiu $sp, $sp, -16
106 ; N32-LE-NEXT:    lui $1, %hi(struct_2byte)
107 ; N32-LE-NEXT:    lhu $1, %lo(struct_2byte)($1)
108 ; N32-LE-NEXT:    sh $1, 8($sp)
109 ; N32-LE-NEXT:    lh $2, 8($sp)
110 ; N32-LE-NEXT:    jr $ra
111 ; N32-LE-NEXT:    addiu $sp, $sp, 16
113 ; N64-BE-LABEL: ret_struct_i16:
114 ; N64-BE:       # %bb.0: # %entry
115 ; N64-BE-NEXT:    daddiu $sp, $sp, -16
116 ; N64-BE-NEXT:    lui $1, %highest(struct_2byte)
117 ; N64-BE-NEXT:    daddiu $1, $1, %higher(struct_2byte)
118 ; N64-BE-NEXT:    dsll $1, $1, 16
119 ; N64-BE-NEXT:    daddiu $1, $1, %hi(struct_2byte)
120 ; N64-BE-NEXT:    dsll $1, $1, 16
121 ; N64-BE-NEXT:    lhu $1, %lo(struct_2byte)($1)
122 ; N64-BE-NEXT:    sh $1, 8($sp)
123 ; N64-BE-NEXT:    lh $1, 8($sp)
124 ; N64-BE-NEXT:    dsll $2, $1, 48
125 ; N64-BE-NEXT:    jr $ra
126 ; N64-BE-NEXT:    daddiu $sp, $sp, 16
128 ; N64-LE-LABEL: ret_struct_i16:
129 ; N64-LE:       # %bb.0: # %entry
130 ; N64-LE-NEXT:    daddiu $sp, $sp, -16
131 ; N64-LE-NEXT:    lui $1, %highest(struct_2byte)
132 ; N64-LE-NEXT:    daddiu $1, $1, %higher(struct_2byte)
133 ; N64-LE-NEXT:    dsll $1, $1, 16
134 ; N64-LE-NEXT:    daddiu $1, $1, %hi(struct_2byte)
135 ; N64-LE-NEXT:    dsll $1, $1, 16
136 ; N64-LE-NEXT:    lhu $1, %lo(struct_2byte)($1)
137 ; N64-LE-NEXT:    sh $1, 8($sp)
138 ; N64-LE-NEXT:    lh $2, 8($sp)
139 ; N64-LE-NEXT:    jr $ra
140 ; N64-LE-NEXT:    daddiu $sp, $sp, 16
141 entry:
142         %retval = alloca {i8,i8}, align 8
143         call void @llvm.memcpy.p0.p0.i64(ptr %retval, ptr @struct_2byte, i64 2, i1 false)
144         %0 = load volatile {i16}, ptr %retval
145         ret {i16} %0
148 ; Ensure that structures bigger than 32-bits but smaller than 64-bits are
149 ; also returned in the upper bits on big endian targets. Previously, these were
150 ; missed by the CCPromoteToType and the shift didn't happen.
151 define inreg {i48} @ret_struct_3xi16() nounwind {
152 ; O32-BE-LABEL: ret_struct_3xi16:
153 ; O32-BE:       # %bb.0: # %entry
154 ; O32-BE-NEXT:    lui $1, %hi(struct_3xi16)
155 ; O32-BE-NEXT:    lw $2, %lo(struct_3xi16)($1)
156 ; O32-BE-NEXT:    sll $3, $2, 16
157 ; O32-BE-NEXT:    addiu $1, $1, %lo(struct_3xi16)
158 ; O32-BE-NEXT:    lhu $1, 4($1)
159 ; O32-BE-NEXT:    or $3, $1, $3
160 ; O32-BE-NEXT:    jr $ra
161 ; O32-BE-NEXT:    srl $2, $2, 16
163 ; O32-LE-LABEL: ret_struct_3xi16:
164 ; O32-LE:       # %bb.0: # %entry
165 ; O32-LE-NEXT:    lui $1, %hi(struct_3xi16)
166 ; O32-LE-NEXT:    lw $2, %lo(struct_3xi16)($1)
167 ; O32-LE-NEXT:    addiu $1, $1, %lo(struct_3xi16)
168 ; O32-LE-NEXT:    jr $ra
169 ; O32-LE-NEXT:    lhu $3, 4($1)
171 ; N32-BE-LABEL: ret_struct_3xi16:
172 ; N32-BE:       # %bb.0: # %entry
173 ; N32-BE-NEXT:    lui $1, %hi(struct_3xi16)
174 ; N32-BE-NEXT:    lw $2, %lo(struct_3xi16)($1)
175 ; N32-BE-NEXT:    dsll $2, $2, 32
176 ; N32-BE-NEXT:    addiu $1, $1, %lo(struct_3xi16)
177 ; N32-BE-NEXT:    lhu $1, 4($1)
178 ; N32-BE-NEXT:    dsll $1, $1, 16
179 ; N32-BE-NEXT:    jr $ra
180 ; N32-BE-NEXT:    or $2, $2, $1
182 ; N32-LE-LABEL: ret_struct_3xi16:
183 ; N32-LE:       # %bb.0: # %entry
184 ; N32-LE-NEXT:    lui $1, %hi(struct_3xi16)
185 ; N32-LE-NEXT:    lwu $2, %lo(struct_3xi16)($1)
186 ; N32-LE-NEXT:    addiu $1, $1, %lo(struct_3xi16)
187 ; N32-LE-NEXT:    lh $1, 4($1)
188 ; N32-LE-NEXT:    dsll $1, $1, 32
189 ; N32-LE-NEXT:    jr $ra
190 ; N32-LE-NEXT:    or $2, $2, $1
192 ; N64-BE-LABEL: ret_struct_3xi16:
193 ; N64-BE:       # %bb.0: # %entry
194 ; N64-BE-NEXT:    lui $1, %highest(struct_3xi16)
195 ; N64-BE-NEXT:    daddiu $1, $1, %higher(struct_3xi16)
196 ; N64-BE-NEXT:    dsll $1, $1, 16
197 ; N64-BE-NEXT:    daddiu $1, $1, %hi(struct_3xi16)
198 ; N64-BE-NEXT:    dsll $1, $1, 16
199 ; N64-BE-NEXT:    lw $2, %lo(struct_3xi16)($1)
200 ; N64-BE-NEXT:    dsll $2, $2, 32
201 ; N64-BE-NEXT:    daddiu $1, $1, %lo(struct_3xi16)
202 ; N64-BE-NEXT:    lhu $1, 4($1)
203 ; N64-BE-NEXT:    dsll $1, $1, 16
204 ; N64-BE-NEXT:    jr $ra
205 ; N64-BE-NEXT:    or $2, $2, $1
207 ; N64-LE-LABEL: ret_struct_3xi16:
208 ; N64-LE:       # %bb.0: # %entry
209 ; N64-LE-NEXT:    lui $1, %highest(struct_3xi16)
210 ; N64-LE-NEXT:    daddiu $1, $1, %higher(struct_3xi16)
211 ; N64-LE-NEXT:    dsll $1, $1, 16
212 ; N64-LE-NEXT:    daddiu $1, $1, %hi(struct_3xi16)
213 ; N64-LE-NEXT:    dsll $1, $1, 16
214 ; N64-LE-NEXT:    lwu $2, %lo(struct_3xi16)($1)
215 ; N64-LE-NEXT:    daddiu $1, $1, %lo(struct_3xi16)
216 ; N64-LE-NEXT:    lh $1, 4($1)
217 ; N64-LE-NEXT:    dsll $1, $1, 32
218 ; N64-LE-NEXT:    jr $ra
219 ; N64-LE-NEXT:    or $2, $2, $1
220 entry:
221         %0 = load volatile i48, ptr @struct_3xi16, align 2
222         %1 = insertvalue {i48} undef, i48 %0, 0
223         ret {i48} %1
226 ; Ensure that large structures (>128-bit) are returned indirectly.
227 ; We pick an extremely large structure so we don't have to match inlined memcpy's.
228 define void @ret_struct_128xi16(ptr sret({[128 x i16]}) %returnval) {
229 ; O32-LABEL: ret_struct_128xi16:
230 ; O32:       # %bb.0: # %entry
231 ; O32-NEXT:    addiu $sp, $sp, -24
232 ; O32-NEXT:    .cfi_def_cfa_offset 24
233 ; O32-NEXT:    sw $ra, 20($sp) # 4-byte Folded Spill
234 ; O32-NEXT:    sw $16, 16($sp) # 4-byte Folded Spill
235 ; O32-NEXT:    .cfi_offset 31, -4
236 ; O32-NEXT:    .cfi_offset 16, -8
237 ; O32-NEXT:    move $16, $4
238 ; O32-NEXT:    lui $1, %hi(struct_128xi16)
239 ; O32-NEXT:    addiu $5, $1, %lo(struct_128xi16)
240 ; O32-NEXT:    jal memcpy
241 ; O32-NEXT:    addiu $6, $zero, 256
242 ; O32-NEXT:    move $2, $16
243 ; O32-NEXT:    lw $16, 16($sp) # 4-byte Folded Reload
244 ; O32-NEXT:    lw $ra, 20($sp) # 4-byte Folded Reload
245 ; O32-NEXT:    jr $ra
246 ; O32-NEXT:    addiu $sp, $sp, 24
248 ; N32-LABEL: ret_struct_128xi16:
249 ; N32:       # %bb.0: # %entry
250 ; N32-NEXT:    addiu $sp, $sp, -16
251 ; N32-NEXT:    .cfi_def_cfa_offset 16
252 ; N32-NEXT:    sd $ra, 8($sp) # 8-byte Folded Spill
253 ; N32-NEXT:    sd $16, 0($sp) # 8-byte Folded Spill
254 ; N32-NEXT:    .cfi_offset 31, -8
255 ; N32-NEXT:    .cfi_offset 16, -16
256 ; N32-NEXT:    lui $1, %hi(struct_128xi16)
257 ; N32-NEXT:    addiu $5, $1, %lo(struct_128xi16)
258 ; N32-NEXT:    sll $16, $4, 0
259 ; N32-NEXT:    jal memcpy
260 ; N32-NEXT:    daddiu $6, $zero, 256
261 ; N32-NEXT:    move $2, $16
262 ; N32-NEXT:    ld $16, 0($sp) # 8-byte Folded Reload
263 ; N32-NEXT:    ld $ra, 8($sp) # 8-byte Folded Reload
264 ; N32-NEXT:    jr $ra
265 ; N32-NEXT:    addiu $sp, $sp, 16
267 ; N64-LABEL: ret_struct_128xi16:
268 ; N64:       # %bb.0: # %entry
269 ; N64-NEXT:    daddiu $sp, $sp, -16
270 ; N64-NEXT:    .cfi_def_cfa_offset 16
271 ; N64-NEXT:    sd $ra, 8($sp) # 8-byte Folded Spill
272 ; N64-NEXT:    sd $16, 0($sp) # 8-byte Folded Spill
273 ; N64-NEXT:    .cfi_offset 31, -8
274 ; N64-NEXT:    .cfi_offset 16, -16
275 ; N64-NEXT:    move $16, $4
276 ; N64-NEXT:    lui $1, %highest(struct_128xi16)
277 ; N64-NEXT:    daddiu $1, $1, %higher(struct_128xi16)
278 ; N64-NEXT:    dsll $1, $1, 16
279 ; N64-NEXT:    daddiu $1, $1, %hi(struct_128xi16)
280 ; N64-NEXT:    dsll $1, $1, 16
281 ; N64-NEXT:    daddiu $5, $1, %lo(struct_128xi16)
282 ; N64-NEXT:    jal memcpy
283 ; N64-NEXT:    daddiu $6, $zero, 256
284 ; N64-NEXT:    move $2, $16
285 ; N64-NEXT:    ld $16, 0($sp) # 8-byte Folded Reload
286 ; N64-NEXT:    ld $ra, 8($sp) # 8-byte Folded Reload
287 ; N64-NEXT:    jr $ra
288 ; N64-NEXT:    daddiu $sp, $sp, 16
289 entry:
290         call void @llvm.memcpy.p0.p0.i64(ptr align 2 %returnval, ptr align 2 @struct_128xi16, i64 256, i1 false)
291         ret void
294 ; Ensure that large structures (>128-bit) are returned indirectly.
295 ; This will generate inlined memcpy's anyway so pick the smallest large
296 ; structure
297 ; This time we let the backend lower the sret argument.
298 define {[6 x i32]} @ret_struct_6xi32() {
299 ; O32-LABEL: ret_struct_6xi32:
300 ; O32:       # %bb.0: # %entry
301 ; O32-NEXT:    lui $1, %hi(struct_6xi32)
302 ; O32-NEXT:    lw $2, %lo(struct_6xi32)($1)
303 ; O32-NEXT:    addiu $1, $1, %lo(struct_6xi32)
304 ; O32-NEXT:    lw $3, 4($1)
305 ; O32-NEXT:    lw $5, 8($1)
306 ; O32-NEXT:    lw $6, 12($1)
307 ; O32-NEXT:    lw $7, 16($1)
308 ; O32-NEXT:    lw $1, 20($1)
309 ; O32-NEXT:    sw $1, 20($4)
310 ; O32-NEXT:    sw $7, 16($4)
311 ; O32-NEXT:    sw $6, 12($4)
312 ; O32-NEXT:    sw $5, 8($4)
313 ; O32-NEXT:    sw $3, 4($4)
314 ; O32-NEXT:    jr $ra
315 ; O32-NEXT:    sw $2, 0($4)
317 ; N32-LABEL: ret_struct_6xi32:
318 ; N32:       # %bb.0: # %entry
319 ; N32-NEXT:    sll $1, $4, 0
320 ; N32-NEXT:    lui $2, %hi(struct_6xi32)
321 ; N32-NEXT:    lw $3, %lo(struct_6xi32)($2)
322 ; N32-NEXT:    addiu $2, $2, %lo(struct_6xi32)
323 ; N32-NEXT:    lw $4, 4($2)
324 ; N32-NEXT:    lw $5, 8($2)
325 ; N32-NEXT:    lw $6, 12($2)
326 ; N32-NEXT:    lw $7, 16($2)
327 ; N32-NEXT:    lw $2, 20($2)
328 ; N32-NEXT:    sw $2, 20($1)
329 ; N32-NEXT:    sw $7, 16($1)
330 ; N32-NEXT:    sw $6, 12($1)
331 ; N32-NEXT:    sw $5, 8($1)
332 ; N32-NEXT:    sw $4, 4($1)
333 ; N32-NEXT:    jr $ra
334 ; N32-NEXT:    sw $3, 0($1)
336 ; N64-LABEL: ret_struct_6xi32:
337 ; N64:       # %bb.0: # %entry
338 ; N64-NEXT:    lui $1, %highest(struct_6xi32)
339 ; N64-NEXT:    daddiu $1, $1, %higher(struct_6xi32)
340 ; N64-NEXT:    dsll $1, $1, 16
341 ; N64-NEXT:    daddiu $1, $1, %hi(struct_6xi32)
342 ; N64-NEXT:    dsll $1, $1, 16
343 ; N64-NEXT:    lw $2, %lo(struct_6xi32)($1)
344 ; N64-NEXT:    daddiu $1, $1, %lo(struct_6xi32)
345 ; N64-NEXT:    lw $3, 4($1)
346 ; N64-NEXT:    lw $5, 8($1)
347 ; N64-NEXT:    lw $6, 12($1)
348 ; N64-NEXT:    lw $7, 16($1)
349 ; N64-NEXT:    lw $1, 20($1)
350 ; N64-NEXT:    sw $1, 20($4)
351 ; N64-NEXT:    sw $7, 16($4)
352 ; N64-NEXT:    sw $6, 12($4)
353 ; N64-NEXT:    sw $5, 8($4)
354 ; N64-NEXT:    sw $3, 4($4)
355 ; N64-NEXT:    jr $ra
356 ; N64-NEXT:    sw $2, 0($4)
357 entry:
358         %0 = load volatile {[6 x i32]}, ptr @struct_6xi32, align 2
359         ret {[6 x i32]} %0