Index: llvm/lib/Target/ARM/Thumb1FrameLowering.cpp =================================================================== --- llvm/lib/Target/ARM/Thumb1FrameLowering.cpp +++ llvm/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -538,18 +538,30 @@ AFI->getDPRCalleeSavedAreaSize() + ArgRegsSaveSize); + // We are likely to need a scratch register and we know all callee-save + // registers are free at this point in the epilogue, so pick one. + unsigned ScratchRegister = ARM::NoRegister; + bool HasFP = hasFP(MF); + for (auto &I : MFI.getCalleeSavedInfo()) { + Register Reg = I.getReg(); + if (isARMLowRegister(Reg) && !(HasFP && Reg == FramePtr)) { + ScratchRegister = Reg; + break; + } + } + if (AFI->shouldRestoreSPFromFP()) { NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; // Reset SP based on frame pointer only if the stack frame extends beyond // frame pointer stack slot, the target is ELF and the function has FP, or // the target uses var sized objects. if (NumBytes) { - assert(!MFI.getPristineRegs(MF).test(ARM::R4) && + assert(ScratchRegister != ARM::NoRegister && "No scratch register to restore SP from FP!"); - emitThumbRegPlusImmediate(MBB, MBBI, dl, ARM::R4, FramePtr, -NumBytes, + emitThumbRegPlusImmediate(MBB, MBBI, dl, ScratchRegister, FramePtr, -NumBytes, TII, *RegInfo, MachineInstr::FrameDestroy); BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP) - .addReg(ARM::R4) + .addReg(ScratchRegister) .add(predOps(ARMCC::AL)) .setMIFlag(MachineInstr::FrameDestroy); } else @@ -558,18 +570,6 @@ .add(predOps(ARMCC::AL)) .setMIFlag(MachineInstr::FrameDestroy); } else { - // For a large stack frame, we might need a scratch register to store - // the size of the frame. We know all callee-save registers are free - // at this point in the epilogue, so pick one. - unsigned ScratchRegister = ARM::NoRegister; - bool HasFP = hasFP(MF); - for (auto &I : MFI.getCalleeSavedInfo()) { - Register Reg = I.getReg(); - if (isARMLowRegister(Reg) && !(HasFP && Reg == FramePtr)) { - ScratchRegister = Reg; - break; - } - } if (MBBI != MBB.end() && MBBI->getOpcode() == ARM::tBX_RET && &MBB.front() != &*MBBI && std::prev(MBBI)->getOpcode() == ARM::tPOP) { MachineBasicBlock::iterator PMBBI = std::prev(MBBI); Index: llvm/test/CodeGen/ARM/cmse.ll =================================================================== --- llvm/test/CodeGen/ARM/cmse.ll +++ llvm/test/CodeGen/ARM/cmse.ll @@ -290,9 +290,9 @@ ; CHECK-8B-NEXT: mov sp, r4 ; CHECK-8B-NEXT: mov r0, sp ; CHECK-8B-NEXT: bl func51 -; CHECK-8B-NEXT: subs r4, r7, #7 -; CHECK-8B-NEXT: subs r4, #1 -; CHECK-8B-NEXT: mov sp, r4 +; CHECK-8B-NEXT: subs r6, r7, #7 +; CHECK-8B-NEXT: subs r6, #1 +; CHECK-8B-NEXT: mov sp, r6 ; CHECK-8B-NEXT: pop {r4, r6, r7} ; CHECK-8B-NEXT: pop {r0} ; CHECK-8B-NEXT: mov lr, r0 Index: llvm/test/CodeGen/ARM/thumb1-varalloc.ll =================================================================== --- llvm/test/CodeGen/ARM/thumb1-varalloc.ll +++ llvm/test/CodeGen/ARM/thumb1-varalloc.ll @@ -33,9 +33,9 @@ bb3: %.0 = phi ptr [ %0, %entry ], [ %5, %bb2 ], [ %2, %bb1 ] -; CHECK: subs r4, r7, #7 -; CHECK-NEXT: subs r4, #1 -; CHECK-NEXT: mov sp, r4 +; CHECK: subs r6, r7, #7 +; CHECK-NEXT: subs r6, #1 +; CHECK-NEXT: mov sp, r6 ; CHECK-NEXT: pop {r4, r6, r7, pc} ret ptr %.0 } Index: llvm/test/CodeGen/Thumb/2011-EpilogueBug.ll =================================================================== --- llvm/test/CodeGen/Thumb/2011-EpilogueBug.ll +++ llvm/test/CodeGen/Thumb/2011-EpilogueBug.ll @@ -5,13 +5,16 @@ %struct.info = type { i32, i32, i32, i32, i32, i32, i32, ptr } define void @t1(ptr %v) { -; CHECK: push {r4 %tmp6 = load i32, ptr null %tmp8 = alloca float, i32 %tmp6 store i32 1, ptr null br label %return return: ; preds = %0 -; CHECK: mov sp, r4 +; CHECK: subs [[SCRATCH:r[0-7]]], r7, #7 +; CHECK: subs [[SCRATCH]], #1 +; CHECK: mov sp, [[SCRATCH]] +; CHECK-NEXT: pop +; CHECK-SAME: [[SCRATCH]] ret void } Index: llvm/test/CodeGen/Thumb/callee_save.ll =================================================================== --- llvm/test/CodeGen/Thumb/callee_save.ll +++ llvm/test/CodeGen/Thumb/callee_save.ll @@ -304,9 +304,9 @@ ; CHECK-NEXT: movs r1, #2 ; CHECK-NEXT: movs r2, #3 ; CHECK-NEXT: movs r3, #4 -; CHECK-NEXT: subs r4, r7, #7 -; CHECK-NEXT: subs r4, #9 -; CHECK-NEXT: mov sp, r4 +; CHECK-NEXT: subs r6, r7, #7 +; CHECK-NEXT: subs r6, #9 +; CHECK-NEXT: mov sp, r6 ; CHECK-NEXT: pop {r4, r6} ; CHECK-NEXT: mov r8, r4 ; CHECK-NEXT: mov r9, r6 Index: llvm/test/CodeGen/Thumb/emergency-spill-slot.ll =================================================================== --- llvm/test/CodeGen/Thumb/emergency-spill-slot.ll +++ llvm/test/CodeGen/Thumb/emergency-spill-slot.ll @@ -29,9 +29,9 @@ ; CHECK-NEXT: ldr r0, [r6] ; CHECK-NEXT: @APP ; CHECK-NEXT: @NO_APP -; CHECK-NEXT: subs r4, r7, #7 -; CHECK-NEXT: subs r4, #5 -; CHECK-NEXT: mov sp, r4 +; CHECK-NEXT: subs r6, r7, #7 +; CHECK-NEXT: subs r6, #5 +; CHECK-NEXT: mov sp, r6 ; CHECK-NEXT: pop {r4, r5, r6, r7, pc} ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: @@ -253,9 +253,9 @@ ; CHECK-NEXT: ldr r0, [sp] ; CHECK-NEXT: @APP ; CHECK-NEXT: @NO_APP -; CHECK-NEXT: subs r4, r7, #7 -; CHECK-NEXT: subs r4, #5 -; CHECK-NEXT: mov sp, r4 +; CHECK-NEXT: subs r6, r7, #7 +; CHECK-NEXT: subs r6, #5 +; CHECK-NEXT: mov sp, r6 ; CHECK-NEXT: pop {r4, r5, r6, r7, pc} ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: @ %bb.1: @@ -300,9 +300,9 @@ ; CHECK-NEXT: str r5, [r7, #124] ; CHECK-NEXT: @APP ; CHECK-NEXT: @NO_APP -; CHECK-NEXT: subs r4, r7, #7 -; CHECK-NEXT: subs r4, #5 -; CHECK-NEXT: mov sp, r4 +; CHECK-NEXT: subs r6, r7, #7 +; CHECK-NEXT: subs r6, #5 +; CHECK-NEXT: mov sp, r6 ; CHECK-NEXT: pop {r4, r5, r6, r7, pc} entry: %y = alloca [4 x i32], align 16 @@ -350,9 +350,9 @@ ; CHECK-NEXT: ldr r0, [sp, #8] @ 4-byte Reload ; CHECK-NEXT: @APP ; CHECK-NEXT: @NO_APP -; CHECK-NEXT: subs r4, r7, #7 -; CHECK-NEXT: subs r4, #5 -; CHECK-NEXT: mov sp, r4 +; CHECK-NEXT: subs r6, r7, #7 +; CHECK-NEXT: subs r6, #5 +; CHECK-NEXT: mov sp, r6 ; CHECK-NEXT: pop {r4, r5, r6, r7, pc} entry: %y = alloca [4 x i32], align 16 Index: llvm/test/CodeGen/Thumb/frame-chain.ll =================================================================== --- llvm/test/CodeGen/Thumb/frame-chain.ll +++ llvm/test/CodeGen/Thumb/frame-chain.ll @@ -151,9 +151,9 @@ ; FP-NEXT: movs r1, #0 ; FP-NEXT: str r1, [r6, #4] ; FP-NEXT: str r0, [r2] -; FP-NEXT: subs r4, r7, #7 -; FP-NEXT: subs r4, #1 -; FP-NEXT: mov sp, r4 +; FP-NEXT: subs r6, r7, #7 +; FP-NEXT: subs r6, #1 +; FP-NEXT: mov sp, r6 ; FP-NEXT: pop {r4, r6, r7, pc} ; ; FP-AAPCS-LABEL: required_fp: @@ -185,9 +185,9 @@ ; FP-AAPCS-NEXT: movs r1, #0 ; FP-AAPCS-NEXT: str r1, [r6, #4] ; FP-AAPCS-NEXT: str r0, [r2] -; FP-AAPCS-NEXT: mov r4, r11 -; FP-AAPCS-NEXT: subs r4, #8 -; FP-AAPCS-NEXT: mov sp, r4 +; FP-AAPCS-NEXT: mov r6, r11 +; FP-AAPCS-NEXT: subs r6, #8 +; FP-AAPCS-NEXT: mov sp, r6 ; FP-AAPCS-NEXT: pop {r4, r6} ; FP-AAPCS-NEXT: pop {r0} ; FP-AAPCS-NEXT: mov r11, r0 @@ -217,9 +217,9 @@ ; NOFP-NEXT: movs r1, #0 ; NOFP-NEXT: str r1, [r6, #4] ; NOFP-NEXT: str r0, [r2] -; NOFP-NEXT: subs r4, r7, #7 -; NOFP-NEXT: subs r4, #1 -; NOFP-NEXT: mov sp, r4 +; NOFP-NEXT: subs r6, r7, #7 +; NOFP-NEXT: subs r6, #1 +; NOFP-NEXT: mov sp, r6 ; NOFP-NEXT: pop {r4, r6, r7, pc} ; ; NOFP-AAPCS-LABEL: required_fp: @@ -251,9 +251,9 @@ ; NOFP-AAPCS-NEXT: movs r1, #0 ; NOFP-AAPCS-NEXT: str r1, [r6, #4] ; NOFP-AAPCS-NEXT: str r0, [r2] -; NOFP-AAPCS-NEXT: mov r4, r11 -; NOFP-AAPCS-NEXT: subs r4, #8 -; NOFP-AAPCS-NEXT: mov sp, r4 +; NOFP-AAPCS-NEXT: mov r6, r11 +; NOFP-AAPCS-NEXT: subs r6, #8 +; NOFP-AAPCS-NEXT: mov sp, r6 ; NOFP-AAPCS-NEXT: pop {r4, r6} ; NOFP-AAPCS-NEXT: pop {r0} ; NOFP-AAPCS-NEXT: mov r11, r0 Index: llvm/test/CodeGen/Thumb/large-stack.ll =================================================================== --- llvm/test/CodeGen/Thumb/large-stack.ll +++ llvm/test/CodeGen/Thumb/large-stack.ll @@ -33,9 +33,11 @@ ; CHECK: sub sp, #508 ; CHECK: sub sp, #508 ; CHECK: sub sp, #508 -; CHECK: subs r4, r7, #7 -; CHECK: subs r4, #1 -; CHECK: mov sp, r4 +; CHECK: subs [[SCRATCH:r[0-7]]], r7, #7 +; CHECK: subs [[SCRATCH]], #1 +; CHECK: mov sp, [[SCRATCH]] +; CHECK: pop +; CHECK-SAME: [[SCRATCH]] %tmp = alloca [ 1524 x i8 ] , align 4 ret void } @@ -56,9 +58,11 @@ ; CHECK-LABEL: test2_nofpelim{{>?}}: ; CHECK: ldr [[TEMP:r[0-7]]], ; CHECK: add sp, [[TEMP]] -; CHECK: subs r4, r7, #7 -; CHECK: subs r4, #1 -; CHECK: mov sp, r4 +; CHECK: subs [[SCRATCH:r[0-7]]], r7, #7 +; CHECK: subs [[SCRATCH]], #1 +; CHECK: mov sp, [[SCRATCH]] +; CHECK: pop +; CHECK-SAME: [[SCRATCH]] %tmp = alloca [ 1528 x i8 ] , align 4 ret void } @@ -85,8 +89,10 @@ ; CHECK: add sp, [[TEMP]] ; CHECK: ldr [[TEMP2:r[0-7]]], ; CHECK: add [[TEMP2]], sp -; CHECK: subs r4, r7, -; CHECK: mov sp, r4 +; CHECK: subs [[SCRATCH:r[0-7]]], r7, +; CHECK: mov sp, [[SCRATCH]] +; CHECK: pop +; CHECK-SAME: [[SCRATCH]] %retval = alloca i32, align 4 %tmp = alloca i32, align 4 %a = alloca [805306369 x i8], align 8