xref: /llvm-project/llvm/test/CodeGen/AArch64/sibling-call.ll (revision 6e54fccede402c9ed0e8038aa258a99c5a2773e5)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s
3
4declare void @callee_stack0()
5declare void @callee_stack8([8 x i64], i64)
6declare void @callee_stack16([8 x i64], i64, i64)
7
8define dso_local void @caller_to0_from0() nounwind {
9; CHECK-LABEL: caller_to0_from0:
10; CHECK:       // %bb.0:
11; CHECK-NEXT:    b callee_stack0
12  tail call void @callee_stack0()
13  ret void
14}
15
16define dso_local void @caller_to0_from8([8 x i64], i64) nounwind{
17; CHECK-LABEL: caller_to0_from8:
18; CHECK:       // %bb.0:
19; CHECK-NEXT:    b callee_stack0
20
21  tail call void @callee_stack0()
22  ret void
23}
24
25define dso_local void @caller_to8_from0() {
26; CHECK-LABEL: caller_to8_from0:
27; CHECK:       // %bb.0:
28; CHECK-NEXT:    sub sp, sp, #32
29; CHECK-NEXT:    str x30, [sp, #16] // 8-byte Folded Spill
30; CHECK-NEXT:    .cfi_def_cfa_offset 32
31; CHECK-NEXT:    .cfi_offset w30, -16
32; CHECK-NEXT:    mov w8, #42
33; CHECK-NEXT:    str x8, [sp]
34; CHECK-NEXT:    bl callee_stack8
35; CHECK-NEXT:    ldr x30, [sp, #16] // 8-byte Folded Reload
36; CHECK-NEXT:    add sp, sp, #32
37; CHECK-NEXT:    ret
38
39; Caller isn't going to clean up any extra stack we allocate, so it
40; can't be a tail call.
41  tail call void @callee_stack8([8 x i64] undef, i64 42)
42  ret void
43}
44
45define dso_local void @caller_to8_from8([8 x i64], i64 %a) {
46; CHECK-LABEL: caller_to8_from8:
47; CHECK:       // %bb.0:
48; CHECK-NEXT:    mov w8, #42
49; CHECK-NEXT:    str x8, [sp]
50; CHECK-NEXT:    b callee_stack8
51
52; This should reuse our stack area for the 42
53  tail call void @callee_stack8([8 x i64] undef, i64 42)
54  ret void
55}
56
57define dso_local void @caller_to16_from8([8 x i64], i64 %a) {
58; CHECK-LABEL: caller_to16_from8:
59; CHECK:       // %bb.0:
60; CHECK-NEXT:    sub sp, sp, #32
61; CHECK-NEXT:    str x30, [sp, #16] // 8-byte Folded Spill
62; CHECK-NEXT:    .cfi_def_cfa_offset 32
63; CHECK-NEXT:    .cfi_offset w30, -16
64; CHECK-NEXT:    bl callee_stack16
65; CHECK-NEXT:    ldr x30, [sp, #16] // 8-byte Folded Reload
66; CHECK-NEXT:    add sp, sp, #32
67; CHECK-NEXT:    ret
68
69; Shouldn't be a tail call: we can't use SP+8 because our caller might
70; have something there. This may sound obvious but implementation does
71; some funky aligning.
72  tail call void @callee_stack16([8 x i64] undef, i64 undef, i64 undef)
73  ret void
74}
75
76define dso_local void @caller_to8_from24([8 x i64], i64 %a, i64 %b, i64 %c) {
77; CHECK-LABEL: caller_to8_from24:
78; CHECK:       // %bb.0:
79; CHECK-NEXT:    mov w8, #42
80; CHECK-NEXT:    str x8, [sp]
81; CHECK-NEXT:    b callee_stack8
82
83; Reuse our area, putting "42" at incoming sp
84  tail call void @callee_stack8([8 x i64] undef, i64 42)
85  ret void
86}
87
88define dso_local void @caller_to16_from16([8 x i64], i64 %a, i64 %b) {
89; CHECK-LABEL: caller_to16_from16:
90; CHECK:       // %bb.0:
91; CHECK-NEXT:    ldp x8, x9, [sp]
92; CHECK-NEXT:    stp x9, x8, [sp]
93; CHECK-NEXT:    b callee_stack16
94
95; Here we want to make sure that both loads happen before the stores:
96; otherwise either %a or %b will be wrongly clobbered.
97  tail call void @callee_stack16([8 x i64] undef, i64 %b, i64 %a)
98  ret void
99
100
101}
102
103@func = dso_local global ptr null
104
105define dso_local void @indirect_tail() {
106; CHECK-LABEL: indirect_tail:
107; CHECK:       // %bb.0:
108; CHECK-NEXT:    adrp x8, func
109; CHECK-NEXT:    mov w0, #42
110; CHECK-NEXT:    ldr x1, [x8, :lo12:func]
111; CHECK-NEXT:    br x1
112
113  %fptr = load ptr, ptr @func
114  tail call void %fptr(i32 42)
115  ret void
116}
117