1; RUN: llc -mtriple=thumbv7m-none-eabi -o - %s | FileCheck %s 2 3declare void @foo() 4 5; Leaf function, no frame so no need for a frame pointer. 6define void @leaf() { 7; CHECK-LABEL: leaf: 8; CHECK-NOT: push 9; CHECK-NOT: sp 10; CHECK-NOT: pop 11; CHECK: bx lr 12 ret void 13} 14 15; Leaf function, frame pointer is requested but we don't need any stack frame, 16; so don't create a frame pointer. 17define void @leaf_nofpelim() "frame-pointer"="all" { 18; CHECK-LABEL: leaf_nofpelim: 19; CHECK-NOT: push 20; CHECK-NOT: sp 21; CHECK-NOT: pop 22; CHECK: bx lr 23 ret void 24} 25 26; Leaf function, frame pointer is requested and we need a stack frame, so we 27; need to use a frame pointer. 28define void @leaf_lowreg_nofpelim() "frame-pointer"="all" { 29; CHECK-LABEL: leaf_lowreg_nofpelim: 30; CHECK: push {r4, r6, r7, lr} 31; CHECK: add r7, sp, #8 32; CHECK: pop {r4, r6, r7, pc} 33 call void asm sideeffect "", "~{r4}" () 34 ret void 35} 36 37; Leaf function, frame pointer is requested and we need a stack frame, so we 38; need to use a frame pointer. A high register is pushed to the stack, so we 39; must use two push/pop instructions to ensure that fp and sp are adjacent on 40; the stack. 41define void @leaf_highreg_nofpelim() "frame-pointer"="all" { 42; CHECK-LABEL: leaf_highreg_nofpelim: 43; CHECK: push {r6, r7, lr} 44; CHECK: add r7, sp, #4 45; CHECK: str r8, [sp, #-4]! 46; CHECK: ldr r8, [sp], #4 47; CHECK: pop {r6, r7, pc} 48 call void asm sideeffect "", "~{r8}" () 49 ret void 50} 51 52; Leaf function, frame pointer requested for non-leaf functions only, so no 53; need for a stack frame. 54define void @leaf_nononleaffpelim() "frame-pointer"="non-leaf" { 55; CHECK-LABEL: leaf_nononleaffpelim: 56; CHECK-NOT: push 57; CHECK-NOT: sp 58; CHECK-NOT: pop 59; CHECK: bx lr 60 ret void 61} 62 63; Has a call, but still no need for a frame pointer. 64define void @call() { 65; CHECK-LABEL: call: 66; CHECK: push {[[DUMMYREG:r[0-9]+]], lr} 67; CHECK-NOT: sp 68; CHECK: bl foo 69; CHECK: pop {[[DUMMYREG]], pc} 70 call void @foo() 71 ret void 72} 73 74; Has a call, and frame pointer requested. 75define void @call_nofpelim() "frame-pointer"="all" { 76; CHECK-LABEL: call_nofpelim: 77; CHECK: push {r7, lr} 78; CHECK: mov r7, sp 79; CHECK: bl foo 80; CHECK: pop {r7, pc} 81 call void @foo() 82 ret void 83} 84 85; Has a call, and frame pointer requested for non-leaf function. 86define void @call_nononleaffpelim() "frame-pointer"="non-leaf" { 87; CHECK-LABEL: call_nononleaffpelim: 88; CHECK: push {r7, lr} 89; CHECK: mov r7, sp 90; CHECK: bl foo 91; CHECK: pop {r7, pc} 92 call void @foo() 93 ret void 94} 95 96; Has a high register clobbered, no need for a frame pointer. 97define void @highreg() { 98; CHECK-LABEL: highreg: 99; CHECK: push.w {r8, lr} 100; CHECK-NOT: sp 101; CHECK: bl foo 102; CHECK: pop.w {r8, pc} 103 call void asm sideeffect "", "~{r8}" () 104 call void @foo() 105 ret void 106} 107 108; Has a high register clobbered, frame pointer requested. We need to split the 109; push into two, to ensure that r7 and sp are adjacent on the stack. 110define void @highreg_nofpelim() "frame-pointer"="all" { 111; CHECK-LABEL: highreg_nofpelim: 112; CHECK: push {[[DUMMYREG:r[0-9]+]], r7, lr} 113; CHECK: add r7, sp, #4 114; CHECK: str r8, [sp, #-4]! 115; CHECK: bl foo 116; CHECK: ldr r8, [sp], #4 117; CHECK: pop {[[DUMMYREG]], r7, pc} 118 call void asm sideeffect "", "~{r8}" () 119 call void @foo() 120 ret void 121} 122 123; Has a high register clobbered, frame required due to variable-sized alloca. 124; We need a frame pointer to correctly restore the stack, but don't need to 125; split the push/pop here, because the frame pointer not required by the ABI. 126define void @highreg_alloca(i32 %a) { 127; CHECK-LABEL: highreg_alloca: 128; CHECK: push.w {[[SOMEREGS:.*]], r7, r8, lr} 129; CHECK: add r7, sp, #{{[0-9]+}} 130; CHECK: bl foo 131; CHECK: pop.w {[[SOMEREGS]], r7, r8, pc} 132 %alloca = alloca i32, i32 %a, align 4 133 call void @foo() 134 call void asm sideeffect "", "~{r8}" () 135 ret void 136} 137 138; Has a high register clobbered, frame required due to both variable-sized 139; alloca and ABI. We do need to split the push/pop here. 140define void @highreg_alloca_nofpelim(i32 %a) "frame-pointer"="all" { 141; CHECK-LABEL: highreg_alloca_nofpelim: 142; CHECK: push {[[SOMEREGS:.*]], r7, lr} 143; CHECK: add r7, sp, #{{[0-9]+}} 144; CHECK: str r8, [sp, #-4]! 145; CHECK: bl foo 146; CHECK: ldr r8, [sp], #4 147; CHECK: pop {[[SOMEREGS]], r7, pc} 148 %alloca = alloca i32, i32 %a, align 4 149 call void @foo() 150 call void asm sideeffect "", "~{r8}" () 151 ret void 152} 153