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()
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()
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
29 declare void @simple_arg_callee(i32 %in)
30 define void @test_simple_arg(i32 %in) {
31 call void @simple_arg_callee(i32 %in)
35 ; CHECK-LABEL: name: test_indirect_call
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
42 define void @test_indirect_call(ptr %func) {
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
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)
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)
76 define void @test_struct_formal({double, i64, i8} %in, ptr %addr) {
77 store {double, i64, i8} %in, ptr %addr
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
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)
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)
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)
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
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
210 ; CHECK-LABEL: name: test_stack_slots
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
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)
251 ; CHECK-LABEL: name: test_mem_i1
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) {
265 ; CHECK-LABEL: name: test_128bit_struct
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)
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
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,
306 ; CHECK-LABEL: name: take_split_struct
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,
319 store [2 x i64] %in, ptr %ptr
323 %size0type = type { }
324 declare %size0type @func.returns.size0.struct()
326 ; CHECK-LABEL: name: call_returns_size0_struct
328 ; CHECK-NEXT: ADJCALLSTACKDOWN
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()
338 declare [0 x i8] @func.returns.size0.array()
340 ; CHECK-LABEL: name: call_returns_size0_array
342 ; CHECK-NEXT: ADJCALLSTACKDOWN
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()
352 declare [1 x %size0type] @func.returns.array.size0.struct()
353 ; CHECK-LABEL: name: call_returns_array_size0_struct
355 ; CHECK-NEXT: ADJCALLSTACKDOWN
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()
365 ; Test extends on return values.
367 ; This should notice that the return value from has_zext_return is zero
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
387 ; Same as above, but with zeroext explicitly on the call. Should produce the
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
406 ; This should notice that the return value from has_sext_return is sign
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
426 ; Same as above, but with signext explicitly on the call. Should produce the
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