Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / ARM / tailcc-call.ll
blob1c1dfde03e5659a7752436048171ed2d219f5012
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()
12   ret void
13 ; CHECK-NOT: add
14 ; CHECK-NOT: sub
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()
22   ret void
24 ; CHECK: add sp, #16
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)
32   ret void
34 ; CHECK-LABEL: _caller_to4_from0:
35 ; CHECK: sub sp, #16
36 ; CHECK: movs [[TMP:r[0-9]+]], #42
37 ; CHECK: str [[TMP]], [sp]
38 ; CHECK-NOT: add 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:
45 ; CHECK-NOT: sub sp
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)
48   ret void
50 ; CHECK: str {{r[0-9]+}}, [sp]
51 ; CHECK-NOT: add 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:
57 ; CHECK: sub sp, #16
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]
69 ; CHECK-NOT: add sp
70 ; CHECK-NOT: sub sp
71 ; CHECK: b.w _callee_stack20
72   ret void
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)
82   ret void
84 ; CHECK: str {{.*}}, [sp, #16]
85 ; CHECK: add 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:
92 ; CHECK-NOT: add sp,
93 ; CHECK-NOT: sub sp,
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)
98   ret void
100   ; If these ever get interleaved make sure aliasing slots don't clobber each
101   ; other.
102 ; CHECK: ldrd {{.*}}, {{.*}}, [sp, #12]
103 ; CHECK: ldm.w sp,
104 ; CHECK: stm.w
105 ; CHECK: strd
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()
113   ret void
115 ; CHECK: bl _callee_stack0
116 ; CHECK: ret
119 define tailcc void @normal_ret_with_stack([4 x i32], i32 %a) {
120 ; CHECK: _normal_ret_with_stack:
121 ; CHECK: add sp, #16
122 ; CHECK: bx lr
123   ret void
126 declare { [2 x float] } @get_vec2()
128 define void @fromC_totail() {
129 ; COMMON-LABEL: fromC_totail:
130 ; COMMON: puch {r4, lr}
131 ; COMMON: sub sp, #8
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)
145   ret void
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
157   ; And here.
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)
169   ret void
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}
177 ; COMMON: sub sp, #8
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)
192   ret void
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}
199 ; COMMON: add sp, #8
200 ; COMMON: bx lr
203   call void @callee_stack0()
204   ret void