1 ; RUN: llc -verify-machineinstrs < %s -mtriple=thumbv7k-apple-watchos | FileCheck %s
3 declare tailcc void @callee_stack0()
4 declare tailcc void @callee_stack4([4 x i32], i32)
5 declare tailcc void @callee_stack20([4 x i32], [5 x i32])
6 declare extern_weak tailcc void @callee_weak()
8 define tailcc void @caller_to0_from0() nounwind {
9 ; CHECK-LABEL: _caller_to0_from0:
11 tail call tailcc void @callee_stack0()
15 ; CHECK: b.w _callee_stack0
18 define tailcc void @caller_to0_from4([4 x i32], i32) {
19 ; CHECK-LABEL: _caller_to0_from4:
21 tail call tailcc void @callee_stack0()
25 ; CHECK-NEXT: b.w _callee_stack0
28 define tailcc void @caller_to4_from0() {
29 ; Key point is that the "42" should go #16 below incoming stack
30 ; pointer (we didn't have arg space to reuse).
31 tail call tailcc void @callee_stack4([4 x i32] undef, i32 42)
34 ; CHECK-LABEL: _caller_to4_from0:
36 ; CHECK: movs [[TMP:r[0-9]+]], #42
37 ; CHECK: str [[TMP]], [sp]
39 ; CHECK: b.w _callee_stack4
43 define tailcc void @caller_to4_from4([4 x i32], i32 %a) {
44 ; CHECK-LABEL: _caller_to4_from4:
46 ; Key point is that the "%a" should go where at SP on entry.
47 tail call tailcc void @callee_stack4([4 x i32] undef, i32 42)
50 ; CHECK: str {{r[0-9]+}}, [sp]
52 ; CHECK-NEXT: b.w _callee_stack4
55 define tailcc void @caller_to20_from4([4 x i32], i32 %a) {
56 ; CHECK-LABEL: _caller_to20_from4:
59 ; Important point is that the call reuses the "dead" argument space
60 ; above %a on the stack. If it tries to go below incoming-SP then the
61 ; _callee will not deallocate the space, even in tailcc.
62 tail call tailcc void @callee_stack20([4 x i32] undef, [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5])
64 ; CHECK: str {{.*}}, [sp]
65 ; CHECK: str {{.*}}, [sp, #4]
66 ; CHECK: str {{.*}}, [sp, #8]
67 ; CHECK: str {{.*}}, [sp, #12]
68 ; CHECK: str {{.*}}, [sp, #16]
71 ; CHECK: b.w _callee_stack20
76 define tailcc void @caller_to4_from24([4 x i32], i64 %a, i64 %b, i64 %c) {
77 ; CHECK-LABEL: _caller_to4_from24:
80 ; Key point is that the "%a" should go where at #16 above SP on entry.
81 tail call tailcc void @callee_stack4([4 x i32] undef, i32 42)
84 ; CHECK: str {{.*}}, [sp, #16]
86 ; CHECK-NEXT: b.w _callee_stack4
90 define tailcc void @caller_to20_from20([4 x i32], [5 x i32] %a) {
91 ; CHECK-LABEL: _caller_to20_from20:
95 ; Here we want to make sure that both loads happen before the stores:
96 ; otherwise either %a or %b.w will be wrongly clobbered.
97 tail call tailcc void @callee_stack20([4 x i32] undef, [5 x i32] %a)
100 ; If these ever get interleaved make sure aliasing slots don't clobber each
102 ; CHECK: ldrd {{.*}}, {{.*}}, [sp, #12]
106 ; CHECK-NEXT: b.w _callee_stack20
109 define tailcc void @disable_tail_calls() nounwind "disable-tail-calls"="true" {
110 ; CHECK-LABEL: disable_tail_calls:
112 tail call tailcc void @callee_stack0()
115 ; CHECK: bl _callee_stack0
119 define tailcc void @normal_ret_with_stack([4 x i32], i32 %a) {
120 ; CHECK: _normal_ret_with_stack:
126 declare { [2 x float] } @get_vec2()
128 define void @fromC_totail() {
129 ; COMMON-LABEL: fromC_totail:
130 ; COMMON: puch {r4, lr}
133 ; COMMON-NOT: sub sp,
134 ; COMMON: movs [[TMP:r[0-9]+]], #42
135 ; COMMON: str [[TMP]], [sp]
136 ; COMMON: bl _callee_stack4
137 ; We must reset the stack to where it was before the call by undoing its extra stack pop.
138 ; COMMON: sub sp, #16
139 ; COMMON: str [[TMP]], [sp]
140 ; COMMON: bl callee_stack4
141 ; COMMON: sub sp, #16
143 call tailcc void @callee_stack4([4 x i32] undef, i32 42)
144 call tailcc void @callee_stack4([4 x i32] undef, i32 42)
148 define void @fromC_totail_noreservedframe(i32 %len) {
149 ; COMMON-LABEL: fromC_totail_noreservedframe:
150 ; COMMON: sub.w sp, sp, r{{.*}}
152 ; COMMON: movs [[TMP:r[0-9]+]], #42
153 ; Note stack is subtracted here to allocate space for arg
154 ; COMMON: sub.w sp, #16
155 ; COMMON: str [[TMP]], [sp]
156 ; COMMON: bl _callee_stack4
158 ; COMMON: sub sp, #16
159 ; COMMON: str [[TMP]], [sp]
160 ; COMMON: bl _callee_stack4
161 ; But not restored here because callee_stack8 did that for us.
162 ; COMMON-NOT: sub sp,
164 ; Variable sized allocation prevents reserving frame at start of function so each call must allocate any stack space it needs.
165 %var = alloca i32, i32 %len
167 call tailcc void @callee_stack4([4 x i32] undef, i32 42)
168 call tailcc void @callee_stack4([4 x i32] undef, i32 42)
172 declare void @Ccallee_stack4([4 x i32], i32)
174 define tailcc void @fromtail_toC() {
175 ; COMMON-LABEL: fromtail_toC:
176 ; COMMON: push {r4, lr}
179 ; COMMON-NOT: sub sp,
180 ; COMMON: movs [[TMP:r[0-9]+]], #42
181 ; COMMON: str [[TMP]], [sp]
182 ; COMMON: bl _Ccallee_stack4
183 ; C callees will return with the stack exactly where we left it, so we mustn't try to fix anything.
184 ; COMMON-NOT: add sp,
185 ; COMMON-NOT: sub sp,
186 ; COMMON: str [[TMP]], [sp]{{$}}
187 ; COMMON: bl _Ccallee_stack4
188 ; COMMON-NOT: sub sp,
190 call void @Ccallee_stack4([4 x i32] undef, i32 42)
191 call void @Ccallee_stack4([4 x i32] undef, i32 42)
195 ; Don't try to return by popping pc if there's stack to reclaim.
196 define tailcc void @notail_stackclean([4 x i32], i32) {
197 ; COMMON-LABEL: notail_stackclean:
198 ; COMMON: pop {r7, lr}
203 call void @callee_stack0()