diff --git a/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp b/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp index 567180476ae0e..6c81d0f686488 100644 --- a/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp +++ b/llvm/lib/Target/MSP430/MSP430FrameLowering.cpp @@ -200,6 +200,31 @@ bool MSP430FrameLowering::spillCalleeSavedRegisters( return true; } +const char *MSP430FrameLowering::tailCallNameForRestoringCalleSavedRegisters(MutableArrayRef CSI) const { + static unsigned Registers[] = { + /*MSP430::R4, ??? */ MSP430::R5, MSP430::R6, MSP430::R7, + MSP430::R8, MSP430::R9, MSP430::R10, + }; + static const char *RestorerNames[] = { + nullptr, + "__mspabi_func_epilog_1", + "__mspabi_func_epilog_2", + "__mspabi_func_epilog_3", + "__mspabi_func_epilog_4", + "__mspabi_func_epilog_5", + "__mspabi_func_epilog_6", + "__mspabi_func_epilog_7", + }; + const unsigned TotalCount = sizeof(Registers) / sizeof(Registers[0]); + const unsigned PoppedCount = CSI.size(); + for (unsigned i = 0; i < PoppedCount; ++i) { + if (CSI[i].getReg() != Registers[TotalCount - PoppedCount + i]) { + return nullptr; + } + } + return RestorerNames[PoppedCount]; +} + bool MSP430FrameLowering::restoreCalleeSavedRegisters( MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef CSI, const TargetRegisterInfo *TRI) const { @@ -212,6 +237,12 @@ bool MSP430FrameLowering::restoreCalleeSavedRegisters( MachineFunction &MF = *MBB.getParent(); const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const char *RestorerName = tailCallNameForRestoringCalleSavedRegisters(CSI); + if (RestorerName != nullptr) { + BuildMI(MBB, MI, DL, TII.get(MSP430::JMP)).addExternalSymbol(RestorerName); + return true; + } + for (unsigned i = 0, e = CSI.size(); i != e; ++i) BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), CSI[i].getReg()); diff --git a/llvm/lib/Target/MSP430/MSP430FrameLowering.h b/llvm/lib/Target/MSP430/MSP430FrameLowering.h index f6995edf4b0ad..d98bad246235a 100644 --- a/llvm/lib/Target/MSP430/MSP430FrameLowering.h +++ b/llvm/lib/Target/MSP430/MSP430FrameLowering.h @@ -38,6 +38,7 @@ class MSP430FrameLowering : public TargetFrameLowering { MachineBasicBlock::iterator MI, ArrayRef CSI, const TargetRegisterInfo *TRI) const override; + const char *tailCallNameForRestoringCalleSavedRegisters(MutableArrayRef CSI) const; bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, diff --git a/llvm/test/CodeGen/MSP430/epilog-spilled-restore.ll b/llvm/test/CodeGen/MSP430/epilog-spilled-restore.ll new file mode 100644 index 0000000000000..784d9eb45326d --- /dev/null +++ b/llvm/test/CodeGen/MSP430/epilog-spilled-restore.ll @@ -0,0 +1,14 @@ +; RUN: llc < %s | FileCheck %s + +target datalayout = "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16" +target triple = "msp430" + +; TODO check other counts +; TODO check 7 regs! (something strange happens...) + +define void @pops_4_regs() nounwind { +; CHECK-LABEL: pops_4_regs + call void asm sideeffect "", "~{r7},~{r8},~{r9},~{r10}"() + ret void +; CHECK: jmp __mspabi_func_epilog_4 +}