1d88f96dfSTim Northover; RUN: llc -verify-machineinstrs < %s -mtriple=thumbv7k-apple-watchos | FileCheck %s 2d88f96dfSTim Northover 3d88f96dfSTim Northoverdeclare tailcc void @callee_stack0() 4d88f96dfSTim Northoverdeclare tailcc void @callee_stack4([4 x i32], i32) 5d88f96dfSTim Northoverdeclare tailcc void @callee_stack20([4 x i32], [5 x i32]) 6d88f96dfSTim Northoverdeclare extern_weak tailcc void @callee_weak() 7d88f96dfSTim Northover 8d88f96dfSTim Northoverdefine tailcc void @caller_to0_from0() nounwind { 9d88f96dfSTim Northover; CHECK-LABEL: _caller_to0_from0: 10d88f96dfSTim Northover 11d88f96dfSTim Northover tail call tailcc void @callee_stack0() 12d88f96dfSTim Northover ret void 13d88f96dfSTim Northover; CHECK-NOT: add 14d88f96dfSTim Northover; CHECK-NOT: sub 15d88f96dfSTim Northover; CHECK: b.w _callee_stack0 16d88f96dfSTim Northover} 17d88f96dfSTim Northover 18d88f96dfSTim Northoverdefine tailcc void @caller_to0_from4([4 x i32], i32) { 19d88f96dfSTim Northover; CHECK-LABEL: _caller_to0_from4: 20d88f96dfSTim Northover 21d88f96dfSTim Northover tail call tailcc void @callee_stack0() 22d88f96dfSTim Northover ret void 23d88f96dfSTim Northover 24d88f96dfSTim Northover; CHECK: add sp, #16 25d88f96dfSTim Northover; CHECK-NEXT: b.w _callee_stack0 26d88f96dfSTim Northover} 27d88f96dfSTim Northover 28d88f96dfSTim Northoverdefine tailcc void @caller_to4_from0() { 29d88f96dfSTim Northover; Key point is that the "42" should go #16 below incoming stack 30d88f96dfSTim Northover; pointer (we didn't have arg space to reuse). 31d88f96dfSTim Northover tail call tailcc void @callee_stack4([4 x i32] undef, i32 42) 32d88f96dfSTim Northover ret void 33d88f96dfSTim Northover 34d88f96dfSTim Northover; CHECK-LABEL: _caller_to4_from0: 35d88f96dfSTim Northover; CHECK: sub sp, #16 36d88f96dfSTim Northover; CHECK: movs [[TMP:r[0-9]+]], #42 37d88f96dfSTim Northover; CHECK: str [[TMP]], [sp] 38d88f96dfSTim Northover; CHECK-NOT: add sp 39d88f96dfSTim Northover; CHECK: b.w _callee_stack4 40d88f96dfSTim Northover 41d88f96dfSTim Northover} 42d88f96dfSTim Northover 43d88f96dfSTim Northoverdefine tailcc void @caller_to4_from4([4 x i32], i32 %a) { 44d88f96dfSTim Northover; CHECK-LABEL: _caller_to4_from4: 45d88f96dfSTim Northover; CHECK-NOT: sub sp 46d88f96dfSTim Northover; Key point is that the "%a" should go where at SP on entry. 47d88f96dfSTim Northover tail call tailcc void @callee_stack4([4 x i32] undef, i32 42) 48d88f96dfSTim Northover ret void 49d88f96dfSTim Northover 50d88f96dfSTim Northover; CHECK: str {{r[0-9]+}}, [sp] 51d88f96dfSTim Northover; CHECK-NOT: add sp 52d88f96dfSTim Northover; CHECK-NEXT: b.w _callee_stack4 53d88f96dfSTim Northover} 54d88f96dfSTim Northover 55d88f96dfSTim Northoverdefine tailcc void @caller_to20_from4([4 x i32], i32 %a) { 56d88f96dfSTim Northover; CHECK-LABEL: _caller_to20_from4: 57d88f96dfSTim Northover; CHECK: sub sp, #16 58d88f96dfSTim Northover 59d88f96dfSTim Northover; Important point is that the call reuses the "dead" argument space 60d88f96dfSTim Northover; above %a on the stack. If it tries to go below incoming-SP then the 61d88f96dfSTim Northover; _callee will not deallocate the space, even in tailcc. 62d88f96dfSTim Northover tail call tailcc void @callee_stack20([4 x i32] undef, [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5]) 63d88f96dfSTim Northover 64d88f96dfSTim Northover; CHECK: str {{.*}}, [sp] 65d88f96dfSTim Northover; CHECK: str {{.*}}, [sp, #4] 66d88f96dfSTim Northover; CHECK: str {{.*}}, [sp, #8] 67d88f96dfSTim Northover; CHECK: str {{.*}}, [sp, #12] 68d88f96dfSTim Northover; CHECK: str {{.*}}, [sp, #16] 69d88f96dfSTim Northover; CHECK-NOT: add sp 70d88f96dfSTim Northover; CHECK-NOT: sub sp 71d88f96dfSTim Northover; CHECK: b.w _callee_stack20 72d88f96dfSTim Northover ret void 73d88f96dfSTim Northover} 74d88f96dfSTim Northover 75d88f96dfSTim Northover 76d88f96dfSTim Northoverdefine tailcc void @caller_to4_from24([4 x i32], i64 %a, i64 %b, i64 %c) { 77d88f96dfSTim Northover; CHECK-LABEL: _caller_to4_from24: 78d88f96dfSTim Northover 79d88f96dfSTim Northover 80d88f96dfSTim Northover; Key point is that the "%a" should go where at #16 above SP on entry. 81d88f96dfSTim Northover tail call tailcc void @callee_stack4([4 x i32] undef, i32 42) 82d88f96dfSTim Northover ret void 83d88f96dfSTim Northover 84d88f96dfSTim Northover; CHECK: str {{.*}}, [sp, #16] 85d88f96dfSTim Northover; CHECK: add sp, #16 86d88f96dfSTim Northover; CHECK-NEXT: b.w _callee_stack4 87d88f96dfSTim Northover} 88d88f96dfSTim Northover 89d88f96dfSTim Northover 90d88f96dfSTim Northoverdefine tailcc void @caller_to20_from20([4 x i32], [5 x i32] %a) { 91d88f96dfSTim Northover; CHECK-LABEL: _caller_to20_from20: 92d88f96dfSTim Northover; CHECK-NOT: add sp, 93d88f96dfSTim Northover; CHECK-NOT: sub sp, 94d88f96dfSTim Northover 95d88f96dfSTim Northover; Here we want to make sure that both loads happen before the stores: 96d88f96dfSTim Northover; otherwise either %a or %b.w will be wrongly clobbered. 97d88f96dfSTim Northover tail call tailcc void @callee_stack20([4 x i32] undef, [5 x i32] %a) 98d88f96dfSTim Northover ret void 99d88f96dfSTim Northover 100d88f96dfSTim Northover ; If these ever get interleaved make sure aliasing slots don't clobber each 101d88f96dfSTim Northover ; other. 102d88f96dfSTim Northover; CHECK: ldrd {{.*}}, {{.*}}, [sp, #12] 103d88f96dfSTim Northover; CHECK: ldm.w sp, 104d88f96dfSTim Northover; CHECK: stm.w 105d88f96dfSTim Northover; CHECK: strd 106d88f96dfSTim Northover; CHECK-NEXT: b.w _callee_stack20 107d88f96dfSTim Northover} 108d88f96dfSTim Northover 109d88f96dfSTim Northoverdefine tailcc void @disable_tail_calls() nounwind "disable-tail-calls"="true" { 110d88f96dfSTim Northover; CHECK-LABEL: disable_tail_calls: 111d88f96dfSTim Northover 112d88f96dfSTim Northover tail call tailcc void @callee_stack0() 113d88f96dfSTim Northover ret void 114d88f96dfSTim Northover 115d88f96dfSTim Northover; CHECK: bl _callee_stack0 116d88f96dfSTim Northover; CHECK: ret 117d88f96dfSTim Northover} 118d88f96dfSTim Northover 119d88f96dfSTim Northoverdefine tailcc void @normal_ret_with_stack([4 x i32], i32 %a) { 120d88f96dfSTim Northover; CHECK: _normal_ret_with_stack: 121d88f96dfSTim Northover; CHECK: add sp, #16 122d88f96dfSTim Northover; CHECK: bx lr 123d88f96dfSTim Northover ret void 124d88f96dfSTim Northover} 125d88f96dfSTim Northover 126d88f96dfSTim Northoverdeclare { [2 x float] } @get_vec2() 127d88f96dfSTim Northover 128d88f96dfSTim Northoverdefine void @fromC_totail() { 129d88f96dfSTim Northover; COMMON-LABEL: fromC_totail: 130d88f96dfSTim Northover; COMMON: puch {r4, lr} 131d88f96dfSTim Northover; COMMON: sub sp, #8 132d88f96dfSTim Northover 133d88f96dfSTim Northover; COMMON-NOT: sub sp, 134d88f96dfSTim Northover; COMMON: movs [[TMP:r[0-9]+]], #42 135d88f96dfSTim Northover; COMMON: str [[TMP]], [sp] 136d88f96dfSTim Northover; COMMON: bl _callee_stack4 137d88f96dfSTim Northover ; We must reset the stack to where it was before the call by undoing its extra stack pop. 138d88f96dfSTim Northover; COMMON: sub sp, #16 139d88f96dfSTim Northover; COMMON: str [[TMP]], [sp] 140d88f96dfSTim Northover; COMMON: bl callee_stack4 141d88f96dfSTim Northover; COMMON: sub sp, #16 142d88f96dfSTim Northover 143d88f96dfSTim Northover call tailcc void @callee_stack4([4 x i32] undef, i32 42) 144d88f96dfSTim Northover call tailcc void @callee_stack4([4 x i32] undef, i32 42) 145d88f96dfSTim Northover ret void 146d88f96dfSTim Northover} 147d88f96dfSTim Northover 148d88f96dfSTim Northoverdefine void @fromC_totail_noreservedframe(i32 %len) { 149d88f96dfSTim Northover; COMMON-LABEL: fromC_totail_noreservedframe: 150d88f96dfSTim Northover; COMMON: sub.w sp, sp, r{{.*}} 151d88f96dfSTim Northover 152d88f96dfSTim Northover; COMMON: movs [[TMP:r[0-9]+]], #42 153d88f96dfSTim Northover ; Note stack is subtracted here to allocate space for arg 154d88f96dfSTim Northover; COMMON: sub.w sp, #16 155d88f96dfSTim Northover; COMMON: str [[TMP]], [sp] 156d88f96dfSTim Northover; COMMON: bl _callee_stack4 157d88f96dfSTim Northover ; And here. 158d88f96dfSTim Northover; COMMON: sub sp, #16 159d88f96dfSTim Northover; COMMON: str [[TMP]], [sp] 160d88f96dfSTim Northover; COMMON: bl _callee_stack4 161d88f96dfSTim Northover ; But not restored here because callee_stack8 did that for us. 162d88f96dfSTim Northover; COMMON-NOT: sub sp, 163d88f96dfSTim Northover 164d88f96dfSTim Northover ; Variable sized allocation prevents reserving frame at start of function so each call must allocate any stack space it needs. 165d88f96dfSTim Northover %var = alloca i32, i32 %len 166d88f96dfSTim Northover 167d88f96dfSTim Northover call tailcc void @callee_stack4([4 x i32] undef, i32 42) 168d88f96dfSTim Northover call tailcc void @callee_stack4([4 x i32] undef, i32 42) 169d88f96dfSTim Northover ret void 170d88f96dfSTim Northover} 171d88f96dfSTim Northover 172d88f96dfSTim Northoverdeclare void @Ccallee_stack4([4 x i32], i32) 173d88f96dfSTim Northover 174d88f96dfSTim Northoverdefine tailcc void @fromtail_toC() { 175d88f96dfSTim Northover; COMMON-LABEL: fromtail_toC: 176d88f96dfSTim Northover; COMMON: push {r4, lr} 177d88f96dfSTim Northover; COMMON: sub sp, #8 178d88f96dfSTim Northover 179d88f96dfSTim Northover; COMMON-NOT: sub sp, 180d88f96dfSTim Northover; COMMON: movs [[TMP:r[0-9]+]], #42 181d88f96dfSTim Northover; COMMON: str [[TMP]], [sp] 182d88f96dfSTim Northover; COMMON: bl _Ccallee_stack4 183d88f96dfSTim Northover ; C callees will return with the stack exactly where we left it, so we mustn't try to fix anything. 184d88f96dfSTim Northover; COMMON-NOT: add sp, 185d88f96dfSTim Northover; COMMON-NOT: sub sp, 186d88f96dfSTim Northover; COMMON: str [[TMP]], [sp]{{$}} 187d88f96dfSTim Northover; COMMON: bl _Ccallee_stack4 188d88f96dfSTim Northover; COMMON-NOT: sub sp, 189d88f96dfSTim Northover 190d88f96dfSTim Northover call void @Ccallee_stack4([4 x i32] undef, i32 42) 191d88f96dfSTim Northover call void @Ccallee_stack4([4 x i32] undef, i32 42) 192d88f96dfSTim Northover ret void 193d88f96dfSTim Northover} 194*19d2e42bSTim Northover 195*19d2e42bSTim Northover; Don't try to return by popping pc if there's stack to reclaim. 196*19d2e42bSTim Northoverdefine tailcc void @notail_stackclean([4 x i32], i32) { 197*19d2e42bSTim Northover; COMMON-LABEL: notail_stackclean: 198*19d2e42bSTim Northover; COMMON: pop {r7, lr} 199*19d2e42bSTim Northover; COMMON: add sp, #8 200*19d2e42bSTim Northover; COMMON: bx lr 201*19d2e42bSTim Northover 202*19d2e42bSTim Northover 203*19d2e42bSTim Northover call void @callee_stack0() 204*19d2e42bSTim Northover ret void 205*19d2e42bSTim Northover} 206