Index: lib/Target/ARM/ARMFrameLowering.cpp =================================================================== --- lib/Target/ARM/ARMFrameLowering.cpp +++ lib/Target/ARM/ARMFrameLowering.cpp @@ -76,8 +76,7 @@ const MachineFrameInfo &MFI = MF.getFrameInfo(); // Always eliminate non-leaf frame pointers. - return ((MF.getTarget().Options.DisableFramePointerElim(MF) && - MFI.hasCalls()) || + return ((MF.getTarget().Options.DisableFramePointerElim(MF)) || RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken()); Index: test/CodeGen/Thumb2/frame-pointer.ll =================================================================== --- test/CodeGen/Thumb2/frame-pointer.ll +++ test/CodeGen/Thumb2/frame-pointer.ll @@ -2,7 +2,65 @@ declare void @foo() -; Has a call, but no need for a frame pointer. +; Leaf function, no frame so no need for a frame pointer. +define void @leaf() { +; CHECK-LABEL: leaf: +; CHECK-NOT: push +; CHECK-NOT: sp +; CHECK-NOT: pop +; CHECK: bx lr + ret void +} + +; Leaf function, frame pointer is requested but we don't need any stack frame, +; so don't create a frame pointer. +define void @leaf_nofpelim() "no-frame-pointer-elim"="true" { +; CHECK-LABEL: leaf_nofpelim: +; CHECK-NOT: push +; CHECK-NOT: sp +; CHECK-NOT: pop +; CHECK: bx lr + ret void +} + +; Leaf function, frame pointer is requested and we need a stack frame, so we +; need to use a frame pointer. +define void @leaf_lowreg_nofpelim() "no-frame-pointer-elim"="true" { +; CHECK-LABEL: leaf_lowreg_nofpelim: +; CHECK: push {r4, r7, lr} +; CHECK: add r7, sp, #4 +; CHECK: pop {r4, r7, pc} + call void asm sideeffect "", "~{r4}" () + ret void +} + +; Leaf function, frame pointer is requested and we need a stack frame, so we +; need to use a frame pointer. A high register is pushed to the stack, so we +; must use two push/pop instructions to ensure that fp and sp are adjacent on +; the stack. +define void @leaf_highreg_nofpelim() "no-frame-pointer-elim"="true" { +; CHECK-LABEL: leaf_highreg_nofpelim: +; CHECK: push {r7, lr} +; CHECK: mov r7, sp +; CHECK: str r8, [sp, #-4]! +; CHECK: ldr r8, [sp], #4 +; CHECK: pop {r7, pc} + call void asm sideeffect "", "~{r8}" () + ret void +} + +; Leaf function, frame pointer requested for non-leaf functions only, so no +; need for a stack frame. +define void @leaf_nononleaffpelim() "no-frame-pointer-elim-non-leaf" { +; CHECK-LABEL: leaf_nononleaffpelim: +; CHECK-NOT: push +; CHECK-NOT: sp +; CHECK-NOT: pop +; CHECK: bx lr + ret void +} + +; Has a call, but still no need for a frame pointer. define void @call() { ; CHECK-LABEL: call: ; CHECK: push {[[DUMMYREG:r[0-9]+]], lr} @@ -24,6 +82,17 @@ ret void } +; Has a call, and frame pointer requested for non-leaf function. +define void @call_nononleaffpelim() "no-frame-pointer-elim-non-leaf" { +; CHECK-LABEL: call_nononleaffpelim: +; CHECK: push {r7, lr} +; CHECK: mov r7, sp +; CHECK: bl foo +; CHECK: pop {r7, pc} + call void @foo() + ret void +} + ; Has a high register clobbered, no need for a frame pointer. define void @highreg() { ; CHECK-LABEL: highreg: