Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / test / CodeGen / AArch64 / GlobalISel / call-translator.ll
blobb1bfe46f4b454cc99ac92f1717fae5034bf838d2
1 ; RUN: llc -mtriple=aarch64-linux-gnu -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s
3 ; CHECK-LABEL: name: test_trivial_call
4 ; CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
5 ; CHECK: BL @trivial_callee, csr_aarch64_aapcs, implicit-def $lr
6 ; CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
7 declare void @trivial_callee()
8 define void @test_trivial_call() {
9   call void @trivial_callee()
10   ret void
13 ; CHECK-LABEL: name: test_simple_return
14 ; CHECK: BL @simple_return_callee, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $x0
15 ; CHECK: [[RES:%[0-9]+]]:_(s64) = COPY $x0
16 ; CHECK: $x0 = COPY [[RES]]
17 ; CHECK: RET_ReallyLR implicit $x0
18 declare i64 @simple_return_callee()
19 define i64 @test_simple_return() {
20   %res = call i64 @simple_return_callee()
21   ret i64 %res
24 ; CHECK-LABEL: name: test_simple_arg
25 ; CHECK: [[IN:%[0-9]+]]:_(s32) = COPY $w0
26 ; CHECK: $w0 = COPY [[IN]]
27 ; CHECK: BL @simple_arg_callee, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0
28 ; CHECK: RET_ReallyLR
29 declare void @simple_arg_callee(i32 %in)
30 define void @test_simple_arg(i32 %in) {
31   call void @simple_arg_callee(i32 %in)
32   ret void
35 ; CHECK-LABEL: name: test_indirect_call
36 ; CHECK: registers:
37 ; Make sure the register feeding the indirect call is properly constrained.
38 ; CHECK: - { id: [[FUNC:[0-9]+]], class: gpr64, preferred-register: '' }
39 ; CHECK: %[[FUNC]]:gpr64(p0) = COPY $x0
40 ; CHECK: BLR %[[FUNC]](p0), csr_aarch64_aapcs, implicit-def $lr, implicit $sp
41 ; CHECK: RET_ReallyLR
42 define void @test_indirect_call(ptr %func) {
43   call void %func()
44   ret void
47 ; CHECK-LABEL: name: test_multiple_args
48 ; CHECK: [[IN:%[0-9]+]]:_(s64) = COPY $x0
49 ; CHECK: [[ANSWER:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
50 ; CHECK: $w0 = COPY [[ANSWER]]
51 ; CHECK: $x1 = COPY [[IN]]
52 ; CHECK: BL @multiple_args_callee, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0, implicit $x1
53 ; CHECK: RET_ReallyLR
54 declare void @multiple_args_callee(i32, i64)
55 define void @test_multiple_args(i64 %in) {
56   call void @multiple_args_callee(i32 42, i64 %in)
57   ret void
61 ; CHECK-LABEL: name: test_struct_formal
62 ; CHECK: [[DBL:%[0-9]+]]:_(s64) = COPY $d0
63 ; CHECK: [[I64:%[0-9]+]]:_(s64) = COPY $x0
64 ; CHECK: [[I8_C:%[0-9]+]]:_(s32) = COPY $w1
65 ; CHECK: [[I8:%[0-9]+]]:_(s8) = G_TRUNC [[I8_C]]
66 ; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x2
68 ; CHECK: G_STORE [[DBL]](s64), [[ADDR]](p0) :: (store (s64) into %ir.addr)
69 ; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
70 ; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST1]](s64)
71 ; CHECK: G_STORE [[I64]](s64), [[GEP1]](p0) :: (store (s64) into %ir.addr + 8)
72 ; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 16
73 ; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST2]](s64)
74 ; CHECK: G_STORE [[I8]](s8), [[GEP2]](p0) :: (store (s8) into %ir.addr + 16, align 8)
75 ; CHECK: RET_ReallyLR
76 define void @test_struct_formal({double, i64, i8} %in, ptr %addr) {
77   store {double, i64, i8} %in, ptr %addr
78   ret void
82 ; CHECK-LABEL: name: test_struct_return
83 ; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
85 ; CHECK: [[LD1:%[0-9]+]]:_(s64) = G_LOAD [[ADDR]](p0) :: (load (s64) from %ir.addr)
86 ; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
87 ; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST1]](s64)
88 ; CHECK: [[LD2:%[0-9]+]]:_(s64) = G_LOAD [[GEP1]](p0) :: (load (s64) from %ir.addr + 8)
89 ; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 16
90 ; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST2]](s64)
91 ; CHECK: [[LD3:%[0-9]+]]:_(s32) = G_LOAD [[GEP2]](p0) :: (load (s32) from %ir.addr + 16, align 8)
93 ; CHECK: $d0 = COPY [[LD1]](s64)
94 ; CHECK: $x0 = COPY [[LD2]](s64)
95 ; CHECK: $w1 = COPY [[LD3]](s32)
96 ; CHECK: RET_ReallyLR implicit $d0, implicit $x0, implicit $w1
97 define {double, i64, i32} @test_struct_return(ptr %addr) {
98   %val = load {double, i64, i32}, ptr %addr
99   ret {double, i64, i32} %val
102 ; CHECK-LABEL: name: test_arr_call
103 ; CHECK: %0:_(p0) = COPY $x0
104 ; CHECK: [[LD1:%[0-9]+]]:_(s64) = G_LOAD %0(p0) :: (load (s64) from %ir.addr)
105 ; CHECK: [[CST1:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
106 ; CHECK: [[GEP1:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST1]](s64)
107 ; CHECK: [[LD2:%[0-9]+]]:_(s64) = G_LOAD [[GEP1]](p0) :: (load (s64) from %ir.addr + 8)
108 ; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 16
109 ; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST2]](s64)
110 ; CHECK: [[LD3:%[0-9]+]]:_(s64) = G_LOAD [[GEP2]](p0) :: (load (s64) from %ir.addr + 16)
111 ; CHECK: [[CST3:%[0-9]+]]:_(s64) = G_CONSTANT i64 24
112 ; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_PTR_ADD %0, [[CST3]](s64)
113 ; CHECK: [[LD4:%[0-9]+]]:_(s64) = G_LOAD [[GEP3]](p0) :: (load (s64) from %ir.addr + 24)
115 ; CHECK: $x0 = COPY [[LD1]](s64)
116 ; CHECK: $x1 = COPY [[LD2]](s64)
117 ; CHECK: $x2 = COPY [[LD3]](s64)
118 ; CHECK: $x3 = COPY [[LD4]](s64)
119 ; CHECK: BL @arr_callee, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0, implicit $x1, implicit $x2, implicit $x3, implicit-def $x0, implicit-def $x1, implicit-def $x2, implicit-def $x3
120 ; CHECK: [[E0:%[0-9]+]]:_(s64) = COPY $x0
121 ; CHECK: [[E1:%[0-9]+]]:_(s64) = COPY $x1
122 ; CHECK: [[E2:%[0-9]+]]:_(s64) = COPY $x2
123 ; CHECK: [[E3:%[0-9]+]]:_(s64) = COPY $x3
124 ; CHECK: $x0 = COPY [[E1]]
125 declare [4 x i64] @arr_callee([4 x i64])
126 define i64 @test_arr_call(ptr %addr) {
127   %arg = load [4 x i64], ptr %addr
128   %res = call [4 x i64] @arr_callee([4 x i64] %arg)
129   %val = extractvalue [4 x i64] %res, 1
130   ret i64 %val
134 ; CHECK-LABEL: name: test_abi_exts_call
135 ; CHECK: [[VAL:%[0-9]+]]:_(s8) = G_LOAD
136 ; CHECK: [[VAL_TMP:%[0-9]+]]:_(s32) = G_ANYEXT [[VAL]]
137 ; CHECK: $w0 = COPY [[VAL_TMP]]
138 ; CHECK: BL @take_char, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0
139 ; CHECK: [[SVAL:%[0-9]+]]:_(s32) = G_SEXT [[VAL]](s8)
140 ; CHECK: $w0 = COPY [[SVAL]](s32)
141 ; CHECK: BL @take_char, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0
142 ; CHECK: [[ZVAL:%[0-9]+]]:_(s32) = G_ZEXT [[VAL]](s8)
143 ; CHECK: $w0 = COPY [[ZVAL]](s32)
144 ; CHECK: BL @take_char, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0
145 declare void @take_char(i8)
146 define void @test_abi_exts_call(ptr %addr) {
147   %val = load i8, ptr %addr
148   call void @take_char(i8 %val)
149   call void @take_char(i8 signext %val)
150   call void @take_char(i8 zeroext %val)
151   ret void
154 ; CHECK-LABEL: name: test_zext_in_callee
155 ; CHECK: bb.1 (%ir-block.0):
156 ; CHECK:   liveins: $x0
157 ; CHECK:   [[COPY:%[0-9]+]]:_(p0) = COPY $x0
158 ; CHECK:   [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[COPY]](p0) :: (load (s8) from %ir.addr)
159 ; CHECK:   ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
160 ; CHECK:   [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[LOAD]](s8)
161 ; CHECK:   $w0 = COPY [[ZEXT]](s32)
162 ; CHECK:   BL @has_zext_param, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0
163 ; CHECK:   ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
164 ; CHECK:   RET_ReallyLR
165 declare void @has_zext_param(i8 zeroext)
166 define void @test_zext_in_callee(ptr %addr) {
167   %val = load i8, ptr %addr
168   call void @has_zext_param(i8 %val)
169   ret void
172 ; CHECK-LABEL: name: test_sext_in_callee
173 ; CHECK: bb.1 (%ir-block.0):
174 ; CHECK:   liveins: $x0
175 ; CHECK:   [[COPY:%[0-9]+]]:_(p0) = COPY $x0
176 ; CHECK:   [[LOAD:%[0-9]+]]:_(s8) = G_LOAD [[COPY]](p0) :: (load (s8) from %ir.addr)
177 ; CHECK:   ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
178 ; CHECK:   [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[LOAD]](s8)
179 ; CHECK:   $w0 = COPY [[SEXT]](s32)
180 ; CHECK:   BL @has_sext_param, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $w0
181 ; CHECK:   ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
182 ; CHECK:   RET_ReallyLR
183 declare void @has_sext_param(i8 signext)
184 define void @test_sext_in_callee(ptr %addr) {
185   %val = load i8, ptr %addr
186   call void @has_sext_param(i8 %val)
187   ret void
190 ; CHECK-LABEL: name: test_abi_sext_ret
191 ; CHECK: [[VAL:%[0-9]+]]:_(s8) = G_LOAD
192 ; CHECK: [[SVAL:%[0-9]+]]:_(s32) = G_SEXT [[VAL]](s8)
193 ; CHECK: $w0 = COPY [[SVAL]](s32)
194 ; CHECK: RET_ReallyLR implicit $w0
195 define signext i8 @test_abi_sext_ret(ptr %addr) {
196   %val = load i8, ptr %addr
197   ret i8 %val
200 ; CHECK-LABEL: name: test_abi_zext_ret
201 ; CHECK: [[VAL:%[0-9]+]]:_(s8) = G_LOAD
202 ; CHECK: [[SVAL:%[0-9]+]]:_(s32) = G_ZEXT [[VAL]](s8)
203 ; CHECK: $w0 = COPY [[SVAL]](s32)
204 ; CHECK: RET_ReallyLR implicit $w0
205 define zeroext i8 @test_abi_zext_ret(ptr %addr) {
206   %val = load i8, ptr %addr
207   ret i8 %val
210 ; CHECK-LABEL: name: test_stack_slots
211 ; CHECK: fixedStack:
212 ; CHECK-DAG:  - { id: [[STACK0:[0-9]+]], type: default, offset: 0, size: 8,
213 ; CHECK-DAG:  - { id: [[STACK8:[0-9]+]], type: default, offset: 8, size: 8,
214 ; CHECK-DAG:  - { id: [[STACK16:[0-9]+]], type: default, offset: 16, size: 8,
215 ; CHECK: [[LHS_ADDR:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[STACK0]]
216 ; CHECK: [[LHS:%[0-9]+]]:_(s64) = G_LOAD [[LHS_ADDR]](p0) :: (invariant load (s64) from %fixed-stack.[[STACK0]], align 16)
217 ; CHECK: [[RHS_ADDR:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[STACK8]]
218 ; CHECK: [[RHS:%[0-9]+]]:_(s64) = G_LOAD [[RHS_ADDR]](p0) :: (invariant load (s64) from %fixed-stack.[[STACK8]])
219 ; CHECK: [[ADDR_ADDR:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[STACK16]]
220 ; CHECK: [[ADDR:%[0-9]+]]:_(p0) = G_LOAD [[ADDR_ADDR]](p0) :: (invariant load (p0) from %fixed-stack.[[STACK16]], align 16)
221 ; CHECK: [[SUM:%[0-9]+]]:_(s64) = G_ADD [[LHS]], [[RHS]]
222 ; CHECK: G_STORE [[SUM]](s64), [[ADDR]](p0)
223 define void @test_stack_slots([8 x i64], i64 %lhs, i64 %rhs, ptr %addr) {
224   %sum = add i64 %lhs, %rhs
225   store i64 %sum, ptr %addr
226   ret void
229 ; CHECK-LABEL: name: test_call_stack
230 ; CHECK: [[C42:%[0-9]+]]:_(s64) = G_CONSTANT i64 42
231 ; CHECK: [[C12:%[0-9]+]]:_(s64) = G_CONSTANT i64 12
232 ; CHECK: [[PTR:%[0-9]+]]:_(p0) = G_CONSTANT i64 0
233 ; CHECK: ADJCALLSTACKDOWN 24, 0, implicit-def $sp, implicit $sp
234 ; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
235 ; CHECK: [[C42_OFFS:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
236 ; CHECK: [[C42_LOC:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[C42_OFFS]](s64)
237 ; CHECK: G_STORE [[C42]](s64), [[C42_LOC]](p0) :: (store (s64) into stack, align 1)
238 ; CHECK: [[C12_OFFS:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
239 ; CHECK: [[C12_LOC:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[C12_OFFS]](s64)
240 ; CHECK: G_STORE [[C12]](s64), [[C12_LOC]](p0) :: (store (s64) into stack + 8, align 1)
241 ; CHECK: [[PTR_OFFS:%[0-9]+]]:_(s64) = G_CONSTANT i64 16
242 ; CHECK: [[PTR_LOC:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[PTR_OFFS]](s64)
243 ; CHECK: G_STORE [[PTR]](p0), [[PTR_LOC]](p0) :: (store (p0) into stack + 16, align 1)
244 ; CHECK: BL @test_stack_slots
245 ; CHECK: ADJCALLSTACKUP 24, 0, implicit-def $sp, implicit $sp
246 define void @test_call_stack() {
247   call void @test_stack_slots([8 x i64] undef, i64 42, i64 12, ptr null)
248   ret void
251 ; CHECK-LABEL: name: test_mem_i1
252 ; CHECK: fixedStack:
253 ; CHECK-NEXT: - { id: [[SLOT:[0-9]+]], type: default, offset: 0, size: 1, alignment: 16, stack-id: default,
254 ; CHECK-NEXT: isImmutable: true,
255 ; CHECK: [[ADDR:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[SLOT]]
256 ; CHECK: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[ADDR]](p0) :: (invariant load (s8) from %fixed-stack.[[SLOT]], align 16)
257 ; CHECK: [[TRUNC8:%[0-9]+]]:_(s8) = G_TRUNC [[LOAD]]
258 ; CHECK: [[TRUNCASSERT:%[0-9]+]]:_(s8) = G_ASSERT_ZEXT [[TRUNC8]], 1
259 ; CHECK: {{%[0-9]+}}:_(s1) = G_TRUNC [[TRUNCASSERT]]
261 define void @test_mem_i1([8 x i64], i1 %in) {
262   ret void
265 ; CHECK-LABEL: name: test_128bit_struct
266 ; CHECK: $x0 = COPY
267 ; CHECK: $x1 = COPY
268 ; CHECK: $x2 = COPY
269 ; CHECK: BL @take_128bit_struct
270 define void @test_128bit_struct(ptr %ptr) {
271   %struct = load [2 x i64], ptr %ptr
272   call void @take_128bit_struct(ptr null, [2 x i64] %struct)
273   ret void
276 ; CHECK-LABEL: name: take_128bit_struct
277 ; CHECK: {{%.*}}:_(p0) = COPY $x0
278 ; CHECK: {{%.*}}:_(s64) = COPY $x1
279 ; CHECK: {{%.*}}:_(s64) = COPY $x2
280 define void @take_128bit_struct(ptr %ptr, [2 x i64] %in) {
281   store [2 x i64] %in, ptr %ptr
282   ret void
285 ; CHECK-LABEL: name: test_split_struct
286 ; CHECK: [[ADDR:%[0-9]+]]:_(p0) = COPY $x0
287 ; CHECK: [[LO:%[0-9]+]]:_(s64) = G_LOAD %0(p0) :: (load (s64) from %ir.ptr)
288 ; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
289 ; CHECK: [[GEP:%[0-9]+]]:_(p0) = G_PTR_ADD [[ADDR]], [[CST]](s64)
290 ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD [[GEP]](p0) :: (load (s64) from %ir.ptr + 8)
292 ; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
293 ; CHECK: [[CST2:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
294 ; CHECK: [[GEP2:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[CST2]](s64)
295 ; CHECK: G_STORE [[LO]](s64), [[GEP2]](p0) :: (store (s64) into stack, align 1)
296 ; CHECK: [[GEP3:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[CST]](s64)
297 ; CHECK: G_STORE [[HI]](s64), [[GEP3]](p0) :: (store (s64) into stack + 8, align 1)
298 define void @test_split_struct(ptr %ptr) {
299   %struct = load [2 x i64], ptr %ptr
300   call void @take_split_struct(ptr null, i64 1, i64 2, i64 3,
301                                i64 4, i64 5, i64 6,
302                                [2 x i64] %struct)
303   ret void
306 ; CHECK-LABEL: name: take_split_struct
307 ; CHECK: fixedStack:
308 ; CHECK-DAG:   - { id: [[LO_FRAME:[0-9]+]], type: default, offset: 0, size: 8
309 ; CHECK-DAG:   - { id: [[HI_FRAME:[0-9]+]], type: default, offset: 8, size: 8
311 ; CHECK: [[LOPTR:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LO_FRAME]]
312 ; CHECK: [[LO:%[0-9]+]]:_(s64) = G_LOAD [[LOPTR]](p0) :: (invariant load (s64) from %fixed-stack.[[LO_FRAME]], align 16)
314 ; CHECK: [[HIPTR:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[HI_FRAME]]
315 ; CHECK: [[HI:%[0-9]+]]:_(s64) = G_LOAD [[HIPTR]](p0) :: (invariant load (s64) from %fixed-stack.[[HI_FRAME]])
316 define void @take_split_struct(ptr %ptr, i64, i64, i64,
317                                i64, i64, i64,
318                                [2 x i64] %in) {
319   store [2 x i64] %in, ptr %ptr
320   ret void
323 %size0type = type { }
324 declare %size0type @func.returns.size0.struct()
326 ; CHECK-LABEL: name: call_returns_size0_struct
327 ; CHECK: bb.1
328 ; CHECK-NEXT: ADJCALLSTACKDOWN
329 ; CHECK-NEXT: BL
330 ; CHECK-NEXT: ADJCALLSTACKUP
331 ; CHECK-NEXT: RET_ReallyLR
332 define void @call_returns_size0_struct() {
333   ; FIXME: Why is this valid IR?
334   %call = call %size0type @func.returns.size0.struct()
335   ret void
338 declare [0 x i8] @func.returns.size0.array()
340 ; CHECK-LABEL: name: call_returns_size0_array
341 ; CHECK: bb.1
342 ; CHECK-NEXT: ADJCALLSTACKDOWN
343 ; CHECK-NEXT: BL
344 ; CHECK-NEXT: ADJCALLSTACKUP
345 ; CHECK-NEXT: RET_ReallyLR
346 define void @call_returns_size0_array() {
347   ; FIXME: Why is this valid IR?
348   %call = call [0 x i8] @func.returns.size0.array()
349   ret void
352 declare [1 x %size0type] @func.returns.array.size0.struct()
353 ; CHECK-LABEL: name: call_returns_array_size0_struct
354 ; CHECK: bb.1
355 ; CHECK-NEXT: ADJCALLSTACKDOWN
356 ; CHECK-NEXT: BL
357 ; CHECK-NEXT: ADJCALLSTACKUP
358 ; CHECK-NEXT: RET_ReallyLR
359 define void @call_returns_array_size0_struct() {
360   ; FIXME: Why is this valid IR?
361   %call = call [1 x %size0type] @func.returns.array.size0.struct()
362   ret void
365 ; Test extends on return values.
367 ; This should notice that the return value from has_zext_return is zero
368 ; extended.
369 declare zeroext i16 @has_zext_return()
370 define i32 @test_zext_return_from_callee() {
371   ; CHECK-LABEL: name: test_zext_return_from_callee
372   ; CHECK: bb.1 (%ir-block.0):
373   ; CHECK-NEXT:   ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
374   ; CHECK-NEXT:   BL @has_zext_return, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $w0
375   ; CHECK-NEXT:   ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
376   ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
377   ; CHECK-NEXT:   [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY]], 16
378   ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_ZEXT]](s32)
379   ; CHECK-NEXT:   [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16)
380   ; CHECK-NEXT:   $w0 = COPY [[ZEXT]](s32)
381   ; CHECK-NEXT:   RET_ReallyLR implicit $w0
382   %val = call i16 @has_zext_return()
383   %ext = zext i16 %val to i32
384   ret i32 %ext
387 ; Same as above, but with zeroext explicitly on the call. Should produce the
388 ; same codegen.
389 define i32 @test_zext_return_from_callee2() {
390   ; CHECK-LABEL: name: test_zext_return_from_callee2
391   ; CHECK: bb.1 (%ir-block.0):
392   ; CHECK-NEXT:   ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
393   ; CHECK-NEXT:   BL @has_zext_return, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $w0
394   ; CHECK-NEXT:   ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
395   ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
396   ; CHECK-NEXT:   [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[COPY]], 16
397   ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_ZEXT]](s32)
398   ; CHECK-NEXT:   [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16)
399   ; CHECK-NEXT:   $w0 = COPY [[ZEXT]](s32)
400   ; CHECK-NEXT:   RET_ReallyLR implicit $w0
401   %val = call zeroext i16 @has_zext_return()
402   %ext = zext i16 %val to i32
403   ret i32 %ext
406 ; This should notice that the return value from has_sext_return is sign
407 ; extended.
408 declare signext i16 @has_sext_return()
409 define i32 @test_sext_return_from_callee() {
410   ; CHECK-LABEL: name: test_sext_return_from_callee
411   ; CHECK: bb.1 (%ir-block.0):
412   ; CHECK-NEXT:   ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
413   ; CHECK-NEXT:   BL @has_sext_return, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $w0
414   ; CHECK-NEXT:   ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
415   ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
416   ; CHECK-NEXT:   [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY]], 16
417   ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_SEXT]](s32)
418   ; CHECK-NEXT:   [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16)
419   ; CHECK-NEXT:   $w0 = COPY [[SEXT]](s32)
420   ; CHECK-NEXT:   RET_ReallyLR implicit $w0
421   %val = call i16 @has_sext_return()
422   %ext = sext i16 %val to i32
423   ret i32 %ext
426 ; Same as above, but with signext explicitly on the call. Should produce the
427 ; same codegen.
428 define i32 @test_sext_return_from_callee2() {
429   ; CHECK-LABEL: name: test_sext_return_from_callee2
430   ; CHECK: bb.1 (%ir-block.0):
431   ; CHECK-NEXT:   ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
432   ; CHECK-NEXT:   BL @has_sext_return, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit-def $w0
433   ; CHECK-NEXT:   ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
434   ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $w0
435   ; CHECK-NEXT:   [[ASSERT_SEXT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[COPY]], 16
436   ; CHECK-NEXT:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[ASSERT_SEXT]](s32)
437   ; CHECK-NEXT:   [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16)
438   ; CHECK-NEXT:   $w0 = COPY [[SEXT]](s32)
439   ; CHECK-NEXT:   RET_ReallyLR implicit $w0
440   %val = call signext i16 @has_sext_return()
441   %ext = sext i16 %val to i32
442   ret i32 %ext